# Eternity II research corpus (eternity2.dev) — full text > Every research page on eternity2.dev, concatenated. This is the machine-ingestible mirror of the wiki at https://eternity2.dev/research. The map with links is at https://eternity2.dev/llms.txt. --- # Research > The open research wiki of the Eternity II community: why the puzzle is so hard, everything you need to build a solver, and the researchers' open notebooks: records, methods, experiments and dead ends, all sourced and reproducible. - Canonical page (with interactive figures/demos): https://eternity2.dev/research/ - Updated: 2026-07-01 --- > **Note** > > This wiki is a work in progress: the site is young and slowly absorbing years of community research. If something you know is missing, the mailing list below is the right place to say so. This wiki is for the people who want to actually solve it. Everyone who has attacked Eternity II took one of nine roads, from modelling why it resists, through pruning the search and building boards up, to throwing hardware at the wall. Pick the road you care about; each opens onto everything the wiki knows about it, drawn from the theory, the solver-building guides, and the lab notebook alike. > **[Interactive: RootsDiagram]** Rendered on the canonical page (link above); not shown in this markdown export. Prefer to browse by reading mode rather than by method? The wiki splits four ways:
- [Why it's hard](/research/why) — The design that was tuned to resist cleverness, and the structural walls (rigidity, entropy, forbidden patterns) that explain the gap between the best known board and a full solution. - [Build a solver](/research/build) — Validation data, the literature ranked by usefulness, the methods behind the records, the dead ends, and how to run the code yourself. - [The lab](/research/lab) — The open notebook: structural findings and the named search experiments built to attack the puzzle, each credited to its author and reproducible from source. - [History & community](/research/community) — The record and the people behind it: two decades told as a story, the record boards themselves, the record-holders and theorists, and the papers.
Or browse by method instead: the nine roads in the left rail are each a hub gathering every article on that theme. ## The reference shelf Two lookups you will reach for again and again while reading or building:
- [Reference](/research/reference) — The exact counts (pieces, colours, edges) to check your own edge-matching and constraint code against. - [Glossary](/research/glossary) — Every term the wiki leans on, defined once: community jargon, the loaded computer-science words, and the notation the boards are written in.
The story of the puzzle, its records and the people who chased them now live together under [History & community](/research/community). ## Community infrastructure The research conversation lives in a few long-standing places:
- [e2.bucas.name board viewer](https://e2.bucas.name) — Jef Bucas's GPL viewer; its URL format is the community's lingua franca (and this site speaks it natively). - [Eternity II Discord](https://discord.gg/Ny5xs3q8w) — An active server where puzzlers share their runs, records and code, in real time. - [groups.io/g/eternity2](https://groups.io/g/eternity2) — The active mailing list: records, techniques, and 15+ years of accumulated folklore.
## Pages in this section - [Build a solver](https://eternity2.dev/research/build) — The practitioner's corner of the wiki: validation data to check your code against, the literature ranked by usefulness, the record timeline and the methods behind it, the dead ends, and how to run the code yourself. - [History & community](https://eternity2.dev/research/community) — The record and the people behind it: two decades of Eternity II told as a story, the record boards themselves, the record-holders and theorists, the academic literature, and how to add your own work to the wiki. - [Contribute your research](https://eternity2.dev/research/contribute) — This wiki is the community's research home, and there is room in it for your work. Three ways to get it published, from a mailing-list post to a pull request, plus the small set of house rules that keep every page trustworthy. - [History: the big steps](https://eternity2.dev/research/history) — The Eternity II story at a glance, from the mailing list founded in 2000 to the 470 record that still stands. A scannable timeline of the turning points, each linking into the full two-part history and the message where it happened. - [The lab](https://eternity2.dev/research/lab) — The wiki's open notebook: structural findings and named search experiments, each credited to the researcher who ran it and reproducible from source. One corner of the community's wider research. - [Papers](https://eternity2.dev/research/papers) — The academic literature on Eternity II and edge-matching puzzles, drawn from the project's research notes and the community reading list, and ranked by how useful each paper actually is if your goal is to write a solver. - [Who's who of E2 research](https://eternity2.dev/research/people) — Two decades of Eternity II research were done by named people on a mailing list. This page is the gallery: who they are, what each of them contributed, and where to read it in their own words. A thank-you as much as an index. - [Records & solvers](https://eternity2.dev/research/records) — Eternity II has never been solved, but fifteen years of community effort have pushed the best board to 470/480. Who holds what, how they did it, and why some headline "480" boards are not actually the real puzzle. - [Reference numbers](https://eternity2.dev/research/reference) — Exact counts of how many valid ways a small block can be filled at a given position of the official Eternity II board, under increasingly constrained rules: known-good numbers to check your solver's edge-matching and constraint code against. - [Why it's hard](https://eternity2.dev/research/why) — Eternity II is not accidentally difficult. It was designed to resist cleverness, and the measurable structural walls (rigidity, entropy, forbidden patterns) explain why no search, however clever, has reached the end. --- # Build a solver > The practitioner's corner of the wiki: validation data to check your code against, the literature ranked by usefulness, the record timeline and the methods behind it, the dead ends, and how to run the code yourself. - Canonical page (with interactive figures/demos): https://eternity2.dev/research/build/ - Updated: 2026-07-01 --- The practitioner's corner. Validation data to check your code against, the literature ranked by usefulness, the record timeline and the methods behind it, plus the dead ends so you don't spend a month on an approach that provably can't work. ## Where to start - **[The builder's toolkit](/research/build/toolkit)** is the ready-to-use starter kit: a Rust workspace that already scores, generates, converts, and benchmarks, with a solve→sweep→compare loop, so you write only the solver. Set it up in your coding agent with one line, or generate boards in the browser. Start here. - **[A map of every known approach](/research/build/approaches-map)** is the one-page survey: every family of attack on Eternity II, what each reached, and where it walls out. The place to orient before you dive in. - **[Concepts](/research/build/techniques)** are the technique shelf: the algorithms and pruning ideas that recur in every serious solver, each with what it costs and what it actually bought on this puzzle. - **[Solver catalogue](/research/build/solvers)** shows how the record engines assemble those parts, from Verhaard's 467 to Blackwood's 470. - **[Reference numbers](/research/reference)** and the **[known facts](/research/build/known-facts)** give you exact counts to check your own edge-matching and constraint code against. - **[Dead ends](/research/build/dead-ends)** lists the approaches that sounded good and provably don't move the score, so you can skip them. - **[Run it yourself](/research/build/run-it-yourself)** is how to build and run this project's own code. The [record timeline](/research/records) and the two-part [history](/research/community/hunt) trace how the community climbed from the first partial boards to today's 470. ## Pages in this section - [The builder's toolkit](https://eternity2.dev/research/build/toolkit) — A ready-to-use Rust starter kit for building your own Eternity II solver: score, generate boards with real colour balance, batch-generate with pinned clues, convert every format, benchmark, and a solve→sweep→compare iteration loop, so you write only the solver. Plus a one-line setup for coding agents, and a board generator right here in the browser. - [A map of every known approach](https://eternity2.dev/research/build/approaches-map) — The survey the community keeps asking for and never finds: every family of attack tried on Eternity II, what each one actually reached, where it walls out, and a link to the deep page. One organising insight runs through all of them. - [Board & puzzle formats, written down](https://eternity2.dev/research/build/formats) — Every format an Eternity II board or puzzle travels in on this site and in the community: the board_edges letter string and the hints clue list, e2pieces.txt, the puzzle CSV, the site's Puzzle JSON, and the viewer URL, with the exact byte-level rules (how the grey border is encoded in each) and, most of all, what each format can and cannot recover. - [Known facts & numbers](https://eternity2.dev/research/build/known-facts) — The numbers every Eternity II researcher ends up re-deriving, collected in one place with their provenance: the puzzle definition, the clue placements, scoring conventions, the record table, search-space sizes and the structural counts. - [The community's benchmarks](https://eternity2.dev/research/build/benchmarks) — How a community forbidden from sharing the pieces built a shared test culture anyway: derived-count verification protocols, the Txibilis and beginner suites, node-count duels, full enumerations, and the one benchmark that is still standing open today. - [The community's toolbox, 2007–2026](https://eternity2.dev/research/build/tooling) — Nineteen years of community software for Eternity II (manual-placement GUIs, editors, public solvers, generators and viewers), plus the quieter layer that made them interoperate: e2pieces.txt, CRC-16 checksums, and the board-in-a-URL format that became the lingua franca. A reference census, with every tool sourced to the message that announced it. - [The four clue puzzles](https://eternity2.dev/research/build/clue-puzzles) — Tomy sold four small companion puzzles for Eternity II: solve one, submit the solution, and the official site revealed one piece's placement on the main board. What each puzzle was, the broken online checker, the eBay grey market, why puzzles 5 and 6 never came, and the clue puzzles' second life as complex-theory test cases and donor piece sets. - [The variants and the claims that live there](https://eternity2.dev/research/build/variants) — Every "Eternity II" that is not the real puzzle: the TopCoder Marathon variant and the unresolved Takahashi 468, McGavin's unframed 480/480, the mixed-set boards, the no-starter challenge, and the claim quarantine, from the 2007 phantom-sets warning to the community's zero-knowledge verification ethic. Ends with a checklist for stating a score properly. - [How the record solvers search](https://eternity2.dev/research/build/solvers) — How the solvers that hold the records actually search. They are all, at heart, depth-first backtrackers; what separates them is the order they try things and how they bend the rules near the end. - [Reduce the search](https://eternity2.dev/research/build/reduce) — Everything that throws away hopeless states before the search wastes time on them: propagation to a fixed point, the all-different matching filter, learned no-goods, and the edge-slipping invariant. - [Backtracking](https://eternity2.dev/research/build/backtracking) — Depth-first search done seriously. The order a solver visits the cells is its one free choice and moves the tree size by orders of magnitude; restarts turn a heavy-tailed runtime into a portfolio. This is the family behind every record backtracker. - [Go faster](https://eternity2.dev/research/build/faster) — Raw throughput: the craft below the algorithm (lookup tables, cache-sized structs, generated code) and spreading the work across many machines. It decides whether a node costs 26 cycles or 2,600, and it is the clearest demonstration that speed alone does not move the wall. - [Build boards up](https://eternity2.dev/research/build/construct) — Building a high-scoring board from an empty grid instead of digging with backtracking: beam search keeps the best partial boards alive and grows them cell by cell. The workhorse behind this project's from-scratch builders, and a clean illustration of why breadth alone stalls in the deep interior. - [Learn from strong boards](https://eternity2.dev/research/build/learning) — Most attacks on Eternity II search from first principles. A distinct family does the opposite: it mines the corpus of boards people have already found for structure, then feeds that structure back into the search. Position priors, learned move-ordering, anti-pattern mining, record decoding, and the failure mode where a learned signal collapses. - [Local search](https://eternity2.dev/research/build/local-search) — Start with a full, imperfect board and improve it by moves: destroy-and-repair, annealing and tempering, evolutionary recombination. The most reliable polishers here, and the cleanest demonstrations of the rigidity wall, where every one of them stops at the same height. - [Exact methods](https://eternity2.dev/research/build/exact) — Solvers that can prove things: SAT and CSP encodings, integer programming and its relaxations, exact-cover, meet-in-the-middle, and iterated projection maps. Complete methods stall on the full board, but their verdicts earn their keep as impossibility proofs on sub-boards. - [The techniques](https://eternity2.dev/research/build/techniques) — The technique shelf: the algorithms and pruning ideas that recur in every serious Eternity II solver, each with what it is, what it costs, and what it actually bought when measured on this puzzle. - [Analysis](https://eternity2.dev/research/build/analysis) — These do not try to solve the puzzle: they measure it, which is how the community knows where the walls are. Parity arguments give one-pass impossibility proofs; solution counting pins down how many full solutions exist to within a factor of two, without anyone having seen one. - [GPU & hardware](https://eternity2.dev/research/build/hardware) — Throwing silicon at the wall: GPU ports, FPGA pipelines, distributed sweeps, and the perennial quantum proposal. This is the ledger of what each one actually delivered, and why the wall it meets is memory and structure, not arithmetic. - [Dead ends](https://eternity2.dev/research/build/dead-ends) — Approaches we tried that look promising and don't move the needle on Eternity II, written down with what we found so you can spend your time elsewhere. - [The dataset](https://eternity2.dev/research/build/dataset) — A public, CC0 dataset for Eternity II in two parts: fourteen benchmark instances to solve, and a corpus of 7,658 distinct strong boards to learn from. Every score is recomputed from the board itself, and the corpus is checked to be genuinely diverse rather than a thousand copies of one board. - [Run it yourself](https://eternity2.dev/research/build/run-it-yourself) — The whole site, the engine, and every result in this section run from one repository. Here is how to get it going, rebuild the WebAssembly engine, and reproduce the numbers. --- # Analysis > These do not try to solve the puzzle: they measure it, which is how the community knows where the walls are. Parity arguments give one-pass impossibility proofs; solution counting pins down how many full solutions exist to within a factor of two, without anyone having seen one. - Canonical page (with interactive figures/demos): https://eternity2.dev/research/build/analysis/ - Updated: 2026-07-13 --- These do not try to solve the puzzle: they measure it, which is how the community knows where the walls are. Parity arguments give one-pass impossibility proofs; solution counting pins down how many full solutions exist to within a factor of two, without anyone having seen one. The pages below go technique by technique: what each is in a line, what it actually reached on the real 16×16 board, where it stops, and the labs and measurements to back it. For the whole territory at once, start with [a map of every known approach](/research/build/approaches-map). ## Pages in this section - [Parity arguments](https://eternity2.dev/research/build/analysis/parity-arguments) — Count anything on an edge-matching board twice, once from each side, and the totals must agree, giving impossibility proofs for the price of one pass. The 479 story shows both the power and the trap: a clean parity claim, true for every interior move, defeated through the sixty border edges nobody scores. - [Solution counting: measuring what you cannot find](https://eternity2.dev/research/build/analysis/solution-counting) — Nobody has ever seen a full Eternity II solution, yet the community knows, to within a factor of two, how many exist. This page is the story and the craft of that number: exact censuses on small boards, the expectation formula and its twenty-year convergence on 14,702, and the culled-search estimates that were trusted only when four independent runs agreed. ## Related - [A map of every known approach](https://eternity2.dev/research/build/approaches-map) — The survey the community keeps asking for and never finds: every family of attack tried on Eternity II, what each one actually reached, where it walls out, and a link to the deep page. One organising insight runs through all of them. - [The techniques](https://eternity2.dev/research/build/techniques) — The technique shelf: the algorithms and pruning ideas that recur in every serious Eternity II solver, each with what it is, what it costs, and what it actually bought when measured on this puzzle. --- # Parity arguments > Count anything on an edge-matching board twice, once from each side, and the totals must agree, giving impossibility proofs for the price of one pass. The 479 story shows both the power and the trap: a clean parity claim, true for every interior move, defeated through the sixty border edges nobody scores. - Canonical page (with interactive figures/demos): https://eternity2.dev/research/build/analysis/parity-arguments/ - Updated: 2026-07-02 - Topics: structure, search-space - Source: kubzpa's parity claim that a 479 score is impossible (August 2007) — https://groups.io/g/eternity2/message/1640 - Source: psykowally's 478 construction: rotate an interior piece with equal opposite edges (msg 1642) — https://groups.io/g/eternity2/message/1642 - Source: Verhaard's refutation: 479 through a flipped border piece (January 2009) — https://groups.io/g/eternity2/message/6317 - Source: angwin_uk & mjqxxxx on border edge-type balance, 12 per side (August 2007) — https://groups.io/g/eternity2/message/2073 - Source: The 2011 parity mega-thread: checkerboard and rotation-balanced piece sets — https://groups.io/g/eternity2/message/8898 - Source: John Gilbert's negative result: balanced sets stall backtrackers faster (msg 8913) — https://groups.io/g/eternity2/message/8913 - Source: Nick's pen-and-paper near-balanced set, and Jamison's global-sum verification (msgs 8977/8978) — https://groups.io/g/eternity2/message/8977 --- A parity argument is double-entry bookkeeping applied to a game board. Every edge inside the puzzle has two sides, so anything counted over the whole board (colour occurrences, matched edges, orientation sums) gets counted twice, once from each side, and the two ledgers must agree. A state where they disagree is not merely unpromising; it is impossible, and no search is needed to prove it. On a puzzle where [no move is ever forced](/research/why/no-forced-moves) and lookahead is expensive, an invariant that costs one pass over the board and never lies is worth taking seriously, as long as you remember which direction it points. ## The 479 story, in three acts The community's best parity tale starts two weeks after launch. In August 2007, kubzpa argued that a placement with *exactly* 479 matched edges, one single mismatch, cannot exist ([msg 1640](https://groups.io/g/eternity2/message/1640)). The intuition is a parity flip: disturb any piece and the edges it touches change state together, so mismatches should come in pairs. psykowally immediately supplied the constructive companion for 478: take a solved board and rotate an interior piece whose opposite edges carry equal colours by 180°: exactly two edges break ([msg 1642](https://groups.io/g/eternity2/message/1642)). The argument is correct for every interior move. It fails at the frame. In January 2009 Louis Verhaard pointed out the leak: the 60 outward-facing grey edges are *unscored*, so a border piece whose two ring-facing sides share a colour can be flipped end-for-end, breaking exactly one scored edge (the seam edge behind it) while the change on the grey side costs nothing ([msg 6317](https://groups.io/g/eternity2/message/6317)). One mismatch, score 479, parity defeated through the edges the scoring convention ignores. This project checked the claim against the official piece set: 14 border pieces qualify (computed), so any full solution implies a 479. That is the version of the story that [known facts](/research/build/known-facts) now carries. Verhaard added a bureaucratic punchline: the prize entry form recorded piece numbers but not rotations, so Tomy's scorer would have read such a board as a 480. The lesson generalises. A parity argument is only as strong as the boundary conditions it accounts for, and Eternity II's scoring rules puncture the boundary in sixty places. ## Flip it yourself The three acts fit on one small board. Below is a genuinely solved, engine-generated framed 8×8: every scored edge matched, and an outward grey rim the score ignores, exactly like the real puzzle's 60 grey edges (32 of them at this size). Every claim in the story above is a single click here. > **[Figure]** Interactive: the parity argument — interactive: ParityFlipLab. Rendered on the canonical page (link above); not shown in this markdown export. ## Step by step 1. **Start solved.** All 112 scored edges match, this board's stand-in for 480/480. The grey band is the rim the scoring convention never reads. 2. **Act one: click any unmarked interior piece.** A 180° turn swaps the up/down edges together and the left/right edges together, so scored edges break in pairs per axis: 0, 2 or 4 at a time, never an odd count. Try as many as you like; no interior click will ever produce exactly one mismatch. That is kubzpa's argument, and for interior moves it is airtight. 3. **Act two: click a sky-ringed interior piece.** One opposite pair equal, the other not: exactly two scored edges break, and the badge reads a 478-class board, psykowally's constructive companion. 4. **Act three: click an emerald-ringed border piece.** Its two ring-facing sides share a colour, so the 180° flip leaves both lateral edges matched. Only the seam edge behind it breaks (*one* scored edge) while the outward change parks on the grey rim (flashed amber), where no scorer ever looks. One mismatch. 479. Verhaard's refutation, in one click. 5. **Audit the boundary.** The counter panel tells you how many pieces of this draw qualify for each move; on the official set, 14 border pieces qualify (computed), so any full solution implies a 479. The proof was correct everywhere the scoring looked; the leak is precisely the edges it exempted. ## What it costs A parity or balance check is a single pass over the scored edges: $$ O(\text{edges}) \;=\; O(480) \ \text{on the full board}, \qquad O(56) \ \text{for NS-1's seam}, $$ with a constant so small it is effectively free: 480 edge reads are microseconds, against search steps counted in billions. That asymmetry of price is why such checks compose with everything: NS-1 after the border closes rejects 10–28% of deep dead-ends for 56 reads, the cheapest pruning this project knows. But the asymmetry of *information* runs the other way, and it never softens: a violated invariant is a proof of impossibility, a satisfied one proves nothing at all. One pass over the edges buys a certificate that only ever says no. It is worth exactly its price, provided nobody mistakes it for guidance. ## Colour sums and multiset balance The second family of counting arguments tallies colours rather than mismatches. Already in August 2007, angwin_uk observed that the border is built balanced: five border edge types, twelve of each on either side of every border piece's grey edge ([msg 2073](https://groups.io/g/eternity2/message/2073)). mjqxxxx sharpened the point: border pieces sit in a fixed orientation, so each type must split *equally* into left-facing and right-facing edges, a strictly stronger condition than even counts ([msg 2098](https://groups.io/g/eternity2/message/2098)). Follow that thought inward and you reach the seam. In any complete solution, the multiset of colours the border ring presents to the interior must equal the multiset the interior presents back: every colour handed in is handed out. That is Hopfer's NS-1 condition, formalised in 2022 and treated at length on [the border balance page](/research/why/border-balance): a genuine necessary condition, cheap to check, and blind to everything that happens interior-to-interior. Same mathematics, two uses. In 2007 the balance served to [estimate how many border solutions exist](/research/build/analysis/solution-counting); in 2022 it was turned around into a pruning certificate. ## The 2011 expedition: balance is abundant and buys nothing After the contest ended, the list spent the summer of 2011 pushing parity as far as it would go. Juraj Pivovarov posed the *oriented set* problem: split the 256 pieces into checkerboard piles A and B so that every colour's directional edge counts balance, because knowing either the orientations or the pile assignment of a solution would make the rest easy ([msg 8898](https://groups.io/g/eternity2/message/8898)). Peter McGavin reduced the condition to per-colour sums, left equals right and top equals bottom ([msg 8906](https://groups.io/g/eternity2/message/8906)). Juraj then counted the qualifying checkerboard rotation-balanced sets: his first estimate of roughly $4.5 \times 10^{485}$ ([msg 8929](https://groups.io/g/eternity2/message/8929)) drew a "something must be wrong" from Michael Field ([msg 8930](https://groups.io/g/eternity2/message/8930)), and the corrected count settled around $3 \times 10^{147}$ ([msg 8931](https://groups.io/g/eternity2/message/8931)). All the while, he framed the search for even one as a hard instance of PARTITION. Two results ended the expedition, both worth keeping. John Gilbert ran the experiment: balanced checkerboard sets can be found one at a time, but feeding the balance to a backtracker as a constraint makes it stall *faster*: each placement now draws on half the candidate pieces, and the restriction costs more than it prunes ([msg 8913](https://groups.io/g/eternity2/message/8913)). And Nick, working with pen and paper while bored on a train ([msg 8960](https://groups.io/g/eternity2/message/8960)), drove a full 256-piece checkerboard-plus-rotation assignment to within a single edge-flip of balance ([msg 8977](https://groups.io/g/eternity2/message/8977)); Jason Jamison verified the global sums under Nick's coding (all tops equal all bottoms at 2,809, all lefts equal all rights at 2,881) and reported that the near-balanced set still stalled his backtracker about 19 pieces out of a corner ([msg 8978](https://groups.io/g/eternity2/message/8978)). Balance is real, abundant, and buys the search nothing. ## What parity buys a solver author Three things, none of them a solution. **Cheap necessary conditions.** A parity or balance check costs one pass and composes with anything: a backtracker, a [local search](/research/build/local-search/local-search-alns), a sanity check on someone else's claimed board. The NS-1 figures above show the going rate. **Certificate asymmetry.** Every argument on this page points one way: a violated invariant says *definitely broken*, a satisfied one never says *definitely fine*. Swap two border pieces and NS-1 stays at zero; balance a piece set perfectly and the backtracker stalls anyway. Parity prunes; it does not guide. **A boundary-conditions reflex.** The 479 proof was correct everywhere the prover looked, and wrong because the scoring rules created sixty edges he did not have to look at. Before trusting any counting argument on this puzzle, including this project's own, audit what the frame, the scoring convention, and the unscored grey are quietly exempting. On Eternity II, the exceptions live at the border, and the border is where the arguments go to die. ## Related - [The border balance](https://eternity2.dev/research/why/border-balance) — A solved board hides a simple bookkeeping law: every colour the border hands to the interior, the interior hands straight back. Break it and you know instantly the board is wrong; obeying it, though, guarantees nothing. - [Known facts & numbers](https://eternity2.dev/research/build/known-facts) — The numbers every Eternity II researcher ends up re-deriving, collected in one place with their provenance: the puzzle definition, the clue placements, scoring conventions, the record table, search-space sizes and the structural counts. --- # Solution counting: measuring what you cannot find > Nobody has ever seen a full Eternity II solution, yet the community knows, to within a factor of two, how many exist. This page is the story and the craft of that number: exact censuses on small boards, the expectation formula and its twenty-year convergence on 14,702, and the culled-search estimates that were trusted only when four independent runs agreed. - Canonical page (with interactive figures/demos): https://eternity2.dev/research/build/analysis/solution-counting/ - Updated: 2026-07-02 - Topics: structure - Source: Brendan Owen's launch-day estimate: 5,930 with the hint, ~4.65M without, reconciling the 'roughly 5 million' Monckton had given Dave Clark (msg 987, 2007-07) — https://groups.io/g/eternity2/message/987 - Source: The closed-form expected-solutions product posted to the list (msg 3385, 2007-11) — https://groups.io/g/eternity2/message/3385 - Source: kubzpa's paper 'E2 has 15 millions of solutions' (msg 3497, 2007-12; v2 after peer review, msg 3583) — https://groups.io/g/eternity2/message/3497 - Source: Owen's four independent culled border searches converge on ≈4.05×10³⁷ (msg 2696, 2007-09; first figure msg 1225) — https://groups.io/g/eternity2/message/2696 - Source: McGavin: 1.1527×10⁷ solutions without the starter vs 14,702 with it, and nodes-per-solution unchanged (msg 8924, 2011) — https://groups.io/g/eternity2/message/8924 - Source: McGavin's canonical statement: 14,702 with the starter, 4×10⁻⁸ with all five clues (msg 11193, 2024) — https://groups.io/g/eternity2/message/11193 - Source: Clue #3 counted exactly: 2,195,647,488 solutions (msg 8168, 2010) — https://groups.io/g/eternity2/message/8168 - Source: Both 9×9 benchmarks exhausted: 2 and 3 solutions against a predicted 3.2 (msg 8793, 2011; corrections 8801–8803) — https://groups.io/g/eternity2/message/8793 --- Nobody has ever exhibited a full Eternity II solution. The community nevertheless agrees on how many exist, to within a claimed factor of two: about **14,702** with the mandatory starter piece, and about **4×10⁻⁸**, effectively exactly one, with all five clues placed ([msg 11193](https://groups.io/g/eternity2/message/11193)). This page is about how a group of people learned to count something none of them could find, and why they bothered. The *why* is not curiosity. A puzzle with 14,702 solutions and a puzzle with 1 are different beasts in every way that matters. **Design**: the puzzle's parameters were tuned so the expected count sits near one; the community reverse-engineered the designer's knob within weeks of the 2007 announcement, when Alan O'Donnell wrote the count as a function of the number of colours $B$ and found it crosses $1$ at $B \approx 14.67$ ([msg 94](https://groups.io/g/eternity2/message/94)); the real puzzle's [17 interior colours](/research/why/phase-transition) sit just past that knife edge. **Difficulty**: solution count divided into search-tree size (nodes per solution) is the real price of the hunt, and it behaves counter-intuitively: Peter McGavin computed that dropping the starter constraint multiplies the solutions by 784 while leaving nodes-per-solution essentially unchanged, $9.2766\times10^{42}$ against $9.2751\times10^{42}$ ([msg 8924](https://groups.io/g/eternity2/message/8924)). More solutions do not mean an easier puzzle; they mean a proportionally bigger haystack. **Verification**: exact counts on small regions are the community's correctness currency: the way two solvers prove they read the same pieces without ever sharing them (see [the benchmark culture](/research/build/benchmarks)). One more reason the count matters: the solutions are not variations on a theme. Brendan Owen and others stressed that distinct solutions are "generally a complete restructure of the entire puzzle", not local swaps of a few pieces ([msgs 7364/7365](https://groups.io/g/eternity2/message/7365)), so 14,702 is a count of genuinely different boards, scattered through the search space. ## Three ways to count Twenty years of list traffic sort every counting result into three regimes, each with its own guarantees, its own price, and its own failure modes. | Regime | What it gives | What it costs | Flagship result | | --- | --- | --- | --- | | Exact enumeration | The true count | The entire search tree | Clue #3: exactly 2,195,647,488 | | First-moment expectation | An average over puzzles like this one | Pencil-and-paper arithmetic | 14,702 with the starter | | Sampled / culled search | An estimate with informal error bars | A fixed node budget per run | Border ring ≈ 4.05×10³⁷ | ### Exact enumeration: counting by exhausting Where the tree is small enough to walk entirely, counting is just searching without stopping at the first success. The community used this from the first weeks as a *verification protocol*: tile the top-left 3×3 corner with all 256 pieces and you must find exactly **2,633,221** solutions ([msg 2229](https://groups.io/g/eternity2/message/2229)), a number safe to publish under the piece-set copyright, and impossible to reproduce with even one piece mistyped. The 5×5 corners followed in 2009, cross-verified by three independent programs (top-left: 1,596,901,885,652 partials with all five hints, [msg 7103](https://groups.io/g/eternity2/message/7103), [7105](https://groups.io/g/eternity2/message/7105)). Matching the consensus got you into the community's half-joking "Right Numbers Club"; the whole story is on the [benchmarks page](/research/build/benchmarks). Two exact results stand above the rest. In 2010, apal1969 exhausted the official Clue #3 puzzle (a real, commercial Tomy instance) and found exactly **2,195,647,488** solutions ([msg 8168](https://groups.io/g/eternity2/message/8168)): the only commercially sold instance of the family whose solution count is known exactly rather than estimated. And in 2011, both of Brendan Owen's 9×9 benchmark puzzles were exhausted, at about $1.9\times10^{14}$ and $1.45\times10^{14}$ nodes and three weeks each on a dual-core Opteron. They yielded **2** and **3** solutions; [complex theory](/research/why/complex-theory) had predicted 3.2 for the first ([msg 8793](https://groups.io/g/eternity2/message/8793)). Even the counting had to be counted carefully: the first report claimed one solution each, and it took McGavin's independently shuffled backtrackers to surface the missing boards ([msgs 8801–8803](https://groups.io/g/eternity2/message/8801)). Exhaustive does not mean bug-free; only replication is. ### The first moment: counting by expectation For the full 16×16 board, exhaustion is off the table, so the community's main tool has always been the *first-moment* (expected-value) calculation: multiply the number of ways to arrange the pieces by the probability that every internal edge matches, treating edge colours as independent draws. The first versions appeared within **days** of the January 2007 announcement, months before anyone had pieces ([msg 38](https://groups.io/g/eternity2/message/38), [94](https://groups.io/g/eternity2/message/94)). On launch day, with the real piece statistics in hand, Owen computed ≈ **5,930** solutions with the mandatory hint and ≈ **4.65 million** without it, then used the split to audit the marketing: Christopher Monckton had given eternity2.net's Dave Clark a best estimate of "roughly 5 million" solutions, so Owen concluded Monckton's mathematicians had simply forgotten the hint constraint ([msg 987](https://groups.io/g/eternity2/message/987)). David Eddy added the same day that [parity corrections](/research/build/analysis/parity-arguments) (every colour's edge count must be even) contribute a factor of roughly $2^{16}$ that brings the estimate families into agreement ([msg 992](https://groups.io/g/eternity2/message/992)). Convergence took years, and it was not monotone. The closed-form product was posted in November 2007 ([msg 3385](https://groups.io/g/eternity2/message/3385)); mjqxxxx had already begun a fully rigorous counting framework that July ([msg 1221](https://groups.io/g/eternity2/message/1221)); kubzpa's December 2007 paper argued for ~**15 million** solutions with the starter. It got genuine peer review on the list: the list's fixes produced a corrected second version ([msg 3497](https://groups.io/g/eternity2/message/3497), [3583](https://groups.io/g/eternity2/message/3583)), and mjqxxxx then caught a Monte-Carlo inconsistency in v2 ([msg 3589](https://groups.io/g/eternity2/message/3589)) that kubzpa traced to a biased shuffle, revising his estimate again ([msg 3591](https://groups.io/g/eternity2/message/3591)). A "20,000 solutions" figure circulated for years before being traced to the archived French official site ([msg 8515](https://groups.io/g/eternity2/message/8515)). The number that survived is complex theory's: jagbrain derived **14,702** from an independent closed-form Markov model in 2008, matching Owen's iterative method exactly ([msg 5758](https://groups.io/g/eternity2/message/5758)); McGavin published the same figure in 2011 ([msg 8924](https://groups.io/g/eternity2/message/8924)) and restated it as the canonical answer in 2024: 14,702 with the starter, "probably accurate to within a factor of 2", and $4\times10^{-8}$ with all five clues, "very strongly suggesting… a single, unique solution" ([msg 11193](https://groups.io/g/eternity2/message/11193)). The machinery behind those numbers, the depth-by-depth expectation and what it predicts about the search tree, lives on the [complex theory page](/research/why/complex-theory); this page only needs its output. One caveat the community itself raised belongs here. E2 was *generated from a solution*, and picking a puzzle by picking a solution oversamples solution-rich piece sets, so the count conditioned on the generation process should run *higher* than the plain expectation, by an amount the thread tried and failed to pin down ([msgs 6892/6894](https://groups.io/g/eternity2/message/6892)). Expectation formulas price a random puzzle with E2's statistics; E2 is not quite a random such puzzle. ### Sampled and culled search: counting by surviving Between exact and expected sits the third regime: run a real search, but randomly cull it to a fixed budget, and scale the survivors back up. The archive's methodological gem is Owen's September 2007 census of the border ring. He ran **four separate searches** of the 60-piece frame, each randomly culling the tree while keeping about 10 million active nodes per depth. Each of the four independently estimated **≈ 4.05×10³⁷** border solutions ([msg 2696](https://groups.io/g/eternity2/message/2696), first posted at [msg 1225](https://groups.io/g/eternity2/message/1225)). The figure disagreed with eternity2.net's published estimate by thirteen orders of magnitude, and the replication is exactly why the community sided with Owen. A single culled run can be silently biased by anything; four independent runs agreeing is an error bar you can see. That habit (replication as error control, not authority) is the same one that later governed the corner censuses and the 9×9 recounts. ## Step by step: the expectation formula on a tiny board The first-moment calculation is worth doing once by hand. Take a miniature E2: a framed 3×3 board (4 corner pieces, 4 edge pieces, 1 interior piece) with a single palette of $c$ colours on every internal edge. **Step 1: count the arrangements.** Corners go to corner cells with their orientation forced by the two grey sides; edge pieces likewise; the single interior piece keeps its 4 rotations: $$ A \;=\; 4! \times 4! \times 4 \;=\; 2304 . $$ **Step 2: count the constraints.** The board has $2\cdot3\cdot2 = 12$ internal edges. If colours were independent uniform draws, each edge would match with probability $1/c$. **Step 3: multiply.** $$ \mathbb{E}[S] \;=\; \frac{2304}{c^{12}} \quad\Longrightarrow\quad c=2:\ 0.56, \qquad c=3:\ 0.0043 . $$ That is the entire designer's dilemma in one line: at two colours the tiny puzzle expects about half a solution, at three it is almost surely unsolvable. A fraction of a colour swings the expectation across the "exactly one" line. Scale the same product up to the real board, with $4!$ corner arrangements, $56!$ edge arrangements, $195!\cdot4^{195}$ interior arrangements (the starter is pinned), 60 frame-ring edges at $1/5$ and $56+364=420$ remaining edges at $1/17$, and you get the form posted to the list in November 2007 ([msg 3385](https://groups.io/g/eternity2/message/3385)): $$ \mathbb{E}[S] \;=\; 4!\;56!\;195!\;4^{195} \left(\tfrac{1}{5}\right)^{60}\left(\tfrac{1}{17}\right)^{420} \;\approx\; 0.02 . $$ There is no hiding the gap: **0.02 is not 14,702**. The naive product is nearly six orders of magnitude too small, and the community knew why from the start. Treating every edge as an independent $1/17$ coin flip prices the last piece like the first, when in reality the real piece set pairs up perfectly (every colour has an even count, with [zero slack](/research/build/known-facts)), so the match probabilities in the endgame are conditioned far above $1/17$ by everything already placed. Those parity and depletion corrections were flagged in the very message that posted the formula, and Eddy's $\sim 2^{16}$ even-count factor ([msg 992](https://groups.io/g/eternity2/message/992)) is the largest of them. [Complex theory](/research/why/complex-theory) is precisely this calculation done properly, tracking the surviving piece and colour counts depth by depth instead of assuming a fixed probability, and *that* is the version that lands at 14,702 and matches exhaustive counts on small boards to within its claimed factor of two. The structure of the formula (arrangements × match probability) is right; where you take the probability from is the whole game. ## What it costs The three regimes are really three points on a cost–knowledge curve. **Exact enumeration costs the tree itself.** Counting is exhaustive search that refuses to stop: each 9×9 census cost on the order of $10^{14}$ nodes and three weeks of 2011 hardware, and the price grows with the search space, not with the answer. For the full puzzle the tree is $\sim 10^{45}$ wide at its plateau; the exact count of E2's solutions will not be computed by anyone, ever, by this route. **Expectation costs almost nothing, and that is its trap.** The first-moment formula is $O(1)$ arithmetic (complex theory's refined version is a few hundred multiplications, one per cell), which is why it existed before the puzzle shipped. But a first moment carries no information about *variance*: it tells you the average count over puzzles with E2's statistics, not whether the mass sits in typical instances or in rare solution-rich freaks, and not whether the partial boards being counted at each depth are genuinely distinct. The [entropy and area-law results](/research/why/entropy-area-law) show exactly where that blindness bites: past ~80 cells, distinctness collapses in a way no independence model can see. Use expectations to compare orders and set expectations, never as bounds. **Sampling buys error bars only through repetition.** A culled search costs one node budget per run and gives an estimate of unknown bias; Owen paid four budgets for the border ring and bought the only kind of confidence this regime offers. The rule the community settled on is the one worth carrying out of this page: a sampled count you have seen once is an anecdote; the same count from independent runs, seeds, and authors is a measurement. ## Related - [Complex theory: counting the search before you run it](https://eternity2.dev/research/why/complex-theory) — Brendan Owen's complex theory estimates how wide the search tree is at every depth, and even how many solutions exist at all. Many in the community consider it the single most important thing to understand about Eternity II. - [The community's benchmarks](https://eternity2.dev/research/build/benchmarks) — How a community forbidden from sharing the pieces built a shared test culture anyway: derived-count verification protocols, the Txibilis and beginner suites, node-count duels, full enumerations, and the one benchmark that is still standing open today. - [Known facts & numbers](https://eternity2.dev/research/build/known-facts) — The numbers every Eternity II researcher ends up re-deriving, collected in one place with their provenance: the puzzle definition, the clue placements, scoring conventions, the record table, search-space sizes and the structural counts. --- # A map of every known approach > The survey the community keeps asking for and never finds: every family of attack tried on Eternity II, what each one actually reached, where it walls out, and a link to the deep page. One organising insight runs through all of them. - Canonical page (with interactive figures/demos): https://eternity2.dev/research/build/approaches-map/ - Updated: 2026-07-08 - Source: The community's own summary of two decades of effort: 1.6 TFlops, 10^19 CPU operations, no solution (groups.io message 3511) — https://groups.io/g/eternity2/message/3511 - Source: The standing 470 record on the official puzzle: Joshua Blackwood, "470 Found", eternity2@groups.io, 2021 (groups.io message 10117) — https://groups.io/g/eternity2/message/10117 - Source: Eternity II (Wikipedia): the puzzle, prize, and public record — https://en.wikipedia.org/wiki/Eternity_II_puzzle --- People who work on Eternity II eventually ask the same question: is there one place that lays out *all* the approaches? The usual answer is no, because the people attacking it are a mix of academics, competitive solvers, and hobbyists, and nobody wrote the map. This page is that map. It does not add a new method; it lines up the ones already documented on this wiki, one family at a time, so you can see the whole territory before you pick a direction. For each family: what it is in a line, what it actually reached on the real 16×16 board, where it stops, and a link to the deep page with the labs, the measurements, and the archive citations. ## The one insight that organises the whole map Every family below stalls in the same place: the community ceiling of 470 out of 480 matched edges, with [this project's own experiments](/research/lab/experiments/raphael-anjou) clustered at 460–463. They stall there for the same reason, and it is worth stating before the catalogue so the rest reads as variations on one theme. The reason is an evaluation problem. The only cheap signal any solver has is the number of matched edges, and that number does not tell you how close you are to a solution. A 470-edge board and a 460-edge board can be equally far from finishing, because the last ten edges are not a polishing job: they sit on the far side of a global wall that no local score can see. So the systematic searchers and the stochastic searchers, which look nothing alike, converge on the same height. This is the **[rigidity wall](/research/why/rigidity-wall)**: record boards are locally frozen, and the step from a great board to a perfect one is one indivisible swap with no gradient to follow. Its companion is **[why a faster computer doesn't help](/research/why/prune-vs-speed)**: when you cannot shrink the search, raw speed buys you almost nothing. The **[why it's hard](/research/why)** section proves both, and **[which wall stops which method](/research/why/walls-and-methods)** lines up each attack against the wall it dies on. Keep that in mind and the map below is easy to read: the families differ in *how* they climb, not in *how high*. ## Systematic search The backtracking family: place pieces one at a time in a fixed or computed order, prune illegal placements, and undo on failure. Everything that holds a record lives here. - **[Fill orders](/research/build/backtracking/fill-order)**. The order a backtracker visits the 256 cells is its one free choice, and it moves the size of the search tree by orders of magnitude at no runtime cost. Twenty years of community science, from the fixed-versus-dynamic debate to Verhaard's comb search. This is the lever, not a wall. - **[Arc consistency](/research/build/reduce/arc-consistency)**. Make every cell's candidate list defend itself against its neighbours to a fixed point, going beyond one-move-ahead forward checking. Mackworth's AC-3 and its refinements prune hard on small boards; on the full board the reachable pruning fades about two cells out and cannot collapse the branching factor. - **[All-different, Régin's matching filter](/research/build/reduce/alldiff-regin)**. No piece may be used twice: one global constraint over 256 cells, filtered completely in polynomial time by bipartite matching. The strongest propagator anyone has measured here, with a sharp caveat once the search tolerates mismatches. - **[No-good learning](/research/build/reduce/nogood-learning)**. A failed subtree is a theorem: record it and never re-enter. Transposition tables and mined constraints both pay on small boards; at 16×16 the number of distinct no-goods outruns any memory you can hold. - **[Restarts and heavy tails](/research/build/backtracking/restarts)**. The same backtracker on the same puzzle finishes in runtimes that differ by powers of ten, so cut off, reshuffle, and restart. Every record solver since 2007 is a restart portfolio. It changes which boards you reach, not the ceiling. - **[Meet in the middle](/research/build/exact/meet-in-the-middle)**. Enumerate two halves and join them on a shared interface, trading memory for half the exponent. Real on bands of the board; this project's BANDSAW experiment measured where it stops paying at full size. - **[Exact cover and dancing links](/research/build/exact/exact-cover-dlx)**. Eternity II states cleanly as exact cover, and Knuth's Algorithm X is the classic machine for it. It shines on small boards and exhaustive counting; on the 16×16 the tree is unshrunk and there is no partial credit for a near-miss. - **[Solver engineering](/research/build/faster/solver-engineering)**. Not an algorithm but the craft below one: lookup tables, perfect hashes, cache-sized structs, generated code. It decides whether a node costs 26 cycles or 2,600, and it is why the record engines run at all. It buys speed, and speed is the thing that does not move the wall. The **[solver catalogue](/research/build/solvers)** shows how the record engines (Verhaard's 467, Blackwood's 470) assemble these parts. ## Encodings to other solvers Rather than write a backtracker, translate the puzzle into the input language of an industrial solver and let a decade of engineering do the search. - **[SAT and CSP encodings](/research/build/exact/sat-csp-encodings)**. Write the puzzle as clauses and hand it to a complete solver. Tried since 2008. The solvers stall on the full board, but their verdicts still earn their keep as impossibility proofs on sub-boards. - **[LP and ILP relaxations](/research/build/exact/lp-relaxations)**. Write it as an integer program and drop the integrality: a linear solver reaches zero error in seconds by placing fractions of pieces. The comfort ends the moment pieces must be whole: a plateau at 420–440 edges, an ILP wall at 8×8, and an academic best of 461 in an hour. ## Local and stochastic search Start with a full (imperfect) board and improve it by moves, guided by an objective. These methods look nothing like backtracking, and they stop at the same height. - **[Local search and ALNS](/research/build/local-search/local-search-alns)**. Destroy part of a board, rebuild it better, and learn which demolitions pay. The most reliable polisher here, and the cleanest demonstration of where polishing ends. - **[Simulated annealing and parallel tempering](/research/build/local-search/parallel-tempering)**. Treat mismatches as energy and temperature as tolerance for getting worse. Annealing holds the longest-standing record in this family; tempering crosses barriers annealing cannot. Both stop at the same wall. - **[Beam search](/research/build/construct/beam-search)**. Keep the K most promising partial boards alive and grow them cell by cell. The workhorse behind this project's from-scratch builders, and a clean illustration of why breadth alone stalls in the deep interior. - **[Evolutionary and genetic approaches](/research/build/local-search/evolutionary)**. Breed a population, keep the fittest, recombine survivors. The most natural metaphor in the toolbox and the one whose central operator, crossover, fights the structure of the puzzle head-on. - **[Iterated maps and divide-and-concur](/research/build/exact/iterated-maps)**. Split the puzzle into two easy-to-project constraint sets and iterate a map whose fixed points are solutions. Elser's method made the cover of PNAS; on the Eternity II list it was tested once and never marched down. ## Learning from strong boards Every method above reasons only from the puzzle's rules. This family reasons from the boards people have already found: mine the corpus of strong boards for structure and feed it back into a search as a bias. It reaches the top of a search's range fast and reliably, and it does not raise the ceiling. - **[Learn from strong boards](/research/build/learning)**. The hub for the family: position and scarce-demand [priors](/research/build/learning/corpus-priors), [learned move-ordering](/research/build/learning/learned-value-ordering) by vote, [anti-pattern mining](/research/build/learning/anti-pattern-mining) that separates shared structure from the shared trap, and [decoding a record](/research/build/learning/decoding-records) to recover the move an ordinary search was missing. The [collapse capstone](/research/build/learning/when-learning-collapses) is where the family stops: over-trust a learned signal and the search falls apart, and even used perfectly none of these methods clears the rigidity wall, because the corpus they learn from is made of boards stuck at that same wall. ## Exotic and hardware roads Every few years someone proposes new hardware or new physics. These pages are the ledger of what each one actually delivered. - **[GPU solving](/research/build/hardware/gpu-solving)**. Looks like the perfect workload (millions of independent subtrees), and eighteen years of attempts measured a different reality: divergent branching and per-thread state that outgrows fast memory. The wall is memory, not arithmetic. - **[FPGA solving](/research/build/hardware/fpga-solving)**. Put the lookup tables one cycle away in on-chip RAM and pipeline dozens of tiny backtrackers. Michael Field designed it, projected 5 billion placements per second per chip, and ran a prototype. The road was mapped in detail and never driven to the end. - **[Distributed solving](/research/build/faster/distributed-solving)**. Throw more computers at it: BOINC screensavers, prize-sharing syndicates, console clusters, single-board farms. The community's total effort reached about 10^19 operations with no solution; the one job distribution is genuinely good at is exhaustive counting on small boards. - **[Quantum approaches](/research/build/hardware/quantum)**. The list's oldest deus ex machina, invoked in the puzzle's first month and every few years since. Two real stories (Grover's quadratic speedup and annealing on a QUBO), the arithmetic against Eternity II's actual numbers, and a record of zero runs. ## Analysis, not solvers These do not try to solve the puzzle. They measure it, which is how the community knows where the walls are. - **[Parity arguments](/research/build/analysis/parity-arguments)**. Count something on the board twice, once from each side, and the totals must agree, giving impossibility proofs for one pass. The 479 story shows both the power and the trap. - **[Solution counting](/research/build/analysis/solution-counting)**. Nobody has seen a full solution, yet the community knows to within a factor of two how many exist: exact censuses on small boards and an expectation formula that converged on about 14,702. ## Dead ends Some ideas sound as good as any above and provably do not move the score. The **[dead ends](/research/build/dead-ends)** page collects them with the reason each fails, so you can skip a month of work: symmetry breaking (there is no global symmetry to break), probability propagation that fades two cells out, and others. ## What the map is telling you Read it top to bottom and the shape is clear. The systematic families own the records because they can prove things and prune hard on small boards, but they cannot shrink the full search enough to reach the end. The stochastic families polish beautifully and reach genuinely different boards, then stall at the same height. The hardware roads change the speed and never the ceiling. And the analysis pages explain why: the last ten edges are not a matter of effort or cleverness in any one family, but a global wall that every family meets from its own direction. If you are choosing where to spend time, the useful question is not which family is best. It is which wall you think you can get past, because that is what actually decides the score. **[Which wall stops which method](/research/why/walls-and-methods)** is the place to start. ## Related - [The techniques](https://eternity2.dev/research/build/techniques) — The technique shelf: the algorithms and pruning ideas that recur in every serious Eternity II solver, each with what it is, what it costs, and what it actually bought when measured on this puzzle. - [How the record solvers search](https://eternity2.dev/research/build/solvers) — How the solvers that hold the records actually search. They are all, at heart, depth-first backtrackers; what separates them is the order they try things and how they bend the rules near the end. - [Why it's hard](https://eternity2.dev/research/why) — Eternity II is not accidentally difficult. It was designed to resist cleverness, and the measurable structural walls (rigidity, entropy, forbidden patterns) explain why no search, however clever, has reached the end. --- # Backtracking > Depth-first search done seriously. The order a solver visits the cells is its one free choice and moves the tree size by orders of magnitude; restarts turn a heavy-tailed runtime into a portfolio. This is the family behind every record backtracker. - Canonical page (with interactive figures/demos): https://eternity2.dev/research/build/backtracking/ - Updated: 2026-07-13 --- Depth-first search done seriously. The order a solver visits the cells is its one free choice and moves the tree size by orders of magnitude; restarts turn a heavy-tailed runtime into a portfolio. This is the family behind every record backtracker. The pages below go technique by technique: what each is in a line, what it actually reached on the real 16×16 board, where it stops, and the labs and measurements to back it. For the whole territory at once, start with [a map of every known approach](/research/build/approaches-map). ## Pages in this section - [Fill orders](https://eternity2.dev/research/build/backtracking/fill-order) — The order in which a backtracker visits the 256 cells is its one free choice: it costs nothing at runtime and moves the size of the search tree by orders of magnitude. Twenty years of community science, from the fixed-vs-dynamic wars and the strategy races to the magic 10×16 square and Verhaard's comb search, all answer the same question: which path through the board is cheapest? - [Restarts and heavy tails](https://eternity2.dev/research/build/backtracking/restarts) — Run the same backtracker on the same puzzle twice and the runtimes differ by powers of ten. The community measured this in 2007; the CSP literature had already named it. The cure (cut off, reshuffle, restart) is why every record solver since has been a restart portfolio. ## Related - [A map of every known approach](https://eternity2.dev/research/build/approaches-map) — The survey the community keeps asking for and never finds: every family of attack tried on Eternity II, what each one actually reached, where it walls out, and a link to the deep page. One organising insight runs through all of them. - [The techniques](https://eternity2.dev/research/build/techniques) — The technique shelf: the algorithms and pruning ideas that recur in every serious Eternity II solver, each with what it is, what it costs, and what it actually bought when measured on this puzzle. --- # Fill orders > The order in which a backtracker visits the 256 cells is its one free choice: it costs nothing at runtime and moves the size of the search tree by orders of magnitude. Twenty years of community science, from the fixed-vs-dynamic wars and the strategy races to the magic 10×16 square and Verhaard's comb search, all answer the same question: which path through the board is cheapest? - Canonical page (with interactive figures/demos): https://eternity2.dev/research/build/backtracking/fill-order/ - Updated: 2026-07-02 - Topics: backtracking, search-space - Source: Owen's "Best Search Order", scanline near-optimal, and the shape-counting argument (September 2007) — https://groups.io/g/eternity2/message/2714 - Source: The fixed-vs-dynamic debate, where fixed paths win empirically (msg 2392; Owen's verdict msg 2425) — https://groups.io/g/eternity2/message/2392 - Source: Speed, istarinz's one-word answer to why fixed paths win (September 2008) — https://groups.io/g/eternity2/message/5860 - Source: Verhaard's "magic 10×16 square" (msg 5868; the depth-160 explanation is msg 5879) — https://groups.io/g/eternity2/message/5868 - Source: Max measures scanline orientations, 2.3 vs 2.7 × 10⁴⁰ nodes (October 2008; thread starts msg 6015) — https://groups.io/g/eternity2/message/6023 - Source: Owen's design experiment showing scanline wins only because E2's 5/17 split is balanced (msg 5263; tables msg 5243) — https://groups.io/g/eternity2/message/5263 - Source: Verhaard reveals the comb search for high scores (October 2008) — https://groups.io/g/eternity2/message/6112 - Source: Max's near-identical high-score order of twelve rows, then columns (October 2008) — https://groups.io/g/eternity2/message/6126 - Source: The 89,794-node strategy race, automated order design vs hand tuning (msg 2896; the comeback msg 2928) — https://groups.io/g/eternity2/message/2896 - Source: Verhaard's Markov chain, optimizing the fill order and the slip array together (January 2009) — https://groups.io/g/eternity2/message/6423 - Source: Markus Zajc's 8×8 head-to-head, minimum-remaining-value beats scanline beats max-reduction (September 2008) — https://groups.io/g/eternity2/message/5918 --- A backtracker has almost no freedom. The pieces are given, the matching rule is given, the board is given. The one thing entirely up to you is the *fill order*: the sequence in which the 256 cells get filled. It looks like a detail (the search is exhaustive either way), and it is instead the highest-leverage decision in the whole solver. Brendan Owen said it plainly in 2007: "One of the biggest node count savings you can have is choosing a good search order" ([msg 2714](https://groups.io/g/eternity2/message/2714)). The same puzzle, walked in a different order, can cost ten orders of magnitude more nodes. And the choice is free, decided before the first piece is placed. That is why the mailing list argued about it for twenty years. The first great debate, in the summer of 2007, was *fixed versus dynamic*: veterans of Eternity I argued for dynamically picking the most-constrained cell at every step, the classic CSP heuristic ([msg 2392](https://groups.io/g/eternity2/message/2392)). The empiricists answered with node counts: the best results came from fixed, precomputed paths, and Owen's verdict was that "a scan-line search after the hint piece is placed seems the best" ([msg 2425](https://groups.io/g/eternity2/message/2425)). A year later, asked why nobody bothered with fully dynamic placement, istarinz compressed the engineering half of the answer into one word, speed: a fixed path keeps the inner loop branch-free and table-driven ([msg 5860](https://groups.io/g/eternity2/message/5860)). The theory half took longer, and is the subject of this page. ## The constraint-count view One idea underneath everything: a piece placement is only ever tested against the neighbours *already on the board*. A 16×16 grid has exactly 480 internal joins, and every complete fill order (row scan, spiral, anything) ends up checking all 480 of them. The order changes only the *schedule*: which joins are paid early, while the tree is still narrow, and which are deferred to where it is wide. A cell that arrives with two placed neighbours admits few candidate pieces; a cell that arrives with none admits nearly all of them and prunes nothing. Good orders are the ones that feed the search a steady diet of constrained cells, which is exactly what a row scan does: after the first row, almost every new cell touches a piece on its left and a piece below. Owen turned this into a method. For a fixed order, the nodes at depth $D$ are (in expectation) the number of ways to tile the *shape* the order has built at depth $D$. Any candidate order can therefore be scored, shape by shape, without running it. His conclusion from doing this exhaustively: the shapes that dominate the total are those of sizes 121–185, and the best shapes in that critical window "form a simple row scan order" ([msg 2714](https://groups.io/g/eternity2/message/2714)). The full machinery, join probabilities and all, became [complex theory](/research/why/complex-theory); this page is what its answers look like in practice. The lab below makes the schedule visible. It animates the visit sequence of four preset orders over a 16×16 grid and plots, live, the constraint count (how many already-placed neighbours each new cell has) together with the running total of joins collected. (It shows the *geometry*; to race real solves along paths you draw yourself, the hands-on companion is the [search-path playground](/playground/paths).) > **[Figure]** Interactive: fill order vs branching — interactive: FillOrderLab. Rendered on the canonical page (link above); not shown in this markdown export. ## What the community measured **The strategy races.** By late 2007 the question had become quantitative: shared benchmark puzzles, full-search node counts, and a public scoreboard. The style peak was doc_s_smith's fully automatic strategy-finding algorithm, which designed a search order that exhausted the size-14 `hints15_2` benchmark in 89,794 nodes, beating Txibilis's hand-tuned 141,628: machine over human ([msg 2896](https://groups.io/g/eternity2/message/2896)). Txibilis struck back within two days with 85,729 ([msg 2928](https://groups.io/g/eternity2/message/2928)); doc_s_smith had already been musing about why humans are so strong in this discipline ([msg 2883](https://groups.io/g/eternity2/message/2883)). The lesson that survived the race: order quality is measurable, and the differences are never small. **Dynamic versus fixed, measured.** The fixed-versus-dynamic argument from 2007 got a small controlled test in September 2008. Markus Zajc ran three orders on the hint-free 8×8, each over ten randomized tile orders to cancel input-order effects, all under a constraint resolver: plain scanline, a minimum-remaining-value order that always takes the cell with the fewest candidates, and a maximum-reduction order that takes the cell whose placement prunes the most. Minimum-remaining-value won; scanline came second but swung with the input order (its best run was still ~2× the winner); maximum-reduction came last, because seeding the open interior early buys a big first cut but then a punishing branch factor on every backtrack ([msg 5918](https://groups.io/g/eternity2/message/5918); the per-order domain dumps are in his files-area folder). It is a small board, but it is the cleanest head-to-head of the classic CSP heuristic against a fixed scan, and it lands where the community's later node counts do: the value is in feeding the search constrained cells, whether a dynamic rule or a good fixed path gets you there. **Scanline's win is a fact about E2's design.** In April 2008 Owen built 16×16 puzzles with the border/interior colour balance deliberately tipped (2 border and 19 interior colours, then 14 and 15) and scored scanline, middle-first and border-first orders on each. The tipped designs are attackable: middle-first beats scanline by ~150× on the 2/19 design, border-first wins on the 14/15. On E2's actual 5/17 split, every deviation *loses*: middle-first costs $1.22\times10^{60}$ nodes against scanline's $1.07\times10^{50}$, because the design balances border and interior tileability, giving the puzzle "no weak areas to start tiling from" ([msg 5263](https://groups.io/g/eternity2/message/5263), [5243](https://groups.io/g/eternity2/message/5243)). Row scan is not a law of nature; it is the correct answer to one specific, adversarial design. **The magic 10×16 square.** Why row scan and not, say, a 4×4 block order? Louis Verhaard's frontier-shape rule of thumb: most orders hit their node-count maximum around depth 160, so what matters is the shape your order has built *there*, and the best known depth-160 shape for E2 is a 10×16 rectangle (with two corners filled). Orders whose frontier passes through "the magic 10×16 square" are near-optimal; a 2×2 block scan does, a 4×4 does not, which is exactly the gap Max had just measured ([msg 5868](https://groups.io/g/eternity2/message/5868), [5879](https://groups.io/g/eternity2/message/5879)). This is the piece the constraint-count curve alone can't see: two orders can pay joins on the same schedule and still differ through the perimeter of the region they build. **Why "solve the border first" is a trap.** The most natural human instinct, build the easy frame and then fill the middle, is quantitatively one of the worst orders, and in 2025 Owen and Peter McGavin spelled out why on exactly this depth-160 peak. The border really is easy: after the start piece there are about $5.17\times10^{37}$ ways to complete it, of which only 14,702 can be filled by the 196 interior pieces, so about $3.5\times10^{33}$ frames must be tried before one even *can* finish ([msg 11572](https://groups.io/g/eternity2/message/11572)). That alone is hopeless, but it is not the real problem. The problem is that with the frame fixed first, the node count keeps *climbing* after the border to a peak of about $10^{57}$ around 160 pieces, versus about $10^{43}$ for scan-row. A border-first order commits early to the border and then walks straight into a peak fourteen orders of magnitude taller than scan-row's, because only about 1 in $10^{31}$ frames leads anywhere and each is expensive to rule out ([msg 11573](https://groups.io/g/eternity2/message/11573)). Row scan wins not by building a nicer frontier but by never paying for a border it cannot yet know is doomed. **Which scanline, though?** Even within row scans there are eight orientations: four corners to start from, rows or columns ([msg 6018](https://groups.io/g/eternity2/message/6018)). Max ran multi-day sampling estimates of the full-tree size per orientation: right-to-left held stable just below $2.7\times10^{40}$ nodes, while bottom-up, left-to-right (the orientation that connects the mandatory starter piece earliest, and the one Verhaard already used) came out around $2.3\times10^{40}$ ([msg 6015](https://groups.io/g/eternity2/message/6015), [6023](https://groups.io/g/eternity2/message/6023)). A folklore choice turned into a measured ~15%: small next to the orders of magnitude above, but free. **Deviations that paid.** The scan-order orthodoxy was tested constantly, and mostly won, but not always. Owen himself solved his 14×14 challenge with a *decreasing squares* order after scanline stalled; on irregular boards the balance argument no longer holds ([msg 3124](https://groups.io/g/eternity2/message/3124)). Hybrids were proposed that start as increasing squares (cheaper early) and switch to scanline before the mid-depth peak ([msg 6142](https://groups.io/g/eternity2/message/6142)). And Max found a genuine within-scanline improvement: at a row start, border candidates that differ only in their unmatched second border colour are equivalent: refute one and you have refuted them all. Verhaard, delighted ("Finally something that beats simple scan-row!"), implemented it and confirmed ~10% of the search space gone at near-zero cost ([msg 5980](https://groups.io/g/eternity2/message/5980), [5983](https://groups.io/g/eternity2/message/5983), [6062](https://groups.io/g/eternity2/message/6062)). ### Comb search: the high-score geometry All of the above optimizes a *full* search, whose node count peaks near depth 161. In October 2008, while privately sitting on the boards that would win the $10,000 scrutiny prize, Verhaard answered a different question from Owen: what is the best order when you are chasing a partial *score*, and therefore living much deeper in the board ([msg 6111](https://groups.io/g/eternity2/message/6111))? His answer named a geometry: the best orders he had found resemble a **comb search** (most rows searched horizontally, then the remaining rows searched vertically), with the tooth length tied to the target: "The lower the score you aim for, the longer the teeth of the comb become" ([msg 6112](https://groups.io/g/eternity2/message/6112)). Max had independently converged on nearly the same order (twelve rows of scanline, then column scan) and reported scores "roughly 1 edge lower" than what Louis's solver accomplished ([msg 6126](https://groups.io/g/eternity2/message/6126)). The intuition: a full search must cross the depth-160 bottleneck as cheaply as possible; a high-score search instead wants many cheap ways to *finish*. Each vertical tooth is a short, nearly independent column whose failures are local, so deep, high-scoring frontiers are reached again and again. The comb was one half of the machine behind the 467; the other half, [depth-gated edge slipping](/research/build/reduce/edge-slipping), decided what the teeth were allowed to place. And the two were tuned *together*: Verhaard optimized the fill order and the slip array jointly with a Markov chain over (depth, slips used), built from measured per-depth fit probabilities ([msg 6423](https://groups.io/g/eternity2/message/6423)). Order design by calculation, not folklore. The full engine is on [the Verhaard eii page](/research/lab/experiments/louis-verhaard/eii). ## Step by step 1. **Watch the row scan.** After the first row, nearly every placement meets exactly two placed neighbours: left and below. The constraint curve flatlines at 2, and the cumulative joins climb steadily: the search pays as it goes. 2. **Switch to the spiral.** The entire first ring (60 placements) arrives with at most one placed neighbour: sixty nearly unconstrained choices stacked up before the interior starts paying them back. The cumulative line sags below the row-scan reference exactly where the tree can least afford it. 3. **Try the diagonal.** Surprise: the counts look almost like the row scan's. This is the limit of the neighbour-count view: the diagonal's frontier is longer than a scanline's for much of the middle game, a shape effect only [complex theory](/research/why/complex-theory) (or the magic 10×16 rule) can score. 4. **Select the comb at teeth 4.** Twelve rows of scanline, then vertical teeth, Max's order from [msg 6126](https://groups.io/g/eternity2/message/6126). Note the little cliff at each new tooth: the first column pays a weak, 1-neighbour cell at its base, the price of the high-score geometry. 5. **Lengthen the teeth.** More of the board moves into vertical mode and the weak placements multiply. That is Verhaard's trade, stated visually: the lower the score you aim for (the more slips you'll allow), the longer the teeth you can afford. 6. **Then race it for real.** The [search-path playground](/playground/paths) lets you draw any of these paths, or your own, on a real puzzle and watch solvers race them, with a live plateau-peak estimate alongside. ## What it costs At runtime, nothing: a fixed fill order is a precomputed array of 256 cell indices, and "choose the next cell" is an index increment: $O(1)$, zero branches, which is precisely the speed argument that killed dynamic ordering for E2 ([msg 5860](https://groups.io/g/eternity2/message/5860)). All the cost and all the payoff live in the tree the order induces: - **Between order families, orders of magnitude.** Middle-first on E2 is $10^{10}$ times more expensive than scanline ([msg 5263](https://groups.io/g/eternity2/message/5263)); a 4×4 block order costs ~70× over 1×1 scanline by Max's complex-theory estimates, the gap the magic 10×16 rule summarizes ([msg 5867](https://groups.io/g/eternity2/message/5867)). - **Within a family, measurable percentages.** Bottom-up-left-right vs right-to-left scanline: ~15% ([msg 6023](https://groups.io/g/eternity2/message/6023)); border-piece equivalence pruning: ~10% ([msg 6062](https://groups.io/g/eternity2/message/6062)). Worth having, never decisive. - **Choosing wrong is invisible.** A bad order produces no error, just a tree that is $10^{10}$ times bigger, silently. That is why the community's real advance was not any single order but the ability to *score an order before running it*: Owen's shape counts, then [complex theory](/research/why/complex-theory), then Verhaard's Markov chain tuning order and slip schedule together ([msg 6423](https://groups.io/g/eternity2/message/6423)). Every record engine since has treated the order as a designed, calculated object: Verhaard's comb-plus-slip-array ([eii](/research/lab/experiments/louis-verhaard/eii)), McGavin's complex-theory-picked bottom-left scan, and the fixed scan order under [Blackwood's](/research/lab/experiments/joshua-blackwood/solver) depth-gated breaks. Twenty years of scan-order science compress into one instruction: before you spend a single CPU-hour, spend a millisecond scoring the path. ## Related - [Complex theory: counting the search before you run it](https://eternity2.dev/research/why/complex-theory) — Brendan Owen's complex theory estimates how wide the search tree is at every depth, and even how many solutions exist at all. Many in the community consider it the single most important thing to understand about Eternity II. - [Verhaard's eii: the solver that won the only prize](https://eternity2.dev/research/lab/experiments/louis-verhaard/eii) — The engine behind the 467, the only Eternity II score ever paid, read from Louis Verhaard's own mailing-list posts: forward pruning, comb-search fill orders, depth-gated edge slipping, a Markov-tuned slip schedule. And why his own source-less Win32 binary cannot be built or run on this machine at all. - [Blackwood's solver, decoded and run here](https://eternity2.dev/research/lab/experiments/joshua-blackwood/solver) — Joshua Blackwood's record backtracker, decoded through Jef Bucas's notes (a colour quota schedule and a late-game mismatch allowance, tuned near-optimally), then built and run on my M1: left as published it flies to 248 of 256 pieces ignoring the clues; pin the five official clues and the same engine stalls near 45. --- # Restarts and heavy tails > Run the same backtracker on the same puzzle twice and the runtimes differ by powers of ten. The community measured this in 2007; the CSP literature had already named it. The cure (cut off, reshuffle, restart) is why every record solver since has been a restart portfolio. - Canonical page (with interactive figures/demos): https://eternity2.dev/research/build/backtracking/restarts/ - Updated: 2026-07-02 - Topics: backtracking, search-space - Source: Txibilis's 500-puzzle experiment: restarts win 52% of races, all of the tail (groups.io message 2822) — https://groups.io/g/eternity2/message/2822 - Source: antminder's original claim, backtracking with multiple restarts (groups.io message 2420) — https://groups.io/g/eternity2/message/2420 - Source: Verhaard on what restart sampling revealed about the score landscape (groups.io message 5182) — https://groups.io/g/eternity2/message/5182 - Source: antminder on deadline-aware search, where probability in the window beats a better average (groups.io message 3089) — https://groups.io/g/eternity2/message/3089 - Source: Blackwood on the 50-billion cap, an "arbitrary" number (groups.io message 10066) — https://groups.io/g/eternity2/message/10066 - Source: McGavin's manually restarted 20-PC farm for the 9×9 census (groups.io message 9342) — https://groups.io/g/eternity2/message/9342 - Source: McGavin's 10×10 solve: 92,907 restarted row searches and the law of large numbers (groups.io message 9688) — https://groups.io/g/eternity2/message/9688 - Source: The PRNG hygiene thread on generator period vs restart campaigns (groups.io message 6798) — https://groups.io/g/eternity2/message/6798 - Source: Gomes, Selman & Kautz, Heavy-Tailed Phenomena in Satisfiability and Constraint Satisfaction Problems (J. Automated Reasoning, 2000) — https://doi.org/10.1023/A:1006314320276 - Source: Gomes, Selman & Kautz, Boosting Combinatorial Search Through Randomization (AAAI-98) — https://cdn.aaai.org/AAAI/1998/AAAI98-061.pdf - Source: Luby, Sinclair & Zuckerman, Optimal Speedup of Las Vegas Algorithms (Information Processing Letters, 1993) — https://doi.org/10.1016/0020-0190(93)90029-9 --- Run the same backtracker on two puzzles drawn from the same distribution and the solve times do not differ by percentages; they differ by powers of ten. The Eternity II community measured this in October 2007. Responding to antminder's claim that "backtracking with multiple restarts" beat plain backtracking ([groups.io message 2420](https://groups.io/g/eternity2/message/2420)), a sceptical Txibilis generated 500 random 7×7 puzzles and raced both policies on every one, the restarting solver cutting off at 10 million nodes per attempt. The restarter won only 52% of the races, a coin flip. Then he looked at the *margins*: among the 240 races the plain backtracker won, its biggest winning margin was 90 million nodes. Among the 260 the restarter won, the biggest margin was **50,463 million**, and in 45 of those races the restarter's margin alone exceeded the plain solver's best win ([message 2822](https://groups.io/g/eternity2/message/2822)). One column of the ledger is bounded; the other is not. That asymmetry has a name in the literature: a **heavy-tailed runtime distribution**. Gomes, Selman and Kautz had described exactly this phenomenon in satisfiability and CSP search a decade earlier ([AAAI-98](https://cdn.aaai.org/AAAI/1998/AAAI98-061.pdf)), and formalized it in [their 2000 paper](https://doi.org/10.1023/A:1006314320276): for backtracking on hard instances, the survival function decays like a power law, $P(T > t) \approx C\,t^{-\alpha}$, not an exponential. The decay is so slow that for $\alpha \le 1$ the *mean* runtime is infinite. Every Eternity II record since, from [Verhaard's 467](/research/lab/experiments/louis-verhaard/eii) and [McGavin's 10×10](/research/lab/experiments/peter-mcgavin/backtracker) to the [468–470 wave](/research/lab/experiments/joshua-blackwood/solver), was found by a solver built around this fact. ## Why tails happen A depth-first backtracker with a fixed [fill order](/research/build/backtracking/fill-order) makes its cheapest decisions first and then never revisits them: a row-scan solver that has reached depth 150 has, in practice, permanently committed its first three rows. If one of those early placements is wrong (legal, plausible, but on no completable board), the entire subtree below it is barren, and the solver must *exhaust* that subtree before the ordinary backtracking mechanism climbs back high enough to undo the mistake. Subtree sizes are exponential in the height of the wrong turn, so a bad commitment at depth 3 costs exponentially more than one at depth 30. The tail of the runtime distribution is precisely the distribution of early wrong commitments, inherited forever. The flip side is a fat *left* tail: some runs get every early decision right by luck and finish absurdly fast. Gomes, Selman and Kautz's point is that both tails come from the same variance-amplifying mechanism, and that the right response is not a better average run but *more draws from the distribution*. Louis Verhaard added an Eternity II-specific observation. He had originally used restarts as a survey instrument, hoping high-scoring regions clustered like mountain ranges: find the Himalaya by coarse sampling, then climb. What his sampling actually found is that high scores are spread "like high buildings in cities": one or a few anywhere, and finding one tells you nothing about where the next one stands ([message 5182](https://groups.io/g/eternity2/message/5182)). There is no regional signal worth staying for, which removes the last argument for loyalty to a struggling run. The original thread carried one caveat: Txibilis reasoned that restarts should pay only when the instance has *many* solutions (many chances for a lucky prefix) and less on a unique-solution benchmark. For Eternity II the distinction is moot in the searcher's favour: [complex theory](/research/why/complex-theory) puts the hint-free full puzzle at roughly $1.15 \times 10^7$ solutions, any one of which wins, and partial-score hunting has astronomically more targets still. ## The cure The remedy is almost embarrassingly simple, and antminder's 2007 recipe already contains all of it: run the backtracker for a fixed budget, and if no solution has appeared, **stop, reshuffle the piece ordering, and start over from the empty board** ([message 2420](https://groups.io/g/eternity2/message/2420)). Two ingredients matter: - **The cutoff** truncates the right tail by decree. No attempt can cost more than the budget $c$, so the unbounded column of Txibilis's ledger simply ceases to exist. - **Fresh randomization** (a shuffled candidate order, a different opening) makes each attempt an independent draw from the runtime distribution instead of a replay of the same doomed descent. Without it, restarting is just the same run with amnesia. When the distribution is known, there is an optimal *fixed* cutoff. When it is not, which is the usual case, [Luby, Sinclair and Zuckerman](https://doi.org/10.1016/0020-0190(93)90029-9) proved you barely need it: their universal schedule $1,1,2,1,1,2,4,1,1,2,\ldots$ (each power of two appearing in a self-similar pattern) is within a logarithmic factor of the optimal fixed cutoff on *every* distribution, and no universal schedule can do better in general. What production looks like, twenty years on: - **Blackwood's engine** caps every attempt at 50 billion nodes and reshuffles the opening, first corner and bottom-row pieces, before each new run, so no two attempts retrace the same prefix ([the solver page](/research/lab/experiments/joshua-blackwood/solver) covers the machinery). Asked how the 50-billion figure was chosen, Blackwood answered: "The 50B number was arbitrary. I tried a few big numbers (over 1B) and they didn't make too much of a difference" ([message 10066](https://groups.io/g/eternity2/message/10066)). That insensitivity is itself a heavy-tail signature: when the enemy is the tail, almost any cutoff that spares the body of the distribution works. - **McGavin's farms** are the same policy at the human timescale. His 9×9 solution census ran on "about 20 PCs" scavenged for up to 60 cores, each running a row-scan backtracker from a randomly shuffled piece array, and he "manually restarted ones that seemed stuck" ([message 9342](https://groups.io/g/eternity2/message/9342)). His 2017 solve of Brendan Owen's 10×10, the community's hardest solved benchmark, was a restart portfolio by construction: 92,907 independent first-row searches, farmed to 400+ cores, where theory predicted about one success per 70,000. His own summary: "no new methods, just systematic persistence and the law of large numbers" ([message 9688](https://groups.io/g/eternity2/message/9688)). There is also a strategic reading, stated on the list as early as 2007: under a contest deadline, a solver with a *worse average* but more probability mass inside the time window is the better solver ([message 3089](https://groups.io/g/eternity2/message/3089)). Restarts are exactly that trade: they reshape the distribution around its body, at the cost of ever finishing a marathon run. > **Feed the portfolio genuine randomness** > > A restart portfolio is only as diverse as its shuffles. In 2009 a member worried his solver's standard generator, with its period of $2^{32}$, could silently limit how much of the tree his restarts could ever sample ([message 6798](https://groups.io/g/eternity2/message/6798)); the list's answer was the Mersenne Twister, the standard remedy for non-cryptographic simulation ([message 6801](https://groups.io/g/eternity2/message/6801)). A weak PRNG doesn't crash a restart campaign; it quietly narrows the distribution being drawn from. ## Watch the tail collapse The lab below draws 400 solver runs from a seeded heavy-tailed mixture, calibrated to match the 2007 measurement: a body of lucky runs around a few million nodes, a tail stretching five orders of magnitude past it. Then it hands you the cutoff. > **[Figure]** Interactive: heavy-tailed runtimes and restarts — interactive: RestartTailLab. Rendered on the canonical page (link above); not shown in this markdown export. ## Step by step 1. **Watch the histogram fill.** The median (emerald marker) settles within the first few dozen runs and barely moves again. The mean (rose marker) never settles: each landing tail run yanks it right. A statistic dominated by its rarest samples is the visual definition of a heavy tail. 2. **Read the log axis.** The body sits near $10^6$ nodes; the worst runs reach past $10^{11}$, the same orders-of-magnitude spread as Txibilis's 90M-vs-50,463M ledger, on a distribution small enough to draw. 3. **Now cut.** The default cutoff is 10 million nodes, Txibilis's own. Every amber run that would have blown past it is abandoned at the dashed line and retried. The restart row's mean and P99 drop far below the single-run row: the tail is not survived, it is *deleted*. 4. **Cut too deep.** Drag the cutoff below the body's left edge. The success probability per attempt collapses, expected attempts explode, and the expected total climbs. At the extreme, no run can finish and the policy never succeeds. The cutoff must spare the lucky runs it is betting on. 5. **Notice how flat the sweet spot is.** Between "too greedy" and "too patient" lies a plateau several orders of magnitude wide where the expected total barely changes. Blackwood's "arbitrary" 50 billion, found empirically, is this plateau speaking. ## What it costs Fix a cutoff $c$ and let $F(c) = P(T \le c)$ be the chance a single attempt succeeds within budget. Failed attempts cost $c$ each and their count is geometric, so the expected total work to first success is $$ \mathbb{E}[T_c] \;=\; \frac{1 - F(c)}{F(c)}\,c \;+\; \mathbb{E}[T \mid T \le c]. $$ Minimizing over $c$ gives the best fixed-cutoff time $\ell^{\ast} = \min_c \mathbb{E}[T_c]$. Against a heavy tail $P(T > t) \approx C\,t^{-\alpha}$ this is not a refinement but a rescue: for $\alpha \le 1$ the unrestarted mean $\mathbb{E}[T]$ diverges while $\ell^{\ast}$ stays finite: the policy turns an infinite expectation into a finite one. And Luby's theorem prices the ignorance of not knowing $F$: the universal schedule achieves expected time $O(\ell^{\ast} \log \ell^{\ast})$ with no knowledge of the distribution at all, and that logarithmic factor is optimal. The price of restarting is the thing it throws away: a deep partial board, abandoned. On Eternity II that price is unusually low, for two reasons. First, the [complex-theory funnel](/research/why/complex-theory): runs stall against a depth wall at a characteristic depth, and progress beyond it is rare in a way that does not compound. McGavin's 92,907 10×10 row searches recorded a maximum placement depth of 88–99 (out of 100) for all but one of them, with well over half the mass on just three depths ([message 9688](https://groups.io/g/eternity2/message/9688)). A run sitting at the wall for hours holds no asset a fresh run cannot re-earn in minutes; its "progress" was a lottery ticket, already scratched. Second, the board state carries no learning: unlike a [clause-learning SAT solver](/research/build/reduce/nogood-learning), a plain backtracker that dies at depth 190 has recorded nothing about *why*, so persisting preserves no knowledge either. What is genuinely lost is the certificate. A restart portfolio samples the tree; it does not sweep it. McGavin says it plainly about his 9×9 census: "I did not systematically traverse the whole search tree, so might have missed some solutions" ([message 9342](https://groups.io/g/eternity2/message/9342)). For proving a region empty, restarts are the wrong tool. For finding one solution, or one record board, in a space where your runtime spans powers of ten, they are the only sane policy, and every engine on the [records timeline](/research/records) uses them. ## Related - [LADDER](https://eternity2.dev/research/lab/experiments/raphael-anjou/pipelines/ladder) — Throw hundreds of cheap short searches at the board, keep only the deepest starts, and promote the survivors through longer and longer rounds. - [Blackwood's solver, decoded and run here](https://eternity2.dev/research/lab/experiments/joshua-blackwood/solver) — Joshua Blackwood's record backtracker, decoded through Jef Bucas's notes (a colour quota schedule and a late-game mismatch allowance, tuned near-optimally), then built and run on my M1: left as published it flies to 248 of 256 pieces ignoring the clues; pin the five official clues and the same engine stalls near 45. - [Fill orders](https://eternity2.dev/research/build/backtracking/fill-order) — The order in which a backtracker visits the 256 cells is its one free choice: it costs nothing at runtime and moves the size of the search tree by orders of magnitude. Twenty years of community science, from the fixed-vs-dynamic wars and the strategy races to the magic 10×16 square and Verhaard's comb search, all answer the same question: which path through the board is cheapest? - [Complex theory: counting the search before you run it](https://eternity2.dev/research/why/complex-theory) — Brendan Owen's complex theory estimates how wide the search tree is at every depth, and even how many solutions exist at all. Many in the community consider it the single most important thing to understand about Eternity II. --- # The community's benchmarks > How a community forbidden from sharing the pieces built a shared test culture anyway: derived-count verification protocols, the Txibilis and beginner suites, node-count duels, full enumerations, and the one benchmark that is still standing open today. - Canonical page (with interactive figures/demos): https://eternity2.dev/research/build/benchmarks/ - Updated: 2026-07-02 - Topics: backtracking, speed - Source: The 3×3 corner census proposal: 'Suggestion for Benchmark/Test' (arthurhucksake), eternity2@groups.io, 2007-08 — https://groups.io/g/eternity2/message/2229 - Source: Txibilis launches the benchmark suite: 'New round of benchmarks...', eternity2@groups.io, 2007-08 — https://groups.io/g/eternity2/message/1610 - Source: Geoff's 'Benchmarks for Beginners' datasets, eternity2@groups.io, 2008-02 — https://groups.io/g/eternity2/message/4322 - Source: hints.20.3 fully enumerated: 'Algorithmic Challenges related to E2' (doc_s_smith), eternity2@groups.io, 2010-07 — https://groups.io/g/eternity2/message/7861 - Source: Both 9x9s exhaustively searched (istarinz), eternity2@groups.io, 2011-03 — https://groups.io/g/eternity2/message/8793 - Source: Brendan's set_1 10×10 solved (Peter McGavin), eternity2@groups.io, 2017-09 — https://groups.io/g/eternity2/message/9686 - Source: Dave Clark's Sample Puzzles suite and documented file format (groups.io Files) — https://groups.io/g/eternity2/files/Sample%20Puzzles - Source: The sized benchmark boards, sides 11-16 (groups.io Files) — https://groups.io/g/eternity2/files/Benchmarks --- Every solver community needs test problems, but Eternity II's had an extra constraint: in August 2007 Christopher Monckton claimed copyright on the piece designs and threatened action against "any circulation of them, in any form or medium", going so far as to disqualify Brendan Owen over a file that did not even contain the real pieces ([messages 1342](https://groups.io/g/eternity2/message/1342) and [1358](https://groups.io/g/eternity2/message/1358)). So the community built its test culture around two things that *could* be shared: derived counts computed from the pieces, and freshly generated E2-like puzzles. Both are still the right way to calibrate a solver today. ## The census protocol: verify without sharing If two people transcribed the same 256 pieces and wrote correct code, their solvers must agree on exhaustive counts. That observation, posted by arthurhucksake in August 2007, became the community's standard correctness test: tile the top-left 3×3 corner with all E2 pieces and count. The answer is **2,633,221** solutions, or **2,582,369** without the mandatory hint piece ([message 2229](https://groups.io/g/eternity2/message/2229), [2370](https://groups.io/g/eternity2/message/2370)). The 2x2 block census followed the same autumn, with two independent programs converging on **5,248** corner blocks, **292,012** edge blocks and **4,059,952** interior blocks ([message 3044](https://groups.io/g/eternity2/message/3044), [3046](https://groups.io/g/eternity2/message/3046)). The protocol earned its keep. When apal1969 posted per-centre-piece counts of all 3×3 interior partials in 2009, the pile-on of independent programs found bugs on *both* sides. One verifier discovered his own hint piece was rotated 90° off, and apal1969 himself found an error affecting every centre piece but one ([message 6625](https://groups.io/g/eternity2/message/6625), [6657](https://groups.io/g/eternity2/message/6657), [6666](https://groups.io/g/eternity2/message/6666)). Matching the consensus numbers got you welcomed, only half-jokingly, into the "Right Numbers Club" ([message 6869](https://groups.io/g/eternity2/message/6869)). Sharing counts instead of pieces was copyright-safe, and it caught more bugs than any code review. The interchange formats crystallized in the same period: the community standardized on the `e2pieces.txt` / `e2hints.txt` files from Dave Clark's eternity2.net project, written down explicitly so tools could interoperate ([messages 3571](https://groups.io/g/eternity2/message/3571) and [3572](https://groups.io/g/eternity2/message/3572)). The metric took longer. A "node vs step" debate over what exactly a solver should count ended with the admission that no common metric would be agreed ([message 3946](https://groups.io/g/eternity2/message/3946)). Txibilis's convention, under which a node is a *committed valid placement* and lookahead is not counted ([message 3843](https://groups.io/g/eternity2/message/3843)), is the one most period numbers use, and the reason old speed claims need care when compared. ## The Txibilis suite and the node-count race In August 2007, after a debate over what a fair E2 stand-in should look like (the flat 17+5 colour distribution, above all), Txibilis generated E2-like boards at sides 11 through 14 with hint variants (the `tiles_N_5.17` files), and Craig Easton set up a results database ([message 1610](https://groups.io/g/eternity2/message/1610), [1683](https://groups.io/g/eternity2/message/1683), [1784](https://groups.io/g/eternity2/message/1784)). The suite immediately became a competitive arena: doc_s_smith's first full scan of the size-12 hint puzzle cost 750,226,469 nodes ([message 1862](https://groups.io/g/eternity2/message/1862)); two months of head-to-head between his automatic strategy finder and Txibilis's hand-built fill orders drove the full search of the size-14 `hints15_2` benchmark down to 89,794 nodes, then 85,729 ([message 2896](https://groups.io/g/eternity2/message/2896), [2928](https://groups.io/g/eternity2/message/2928)): orders of magnitude below where the race began, with machine-designed and human-designed strategies trading the lead. The same weeks produced a preview of the other lever: newcomer Geoff's constraint-propagation solver traversed just 198 nodes to a first solution on a 14×14 hint benchmark ([message 2902](https://groups.io/g/eternity2/message/2902)). And at the heavyweight end, Txibilis exhausted the full 14×14 search space (about 2.2 × 10¹³ nodes) with the help of friends' computers ([message 2550](https://groups.io/g/eternity2/message/2550)). The lesson the race taught is the one this wiki keeps returning to: node count is a property of the *fill order*, and the gap between a naive order and a designed one is measured in orders of magnitude, not percent. That gap is exactly what [complex theory](/research/why/complex-theory) later made computable in advance. ## Benchmarks for Beginners In February 2008 Geoff packaged the on-ramp: three puzzles drawn from Brendan Owen's generated "Set 1" (a 6×6 with one hint, an 8×8 with two, a 10×10 with three), published inline with a self-documented format ([message 4322](https://groups.io/g/eternity2/message/4322)). Complete solution sets followed (the 6×6 has 65 distinct solutions, 260 counting rotations; [message 4604](https://groups.io/g/eternity2/message/4604)), and the suite accumulated canonical calibration numbers newcomers still get pointed to: 260 rotated solutions and a full row-scan search of exactly 69,284,103 nodes for the 6×6 ([message 7771](https://groups.io/g/eternity2/message/7771), [7777](https://groups.io/g/eternity2/message/7777)). If your solver gets a different count, your solver is wrong; that is the entire value proposition. ## The 40-hint 12×12 shoot-out In May 2008 Max uploaded a designed instance, Brendan's 12×12 with 40 hints (four 3×3 corners plus a central 2×2), to measure how much knowing the hint "environments" shrinks the search ([message 5453](https://groups.io/g/eternity2/message/5453)). What followed is the era's best single-instance comparison of every school at once: Geoff's arc-consistency + backtracking hybrid found the solution in ~7 s and 1.29 × 10⁸ nodes ([message 5455](https://groups.io/g/eternity2/message/5455)); Brendan's complex theory priced the plain scanline full search at 5.6 × 10⁸ nodes ([message 5458](https://groups.io/g/eternity2/message/5458)); istarinz's generated-C brute-forcer ran at ~68 million placements per second ([message 5459](https://groups.io/g/eternity2/message/5459)); and Txibilis's hand-tuned path cut the full search to 2.89 × 10⁸ nodes, over 20x below scanline, with a theory-derived path landing close behind ([message 5494](https://groups.io/g/eternity2/message/5494), [5522](https://groups.io/g/eternity2/message/5522)). Propagation, theory, raw speed and path design, all on one board: the shoot-out format every solver author secretly wants. ## hints.20.3: the full-enumeration challenge When doc_s_smith returned in 2010 he reframed the game: solving E2 itself is brute force and therefore boring; the interesting, *comparable* problem is exhaustively counting the solutions of hint-rich benchmarks ([message 7803](https://groups.io/g/eternity2/message/7803)). His flagship was the 16×16 `hints.20.3` puzzle, fully enumerated on a single 3.5 GHz core: **29,481,602,025,785 nodes** (about 2.9 × 10¹³), 15.6 CPU-days, exactly **one** solution ([message 7861](https://groups.io/g/eternity2/message/7861)). He posted it as a standing challenge: beat the node count, the time, or both. The challenge did what good benchmarks do: it forced collaboration. Over three weeks Martin (capiman), istarinz and doc converged their arc-consistency and domain-reduction implementations by exchanging full 16×16 domain dumps for this exact instance, catching each other's coordinate mirroring and propagation bugs; doc's estimated node count for the benchmark fell from 1.6 × 10¹³ to 2.6 × 10¹² ([message 7890](https://groups.io/g/eternity2/message/7890), [7902](https://groups.io/g/eternity2/message/7902)). ## The 9×9 pair: exhausted, then re-verified on a GPU In March 2011 istarinz reported exhausting the full search spaces of *both* of Brendan's 9×9 puzzles, three weeks each on a dual-core Opteron: 191,750,810,226,600 nodes for set 1, 145,088,777,827,367 for set 2, against a theory estimate of ~1.84 × 10¹⁴ ([message 8793](https://groups.io/g/eternity2/message/8793)). The census protocol then did its job on the answer itself: he initially claimed one solution each, Peter McGavin's independently shuffled backtrackers found a *second* set-1 solution ([message 8801](https://groups.io/g/eternity2/message/8801)), and the corrected tallies (**2 solutions for set 1, 3 for set 2**) were confirmed when McGavin found all three set-2 solutions ([message 8803](https://groups.io/g/eternity2/message/8803)). Complex theory had predicted 3.2 solutions for set 1: right order of magnitude on the largest instance ever fully searched. Seven years later the numbers were re-verified from scratch by a completely different implementation on absurdly different hardware: Adam Miles's DirectX 12 compute-shader solver ran the full 9×9 set-1 tree on an Xbox One X in 25 h 24 m and found exactly the 2 known solutions ([message 9822](https://groups.io/g/eternity2/message/9822)). That is what a mature benchmark culture looks like: a 2011 CPU census and a 2018 console GPU agreeing to the solution. ## Brendan's 10×10s: one fell, one is still standing Brendan Owen's hint-free 10×10 puzzles were the community's acknowledged frontier: "No one has even solved his 10×10 yet. The largest solved one is the 9x9" ([message 8936](https://groups.io/g/eternity2/message/8936)). In September 2017, Peter McGavin solved **set_1**: enumerate the ~20 million first rows, rank them by complex theory's chance-of-solution per search-tree node, and farm the backtracking out to 400+ cores of home ARM boards and borrowed servers. The solution arrived after ~2 × 10¹⁷ nodes (about **180 core-years**), on row-search ~92,907 of a predicted one-per-70,000, having covered under 0.5% of the whole tree ([message 9686](https://groups.io/g/eternity2/message/9686), method and statistics in [9688](https://groups.io/g/eternity2/message/9688)). Martin validated the board independently ([message 9725](https://groups.io/g/eternity2/message/9725)), and the community's verdict, "amazing that it is being truly just as hard as predicted" ([message 9693](https://groups.io/g/eternity2/message/9693)), doubled as the strongest empirical validation [complex theory](/research/why/complex-theory) has ever received. In McGavin's own words: no new methods, just systematic persistence and the law of large numbers. **Set_2 has never been solved.** As of this page's last update it remains exactly what set_1 was for a decade: a hint-free 10×10, statistics known, difficulty priced by theory, waiting for somebody's 180 core-years. If you want a benchmark with a name to make, this is the one. ## Throughput, in 2026 terms The period speed claims above (istarinz's ~68 million placements per second in 2008) are worth updating, because "placements per second" is still how the community sizes a solver, and the ceiling has moved. Asked directly in June 2026 what state-of-the-art engines do, Adam Miles gave the current rule of thumb: a well-tuned CPU backtracker reaches roughly **50 million valid placements per second per core**, and GPU solvers run **north of 10 billion placements per second** ([message 11826](https://groups.io/g/eternity2/message/11826)). Concrete numbers from the same thread bear that out: David Barr measured his own single CPU core at ~23 million placements per second and his GPU port at ~2.4 billion ([message 11835](https://groups.io/g/eternity2/message/11835)), and Peter McGavin's optimised backtracker hit ~295 million per second on a fast single core ([message 11750](https://groups.io/g/eternity2/message/11750)) - though that is an *easy-board* figure; on a hard board the same engine runs ~105M, where a [portable-Rust engine on this site](/research/lab/experiments/raphael-anjou/jit-backtracker) ties it. Two cautions carry over from the old node-vs-step debate: a "valid placement" counts only pieces that pass the colour-fit lookup, not every piece tried, and single-core speed on a full 16×16 is typically about half the small-puzzle figure, because the search spends its time in the dense forest of near-border constraints. (These placements/s figures are one axis of "fast" and unrelated to a board's matched-edge score; the [solver-engineering ledger](/research/build/faster/solver-engineering) pins down all three senses of the word.) None of this changes the [prune-versus-speed](/research/why/prune-vs-speed) verdict: a 400× throughput jump since 2008 has not moved the record, because it makes the tree cheaper to walk, not smaller. ## What to run today The historical suites live in the group's Files area (with some link rot); the protocol they embody is easier to follow now than it was then: 1. **Join the Right Numbers Club first.** Before trusting any timing, check your solver against exhaustive counts. This site maintains the modern equivalent of the census posts (exact block counts at every board position, under increasingly constrained rules) on the [reference numbers](/research/reference) page. The classics still work too: 2,633,221 for the 3×3 corner, 69,284,103 row-scan nodes for Brendan's 6×6. 2. **Climb the ladder.** Brendan's generated puzzles have agreed answers: 6×6 (65 solutions), 7×7 (set 1: 6,297 solutions in 67,667,477,364 nodes, the standard micro-benchmark since [message 9793](https://groups.io/g/eternity2/message/9793)), 8x8 (24 corner-fixed solutions, [message 8890](https://groups.io/g/eternity2/message/8890)), the 9x9 pair (2 and 3 solutions), then `hints.20.3` (exactly 1 solution in 2.9 × 10¹³ nodes). 3. **Report node counts with your times**, and say what you count: the 2007 node-vs-step ambiguity never fully died, and a timing without a node count is unfalsifiable. The habit of posting both is what made the 2017–2018 results comparable across a Phenom, a Xeon and an Xbox. 4. **Then aim at set_2.** The [known facts page](/research/build/known-facts) has the numbers for the real board; the open 10×10 is the community's agreed next rung below it. ## Where the files actually are Two of these suites survived the Yahoo-to-groups.io migration intact and are worth pointing your parser at directly. Dave Clark's [Sample Puzzles](https://groups.io/g/eternity2/files/Sample%20Puzzles) (2007) are the cleanest starting set: E2-like 16×16 boards at 16 and 40 border colours, each with its solution, in a self-documenting format. A puzzle file `sample_16_16_16_flat.txt` opens with a `width height borders` line, then one line of `Left Top Right Bottom` colours per cell (`0` is grey); the matching `solution_…` file lists `piece x y orientation` rows, orientation `0`–`3` for 0°/90°/180°/270° clockwise. The `flat` variants spread the colours evenly; the `rand` variants assign each edge independently, so a `flat`/`rand` pair is a ready-made test of how much your solver leans on a uniform colour distribution. The [Benchmarks folder](https://groups.io/g/eternity2/files/Benchmarks) collects the sized boards the node-count race above was fought on (sides 11 through 16, plus `8x8x8.txt`, a unique-solution 8×8 that a correct backtracker clears in about twenty minutes). Between these two folders you can walk the whole ladder, from a puzzle that solves over a coffee to the generated 16×16s, without ever touching the copyrighted prize pieces. ## Related - [Reference numbers](https://eternity2.dev/research/reference) — Exact counts of how many valid ways a small block can be filled at a given position of the official Eternity II board, under increasingly constrained rules: known-good numbers to check your solver's edge-matching and constraint code against. - [Known facts & numbers](https://eternity2.dev/research/build/known-facts) — The numbers every Eternity II researcher ends up re-deriving, collected in one place with their provenance: the puzzle definition, the clue placements, scoring conventions, the record table, search-space sizes and the structural counts. - [Complex theory: counting the search before you run it](https://eternity2.dev/research/why/complex-theory) — Brendan Owen's complex theory estimates how wide the search tree is at every depth, and even how many solutions exist at all. Many in the community consider it the single most important thing to understand about Eternity II. --- # The four clue puzzles > Tomy sold four small companion puzzles for Eternity II: solve one, submit the solution, and the official site revealed one piece's placement on the main board. What each puzzle was, the broken online checker, the eBay grey market, why puzzles 5 and 6 never came, and the clue puzzles' second life as complex-theory test cases and donor piece sets. - Canonical page (with interactive figures/demos): https://eternity2.dev/research/build/clue-puzzles/ - Updated: 2026-07-02 - Source: The official rules: four clue puzzles, two per year, one hint each, eternity2@groups.io, 2007-05 — https://groups.io/g/eternity2/message/182 - Source: The rules text on clue puzzles quoted verbatim (Jim Towler), eternity2@groups.io, 2008-01 — https://groups.io/g/eternity2/message/4187 - Source: Clue Puzzles 3 & 4 surface on the UK site (Mark Sheppard), eternity2@groups.io, 2008-01 — https://groups.io/g/eternity2/message/3858 - Source: The online checker accepts a wrong clue-4 answer, eternity2@groups.io, 2008-01 — https://groups.io/g/eternity2/message/4109 - Source: Clue-puzzle hints sold on eBay (Martin / capiman), eternity2@groups.io, 2008-01 — https://groups.io/g/eternity2/message/3971 - Source: TOMY: no plans for clue puzzles 5 & 6 (Steve Grant), eternity2@groups.io, 2009-01 — https://groups.io/g/eternity2/message/6381 - Source: Clue puzzles 3 & 4 sold out at the supplier, eternity2@groups.io, 2009-10 — https://groups.io/g/eternity2/message/7185 - Source: Exhaustive clue-puzzle counts vs complex-theory estimates (apal1969, Peter McGavin), eternity2@groups.io, 2010-11 — https://groups.io/g/eternity2/message/8142 - Source: Jef Bucas ships the viewer's Clues page, eternity2@groups.io, 2021-01 — https://groups.io/g/eternity2/message/10082 - Source: A "480" built from one E2 set + Clue-1 + Clue-2 pieces (Peter McGavin), eternity2@groups.io, 2023-10 — https://groups.io/g/eternity2/message/11169 - Source: Armel Le Bail's SHORTER solver, whose example files carry the Clue 1 & 2 pieces (cristal.org, 2007) — http://www.cristal.org/Eternity-II/ - Source: Janos Wortmann's Eternity2Puzzles.jl, whose piece files carry all four clue puzzles including Clues 3 & 4 (GitHub, 2024–25) — https://github.com/jwortmann/Eternity2Puzzles.jl - Source: eternity2.net's own clue-puzzle position files (Wayback Machine, 2007-10-17) — https://web.archive.org/web/20071017024639/http://eternity2.net:80/e2pieces_clue2.txt --- Alongside the 256-piece prize puzzle, Tomy sold four small companion puzzles, **Clue Puzzle 1** through **Clue Puzzle 4**. Each was an edge-matching puzzle in its own right, and each one, once solved and submitted on the official website, revealed the placement of one piece on the main board. This page is about those four *products*: what they contained, how the hint mechanism worked, how they were sold and then quietly discontinued, and what the community did with them afterwards. It is **not** the page about the five clue placements of the main puzzle. Those placements (the mandatory centre piece 139 at I8 plus the four optional ones the clue puzzles revealed) are tabulated with provenance in [Known facts & numbers](/research/build/known-facts). The two topics meet in the middle: the four optional rows of that table are exactly what the four clue puzzles were for. ## The mechanism: solve, submit, receive one placement The rules published in May 2007 announced four clue puzzles, each carrying one hint: two on sale with the main puzzle in 2007, two more to follow in 2008 ([msg 182](https://groups.io/g/eternity2/message/182)). The Australian rules text spelled the mechanism out: "For each Clue Puzzle you solve, submit your solution to obtain a hint that gives the correct position of one piece of the prize puzzle" ([msg 4187](https://groups.io/g/eternity2/message/4187)). In practice the reward was the piece number, its square on the 16×16 board **and its exact rotation** ([msg 7747](https://groups.io/g/eternity2/message/7747)). Three details of the design mattered: - **The clue puzzles have many solutions.** Unlike the main puzzle they contain duplicated pieces and near-duplicates; Clue Puzzle 1's 36 pieces carry only 110 distinct edge patterns out of a possible 288 ([msg 2875](https://groups.io/g/eternity2/message/2875)). Any valid arrangement was accepted. - **Everyone got the same hint.** Submitting different solutions to the same clue puzzle returned the same clue piece ([msg 2860](https://groups.io/g/eternity2/message/2860)); the hints were fixed properties of the main puzzle, not per-customer secrets. - **The hints were optional.** Under the contest rules only the starter piece was mandatory; prize entries were free to ignore the four clue-puzzle placements ([msg 11046](https://groups.io/g/eternity2/message/11046)), and the open record line (467→470) does ignore them; the strict five-clue line that honours all four is tracked separately (best known: 464, see [Records & solvers](/research/records)). ## The four puzzles | Puzzle | Size | Pieces | Colours (border / interior) | On sale | Solutions | | --- | --- | --- | --- | --- | --- | | Clue Puzzle 1 | 6×6 | 36 | 4 / 3 | July 2007 | ≈ 3.6 × 10¹⁰ (sampled) | | Clue Puzzle 2 | 12×6 | 72 | 4 / 4 | July 2007 | never fully counted (≥ 1.4 × 10⁶ found) | | Clue Puzzle 3 | 6×6 | 36 | n/a | January 2008 | 2,195,647,488 (exact) | | Clue Puzzle 4 | 12×6 | 72 | 5 / 4 | January 2008 | never fully counted | Sizes and launch dates: [msg 4187](https://groups.io/g/eternity2/message/4187), [msg 3858](https://groups.io/g/eternity2/message/3858); colour counts: [msg 8052](https://groups.io/g/eternity2/message/8052) (Clue 1), [msg 8137](https://groups.io/g/eternity2/message/8137) (Clues 2 and 4); solution counts: below. ### Clue Puzzle 1: the hand-solvable one A 6×6 square, launched with the main puzzle in July 2007. It is genuinely easy: solved by hand in about a hundred moves, and a plain backtracker needs on the order of 10²–10⁴ nodes ([msg 2873](https://groups.io/g/eternity2/message/2873); Anthony Cole's solver: 108 nodes, [msg 8775](https://groups.io/g/eternity2/message/8775)). The flip side of easy is degenerate: apal1969's partial exhaustive search extrapolated to roughly 3.6 × 10¹⁰ non-degenerate solutions ([msg 8052](https://groups.io/g/eternity2/message/8052)). Its CRC-16 checksums are the only clue-puzzle checksums ever published on the list ([msg 6769](https://groups.io/g/eternity2/message/6769); see below). > **[Interactive: CluePuzzlePieces]** Rendered on the canonical page (link above); not shown in this markdown export. ### Clue Puzzle 2: the hard one A 12×6 rectangle, also from July 2007, and by consensus the hardest of the four. "How to solve Clue2?" was a thread within months ([msg 3381](https://groups.io/g/eternity2/message/3381)). A computer does it in milliseconds ([msg 3386](https://groups.io/g/eternity2/message/3386)), but by hand it stumped people who had breezed through Clue 1 ([msg 3773](https://groups.io/g/eternity2/message/3773)), and apal1969 reported roughly a day of hand-solving as late as 2010 ([msg 8137](https://groups.io/g/eternity2/message/8137)). It is also the only clue puzzle whose solutions were never exhaustively counted: an 8-hour run had found ≈ 1.4 × 10⁶ non-degenerate solutions "and continuing" ([msg 8142](https://groups.io/g/eternity2/message/8142)), and Brendan Owen judged the space too large for a complete search ([msg 8143](https://groups.io/g/eternity2/message/8143)). For a solver it is still trivial: 1,637,300 nodes, about one second ([msg 8775](https://groups.io/g/eternity2/message/8775)). > **[Interactive: CluePuzzlePieces]** Rendered on the canonical page (link above); not shown in this markdown export. ### Clue Puzzle 3: the exactly-counted one A second 6×6, advertised on the UK site (with Clue 4) in January 2008 ([msg 3858](https://groups.io/g/eternity2/message/3858)); early buyers had solved it and claimed the hint by mid-January ([msg 3982](https://groups.io/g/eternity2/message/3982)). Its claim to fame came later: it is the only clue puzzle whose solution count is known **exactly**, at 2,195,647,488, from apal1969's ~1-day exhaustive run ([msg 8168](https://groups.io/g/eternity2/message/8168)). That count made it the sharpest of the clue-puzzle test cases for [complex theory](/research/why/complex-theory) (next section). A backtracker finds a first solution in 78 nodes ([msg 8775](https://groups.io/g/eternity2/message/8775)). > **[Interactive: CluePuzzlePieces]** Rendered on the canonical page (link above); not shown in this markdown export. ### Clue Puzzle 4: the last one A second 12×6, launched alongside Clue 3 in January 2008, with 5 border and 4 interior colours ([msg 8137](https://groups.io/g/eternity2/message/8137)). Easier than Clue 2 for a machine (first solution in 4,951 nodes, [msg 8775](https://groups.io/g/eternity2/message/8775)); like Clue 2, its solutions were never fully counted, so McGavin's complex-theory estimates for the 12×6 puzzles stood in for exact numbers ([msg 10236](https://groups.io/g/eternity2/message/10236)). Its lasting mark on the archive is the checker fiasco below. > **[Interactive: CluePuzzlePieces]** Rendered on the canonical page (link above); not shown in this markdown export. Cole's benchmark message also names a fifth, unofficial sibling: the 16-piece "web teaser" demo on the official site, solved in 34 nodes ([msg 8775](https://groups.io/g/eternity2/message/8775)). ## The checker fiasco and the grey market The clue puzzles' launch was not smooth. When the Clue 3/4 submission forms opened in January 2008, members probing them found the validation broken: petzi.petzi typed his **Clue 2** solution into the **Clue 4** form (with a typo piece "449" that does not exist in a 72-piece puzzle), and the site accepted it and handed over the clue-4 hint ([msg 4109](https://groups.io/g/eternity2/message/4109), [4119](https://groups.io/g/eternity2/message/4119), [4141](https://groups.io/g/eternity2/message/4141)). The same trick failed for another member ([msg 4117](https://groups.io/g/eternity2/message/4117)), so the checker was not just lenient but inconsistent. The community's best guess at a partial explanation: the clue puzzles' heavy piece redundancy means wildly many valid arrangements, so wrong-looking submissions can collide with real solutions ([msg 4118](https://groups.io/g/eternity2/message/4118)). But "449" rules out any reading in which the form was validating real pieces. Nobody ever reported Tomy fixing or acknowledging it. The hints themselves leaked immediately: - **eBay.** By January 2008, sellers offered the hint information from Clue Puzzles 1 & 2 as a product ([msg 3971](https://groups.io/g/eternity2/message/3971)); one had reportedly sold it over two dozen times ([msg 3976](https://groups.io/g/eternity2/message/3976)), with a brief debate about whether reselling information you bought is even wrong ([msg 3972](https://groups.io/g/eternity2/message/3972)). - **Derivation.** In July 2008 danmayoh derived the Clue 3 & 4 hints from a "possibility matrix" another member had posted. The matrix had been built using the hints, and the construction could be inverted despite deliberate typos. Moderator Brendan Owen deleted every message containing the matrix "to be safe" ([msg 5650](https://groups.io/g/eternity2/message/5650), [5651](https://groups.io/g/eternity2/message/5651)); danmayoh confirmed the trick could not conjure hints that were not already baked in ([msg 5732](https://groups.io/g/eternity2/message/5732)). ## A short shelf life: sold out, and no puzzles 5 and 6 Distribution was patchy from the start: Clues 1 & 2 were at first unobtainable in the US ([msg 2855](https://groups.io/g/eternity2/message/2855) thread), and Clues 3 & 4 appeared UK-first, drawing complaints from Sweden, Australia, Spain and the US ([msg 3858](https://groups.io/g/eternity2/message/3858), [4502](https://groups.io/g/eternity2/message/4502) and [7517](https://groups.io/g/eternity2/message/7517) threads). Then the supply dried up entirely: - **January 2009.** After the first scrutiny found no winner, Steve Grant emailed the Tomy Careline asking when clue puzzles 5 & 6 would come. The answer: Tomy has **no plans to release any further clue puzzles** ([msg 6381](https://groups.io/g/eternity2/message/6381)). Most of the group was relieved; more hints would have cheapened the challenge. - **October 2009.** A Swedish buyer was told Clues 3 & 4 sold out in spring 2009 and the supplier could not reorder ([msg 7185](https://groups.io/g/eternity2/message/7185)); by November no stock existed anywhere, as if production had stopped ([msg 7232](https://groups.io/g/eternity2/message/7232)). - **May 2010.** The puzzles had been off the UK market for around 18 months and were **never released at all in some regions**; second-hand was the only route ([msg 7752](https://groups.io/g/eternity2/message/7752)), and eBay listings already included the solved hint positions themselves ([msg 7350](https://groups.io/g/eternity2/message/7350)). So the clue puzzles were purchasable for roughly two years, in some countries never, and the information they sold became unbuyable while the $2M contest still had a year and a half to run. ## Did the hints even help? Mostly no, and the community knew it early. Brendan Owen never bought them ("just a marketing ploy"), calculating that the hints help but "there are not nearly enough hints" to make E2 tractable ([msg 2842](https://groups.io/g/eternity2/message/2842)); his hints-theory simulations put the requirement at roughly 20+ well-placed hints ([msg 1107](https://groups.io/g/eternity2/message/1107)), later refined to ~12–13 spread-out ones ([msg 5652](https://groups.io/g/eternity2/message/5652)). Spread-out beats bunched, a conclusion still being sharpened in 2026 ([msg 11736](https://groups.io/g/eternity2/message/11736)). The quantitative picture, in three numbers: - **One clue cuts the local search space by ~767×**: Verhaard counted 3,366 ways to fill the corner rectangle up to a clue piece versus 2,582,369 without it ([msg 3543](https://groups.io/g/eternity2/message/3543)). - **All four cut the expected solution count from ≈ 14,702 to ≈ 4 × 10⁻⁸** ([complex theory](/research/why/complex-theory); [msg 11193](https://groups.io/g/eternity2/message/11193)); the clues buy *uniqueness*, by design. - **But the expected nodes-per-solution barely moves**: McGavin measured essentially the same backtracker cost with and without the extra constraint ([msg 8924](https://groups.io/g/eternity2/message/8924)). Fewer needles, proportionally smaller haystack. Hence the standing verdict, delivered by Jef Bucas when he finally published the placements on his viewer: "so far, most progress has been done *without* the clues" ([msg 10082](https://groups.io/g/eternity2/message/10082)). The best board that respects all five placements scores 464 (Benjamin Riotte, 2026); the open record, which respects only the mandatory starter, is 470 ([Records & solvers](/research/records)). ## Verifying a clue set without the pieces Like the main set, the clue puzzles' piece designs fell under the inventor's copyright claim, so they were never published. The community's answer, as for the prize puzzle, was checksums instead of data ([msg 983](https://groups.io/g/eternity2/message/983), [msg 1063](https://groups.io/g/eternity2/message/1063): Owen's launch-week CRC-16 scheme). Requests to extend it to the clue puzzles started in 2007 ([msg 3417](https://groups.io/g/eternity2/message/3417)), but only in 2009 did Thomas (E2_Manual's author) publish CRC-16 checksums, for Clue Puzzle 1 alone, asking others to confirm them and cover Clues 2–4 ([msg 6768](https://groups.io/g/eternity2/message/6768), [6769](https://groups.io/g/eternity2/message/6769)). **No confirmation and no checksums for Clues 2, 3 or 4 ever appeared on the list**: anyone typing in a second-hand clue set today still has no public way to validate it. There was also a placement-level checksum: an e2hints.txt CRC to check your *hint* data without posting it ([msg 1147](https://groups.io/g/eternity2/message/1147)). ## Afterlife ### The hints become community lore Once the puzzles left retail, the placements they sold circulated on the list as unofficial data: a piece/position list in 2009 ([msg 6778](https://groups.io/g/eternity2/message/6778)), re-pointed to whenever someone asked ([msg 8808](https://groups.io/g/eternity2/message/8808), [8809](https://groups.io/g/eternity2/message/8809)), restated with rotations in 2012 ([msg 9067](https://groups.io/g/eternity2/message/9067)). The group owner refused to bless publication ("That would be a violation of Mr. Moncton's copyright!", [msg 9210](https://groups.io/g/eternity2/message/9210)), but the data outlived the objection: in January 2021 Jef Bucas added a Clues page to the community viewer ([msg 10082](https://groups.io/g/eternity2/message/10082)), piece 181 was confirmed first-hand by a member who had solved his clue puzzle and received that hint from Tomy ([msg 10085](https://groups.io/g/eternity2/message/10085)), and the rotations were cross-checked once more in 2021 ([msg 10542](https://groups.io/g/eternity2/message/10542)). The resulting placements are the four optional rows in [Known facts & numbers](/research/build/known-facts). ### Test cases for complex theory The clue puzzles' second career was as calibration targets for [Brendan Owen's complex theory](/research/why/complex-theory). In November 2010 apal1969 ran exhaustive counts (Clue 3: exactly 2,195,647,488 solutions) and compared them with Peter McGavin's estimates from the theory; the initial 10² discrepancy was traced to McGavin forgetting to halve the edge-type counts, and after the fix the estimates landed within roughly an order of magnitude, exactly the accuracy Owen claimed for small boards ([msgs 8142–8172](https://groups.io/g/eternity2/message/8142); Owen's accuracy note [8171](https://groups.io/g/eternity2/message/8171), the bugfix [8172](https://groups.io/g/eternity2/message/8172)). McGavin then filed backtracker estimates for all the clue puzzles in the group's database ([msg 8901](https://groups.io/g/eternity2/message/8901)). These were the first of the exhaustive-vs-estimated [benchmarks](/research/build/benchmarks) that eventually made the community trust the theory's E2-scale numbers. By 2011 the puzzles themselves were solver warm-ups: all four fall in under a second ([msg 8773](https://groups.io/g/eternity2/message/8773), [8775](https://groups.io/g/eternity2/message/8775)). ### Donor piece sets for the mixed "480"s Finally, the physical pieces found a use the designers never intended. In 2014 Peter McGavin showed complete 16×16 "solutions" assembled from an E2 set plus clue-puzzle pieces ([msg 9309](https://groups.io/g/eternity2/message/9309), [9310](https://groups.io/g/eternity2/message/9310)), and in 2023 he built a full 480/480 board from the pieces of **one E2 set, one Clue-1 set and one Clue-2 set** ([msg 11169](https://groups.io/g/eternity2/message/11169)), in Vlastislav W.'s max-distinct-tiles challenge ([msg 11167](https://groups.io/g/eternity2/message/11167)). To be perfectly plain: **these boards are not Eternity II solutions**. They use pieces that are not in the official 256-piece set, and they are why headline "480" claims must always be checked against the piece list ([Records & solvers](/research/records)). ## Recovered and solved: all four The one thing everyone assumed was gone turns out to be recoverable, and not just for the first two. The community withheld the clue puzzles' piece designs on copyright grounds, and no one posted the layouts to the list. But two independent solver projects bundled them as worked examples anyway. Armel Le Bail's **SHORTER** solver, a Fortran program published at cristal.org in August 2007, ships three: a 36-piece 6×6, a 72-piece 12×6, and the full 256-piece board. The 256-piece file is the real official Eternity II set, which is how the provenance checks out: Le Bail was reading genuine Tomy data in the eternity2.net format. The other two are **Clue Puzzle 1 and Clue Puzzle 2**, motifs and all. **Clues 3 and 4** turned up in a second, much more recent source: Janos Wortmann's [`Eternity2Puzzles.jl`](https://github.com/jwortmann/Eternity2Puzzles.jl), a Julia package that carries all four clue puzzles as plain piece files (`clue1.txt` … `clue4.txt`). Its `clue1`/`clue2` are the same two puzzles Le Bail bundled: we canonicalised each into a rotation-invariant, colour-relabelled multiset of pieces and they match Le Bail's Clue 1 and Clue 2 exactly, piece for piece. A source that reproduces the two puzzles we can already cross-check is a trustworthy source for the two we cannot, so its Clue 3 and Clue 4 stand on the same footing. The files eternity2.net published itself, recovered from the Wayback Machine, corroborate the sizes and board positions of Clues 1 and 2 but not the motifs. They lay each out as a block on a 16×16 grid, the 6×6 at rows 5–10 and columns 5–10, the 6×12 at rows 5–10 and columns 2–13, and collapse every interior edge to one placeholder colour. (The site never hosted files for Clues 3 or 4, which launched after its last capture.) So the official files fix *where* Clues 1 and 2 sat; the solver files are the public record of *what* the pieces are, for all four. Each one was solved from scratch to confirm they are real, coherent puzzles. The solve encodes "place every piece so all edges match and grey sits on the rim" as a SAT instance and hands it to a solver; a separate pass then checks the answer independently (each piece used once, every internal edge matched, grey only on the outer ring). All four close perfectly: Clues 1 and 3 on all 60 of their internal edges, Clues 2 and 4 on all 126. Each solved board is shown in its own section above ([Clue 1](#clue-puzzle-1-the-hand-solvable-one), [Clue 2](#clue-puzzle-2-the-hard-one), [Clue 3](#clue-puzzle-3-the-exactly-counted-one), [Clue 4](#clue-puzzle-4-the-last-one)), drawn with the real Eternity II motifs. Each puzzle offers two downloads: the pieces as solver-ready data (the same instance JSON published in the [dataset](/research/build/dataset), edges in up-right-down-left order, colour 0 the rim) and as a set of per-piece SVGs the same way the main puzzle's pieces are offered on the [puzzle page](/puzzle). A caveat on the motifs. The *pieces* are certainly right: they are the recovered edge data, they cross-check between the two sources for Clues 1 and 2, and each solves into a complete edge-matched board, which a wrong piece set would not. The *motifs* shown are the real Eternity II glyphs, assigned to each clue's colour numbers in order; they are almost certainly not Tomy's exact printed motifs for the clue puzzles, which no public source records. So read the boards and downloads as the correct pieces drawn in Eternity II's own art, not a facsimile of the physical tiles. The full recovery, the piece data for all four, and the reproducible solve are in the [clue-puzzle-pieces topic](https://github.com/raphael-anjou/eternity2/tree/main/research/topics/clue-puzzle-pieces). This says nothing about the copyright the layouts were withheld over; it simply records that they were already public in two solvers' example files, and shows them solved. ## What is not publicly documented Gaps a careful reader should know about: - **The clue puzzles' piece definitions were never posted to the list** (copyright), and the only community checksums cover Clue Puzzle 1 and remain unconfirmed ([msg 6769](https://groups.io/g/eternity2/message/6769)). They survive anyway in two solver projects' example files, Clues 1 and 2 in Le Bail's SHORTER and all four in Wortmann's `Eternity2Puzzles.jl`, cross-checked and solved above. - **Which puzzle revealed which placement.** The archive never cleanly maps Clue Puzzle *n* to a specific square among C3, C14, N3, N14. Only piece 181 has a first-hand puzzle-to-hint attestation ([msg 10085](https://groups.io/g/eternity2/message/10085)), and even that message does not say which numbered puzzle produced it. - **Exact solution counts for Clues 2 and 4.** Only estimates and partial counts exist ([msg 8142](https://groups.io/g/eternity2/message/8142), [10236](https://groups.io/g/eternity2/message/10236)). - **Production and sales figures.** How many clue puzzles were made or sold, and why production stopped in early 2009, was never stated by Tomy; the sold-out story is reconstructed from retailer answers ([msg 7185](https://groups.io/g/eternity2/message/7185)). - **The official hint records.** Whether Tomy's submission database and the canonical hint answers survive anywhere is unknown; the placements rest on community cross-checks, not an official publication. ## Related - [Known facts & numbers](https://eternity2.dev/research/build/known-facts) — The numbers every Eternity II researcher ends up re-deriving, collected in one place with their provenance: the puzzle definition, the clue placements, scoring conventions, the record table, search-space sizes and the structural counts. - [Records & solvers](https://eternity2.dev/research/records) — Eternity II has never been solved, but fifteen years of community effort have pushed the best board to 470/480. Who holds what, how they did it, and why some headline "480" boards are not actually the real puzzle. - [Complex theory: counting the search before you run it](https://eternity2.dev/research/why/complex-theory) — Brendan Owen's complex theory estimates how wide the search tree is at every depth, and even how many solutions exist at all. Many in the community consider it the single most important thing to understand about Eternity II. --- # Build boards up > Building a high-scoring board from an empty grid instead of digging with backtracking: beam search keeps the best partial boards alive and grows them cell by cell. The workhorse behind this project's from-scratch builders, and a clean illustration of why breadth alone stalls in the deep interior. - Canonical page (with interactive figures/demos): https://eternity2.dev/research/build/construct/ - Updated: 2026-07-13 --- Building a high-scoring board from an empty grid instead of digging with backtracking: beam search keeps the best partial boards alive and grows them cell by cell. The workhorse behind this project's from-scratch builders, and a clean illustration of why breadth alone stalls in the deep interior. The pages below go technique by technique: what each is in a line, what it actually reached on the real 16×16 board, where it stops, and the labs and measurements to back it. For the whole territory at once, start with [a map of every known approach](/research/build/approaches-map). ## Pages in this section - [Beam search](https://eternity2.dev/research/build/construct/beam-search) — Keep the K most promising partial boards alive at once and grow them cell by cell. Beam search is the workhorse behind this project's from-scratch builders, and a clean illustration of why breadth alone stalls in the deep interior. ## Related - [A map of every known approach](https://eternity2.dev/research/build/approaches-map) — The survey the community keeps asking for and never finds: every family of attack tried on Eternity II, what each one actually reached, where it walls out, and a link to the deep page. One organising insight runs through all of them. - [The techniques](https://eternity2.dev/research/build/techniques) — The technique shelf: the algorithms and pruning ideas that recur in every serious Eternity II solver, each with what it is, what it costs, and what it actually bought when measured on this puzzle. --- # Beam search > Keep the K most promising partial boards alive at once and grow them cell by cell. Beam search is the workhorse behind this project's from-scratch builders, and a clean illustration of why breadth alone stalls in the deep interior. - Canonical page (with interactive figures/demos): https://eternity2.dev/research/build/construct/beam-search/ - Updated: 2026-07-02 - Topics: construction - Source: Zhou & Hansen, Beam-Stack Search: Integrating Backtracking with Beam Search (ICAPS 2005) — https://cdn.aaai.org/ICAPS/2005/ICAPS05-010.pdf --- A depth-first backtracker commits to one partial board and digs. Beam search hedges: it keeps the $K$ best partial boards alive at once, extends every one of them by a single cell, scores all the children, and keeps the top $K$ again. The idea goes back to Bruce Lowerre's HARPY speech-recognition system in the 1970s; Zhou and Hansen's [beam-stack search paper](https://cdn.aaai.org/ICAPS/2005/ICAPS05-010.pdf) is a good modern treatment of the family and its trade-offs. ## How it runs on a board Fix a scan order over the 256 cells. A beam state is a partial placement, the set of pieces already spent, and a matched-edge score. Extending a state at depth $d$ means trying every legal (piece, rotation) for cell $d$ (legal with respect to the placed neighbours and the remaining inventory) and adding the number of newly matched edges to the score. Pool all children from all $K$ survivors, sort, truncate to $K$, repeat 256 times, and every survivor is a complete board. The inventory is what makes this different from beam search on a generic constraint problem: each piece exists exactly once, so a placement is not just a local choice but a withdrawal from a global budget. That detail decides everything below. ## Watch a beam descend The lab below runs a beam down a synthetic tree: branching factor $b = 4$, depth $d = 14$, deterministic hash-based scores, no board, because the pathologies are easier to *see* when the instance is small enough to draw. Two features are planted deliberately: node scores are partly heritable (a good prefix tends to have good children, which is what makes a beam collapse onto one prefix), and a few **trap** nodes pay a large immediate score while quietly poisoning every descendant: a two-line synthetic model of [piece theft](/research/why/piece-theft), where a placement that scores now spends a piece the deep interior will need later. > **[Figure]** Interactive: beam width vs survival — interactive: BeamWidthLab. Rendered on the canonical page (link above); not shown in this markdown export. ## Step by step 1. **Depth 0.** The beam is just the root. On every tick, each survivor spawns its $b = 4$ children, at most $K \cdot 4$ candidates in the pool. 2. **Score, sort, truncate.** The pooled children are ranked and only the top $K$ survive. Everything below the cut is deleted *forever*: a beam never backtracks, so a good prefix pruned at depth 5 is unreachable at depth 10. This is where completeness is given away. 3. **Watch the huddle.** A dot's horizontal position encodes its path prefix, so distinct branches live in distinct clusters. Within a few levels most survivors share one high-scoring prefix: the *distinct prefixes* counter falling toward 1 is diversity collapse, the beam degenerating into greedy-with-bookkeeping. 4. **Follow the rose trace.** That is $K = 1$, plain greedy. When it swallows an amber trap (big gain now, poisoned subtree after), its score curve flattens for good. A wider beam survives the same trap only while its survivors are still spread across branches; once collapsed, it is exactly as gullible. 5. **Slide $K$ from 1 to 64.** The final score climbs and then flattens; each doubling of width buys less, the same roughly-logarithmic returns this project measured on real boards. Note what the slider never changes: the collapse still happens, just a few levels later. ## What it costs Beam search is exponential search with the exponential deleted by fiat: $$ \text{time} \;=\; O(K \cdot b \cdot d), \qquad \text{memory} \;=\; O(K \cdot d), $$ for width $K$, branching factor $b$ and depth $d$ (plus an $O(Kb \log Kb)$ sort per level). Both are linear in $K$, which is the whole appeal. The price is *incompleteness*: a beam offers no optimality guarantee, no certificate on failure, and no way back to a pruned prefix. Its one systematic failure mode is the collapse the lab shows: when the survivors become $K$ copies of one prefix, the effective width is 1 regardless of what you paid for. At Eternity II scale the arithmetic is friendly, which is exactly why beams are the from-scratch workhorse here: $d = 256$ cells, $b$ = the legal (piece, rotation) candidates per cell, a few hundred early, dwindling as the inventory drains, so even $K = 10^4$ costs on the order of $10^8$–$10^9$ child evaluations per complete board: minutes on a laptop, incomparably cheaper than any exhaustive figure on the [dead ends page](/research/build/dead-ends). What $O(K \cdot b \cdot d)$ really says is not "cheap" but "only as good as its scoring function": the beam evaluates a vanishing fraction of the tree, and no known score predicts which depth-100 prefixes still complete well. Width is bought in linear coin; foresight is not for sale. ## Width buys less than you'd hope At $K = 1$ the beam is plain greedy construction, and greedy with random restarts has a brutally heavy tail: on this project's engine, tens of thousands of random greedy runs topped out around 408 of 480, and extrapolating the tail put a 440 at billions of restarts. Widening the beam is far better, but the returns are roughly logarithmic. A beam of a few hundred states builds boards around 450; pushing $K$ past ten thousand reached the mid-450s and then flattened. (Measured on this project's engine; not independently replicated.) There is a structural reason a plain beam cannot be much more than "greedy, wider". A beam state at depth $d$ faces exactly the same edge-matching and inventory constraints as a DFS node at depth $d$; keeping many states alive relaxes nothing. Without a scoring function that reliably predicts which depth-100 prefixes still complete well (and no such heuristic is known for Eternity II), the beam's extra breadth mostly duplicates what randomized restarts of a backtracker already provide. ## Diversity is the real dial Left to itself a beam collapses: within a few dozen cells most survivors share one high-scoring prefix, and the beam degenerates toward greedy with extra bookkeeping. Standard fixes are prefix deduplication and sampling from the top $2K$ instead of taking the top $K$, and this project's builders use both. But the strongest diversity lever found here was not inside the beam at all: it was the scan order. Running the same beam under nine different visit orders ([GAUNTLET](/research/lab/experiments/raphael-anjou/pipelines/gauntlet)) produced eighteen distinct board families where sixteen seeds of a single order had produced one. The other productive dial is the tiebreak. [PRIOR](/research/lab/experiments/raphael-anjou/learning/prior) breaks score ties toward pieces that are frequent at that position in a corpus of strong boards, lifting the from-scratch ceiling by a few edges and reaching 460 after refinement. [LODESTONE](/research/lab/experiments/raphael-anjou/learning/lodestone) breaks ties toward pieces that serve scarce demands, buying a small median gain and much better consistency, then collapsing badly the moment the prior is promoted from tiebreaker to objective. ## The depth wall Every beam variant tried here stalls the same way. The border and early interior fill almost perfectly; the mismatches concentrate in the last rows, where the pieces a cell needs were already spent serving easier cells long ago: the [piece theft](/research/why/piece-theft) problem. A greedy local objective cannot see that global budget, and doubling $K$ pushes the wall back by only an edge or two. From-scratch beams on this engine ceiling in the mid-450s; the remaining distance is bought by [destroy-and-repair polish](/research/build/local-search/local-search-alns), not by more width. Beam search, on this puzzle, is a fine way to reach the plateau quickly, and no way at all to leave it. ## Related - [GAUNTLET](https://eternity2.dev/research/lab/experiments/raphael-anjou/pipelines/gauntlet) — Run the same beam search across nine different scan orders, so it lands in different regions instead of always converging to the same one. The zigzag order found a brand-new 458 board. - [KEYRING](https://eternity2.dev/research/lab/experiments/raphael-anjou/learning/keyring) — Build a board from scratch, ranking each next piece by three signals learned from past strong boards. Reached 460 in a board family no earlier search had cracked. - [PRIOR](https://eternity2.dev/research/lab/experiments/raphael-anjou/learning/prior) — Build a board from nothing, breaking ties by where pieces tend to sit in the strong boards we already have. It reaches a high score with no starting board to copy. - [STAGED](https://eternity2.dev/research/lab/experiments/raphael-anjou/pipelines/staged) — Build the whole board from scratch with no pre-set frame, in stages, letting the border emerge last from whatever pieces are left. - [LODESTONE](https://eternity2.dev/research/lab/experiments/raphael-anjou/learning/lodestone) — A faint compass for a from-scratch search: nudge it to commit the rare pieces early, where they're needed. It doesn't raise the ceiling; it makes the search reliably reach the top of its own range. - [Piece theft, where solvers die](https://eternity2.dev/research/why/piece-theft) — A solver fills a few rows for free, then hits a wall in the middle of the board. Here's the mechanism: a scarce piece spent in the wrong place, rows ago. - [Local search and ALNS](https://eternity2.dev/research/build/local-search/local-search-alns) — Destroy part of a board, rebuild it better, and let the algorithm learn which demolitions pay. Adaptive large-neighborhood search is the most reliable polisher this project has, and the cleanest demonstration of the wall where polishing ends. --- # The dataset > A public, CC0 dataset for Eternity II in two parts: fourteen benchmark instances to solve, and a corpus of 7,658 distinct strong boards to learn from. Every score is recomputed from the board itself, and the corpus is checked to be genuinely diverse rather than a thousand copies of one board. - Canonical page (with interactive figures/demos): https://eternity2.dev/research/build/dataset/ - Updated: 2026-07-16 - Topics: structure, learning - Source: The dataset (this repo): instances, the strong-board corpus zip, README, and the build script — https://github.com/raphael-anjou/eternity2/tree/main/research/datasets --- Two things recur when you work on Eternity II: you need instances to run a solver against, and, if you want to learn from strong boards, you need a corpus of them. This dataset packages both, released into the public domain under [CC0](https://creativecommons.org/publicdomain/zero/1.0/) so it can be reused for anything without attribution. It has two parts, and both live in the [dataset directory](https://github.com/raphael-anjou/eternity2/tree/main/research/datasets). ## Part A: benchmark instances Fourteen instances a solver runs on, each a self-contained JSON file with the piece set, any pinned hints, and the maximum reachable score. - **Ten 16×16 instances** (`e2-16x16-v00` … `v09`): the official Eternity II piece set with three corners pinned, in ten different corner arrangements. Pinning the corners gives ten distinct but equally hard instances off one piece set, which is what lets a study compare engines on a diversity axis rather than a single board. All three of this project's engine studies (the [DFS study](/research/lab/experiments/raphael-anjou/dfs-study), the [repair study](/research/lab/experiments/raphael-anjou/repair-study), and the [single-core benchmark](/research/lab/experiments/single-core-benchmark)) solve exactly these ten. Maximum score 480. - **Four clue sub-puzzles** (`e2-clue-clue1` … `clue4`): the smaller 6×6 and 12×6 boards from the puzzle's official clue set. Each is known to have a full solution, which makes them a fast correctness fixture: a solver that cannot close a clue board has a bug before it ever meets the full puzzle. Each cell is described in up, right, down, left order, colour 0 is the grey rim, and `pos` is the row-major cell index. The shape of an instance file: ```json { "id": "e2-16x16-v00", "family": "official-16x16-pin3corners", "width": 16, "height": 16, "numColors": 22, "pieces": [[up, right, down, left], ...], "hints": [{"pos": 0, "piece": 0, "rot": 3}, ...], "maxScore": 480 } ``` ## Part B: a corpus of strong boards **7,658 distinct boards** scoring 400 to 470, the raw material for methods that [learn from strong boards](/research/lab/experiments/raphael-anjou/learning): position priors, learned move-ordering, anti-pattern mining. It ships as a zip (`e2-strong-boards.zip`, about 16 MB) that unpacks to the same rows as CSV and as JSON-lines: ``` id,score,family,edges e2b-00001,469,f008,adcaaendadwe… (1024 lowercase letters) ``` The `edges` field is the board itself: 256 cells times four sides, row-major, in up-right-down-left order, `a` for the grey rim. It is the same string the [e2.bucas.name](https://e2.bucas.name) viewer reads, so any board pastes straight into the viewer. The `family` is the board's four corner pieces, a proxy for which basin it sits in; there are 28 distinct families. The score distribution spikes sharply in the low-450s, where a large single-core beam harvest concentrates, then thins to a long tail, with 38 boards at 460 or above and the best at 470. > **[Interactive: CorpusScoreDistribution]** Rendered on the canonical page (link above); not shown in this markdown export. ## Every score is recomputed, not trusted No score in this dataset is copied from a source field. Each one is recomputed from the board's own edge string by counting matched interior adjacencies. This is not a formality: in the source data one board carried a stale score, claiming 453 when its edges actually score 456, and recomputing from edges corrects it automatically. Re-derive the scores yourself from the edge strings and you will get the published numbers exactly. ## The corpus is diverse, not derivative A pile of several thousand boards is only worth publishing if the boards are actually different. Before releasing this one we checked that they are not just perturbations of a single board, and they are not: - Only 13 of the 7,671 source boards were exact duplicates; the rest are distinct, leaving 7,658. - The *median* board differs from its closest sibling by 235 of its 256 piece placements. Almost no board sits within 10 placements of another, and only 1% within 25. Even though most boards share a narrow score band, they are structurally almost entirely different. - The boards spread across 28 distinct corner families rather than piling into one. So the corpus is a genuinely varied sample of the strong-board landscape. That matters for anything that mines it: a learned prior built from thousands of copies of one board would encode that board, not the structure of good boards in general. ## Rebuilding it The [build script](https://github.com/raphael-anjou/eternity2/tree/main/research/datasets) regenerates the whole dataset. The instances are assembled from the public variant files; the corpus is deduplicated, rescored from edges, stripped of every working-store label (source paths, internal preset and seed names, filenames), and re-keyed with neutral ids, so what ships is board content and verified scores and nothing else. ## Related - [Known facts & numbers](https://eternity2.dev/research/build/known-facts) — The numbers every Eternity II researcher ends up re-deriving, collected in one place with their provenance: the puzzle definition, the clue placements, scoring conventions, the record table, search-space sizes and the structural counts. - [Reference numbers](https://eternity2.dev/research/reference) — Exact counts of how many valid ways a small block can be filled at a given position of the official Eternity II board, under increasingly constrained rules: known-good numbers to check your solver's edge-matching and constraint code against. - [Learning from strong boards](https://eternity2.dev/research/lab/experiments/raphael-anjou/learning) — A study in five experiments of one idea: instead of searching Eternity II from first principles, mine the corpus of strong boards already found for structure and feed it back into a search. A position prior, a learned move-vote, a scarce-demand compass, an anti-pattern miner, and a record decode, ordered from the simplest signal to the subtlest, and the one wall all five reach. --- # Dead ends > Approaches we tried that look promising and don't move the needle on Eternity II, written down with what we found so you can spend your time elsewhere. - Canonical page (with interactive figures/demos): https://eternity2.dev/research/build/dead-ends/ - Updated: 2026-07-02 - Topics: search-space, learning, exact-methods - Source: eternity2.net shuts down: 1.6 TFlops, 10^19 CPU operations, no solution (groups.io message 3511) — https://groups.io/g/eternity2/message/3511 - Source: Max on probability propagation: constraint influence fades out about two cells away (groups.io message 6208) — https://groups.io/g/eternity2/message/6208 - Source: Markus Zajc: macro-tiles are a speedup but no domain reduction (groups.io message 5883) — https://groups.io/g/eternity2/message/5883 - Source: Markus Zajc benchmarks border-supply pruning: 0.0014% fewer tests, 8% slower (groups.io message 6060) — https://groups.io/g/eternity2/message/6060 --- Approaches we tried that look promising and don't move the needle on Eternity II. None of these are bad ideas in general; they just don't crack this puzzle. We're writing down what we found so you can spend your time elsewhere. Each entry opens its verdict with a firmness tag: **Proven** means a theorem or an exact computation closes the door; **Measured** means we ran it (or the community did) and watched it fail; **Reported** means another researcher ran it and wrote up the failure, and we have not re-run it ourselves. Where the verdict comes from our own runs, the linked “why” page carries the exact reproduction command, and [run it yourself](/research/build/run-it-yourself) has the setup; where the community got there first, we cite the archive message. ## Symmetry breaking *Assume the board has rotational or mirror symmetries and fix some pieces to shrink the search.* **Proven.** The official set was built with no rotationally-symmetric pieces and no duplicates, and the single center clue pins orientation. There's no global symmetry to break, so fixing corners just makes an arbitrary, not a free, choice. [Why this is a wall →](/research/why/rare-color-geography) ## Just throw more compute at it *Run the same SAT or search solver on a bigger machine, a GPU, an FPGA, or quantum hardware.* **Measured.** The wall isn't clock speed, it's how well the problem is encoded and how the search space is shaped. GPU SAT solvers give a small constant speedup at best; quantum annealers show no advantage at the scale this would need. The same algorithm, faster, hits the same wall a little sooner. The community ran this experiment at scale: the eternity2.net grid put 1.6 teraflops and over $10^{19}$ CPU operations on the puzzle, then shut down without a solution ([msg 3511](https://groups.io/g/eternity2/message/3511)). And the quantum hope has been re-floated regularly, from [2007](https://groups.io/g/eternity2/message/1446) to [2024](https://groups.io/g/eternity2/message/11407). [Why this is a wall →](/research/why/prune-vs-speed) ## Survey propagation *The message-passing method that cracked huge random SAT problems by finding solution clusters.* **Proven.** It assumes the problem looks locally like a tree. Eternity II is a grid with a short cycle in every 2×2, which breaks that assumption. In practice the messages flatten out instead of sharpening, the opposite of what makes it work on random SAT. There are no published successes for it on grid puzzles. The community noticed the flattening early: in 2008, experiments with propagating piece probabilities found that constraint influence from the clues and corners seems to “fade out” about two cells away ([msg 6208](https://groups.io/g/eternity2/message/6208)). ## Belief-propagation move ordering *Run belief propagation over the colors and use its per-cell hints to decide which piece to try first.* **Measured.** The hints come out almost uniform, so they barely rank the candidates. When we raced it head-to-head, picking the next move at random did as well or better, because a fixed informed order tends to repeat the same mistakes. [Why this is a wall →](/research/why/no-forced-moves) ## Tensor-network counting *Treat the board as a tensor network and contract it to count or score boundary-consistent colorings.* **Proven.** It can only enforce that touching edges match, not that every piece is used exactly once. That blind spot is enormous: it counts on the order of $10^{90}$ boundary-consistent colorings against the puzzle's roughly one real solution. Local message passing simply can't see the global one-piece-per-cell rule. [Why this is a wall →](/research/why/entropy-area-law) ## Solve the colors first, place pieces later *Reformulate the board as a line graph over colors, solve for a color-adjacency arrangement that is edge-consistent everywhere, then hope that arrangement is easier to turn into a real tiling than solving for pieces directly.* **Measured.** It is a clean idea, explored on the list in 2023 to 2025: strip the puzzle down to which color meets which, solve that smaller object, and use it as a scaffold. The trouble is the smaller object is not small. Enumerating just the interior color arrangements for E2 leaves about $6.6\times10^{11}$ permutations, and 17×17 blows up to $2.97\times10^{13}$ ([msg 11182](https://groups.io/g/eternity2/message/11182)), and every one of those still has to be checked against a real piece assignment, because a color-consistent arrangement need not be tileable by the actual 256 pieces at all. It is the tensor-network blind spot in another costume: satisfying the color adjacencies is necessary but nowhere near sufficient, and the use-each-piece-once constraint that does the real work is exactly what the color-only view drops. The author's own summary after the enumeration was that you would "spend a lot of time just validating one" arrangement against all its inner-color permutations. [Why this is a wall →](/research/why/entropy-area-law) ## Relaxation bounds *Solve the linear-programming relaxation to get a tight ceiling on how many edges a board can match.* **Measured.** The relaxation lets pieces be fractional and spread across cells, which fakes matches that no real board can have. The result is a ceiling around 478 while the best real boards sit near 458, a gap too large to certify anything. The binding constraint is global piece-uniqueness, which the relaxation throws away. LP formulations were on the community's table in the first summer, and already there a 4×4 took over an hour to solve ([msg 1678](https://groups.io/g/eternity2/message/1678)). ## Learn a heuristic on small boards *Train a neural network on small puzzles, then transfer it to the full 16×16 to guide the search.* **Measured.** We trained a model that nailed small boards and watched it collapse on the real one. It learns from candidate moves filtered one way and is then asked about moves filtered very differently, and the full puzzle's colors never appeared in training. The skill doesn't carry across the size and color gap. [Why this is a wall →](/research/why/rigidity-wall) ## Enumerate local clusters first *List every valid 3×3 or 4×4 cluster, then stitch the clusters together into a full board.* **Measured.** The counts blow up before they help. When we tried it, valid clusters around a single region already ran into the tens of millions, and combining four corners reaches the order of $10^{12}$ piece-disjoint tuples. You run out of time and disk long before the constraints prune anything. The idea keeps getting rediscovered. In late 2024, 2×2 “macro pieces” came up again, at around 4 million blocks before piece-disjointness even enters ([msg 11428](https://groups.io/g/eternity2/message/11428)), and veterans pointed back at years of earlier 2×2 work in the archive ([msg 11429](https://groups.io/g/eternity2/message/11429)). [Why this is a wall →](/research/why/rigidity-wall) ## Cube and conquer *Split the SAT instance into millions of sub-cases (cubes), solve each independently, and recombine. The technique that settled Schur number five and the Pythagorean triples problem.* **Reported.** William Millilaw tested it exhaustively in May 2026 and it does not clear the board. On 16×16 the cubing phase does not partition the instance into anything tractable without heavy preprocessing, and the conquer step (a lookahead solver on each cube) was itself slower than running kissat straight. The clean result was a firm boundary: the method works up to about 8×8 and stops there. It joins the long line of exact methods that meet the same wall as integer programming and SAT decision, without a foothold past it. ## Generate boards with a transformer *Train a GPT-style model on a corpus of boards, condition it on a target score, and have it emit fresh high-scoring boards the search never found.* **Reported.** William Millilaw ran the full arc in May 2026 and each stage failed for its own reason. A 51-million-parameter model learned the grammar of a board (each piece used once, 96 percent structurally valid) but not the physics: unconditioned, its boards averaged around 250 matched edges, near random. Conditioning on a target score raised the average, but every board it emitted at the top of the range was an exact token-for-token copy of a memorized community board, McGavin's 469 among them. With only a couple of dozen distinct elite boards in the training set against tens of millions of parameters, the model had simply memorized them; the score condition became an index lookup. A final reinforcement-learning pass made it worse, not better, because the elite tail is sampled far too rarely to give a stable gradient. The lesson matches the [small-board transfer](/research/why/rigidity-wall) result on this page: imitation learns the distribution it is shown and cannot invent the rare structure that a record needs. ## Recombine two good boards *Take two high-scoring boards, keep the cells where they agree, and use partition crossover to splice the disagreeing regions into a child at least as good as both parents. The genetic operator with a tunneling guarantee on pseudo-Boolean problems.* **Reported.** William Millilaw implemented it and benchmarked it on pairs of boards scoring 455 and above. It degenerates. The permutation constraint (a piece cannot be reused) forces the disagreeing regions to merge into one component the moment you close them under piece-uniqueness, so the operator collapses into "pick the better parent" on more than 99 percent of pairs. The rare improving splices topped out at 469, the score of the parents, never above. It is the same lesson as the [rigidity wall](/research/why/rigidity-wall) from the recombination side: the good boards all sit in one narrow basin, so mixing them produces more of the same rather than something new. ## Force a diverse border, then fill *The border is a smaller sub-puzzle. Solve for many different valid frames first, on the theory that variety in the frame seeds variety in the whole board.* **Reported.** William Millilaw tried it and found the premise backwards. The border is the easy part: from scratch it is already varied and quick to place. The scarce resource is the interior fill, where the pieces run thin and the mismatches concentrate. Forcing frame diversity spends effort where there is no shortage and buys nothing where there is one. It is a recurring theme in this project's own experiments too: the frame is worth surprisingly little ([STAGED](/research/lab/experiments/raphael-anjou/pipelines/staged) measures exactly how little), and the endgame damage lands in the interior corners ([MOSAIC](/research/lab/experiments/raphael-anjou/pipelines/mosaic)). ## Build a fake 480 and repair it *Start from a board with every edge matched by allowing duplicate pieces, then greedily swap in the real pieces one at a time, hoping to keep the score at 480.* **Reported.** William Millilaw ran it and it collapses into whack-a-mole: every real piece you force in breaks edges elsewhere, and the repair never converges, topping out around 463. The reason is the lesson underneath this whole page. The barrier to 480 is not that the edges are hard to match; a fake board with repeated pieces matches all of them easily. The barrier is the global constraint that each of the 256 pieces is used exactly once, and that is exactly what the fake-480 construction throws away. The wall is informational, not a matter of local edge repair. ## Precompute 2×2 (or bigger) macro-tiles *Solve every 2×2 block once, store the valid ones, and place four cells at a time so the search is shorter.* **Measured.** Markus Zajc worked through it in 2008: building the macro-tiles just moves the work, it doesn't remove it. You trade a small set of single pieces for a very large set of 2×2 blocks, so placing a block is faster but the number of distinct partial boards is unchanged, still on the order of $10^{40}$ where it needs to be $10^{4}$. A 10× or 100× speedup on an out-of-reach tree is still out of reach ([msg 5883](https://groups.io/g/eternity2/message/5883)). Macro-tiles are a real constant-factor win for a fast solver, which is why the [block-order playground](/playground/paths) supports them, they are just not a domain reduction, and only a domain reduction would move the needle. ## Border-supply pruning (the "lollypop" check) *Before recursing, count the remaining border-colour demand against the pieces still available; if supply can't meet demand, cut the branch early.* **Measured.** Markus Zajc implemented this supply-versus-demand check as an add-on to his constraint solver and benchmarked it on the 8×8: it cut about 0.0014% of tests while adding 8% to the runtime, a clear net loss. The reason is instructive: on almost every branch the border-supply check would have failed, the ordinary constraint propagation has *already* failed a step or two earlier, so the extra bookkeeping pays for a cut the solver was about to make for free ([msg 6060](https://groups.io/g/eternity2/message/6060)). A pruning rule only helps if it fires before the checks you already run, not after. ## What every dead end has in common The gap from the best known board to a full solution doesn't look like a missing optimization. The good boards are locally frozen and globally constrained in ways that local fixes, faster hardware, and standard relaxations don't touch. Reaching the end seems to need an idea of a different kind, not more of the same. See [why a faster computer doesn't help](/research/why/prune-vs-speed). ## Related - [Run it yourself](https://eternity2.dev/research/build/run-it-yourself) — The whole site, the engine, and every result in this section run from one repository. Here is how to get it going, rebuild the WebAssembly engine, and reproduce the numbers. --- # Exact methods > Solvers that can prove things: SAT and CSP encodings, integer programming and its relaxations, exact-cover, meet-in-the-middle, and iterated projection maps. Complete methods stall on the full board, but their verdicts earn their keep as impossibility proofs on sub-boards. - Canonical page (with interactive figures/demos): https://eternity2.dev/research/build/exact/ - Updated: 2026-07-13 --- Solvers that can prove things: SAT and CSP encodings, integer programming and its relaxations, exact-cover, meet-in-the-middle, and iterated projection maps. Complete methods stall on the full board, but their verdicts earn their keep as impossibility proofs on sub-boards. The pages below go technique by technique: what each is in a line, what it actually reached on the real 16×16 board, where it stops, and the labs and measurements to back it. For the whole territory at once, start with [a map of every known approach](/research/build/approaches-map). ## Pages in this section - [Exact cover and dancing links](https://eternity2.dev/research/build/exact/exact-cover-dlx) — Eternity II states cleanly as an exact-cover problem, and Knuth's Algorithm X with dancing links is the classic machine for those. Where it genuinely shines (small boards, exhaustive counting) and the two reasons it does not crack the 16×16: an unshrunk search tree, and no partial credit. - [Meet in the middle](https://eternity2.dev/research/build/exact/meet-in-the-middle) — Enumerate two halves of a problem and join them on a shared interface, trading memory for an exponent cut in half. The classic Horowitz–Sahni trick, what it looks like on bands of the board, and what this project's BANDSAW experiment measured, including the one-sided method that beat it. - [SAT and CSP encodings](https://eternity2.dev/research/build/exact/sat-csp-encodings) — Write the puzzle as clauses and hand it to an industrial solver: the obvious move, tried since 2008. Why complete solvers stall on the full board, and where their verdicts still earn their keep as impossibility proofs. - [LP and ILP relaxations: half a piece everywhere](https://eternity2.dev/research/build/exact/lp-relaxations) — Write Eternity II as an integer program, drop the integrality, and a linear solver reaches zero error in seconds, with 30% of one piece and 20% of another sharing a corner. Eighteen years of community campaigns measured where the fractional comfort ends: a plateau at 420–440 edges the moment the pieces must be whole, an ILP wall at 8×8, and an academic best of 461-in-an-hour. What the optimizer's road teaches, and where LP still earns its keep. - [Iterated maps and divide-and-concur](https://eternity2.dev/research/build/exact/iterated-maps) — The physicist's attack on constraint satisfaction: split the puzzle into two constraint sets that are each easy to project onto, then iterate a map whose fixed points are solutions. Veit Elser's method made the cover of PNAS, yet on the Eternity II list it remains a road admired, tested once, and never marched down. ## Related - [A map of every known approach](https://eternity2.dev/research/build/approaches-map) — The survey the community keeps asking for and never finds: every family of attack tried on Eternity II, what each one actually reached, where it walls out, and a link to the deep page. One organising insight runs through all of them. - [The techniques](https://eternity2.dev/research/build/techniques) — The technique shelf: the algorithms and pruning ideas that recur in every serious Eternity II solver, each with what it is, what it costs, and what it actually bought when measured on this puzzle. --- # Exact cover and dancing links > Eternity II states cleanly as an exact-cover problem, and Knuth's Algorithm X with dancing links is the classic machine for those. Where it genuinely shines (small boards, exhaustive counting) and the two reasons it does not crack the 16×16: an unshrunk search tree, and no partial credit. - Canonical page (with interactive figures/demos): https://eternity2.dev/research/build/exact/exact-cover-dlx/ - Updated: 2026-07-02 - Topics: exact-methods - Source: Knuth 2000, "Dancing Links" (arXiv cs/0011047) — https://arxiv.org/abs/cs/0011047 - Source: Knuth's Algorithm X (Wikipedia) — https://en.wikipedia.org/wiki/Knuth%27s_Algorithm_X - Source: Exact cover (Wikipedia) — https://en.wikipedia.org/wiki/Exact_cover --- Some puzzles have to be bent to fit a formalism; Eternity II drops into exact cover almost by itself. An exact-cover problem asks: given a set of items and a collection of options, each option covering some items, pick options so that every item is covered *exactly once*. Pentomino tilings, sudoku and the n-queens problem are the textbook customers, and edge matching is next door. ## The board as an exact cover Take 512 items: one per cell ("cell $c$ is filled") and one per piece ("piece $p$ is used"). Each option is a concrete placement, piece $p$ at cell $c$ in rotation $r$, covering exactly two items, its cell and its piece. A selection of options covering every item exactly once is precisely a board with every cell filled and every piece used once. What pure exact cover cannot say is that touching edges must agree. Knuth's own extension handles it: XCC, exact covering with colours, where secondary items (here, one per interior edge of the grid) carry a colour, and two options may share a secondary item only if they assign it the same colour. A full XCC solution is then exactly a perfect Eternity II board. The encoding is faithful: nothing about the puzzle is approximated away. ## Algorithm X, and why the links dance Knuth's Algorithm X solves exact cover by disciplined trial and error: pick the item with the fewest remaining options (the fail-first rule), try each option that covers it, remove everything that option makes impossible, and recurse; on failure, restore and try the next. Dancing links (DLX) is the data structure that makes the restore step beautiful. The matrix of options lives in circular doubly linked lists, and removing an element is two pointer writes, `left.right = right; right.left = left`, which leaves the removed node's own pointers intact. Undoing the removal is the same two writes reversed. Backtracking becomes pointer surgery with zero copying, and the memory touched is exactly proportional to work done. It is one of the most elegant algorithms in the combinatorial toolbox, and Knuth's paper is a genuine pleasure to read. ## Watch the links dance Here is the complete search on the exact instance Knuth uses in the paper: seven items A–G, six options R1–R6, exactly one solution. Step through it and watch the three moves that make up the whole algorithm: choose the emptiest column, cover it (columns and rows detach from the lattice), and, on failure, uncover in reverse (the same links splice back). The dead end at column E is the moment worth stepping slowly: everything the wrong guess removed comes back in exactly the opposite order, for two pointer writes per link. > **[Figure]** Interactive: dancing links cover and uncover — interactive: DancingLinksLab. Rendered on the canonical page (link above); not shown in this markdown export. Note what never happens: no copying, no rebuilding, no scanning for what to restore. The removed nodes keep their own pointers while detached, and that is the entire trick, so undoing a cover is as cheap as doing it. ## Step by step The same run, in words. The matrix is R1 \{C,E,F\}, R2 \{A,D,G\}, R3 \{B,C,F\}, R4 \{A,D\}, R5 \{B,G\}, R6 \{D,E,G\}: 1. **Choose column A.** Two live options, tied for fewest; fail-first says branch on the most constrained item. Try its first option, R2 \{A,D,G\}: cover columns A, D and G. Every row touching them (R2, R4, R5, R6) detaches. 2. **Recurse.** Only R1 and R3 survive. Column B now has a single live option, so choose it, try R3 \{B,C,F\}: cover B, C, F, which detaches R1. 3. **Dead end.** Column E is still uncovered and no live option covers it. This branch can never complete, so no deeper search is even attempted. 4. **The dance.** Uncover F, C, B, then G, D, A, exact reverse order, each restoration the mirror image of the removal. The matrix is bit-for-bit back to its initial state, without having been saved anywhere. 5. **Try A's other option, R4 \{A,D\}.** Cover A, D. Column E now has exactly one live option, R1 \{C,E,F\}: cover C, E, F. Column B has one option left, R5 \{B,G\}: cover B, G. 6. **No columns remain**, every item covered exactly once. Solution: R1 + R4 + R5, found at depth 3 with a single dead end. The search then unwinds fully, verifies no other branch exists, and reports exactly one solution, and that certainty of exhaustion is the whole product. ## What it costs The ledger has two very different lines: - **The problem is NP-complete.** Exact cover is on Karp's original 1972 list, so no polynomial algorithm is known for it, and Algorithm X is exponential in the worst case: it is a complete backtracking search, and its tree can grow like the product of the branching at each level. - **The data structure is what's cheap.** DLX makes each link removal and each restoration $O(1)$: two pointer writes, with an exact undo, so the total time is $O(1)$ per link touched, proportional to the tree the search actually explores. Dancing links buys a superb constant factor and zero restore cost; it does not shrink the tree by a single node. On Eternity II's scale: the XCC matrix itself is perfectly manageable, with 512 primary items (256 cells + 256 pieces), 480 secondary items for the interior edges and their 22 colours, and at most $256 \times 256 \times 4 = 262{,}144$ options before symmetry and border pruning. Building it is minutes of work. The tree above it is the wall: with [no forced moves](/research/why/no-forced-moves) the branching stays wide all the way down, over a space usually estimated near $10^{100}$, and $O(1)$ per node times an astronomical node count is still astronomical. That is the precise sense in which DLX is the right tool for small boards and the wrong weapon for the 16×16. ## Where it shines DLX is the right tool when you want *all* solutions, or a count, or a proof of uniqueness, on instances small enough to exhaust. On small edge-matching boards it does exactly that: complete enumeration with excellent constant factors, no solution missed, no state repeated. Counting complete tilings of clue-sized regions, verifying that a generated mini-puzzle has a unique solution, cross-checking another solver's exhaustive counts: this is its home turf, and nothing heuristic competes there. One project note from the trenches, offered as a warning rather than a result: a from-scratch XCC implementation here validated cleanly on n-queens and trivial boards, then spent days broken on anything larger, because the interaction between colour-driven purification and cover/uncover restoration is genuinely subtle. If you build it, follow Knuth's published algorithm to the letter; the days lost above were this project's own to lose. ## Why it does not crack the 16×16 Two independent walls, either of which would suffice. **The tree is the same tree.** Exact cover re-describes the search; it does not shrink it. The fail-first item choice is a good variable ordering, but [no move is ever forced](/research/why/no-forced-moves) on this puzzle: the least-covered item still offers dozens of live options deep into the search, so the branching stays enormous all the way down, over a space usually estimated near $10^{100}$ boards. A DLX engine walks that tree completely or not usefully at all; and its pointer-chasing inner loop is memory-bound, an order of magnitude behind the cache-tuned array engines the [record backtrackers](/research/lab/experiments/joshua-blackwood/solver) use. **No partial credit.** DLX answers one question: covered exactly, or not. The entire Eternity II economy runs on partial scores (467, 469, 470) and on searches that deliberately tolerate a few mismatched edges to get there. Exact cover has no native way to leave an edge unmatched and pay a penalty; relaxing it that far means rebuilding it into a branch-and-bound, at which point the elegance that justified it is gone. ## Verdict Keep DLX on the shelf for what it is: the exhaustive instrument. Counting, uniqueness proofs, ground truth on small boards: unbeatable, and worth the implementation care it demands. As an attack on the full puzzle it is a [dead end](/research/build/dead-ends), for structural reasons no constant factor will fix: the tree it must exhaust is astronomical, and the partial-score game every record method plays is one it cannot enter. ## Related - [Dead ends](https://eternity2.dev/research/build/dead-ends) — Approaches we tried that look promising and don't move the needle on Eternity II, written down with what we found so you can spend your time elsewhere. - [No forced moves](https://eternity2.dev/research/why/no-forced-moves) — The usual way to crack a logic puzzle is to find a spot where only one piece fits, place it, and repeat. That lever doesn't exist here: every interior piece has between 73 and 137 possible neighbours, and not one is ever pinned to a single option. - [Blackwood's solver, decoded and run here](https://eternity2.dev/research/lab/experiments/joshua-blackwood/solver) — Joshua Blackwood's record backtracker, decoded through Jef Bucas's notes (a colour quota schedule and a late-game mismatch allowance, tuned near-optimally), then built and run on my M1: left as published it flies to 248 of 256 pieces ignoring the clues; pin the five official clues and the same engine stalls near 45. --- # Iterated maps and divide-and-concur > The physicist's attack on constraint satisfaction: split the puzzle into two constraint sets that are each easy to project onto, then iterate a map whose fixed points are solutions. Veit Elser's method made the cover of PNAS, yet on the Eternity II list it remains a road admired, tested once, and never marched down. - Canonical page (with interactive figures/demos): https://eternity2.dev/research/build/exact/iterated-maps/ - Updated: 2026-07-02 - Topics: exact-methods, learning - Source: Elser, Rankenburg & Thibault, Searching with iterated maps (PNAS 104:418, 2007) — https://doi.org/10.1073/pnas.0606359104 - Source: Gravel & Elser, Divide and concur: a general approach to constraint satisfaction (Phys. Rev. E 78, 036706, 2008) — https://doi.org/10.1103/PhysRevE.78.036706 - Source: Gravel & Elser, Divide and concur: open preprint (arXiv:0801.0222) — https://arxiv.org/abs/0801.0222 - Source: Aragón Artacho, Borwein & Tam, Recent results on Douglas–Rachford methods for combinatorial optimization problems (arXiv:1305.2657) — https://arxiv.org/abs/1305.2657 - Source: JSA formalizes the dual problem and introduces Elser's work to the list (groups.io message 9347) — https://groups.io/g/eternity2/message/9347 - Source: JSA on the divide-and-concur papers and the open scaling question (groups.io message 9350) — https://groups.io/g/eternity2/message/9350 - Source: Dima's test: a simple hill-climber beats the difference map on the paper's own benchmark (groups.io message 9351) — https://groups.io/g/eternity2/message/9351 - Source: Elser's ICCOPT-MOPTA 2007 slides uploaded to the group files, "Eternity II mentioned in last 3 slides" (groups.io message 9349) — https://groups.io/g/eternity2/message/9349 - Source: Source code from Veit Elser, with a 5×5 example puzzle, shared in the group files (groups.io message 9362) — https://groups.io/g/eternity2/message/9362 - Source: JSA's 2015 recap: small model versions solved, the big one not (groups.io message 9442) — https://groups.io/g/eternity2/message/9442 - Source: Dima's primal–dual transfer sketch with Hungarian matching (groups.io message 9445) — https://groups.io/g/eternity2/message/9445 - Source: The SRD edge-swap precedent: solved 8×8, never made 10×10 (groups.io message 9447) — https://groups.io/g/eternity2/message/9447 - Source: Douglas–Rachford named on the list, via Wikipedia's TetraVex note (groups.io message 11592) — https://groups.io/g/eternity2/message/11592 - Source: JSA connects Douglas–Rachford back to the Elser lineage (groups.io message 11594) — https://groups.io/g/eternity2/message/11594 --- Every method on this shelf so far treats Eternity II as a discrete search: place, check, backtrack. The physics community proposed something stranger. Veit Elser's group at Cornell reformulated constraint satisfaction as geometry, a point bouncing between two sets in a high-dimensional space, and rode one iteration scheme from X-ray phase retrieval to Sudoku, 3-SAT and protein folding, landing the method on the cover of PNAS ([Elser, Rankenburg & Thibault, 2007](https://doi.org/10.1073/pnas.0606359104)). Edge-matching puzzles are almost a poster child for the formulation, and the cover of that PNAS issue showed one, as the member who brought the work to the list pointed out ([groups.io message 9347](https://groups.io/g/eternity2/message/9347)). This page explains the method properly, because it is genuinely striking and genuinely different from everything else in the catalogue. It then reports what the Eternity II community actually did with it: a flurry of interest in 2014–2015, one empirical test, one shared tarball of Elser's own code, and no campaign. This is a known road, lightly traveled here. ## Two easy sets, one hard intersection Embed a board state as a point $x$ in a Euclidean space, say a real vector with one coordinate per (cell, piece, rotation) triple, where a legal board is a 0/1 assignment. Now define two constraint sets: - $C_1$, **pieces used once**: every cell holds exactly one piece-rotation, and every piece is used exactly once. Edge colors are ignored. - $C_2$, **edges match**: every pair of touching edges agrees in color, and the rim is gray. Piece inventory is ignored, so cells may hold fractional blends or duplicate pieces. A solved Eternity II is exactly a point in $C_1 \cap C_2$. The trick that makes the formulation useful is that each set *alone* is easy to project onto. Given an arbitrary $x$, you can cheaply compute the nearest point of the set: - $P_1(x)$, the nearest valid piece assignment, is a bipartite matching problem: assign 256 pieces to 256 cells to maximize total affinity. The Hungarian algorithm solves it exactly in polynomial time, the same assignment engine that powers the refill step in [local search](/research/build/local-search/local-search-alns). - $P_2(x)$, the nearest edge-consistent coloring, decomposes edge by edge: each interior join just averages its two sides toward agreement. Purely local, embarrassingly parallel. Each projection is a solved problem. The hardness of Eternity II lives entirely in the *intersection*, and the naive scheme, alternating projections $x \mapsto P_1(P_2(x))$, fails exactly the way you'd guess: it converges to a pair of points, one in each set, locally as close as possible and globally wrong. A local minimum, in projection clothing. This two-sided view reached the list independently of Elser. As early as 2008, antminder proposed cutting the pieces into edge-triangles and searching in the domain of colored diamonds ([message 6184](https://groups.io/g/eternity2/message/6184)), and JSA immediately recognized it as the *dual problem* ([message 6185](https://groups.io/g/eternity2/message/6185)): Eternity II is 256 pieces to be arranged so that 480 edges match, or 480 colored edge squares to be arranged so that they generate the correct 256 pieces. Solving means making both descriptions true at once. ## The difference map Elser's answer to the local-minimum trap is not to alternate projections but to iterate a *difference map*. In the published form, with the parameter set to $\beta = 1$, one step is $$ x \;\mapsto\; D(x) \;=\; x \;+\; P_1\!\big(2P_2(x) - x\big) \;-\; P_2(x), $$ and the general-$\beta$ family interpolates around this using inner "estimate" points $f_i(x)$ built from the projections ([PNAS 2007](https://doi.org/10.1073/pnas.0606359104)). Three properties do all the work: 1. **Fixed point = solution.** If $D(x^\ast) = x^\ast$, then $P_1(2P_2(x^\ast) - x^\ast) = P_2(x^\ast)$: the same point lies in both sets. You read the solution off as $P_2(x^\ast)$, not as $x^\ast$ itself: the iterate is a *searcher*, not a board. Termination is detected when the displacement $\Delta = \lVert D(x) - x \rVert$ falls below a threshold, and the candidate is then verified exactly. 2. **No cost function.** The map does not descend anything. That sounds like a defect and is the point: a hill-climber sticks wherever its score function has a local optimum, but the difference map has no score to flatter it into staying. Away from fixed points it keeps moving, in practice chaotically, so near-miss configurations that trap [local search](/research/build/local-search/local-search-alns) are places it visits and leaves. This is the "tunneling" the physicists prized. 3. **The iterate lives outside both sets.** $x$ need not satisfy either constraint while searching. Like the fractional boards of the [LP relaxation](/research/build/exact/lp-relaxations), it explores a superposition of boards. Unlike the LP, it has no objective to optimize and no optimum to plateau at: its only resting places are solutions. For $\beta = 1$ the difference map coincides with the **Douglas–Rachford iteration**, a projection method convex analysts have studied since the 1950s; convergence is provable when both sets are convex, and entirely unguaranteed here, where $C_1$ is a scatter of permutation points. The Eternity II list only learned the family name in 2025, when Wyatt Carpenter found Wikipedia crediting "the Douglas–Rachford algorithm" for TetraVex solving and flagged it as a possibly promising avenue no one had raised ([message 11592](https://groups.io/g/eternity2/message/11592)); JSA closed the loop, pointing back to the Elser thread of 2014–2016 and framing Douglas–Rachford as the $f(x) + g(x)$ splitting view of the same attack ([message 11594](https://groups.io/g/eternity2/message/11594)). The optimization literature had indeed adopted the method for exactly this family of puzzles ([Aragón Artacho, Borwein & Tam](https://arxiv.org/abs/1305.2657)). ## Divide and concur: the replica trick The two-set picture above needed a global projection ($P_1$ is one big matching). Gravel and Elser's follow-up, [*Divide and concur*](https://doi.org/10.1103/PhysRevE.78.036706) ([open preprint](https://arxiv.org/abs/0801.0222)), makes the construction mechanical for *any* CSP. Give every constraint its own private **replica** of each variable it touches: - The **divide** projection satisfies each constraint independently on its own replicas. Every constraint is now a tiny local problem (for Eternity II: one edge, two piece-sides), trivially projectable. - The **concur** projection forces all replicas of the same variable to agree, by replacing each with their average, the cheapest projection imaginable. Run the difference map between *divide* and *concur* and you get a general CSP solver whose per-iteration work is entirely local, with the averaging step playing the role of communication. Gravel and Elser benchmarked it on 3-SAT, where it scaled comparably to WalkSAT, and used it to improve known sphere packings. When the method reached the list, Dima immediately recognized the structure from his own field: the replica-averaging scheme is a close relative of belief propagation on the constraint graph, a connection the authors draw themselves ([message 9348](https://groups.io/g/eternity2/message/9348)). For readers of this wiki the family resemblance goes further: a message-passing search over a graph that is locally tree-like nowhere (every 2×2 block is a cycle) is exactly the setting where the related methods on the [dead ends](/research/build/dead-ends) page (survey propagation, belief-propagation move ordering) flattened out and died. ## What the archive actually shows The record, in full, because it is short. - **2008, a dismissal in passing.** The first mention of the method on the list is Don Milne listing "difference map" among the optimization techniques he judged unable to solve complex CSPs: they shine only when solutions are dense, and Eternity II was [designed to have almost exactly one](/research/why/complex-theory) ([message 5479](https://groups.io/g/eternity2/message/5479)). - **2014, the real introduction.** A member's diagram of the puzzle's edge lattice prompted JSA to state the dual problem and introduce Elser's work: the difference map "moves back and forth between the two dual problems" ([message 9347](https://groups.io/g/eternity2/message/9347)), with pointers to the PNAS paper and the divide-and-concur Physical Review paper ([message 9350](https://groups.io/g/eternity2/message/9350)). Elser's own ICCOPT-MOPTA 2007 slides, which mention Eternity II in their final three slides, were uploaded to the group's files ([message 9349](https://groups.io/g/eternity2/message/9349)). - **2014, the one empirical test.** Dima read the PNAS paper, liked it, and checked it: he wrote a simple hill-climber for the paper's own graph 3-coloring benchmark and solved the $N=16$ instance in seconds, where the paper's Table 2 has the difference map taking on the order of ten minutes. "So this makes me wonder whether it is really all that it is hyped up to be" ([message 9351](https://groups.io/g/eternity2/message/9351)), while still calling the two-sided tiles-versus-edges idea worth exploring for E2. - **2015, code and a promise.** Someone obtained source code from Elser himself, with a worked 5×5 edge-matching example, and shared it in the group files ([message 9362](https://groups.io/g/eternity2/message/9362)). In the "New Approach?" thread that summer, JSA recapped the method's standing: it "has solved small model version[s] of Eternity II," and had it solved the big one "we would have heard about it" ([message 9442](https://groups.io/g/eternity2/message/9442)). Juraj Pivovarov asked for a concrete difference map written down for Eternity II ([message 9443](https://groups.io/g/eternity2/message/9443)); JSA promised a short write-up ([message 9446](https://groups.io/g/eternity2/message/9446)) that never appears in the archive. In the same thread Dima sketched the primal–dual transfer explicitly (carry an edge-coloring solution to the nearest piece assignment with the Hungarian algorithm and back) and reported his own dual-side annealer stalling at 48/49 correct tiles on Brendan Owen's 7×7 ([message 9445](https://groups.io/g/eternity2/message/9445)), while Mike Pringle recalled the list's home-grown cousin, the SRD edge-swap approach of 2007: capable of 8×8, never 10×10 ([message 9447](https://groups.io/g/eternity2/message/9447)). - **2025, a name and a shrug.** The Douglas–Rachford thread ([message 11592](https://groups.io/g/eternity2/message/11592)) drew one quick evaluation, useful for theory, "but not much else" ([message 11593](https://groups.io/g/eternity2/message/11593)), and JSA's reflection that on a puzzle built to be optimally difficult, he'd expect the iteration count to be "on the order of" a backtracker's node count anyway ([message 11594](https://groups.io/g/eternity2/message/11594)). That is the whole record: no member ever reported running the difference map or divide-and-concur on the full 480-edge puzzle, or even on the 10×10 benchmark ladder. The peer-reviewed literature is similar in shape. Elser's group published the method's successes on coloring, SAT, packing and folding, and kept Eternity II to talks, cover art and example code. Nobody has published a difference-map result on the full puzzle, positive or negative. > **Why so little uptake?** > > Partly timing (the 2014 thread landed in the archive's quietest years) and partly Dima's data point, which took the shine off fast. But the deeper reason is the one Don Milne gave in 2008 and JSA repeated in 2025: stochastic continuous methods pay off when solutions are plentiful relative to the space, and Eternity II sits at the [designed hardness peak](/research/why/complex-theory) where they are not. The method is famous *because* edge matching illustrates it beautifully, not because it solves edge matching at scale. ## What an attempt today would look like The gap between "discussed" and "measured" is narrow enough that one person could close it. A modern attempt would: 1. **Fix the embedding.** Per-cell one-hot vectors over 1,024 piece-rotations (the two-set version), or divide-and-concur replicas per edge constraint. This is the step Juraj asked for in 2015 and nobody wrote down for E2; Elser's shared 5x5 code ([message 9362](https://groups.io/g/eternity2/message/9362)) is the natural starting template. 2. **Implement the two projections.** Edge-agreement is a local average; piece-validity is one Hungarian solve per iteration (256 cells x 1,024 candidates), or pure replica-averaging in the divide-and-concur form. 3. **Climb the benchmark ladder.** Run against [Brendan Owen's puzzle suite](/research/build/benchmarks), the same 7×7 where Dima's dual annealer got 48/49, then 8×8, 9×9, 10×10, with a plain hill-climber and a restart-driven backtracker as controls, plotting iterations-to-solution against instance hardness. 4. **Report the curve, not the anecdote.** The interesting output is the scaling exponent: Elser's own papers report iteration counts growing steeply with instance hardness, and the open question JSA posed in 2014, how does it scale to E2-class instances? ([message 9350](https://groups.io/g/eternity2/message/9350)), has never been answered with a graph. The realistic best case is not a solved puzzle. It is a characterized method: either a scaling curve that crosses the backtracker's somewhere interesting, which would be news, or a clean negative entry for the [dead ends](/research/build/dead-ends) ledger, which is also progress. ## What it costs - **Per iteration: two projections.** The edge projection is linear in the number of edges. The piece projection is the expensive one: an exact assignment solve is $O(n^3)$ in the Hungarian algorithm, and at $n = 256$ cells that is millions of operations per *iteration*, against a tuned backtracker's [tens of millions of placements per second](/research/build/faster/solver-engineering). Divide-and-concur trades this for pure local averaging, at the price of a much larger replicated state. - **No convergence guarantee.** Douglas–Rachford convergence theory is convex; both Eternity II sets are combinatorial scatter. On feasible instances the map usually finds fixed points in practice (that is the papers' empirical content), but nothing bounds the iteration count, and on this puzzle JSA's expectation is that it matches backtracking's node count ([message 11594](https://groups.io/g/eternity2/message/11594)). - **Fixed point = solution, and nothing less.** The method has no useful partial output: until $\Delta \to 0$ you have a wandering point in a fractional space, not a scored board. There is no 460-edge consolation prize along the way, which matters on the only puzzle where the [record ladder](/research/records) is denominated in partial scores. - **The scoreboard.** One community test, lost to a hill-climber on the method's own benchmark ([message 9351](https://groups.io/g/eternity2/message/9351)); small edge-matching models solved in Elser's materials; the full puzzle untouched. Elegant, principled, unproven here, and, unusually for this wiki, still unmeasured rather than measured-and-buried. ## Related - [Dead ends](https://eternity2.dev/research/build/dead-ends) — Approaches we tried that look promising and don't move the needle on Eternity II, written down with what we found so you can spend your time elsewhere. - [LP and ILP relaxations: half a piece everywhere](https://eternity2.dev/research/build/exact/lp-relaxations) — Write Eternity II as an integer program, drop the integrality, and a linear solver reaches zero error in seconds, with 30% of one piece and 20% of another sharing a corner. Eighteen years of community campaigns measured where the fractional comfort ends: a plateau at 420–440 edges the moment the pieces must be whole, an ILP wall at 8×8, and an academic best of 461-in-an-hour. What the optimizer's road teaches, and where LP still earns its keep. - [SAT and CSP encodings](https://eternity2.dev/research/build/exact/sat-csp-encodings) — Write the puzzle as clauses and hand it to an industrial solver: the obvious move, tried since 2008. Why complete solvers stall on the full board, and where their verdicts still earn their keep as impossibility proofs. --- # LP and ILP relaxations: half a piece everywhere > Write Eternity II as an integer program, drop the integrality, and a linear solver reaches zero error in seconds, with 30% of one piece and 20% of another sharing a corner. Eighteen years of community campaigns measured where the fractional comfort ends: a plateau at 420–440 edges the moment the pieces must be whole, an ILP wall at 8×8, and an academic best of 461-in-an-hour. What the optimizer's road teaches, and where LP still earns its keep. - Canonical page (with interactive figures/demos): https://eternity2.dev/research/build/exact/lp-relaxations/ - Updated: 2026-07-02 - Topics: exact-methods - Source: The max-clique framing: 262,144 placement vertices, find a clique of 256 (groups.io message 627, 2007) — https://groups.io/g/eternity2/message/627 - Source: Rotation sets solved by ILP (glpsol) in about 5 seconds each (groups.io message 3320, 2007) — https://groups.io/g/eternity2/message/3320 - Source: Vlasta's LP status report: 160,254 binaries; ILP 'applicable only for 8×8 puzzles' (groups.io message 5602, 2008) — https://groups.io/g/eternity2/message/5602 - Source: Andrew's continuous-ascent formulation and the 800,000-day estimate (groups.io message 5304, 2008) — https://groups.io/g/eternity2/message/5304 - Source: Benjamin's 50,000-variable LP and its fractional corner: 30% piece 1, 20% piece 2 (groups.io message 6905, 2009) — https://groups.io/g/eternity2/message/6905 - Source: Benjamin's constraint counts (7,952 equations) and the quadratic integrality trick (groups.io messages 6910/6913, 2009) — https://groups.io/g/eternity2/message/6913 - Source: Andrew on the implicit solver: 'every piece is everywhere', Newton–Raphson over 250,000 weights (groups.io message 6911, 2009) — https://groups.io/g/eternity2/message/6911 - Source: Timmermans's AMPL/CPLEX binary integer program: 272,704 variables, 24,566 equations (groups.io message 6728, 2009) — https://groups.io/g/eternity2/message/6728 - Source: The real-domain 12×12 'solution' at 5.3% infeasibility (groups.io message 6745, 2009) — https://groups.io/g/eternity2/message/6745 - Source: Munjak's retrospective: side-constrained assignment, 200–224 pieces, no backtracking (groups.io message 8791, 2011) — https://groups.io/g/eternity2/message/8791 - Source: Wauters: the academic line, 461/480 matched edges in one hour (groups.io message 9023, 2012) — https://groups.io/g/eternity2/message/9023 - Source: Wauters: rotation sets by MILP in milliseconds (groups.io message 9071, 2012) — https://groups.io/g/eternity2/message/9071 - Source: The MILP + Max-Clique paper reaches the list (groups.io message 9683, 2017) — https://groups.io/g/eternity2/message/9683 - Source: Salassa, Vancroonenburg, Wauters, Della Croce & Vanden Berghe, MILP and Max-Clique based heuristics for the Eternity II puzzle (arXiv:1709.00252, 2017) — https://arxiv.org/abs/1709.00252 - Source: Wauters, Vancroonenburg & Vanden Berghe, A guide-and-observe hyper-heuristic approach to the Eternity II puzzle (JMMA, 2012) — https://link.springer.com/article/10.1007/s10852-012-9178-4 - Source: Garvie's modern ILP: a 10×10, 6-colour instance solved in about 19 minutes (groups.io message 11502, 2025) — https://groups.io/g/eternity2/message/11502 --- There are three classic roads into Eternity II. Backtracking walks the tree. [SAT and CSP encodings](/research/build/exact/sat-csp-encodings) hand the logic to an industrial solver. The third road belongs to the optimizers: write the puzzle as an integer program (variables, linear constraints, an objective) and call CPLEX. It is the road every operations-research person tries first, because it comes with a move the other two don't have: *relaxation*. Delete the requirement that variables be whole numbers and the NP-hard integer program becomes a linear program, solvable in polynomial time. Solve the easy version, hope the answer is nearly integral, repair the rest. The community walked this road repeatedly between 2007 and 2025, with solvers from `glpsol` to CPLEX to hand-rolled Newton–Raphson, and the outcome was measured precisely enough to be worth a page: the relaxation solves fast and reports a nearly perfect board, one made of fractions of pieces. Force the pieces whole and the score collapses onto a plateau around 420–440 of 480 edges. The gap between the fractional optimum and the integer one is not a technicality. It is the exact place where the puzzle lives. ## The formulation One binary variable per placement, exactly as in the SAT encoding: let $x_{c,p,r} \in \{0,1\}$ mean "piece $p$ sits at cell $c$ with rotation $r$". Two families of assignment constraints and one per-seam accounting give the whole model: $$ \begin{aligned} \max \;\; & \sum_{s} y_s && \text{(matched seams)} \\ \text{s.t.} \;\; & \sum_{p,\,r} x_{c,p,r} = 1 && \forall\, \text{cell } c \\ & \sum_{c,\,r} x_{c,p,r} = 1 && \forall\, \text{piece } p \\ & y_s \,\le\, \sum_{k} \min\!\big( f_{s,k}^{1},\, f_{s,k}^{2} \big) && \forall\, \text{seam } s \end{aligned} $$ where $f_{s,k}^{i}$ is the colour flow, the total weight of placements on side $i$ of seam $s$ that show colour $k$ across it, $f_{s,k}^{i} = \sum_{(p,r)\,\text{showing}\,k} x_{c_i,p,r}$. The $\min$ is linearized with one auxiliary variable per seam and colour; for the *feasibility* version you instead demand equal colour flow on both sides of every seam. Community models land exactly where the arithmetic says they should. Benjamin's 2009 LP had ~50,000 variables (placements pruned to valid positions) and 7,952 equations: 256 per-cell, 256 per-piece, and $60 \times 5 + 420 \times 17 = 7{,}440$ seam-colour balance constraints ([message 6910](https://groups.io/g/eternity2/message/6910)). Vlasta's 2008 model carried 160,254 binaries ([message 5602](https://groups.io/g/eternity2/message/5602)); Jimmy Timmermans's AMPL/CPLEX binary program, 272,704 variables and 24,566 equations ([message 6728](https://groups.io/g/eternity2/message/6728)). Günter Stertenbrink had already posed the equivalent graph form in 2007: make the 262,144 placements vertices, join compatible pairs, and ask for a clique of size 256 ([message 627](https://groups.io/g/eternity2/message/627)), the framing the academic literature returned to a decade later. ## Relax it, and it solves in seconds Relaxation means one edit: replace $x_{c,p,r} \in \{0,1\}$ with $0 \le x_{c,p,r} \le 1$. That single change moves the problem across the most important boundary in optimization. The integer program is NP-hard: 0–1 integer programming is one of Karp's original 21 complete problems. The linear program is solvable in polynomial time (ellipsoid, interior-point), and in practice simplex dispatches these model sizes almost instantly. Benjamin measured it: his 50,000-variable system reached an error below 0.01 in about ten seconds ([message 6913](https://groups.io/g/eternity2/message/6913)). Two properties make the relaxation genuinely useful, not just fast. Every integer solution is also a fractional one, so the LP optimum is a *bound*: no real board can ever score more than the relaxation says. And LP solvers return certificates (dual values, infeasibility proofs) that integer-free methods don't. The whole question is how much of that speed survives the return trip to whole pieces. ## The fractional board Here is what the LP optimum actually looks like, in the words of the person who computed it. Benjamin's system "converged relatively fast to zero error" (a perfect board, as far as the constraints could see), and the upper-left corner held "30% piece 1, 20% piece 2, 10% piece 3, 40% piece 4" ([message 6905](https://groups.io/g/eternity2/message/6905)). Andrew's parallel experiment ran the same idea as an iterated ascent over a 256×256×4 grid of weights: "every piece is everywhere" ([message 6911](https://groups.io/g/eternity2/message/6911)). The relaxation is happy because a superposition can hedge. A quarter of a blue-edged piece plus three quarters of a pink-edged one presents a blend that simultaneously part-matches a blue neighbour and a pink one, a match no physical board can realize. Linear constraints can price how much of each piece sits where; they cannot express "exactly one of these is real," because *one-of* is not a linear fact. It takes a quadratic constraint (or an integrality one) to say it. Benjamin used $(\sum v_i)^2 - \sum v_i^2 = 0$, which forces all but one variable in a group to zero ([message 6913](https://groups.io/g/eternity2/message/6913)), and the moment he added it, convergence died: the system "stalls at higher values which resemble results like 420-440 / 480 correct edges" ([message 6905](https://groups.io/g/eternity2/message/6905)). There is clean theory underneath the observation. The two assignment families alone define a polytope whose vertices are all integral (that is Birkhoff–von Neumann, and it is exactly why the Hungarian algorithm solves pure assignment in polynomial time). Add the seam constraints and that integrality property is destroyed: the polytope grows fractional vertices, and the LP optimum sits on one of them. David Munjak's retrospective compresses this into one line, listing among his tried approaches "Assignment problem (integral solutions)" followed by "Assignment problem with side constraints (not necessarily integral solutions)" ([message 8791](https://groups.io/g/eternity2/message/8791)). The side constraints (the edges, the actual puzzle) are precisely what breaks the guarantee. Eternity II is an easy assignment problem welded to a hard coupling, and the relaxation quietly optimizes only the easy half. ## The measured plateau Every few years someone new drove the road, with better solvers and more memory, and hit the same three walls: the full ILP is unsolvable past toy sizes; the LP is solvable and fractional; rounding or constraining toward integrality lands in the mid-400s. The campaigns, in order: | Year | Who | Model | Where it stopped | Msg | | --- | --- | --- | --- | --- | | 2007 | Günter Stertenbrink | Max-clique, 262,144 vertices | Framing only; never scaled | [166](https://groups.io/g/eternity2/message/166), [627](https://groups.io/g/eternity2/message/627) | | 2007 | dmitri_ulitski | ILP (glpsol) on rotation sets | Solved in ~5 s per set; the subproblem is easy | [3320](https://groups.io/g/eternity2/message/3320) | | 2008 | Vlasta | ILP, 160,254 binaries | "Applicable only for 8x8 puzzles"; switched to SAT, reached 428 | [5602](https://groups.io/g/eternity2/message/5602) | | 2008–09 | Andrew (bozmo2004) | Continuous ascent, Newton–Raphson over ~250k weights | ~800,000 days projected with his VBA prototype | [5304](https://groups.io/g/eternity2/message/5304), [6911](https://groups.io/g/eternity2/message/6911) | | 2009 | Benjamin (okifinoki) | LP, ~50,000 vars, 7,952 constraints | Zero error in ~10 s, fractional; forced integral: stalls at 420–440/480 | [6905](https://groups.io/g/eternity2/message/6905), [6913](https://groups.io/g/eternity2/message/6913) | | 2009–10 | Jimmy Timmermans | Toric ideals; AMPL/CPLEX BIP, 272,704 then 153k vars | Singular's 32k-variable limit; a 12x12 "solved" at 5.3% infeasibility (converges, integrality doesn't) | [6716](https://groups.io/g/eternity2/message/6716), [6728](https://groups.io/g/eternity2/message/6728), [6745](https://groups.io/g/eternity2/message/6745), [8077](https://groups.io/g/eternity2/message/8077) | | 2010 | Vlasta | MILP (164,256 booleans) converted to SAT | 8x8 in ~1 min; parity with backtrackers, no further | [7858](https://groups.io/g/eternity2/message/7858) | | 2008–10 | David Munjak | Side-constrained assignment, fractional values as probabilities | 200–224 pieces placed, then a detected dead end; never backtracked | [8791](https://groups.io/g/eternity2/message/8791) | | 2012 | Wauters group | Hyper-heuristic (peer-reviewed) | 461/480 in one hour (the academic line) | [9023](https://groups.io/g/eternity2/message/9023) | | 2012 | Tony Wauters | MILP for rotation sets | Milliseconds; again, the easy subproblem | [9071](https://groups.io/g/eternity2/message/9071) | | 2017 | Salassa, Vancroonenburg, Wauters et al. | MILP + Max-Clique formulations | "Computationally intractable for medium and large sized instances"; recycled as heuristic decompositions | [9683](https://groups.io/g/eternity2/message/9683), [arXiv](https://arxiv.org/abs/1709.00252) | | 2025 | Marcus Garvie | Modern ILP | 10x10 with 6 colours in ~19 min; full E2 out of reach | [11502](https://groups.io/g/eternity2/message/11502) | Three readings of the table. First, notice where ILP *wins*: rotation sets, where you fix only each piece's orientation so the directional edge counts balance, fell to `glpsol` in five seconds in 2007 and to CPLEX in milliseconds in 2012. When the integer structure is genuinely easy, the solver says so immediately; the full puzzle's silence is a verdict, not a tooling problem. Second, the plateau numbers agree across totally different machinery: Benjamin's 420–440 by penalized LP, Munjak's 200–224 pieces placed mismatch-free by iterated assignment, the Wauters group's 461 with an hour of metaheuristic repair on top. Everything optimizer-shaped lands in the same mid-400s band that plain [local search](/research/build/local-search/local-search-alns) reaches without any LP at all. Third, the 2017 paper, the strongest academic treatment, with both a MILP and a Max-Clique formulation, concedes intractability in its abstract and pivots to using the formulations *inside* heuristics. The road's own builders posted the detour sign. The bound side of the story has the same shape and lives on the [dead-ends ledger](/research/build/dead-ends): this project's measured LP ceiling sits around 478 while the best real boards sit near 458, a gap far too wide to certify anything, for exactly the fractional-hedging reason above. ## What it costs - **The LP: polynomial, genuinely fast.** Interior-point methods solve linear programs in polynomial time; on models of this size (50k–270k variables, thousands to hundreds of thousands of constraints) modern solvers finish in seconds to minutes. This is the one genuinely cheap object on the page. - **The ILP: NP-hard, and not abstractly.** Branch-and-bound is backtracking with an LP bound at every node: worst-case exponential, and an instance [built at the hardness peak](/research/why/phase-transition) is engineered to realize the worst case. The measured form of the cost: a solver that handles 8×8 (64 pieces) returns nothing on 16×16, because the tree under the root is squared, not doubled. - **The integrality gap is the real currency.** The whole method's value is the distance between the LP optimum and the best integer solution. Here that distance is roughly 478 versus 458-and-stalling: the relaxation spends its polynomial budget answering a question about a different, fractional puzzle. Cutting planes exist to buy the gap down; nobody has reported cuts that close a dent of it on E2, and the per-seam structure that fakes matches regenerates the slack everywhere. - **Branch-and-bound prunes with the bound it has.** A node is cut only when its LP bound falls below the incumbent. With the bound floating ~20 edges above anything real, almost nothing prunes: the exact analogue of wide, useless learned clauses in [CDCL](/research/build/exact/sat-csp-encodings), one road over. ## What LP and MIP are still for The fair conclusion is relocation, not dismissal, the same one the [SAT page](/research/build/exact/sat-csp-encodings) reaches for CDCL. - **Bounds, stated with their error bars.** The relaxation *is* a valid ceiling, computed in polynomial time; it is just a loose one here. The [dead-ends entry](/research/build/dead-ends) records the verdict so nobody re-derives it expecting a certificate. - **Assignment subproblems, where integrality is free.** Inside repair loops, refilling $k$ pairwise non-adjacent holes is a pure $k \times k$ assignment problem: Birkhoff's polytope, integral vertices, Hungarian algorithm in $O(k^3)$. That is Schaus's Eternity II neighborhood, and it is the one place on this wiki where the optimizer's machinery runs at full power: see [local search and ALNS](/research/build/local-search/local-search-alns). - **Easy integer subproblems, dispatched instantly.** Rotation sets by MILP in milliseconds ([message 9071](https://groups.io/g/eternity2/message/9071)) is the pattern: when a sub-question has tractable structure, a MIP solver is the fastest reliable way to settle it, including settling that the answer doesn't help. - **Infeasibility as a theorem.** An ILP that comes back infeasible on a pinned region proves the same impossibility a SAT UNSAT call does: the certificate currency behind the [rigidity wall](/research/why/rigidity-wall). This project mints those certificates with SAT, which is faster on this encoding; a MIP solver is a legitimate second mint, and Munjak's placer used exactly that signal, "identifying an issue that would prevent all 256 pieces from being placed" ([message 8791](https://groups.io/g/eternity2/message/8791)). - **Formulations as neighbourhood generators.** The 2017 paper's lasting contribution is methodological: MILP-based constructive methods seeding a multi-neighbourhood local search, plus new hard benchmark instances for the community ([arXiv:1709.00252](https://arxiv.org/abs/1709.00252)). The formulation survives as a *part*, inside a heuristic that owns the integrality problem instead of relaxing it away. The optimizer's road, walked to its end, teaches one clean fact about Eternity II: the puzzle is exactly the integrality constraint. Everything linear about it, the flows, the balances, the assignment skeleton, is polynomial and was solved by 2009, to zero error, in ten seconds. What remains is the requirement that every piece be somewhere *whole*, once. The relaxation's cheerful fractional board is the sharpest picture anyone has drawn of what the easy 99% looks like without the hard 1%. ## Related - [The rigidity wall](https://eternity2.dev/research/why/rigidity-wall) — Every record board we have is frozen in place. You cannot nudge your way from a great board to a perfect one, and we can prove it. - [Dead ends](https://eternity2.dev/research/build/dead-ends) — Approaches we tried that look promising and don't move the needle on Eternity II, written down with what we found so you can spend your time elsewhere. - [SAT and CSP encodings](https://eternity2.dev/research/build/exact/sat-csp-encodings) — Write the puzzle as clauses and hand it to an industrial solver: the obvious move, tried since 2008. Why complete solvers stall on the full board, and where their verdicts still earn their keep as impossibility proofs. - [All-different, Régin's matching filter](https://eternity2.dev/research/build/reduce/alldiff-regin) — No piece may be used twice: one global all-different constraint over 256 cells. Jean-Charles Régin showed in 1994 how bipartite matching filters it completely in polynomial time; its per-colour cousin is the strongest propagator anyone has measured on edge matching, with one sharp caveat about mismatch-tolerant searches. --- # Meet in the middle > Enumerate two halves of a problem and join them on a shared interface, trading memory for an exponent cut in half. The classic Horowitz–Sahni trick, what it looks like on bands of the board, and what this project's BANDSAW experiment measured, including the one-sided method that beat it. - Canonical page (with interactive figures/demos): https://eternity2.dev/research/build/exact/meet-in-the-middle/ - Updated: 2026-07-02 - Topics: exact-methods - Source: Horowitz & Sahni 1974, "Computing Partitions with Applications to the Knapsack Problem" (JACM), the classic origin — https://doi.org/10.1145/321812.321823 - Source: Meet-in-the-middle attack (Wikipedia), the cryptanalytic branch of the same idea — https://en.wikipedia.org/wiki/Meet-in-the-middle_attack - Source: Bidirectional search (Wikipedia) — https://en.wikipedia.org/wiki/Bidirectional_search --- Meet in the middle is the oldest exponent-cutting trick in combinatorial search: instead of exploring one tree of depth $n$, explore two trees of depth $n/2$ and join their leaves on a shared interface. Ellis Horowitz and Sartaj Sahni introduced it in 1974 for the knapsack problem, turning $O(2^n)$ time into $O(2^{n/2})$ time, at the price of storing one half's $2^{n/2}$ results in a table keyed so the other half can look them up. The same idea resurfaces as the meet-in-the-middle attack in cryptanalysis (why double DES buys almost nothing over single) and as bidirectional search in pathfinding. The pattern is always the same: two cheap enumerations plus a join, instead of one impossible enumeration. ## What it looks like on the board Eternity II offers a natural cut: a horizontal seam. Take a band of rows to finish; split it into a top half and a bottom half. Enumerate every way to fill the top half, keyed by two things: the exact set of pieces it consumed, and the vector of edge colours it leaves dangling at the seam. Enumerate the bottom half symmetrically. Then join: any top and bottom whose seam colours agree and whose piece sets are disjoint form a complete filling, found without ever walking the full band's tree. The disjointness clause is the E2-specific pain, and it is not optional. In knapsack the two halves are independent by construction; here they draw on one shared pool of pieces, so tops must be grouped by their exact pool fingerprint and each group joined only against bottoms built from the complementary pieces. Skip that bookkeeping and the join happily produces phantom boards that use a piece twice. Getting exact complementary-pool accounting right was a hard-won correctness lesson of the project's experiment below. ## The trade The textbook trade is time for memory: the exponent halves, and one half's enumeration must be held in a hash table. On the board the interface state is a row of edge colours (16 cells wide on the full puzzle) plus the pool fingerprint, so the table's key space grows fast with band width, and memory, not time, is usually the first wall. The join itself is cheap (hashing); everything hinges on how many entries each side must store and on how often seam signatures actually coincide. ## Feel the square root Numbers pin down the trade in a way prose cannot. The lab below has two views. *The trade* puts the three bills side by side on a log scale as you grow the problem: one-sided time $2^n$, MITM time $2 \cdot 2^{n/2}$, MITM memory $2^{n/2}$ table entries. *The join* runs a complete micro-instance ($n = 10$, two halves of $2^5 = 32$ candidates each) through the store phase and the probe phase, so you can watch where the speed comes from and where the memory goes. > **[Figure]** Interactive: meet-in-the-middle memory cost — interactive: MitmCostLab. Rendered on the canonical page (link above); not shown in this markdown export. ## Step by step 1. **Drag $n$ in the trade view.** Every $+2$ on the slider *quadruples* the red one-sided bar but only *doubles* the two MITM bars. That factor-of-two difference in growth rate is the entire trick: the exponent is halved, so on a log scale the MITM bars climb at half the slope. 2. **Watch the memory bar arrive.** Around $n \approx 56$ the table (at an optimistic 16 bytes per entry) outgrows a 16 GiB machine, while the MITM *time* bar is still comfortable. Memory hits the wall first: the same order of events BANDSAW recorded, where real entries carry a pool fingerprint and a seam vector and are far fatter than 16 bytes. 3. **Switch to the join view.** The left half enumerates its 32 candidates and stores each one in a hash table keyed by its seam signature (one of 48). This is the phase that pays the memory bill: the counter under *table memory* is the bill arriving, entry by entry. 4. **The probe phase.** The right half's 32 candidates arrive one per tick, and each performs exactly one lookup. An empty bucket dismisses an entire family of combinations in one step; an occupied one yields a joined solution per stored partner, found without walking the full tree. 5. **Read the final tally.** $2 \cdot 32 = 64$ enumeration steps plus $32$ stored entries replace $2^{10} = 1{,}024$ full walks. On Eternity II the same arithmetic holds, with the caveat that a join only counts if the seam colours match *and* the piece pools are disjoint, which is what the grouping-by-fingerprint bookkeeping above is for. ## What it costs The classic Horowitz–Sahni accounting, for a problem of $n$ binary choices: $$ \underbrace{O(2^n)\ \text{time},\ O(n)\ \text{space}}_{\text{one-sided enumeration}} \quad\longrightarrow\quad \underbrace{O(2^{n/2})\ \text{time},\ O(2^{n/2})\ \text{space}}_{\text{meet in the middle}} $$ (plus a $\log$ factor if the halves are sorted rather than hashed). Note what is conserved: the *product* of time and space stays around $2^n$. Meet in the middle never destroys the exponential; it splits one unpayable bill into two smaller ones, and both must clear. The square root of the runtime is bought with an exponential memory bill, which is why the method wins exactly when $2^{n/2}$ entries still fit in RAM and loses the moment they don't. On Eternity II the clean $n$-choices model needs two corrections. First, the interface is not one number but a wide state (a seam vector of up to 16 edge colours plus the exact piece-pool fingerprint), so the table keys are big, entries are fat, and the memory wall arrives well before the textbook crossover. Second, the halves are coupled through the shared piece pool, so the join is not a free hash hit but a hash hit *filtered by complementary pools*. BANDSAW measured the consequence: within small mismatch budgets both sides stay enumerable and the method is exact, but each extra budget unit inflates both trees roughly twenty-fold per side, and near the horizon the project paid for millions of stored tops whose buckets no bottom ever probed successfully. ## What BANDSAW measured This project ran the idea to the end, rigorously, in the [BANDSAW experiment](/research/lab/experiments/raphael-anjou/meet-in-the-middle/bandsaw): exact best completion of a band, meet-in-the-middle join with exact pool accounting, iterative deepening on the mismatch budget, all validated on a 10×10 testbed against brute force. Three findings, measured on this project's engine and not independently replicated: - **It works, near perfection only.** Within small mismatch budgets the method is exact and affordable. But each unit of mismatch budget inflates the enumeration trees roughly twenty-fold *per side*, so the regime where exactness is payable dissolves within a handful of allowed defects. - **A one-sided method beat it.** Armed with the same exact lower-bound tables (min-plus suffix bounds computed column by column), a plain iterative-deepening branch-and-bound proved optimality in about 12 seconds on a rung where the bidirectional join did not finish. The MITM pays full enumeration of *both* halves even when a single optimum plus an exhaustion proof would do; near the decidability horizon its join almost never fired: millions of stored tops, zero matching bottoms, both bills paid for nothing. - **The durable outputs were the bounds.** What survived the experiment was not the join but the admissible lower-bound tables and the exact budget-certificates they enable, instruments now used elsewhere. The registered conclusion was blunt: no meet-in-the-middle deployment at full board size. ## Limits, and what is still open The general lesson matches the classic literature: meet in the middle wins when the interface is narrow, the halves are truly independent, and a solved/unsolved answer suffices. Eternity II strains all three: the seam carries a wide colour vector, the shared piece pool couples the halves, and the record game runs on partial credit, which re-inflates both trees. What remains genuinely untested here is the *heuristic* cousin: two beams growing from opposite edges of the board, cross-filtered by hashes of their seam colours, meeting at a middle row. That design was written down in this project but never run; whether bidirectional pruning helps a beam the way it fails an exact join is an open question, not a verdict. ## Related - [BANDSAW](https://eternity2.dev/research/lab/experiments/raphael-anjou/meet-in-the-middle/bandsaw) — Solve a band of rows exactly by meeting in the middle, to find the true best ending and to measure how far ahead an endgame can be decided. - [CLOISTER](https://eternity2.dev/research/lab/experiments/raphael-anjou/pipelines/cloister) — Fix a perfect border, then search the interior with the border's edges treated as hard constraints from the very first cell. - [Exact cover and dancing links](https://eternity2.dev/research/build/exact/exact-cover-dlx) — Eternity II states cleanly as an exact-cover problem, and Knuth's Algorithm X with dancing links is the classic machine for those. Where it genuinely shines (small boards, exhaustive counting) and the two reasons it does not crack the 16×16: an unshrunk search tree, and no partial credit. - [Dead ends](https://eternity2.dev/research/build/dead-ends) — Approaches we tried that look promising and don't move the needle on Eternity II, written down with what we found so you can spend your time elsewhere. --- # SAT and CSP encodings > Write the puzzle as clauses and hand it to an industrial solver: the obvious move, tried since 2008. Why complete solvers stall on the full board, and where their verdicts still earn their keep as impossibility proofs. - Canonical page (with interactive figures/demos): https://eternity2.dev/research/build/exact/sat-csp-encodings/ - Updated: 2026-07-02 - Topics: exact-methods - Source: Heule, Solving edge-matching problems with satisfiability solvers (2008) — https://www.cs.cmu.edu/~mheule/publications/eternity.pdf - Source: Ansótegui, Béjar, Fernàndez & Mateu, Edge Matching Puzzles as Hard SAT/CSP Benchmarks (CP 2008) — https://link.springer.com/chapter/10.1007/978-3-540-85958-1_39 - Source: Ansótegui, Béjar, Fernàndez & Mateu, On the hardness of solving edge matching puzzles as SAT or CSP problems (Constraints, Springer) — https://link.springer.com/article/10.1007/s10601-012-9128-9 - Source: Ansótegui, Béjar, Fernàndez & Mateu, How Hard is a Commercial Puzzle: the Eternity II Challenge (CCIA 2008) — https://repositori.udl.cat/bitstreams/0b6533fe-54e5-4070-85fe-80f7d35837d8/download --- Modern SAT solvers settle industrial problems with millions of variables, so the obvious move is to write Eternity II as clauses and let CDCL do the digging. People have been making exactly this move since 2008. The encodings are clean and the small sizes fall instantly; the full puzzle does not budge. Understanding why is a lesson in what conflict-driven search actually feeds on. ## The encoding The direct encoding introduces a variable $x_{c,p,r}$ for "piece $p$ sits at cell $c$ with rotation $r$", then three families of constraints: every cell holds exactly one placement, every piece is used at most once, and any two placements that disagree across a shared edge are mutually excluded. The same model reads naturally as a CSP: one variable per cell, placements as domain values, an *alldifferent* over pieces, and table constraints on adjacent cells. That formulation is the one the benchmark papers study alongside the clausal one. The direct clausal form blows up fast, because the pairwise edge-disagreement clauses multiply. Marijn Heule's [2008 paper](https://www.cs.cmu.edu/~mheule/publications/eternity.pdf) showed the standard remedy: introduce auxiliary variables for the colour shown on each internal seam, so a placement implies its four seam colours and disagreement is excluded once per seam rather than once per pair. With compact encodings, symmetry breaking, and solver tuning, Heule solved edge-matching instances well beyond what the naive encoding reached. Even so, community-built CNFs of the full 16×16 puzzle run to roughly a hundred thousand variables and hundreds of millions of clauses (as reported on the [community mailing list](https://groups.io/g/eternity2)). They load fine, and they remain utterly unsolved. ## Take the measure of it Numbers with fourteen digits stop meaning anything in prose, so measure them instead. The explorer below computes both encodings live from the derivation above. Slide the board size across the community's pure-SAT ceiling at 10×10 and up to the full 16×16, and watch the log-scale bars. Underneath it, a six-clause instance shows the other half of the story: the unit-propagation cascade that CDCL's clause learning feeds on, and that this puzzle starves. > **[Figure]** Interactive: SAT/CSP encoding size blowup — interactive: EncodingSizeLab. Rendered on the canonical page (link above); not shown in this markdown export. ## Step by step Derive the sizes once by hand; they stop being folklore. 1. **Placement variables.** $p = n^2$ pieces, $4$ rotations, $n^2$ cells: $x_{c,p,r}$ gives $n^2 \cdot p \cdot 4 = 4n^4$ variables. At $n = 16$ that is $262{,}144$ raw placements; pruning the impossible ones (border pieces only sit on the rim, corners only in corners) brings this down to the "roughly a hundred thousand variables" the community CNFs actually carry. 2. **Cell and piece constraints.** Every cell holds exactly one placement: one long clause plus, pairwise, $\binom{4n^2}{2}$ exclusions per cell. Every piece is used at most once: another $\binom{4n^2}{2}$ per piece. Pairwise at-most-one is quadratic; this is what compact encodings (sequential, commander) reduce to $O(4n^2)$ clauses each, at the price of auxiliary variables. 3. **The direct conflict clauses: the blow-up.** The board has $2n(n-1)$ internal seams. For each seam, every pair of placements that disagrees across it gets a binary clause: about $(4n^2)^2 (1 - 1/c)$ pairs per seam if colours were uniform. At $n = 16$, $c = 17$: $480 \times 1024^2 \times \tfrac{16}{17} \approx 4.7 \times 10^8$ clauses, the "hundreds of millions" reported for full-board CNFs, recovered from first principles. 4. **Heule's seam trick.** Name the colour of each seam: $2n(n-1) \cdot c$ auxiliary variables ($8{,}160$ at full size). Now each placement *implies* its four seam colours (at most $16n^4$ binary clauses) and disagreement is forbidden once per seam, not once per pair: $\binom{c}{2}$ clauses per seam, about $65{,}000$ total. The conflict machinery collapses by three orders of magnitude. That is exactly why Heule's instances reached sizes the naive encoding never touched, and why the ceiling still sits near 10×10 rather than 16×16: size was never the only problem. ## What it costs - **The solver, in the worst case: exponential.** SAT is NP-complete, and CDCL is a resolution-based procedure: on families with exponential resolution lower bounds, *no* run of it can be subexponential. Its industrial success is a statement about typical structure, not worst-case cost, and an instance built at the hardness peak is as far from typical as it gets. - **Unit propagation: cheap by design.** With two watched literals per clause, a clause is only examined when one of its two watches is falsified, and each visit costs $O(\text{clause length})$ to find a new watch. Propagation is why CDCL can afford millions of decisions per second even on enormous CNFs; loading Eternity II was never the issue. - **Conflict analysis: pay proportional to the implication graph.** Each conflict is analysed by walking the implication graph back to a cut (first-UIP), costing time linear in the graph traversed, and yields one learned clause whose pruning power depends on being *short*. That is the step this puzzle starves: flat implication chains make the walk trivial and the learned clause wide. Full price, no product. - **The CSP side has the same shape.** Enforcing [arc consistency](/research/build/reduce/arc-consistency) on the table constraints is polynomial per node, and Régin's GAC *alldifferent* filter runs a bipartite matching in $O(m\sqrt{n})$ per call (see the [alldifferent page](/research/build/reduce/alldiff-regin)). Polynomial propagation atop an exponential search tree: strong locally, helpless globally. - **Where the account balances.** On the full board, worst-case behaviour is the observed behaviour. On pinned subproblems, the same machinery returns UNSAT in under two seconds, an impossibility theorem per query at the price of a database lookup. The costs did not change; the question did. ## What the published benchmarks showed The systematic study is due to Ansótegui, Béjar, Fernàndez and Mateu, in a [CP 2008 paper](https://link.springer.com/chapter/10.1007/978-3-540-85958-1_39) and an extended [journal version in Constraints](https://link.springer.com/article/10.1007/s10601-012-9128-9), with a companion paper asking, verbatim, [how hard the commercial puzzle actually is](https://repositori.udl.cat/bitstreams/0b6533fe-54e5-4070-85fe-80f7d35837d8/download). Their headline: generalized edge-matching puzzles make excellent SAT/CSP benchmarks precisely because difficulty is tunable: vary the number of colours and solve time rises to a sharp peak where solutions are scarce but real. Eternity II's colour counts sit at that peak, by design; the [phase transition page](/research/why/phase-transition) walks through it. In practice, complete solvers dispatch small boards in seconds and then hit an exponential cliff; community experiments over the years put the practical ceiling for pure SAT on Eternity-style instances somewhere around the 10×10 scale, far short of 16×16. See the [papers page](/research/papers) for the full literature trail. ## Why CDCL stalls on the full board CDCL earns its power from clause learning: when propagation hits a conflict, the solver walks the implication graph back to a small set of decisions that caused it, and records that combination as forbidden. The learned clause is short and general when conflicts arise from long chains of unit propagation. Eternity II starves that mechanism. This project's analysis of its own CSP engine (hedged accordingly: measured here, not independently replicated) found the implication structure is nearly flat (a domain deletion traces back to a single neighbouring placement, not to a deep chain), so conflict analysis has almost nothing to compress, and the learned [no-goods](/research/build/reduce/nogood-learning) come out wide and specific instead of short and general. Worse, conflicts surface late: with strong propagation running, domain wipeouts essentially never occurred before depth 50, with the median deep in the board. A wide clause about a deep, specific configuration prunes almost nothing else. Add an instance deliberately tuned to the hardness peak, and the full puzzle is close to a worst case for conflict-driven search. ## Where the exact verdicts still pay None of this makes the encodings useless; it relocates them. A complete solver's UNSAT answer is a theorem, and on subproblems those theorems come cheap. This project's most productive use of SAT (same hedge as above) is as an *oracle on regions*: pin most of a strong board, free a neighbourhood of its remaining mismatches, and ask for a fully matched completion. The answer comes back UNSAT, typically in under two seconds, and proves that no local rearrangement of that region can ever finish the board, which is the machinery behind the [rigidity wall](/research/why/rigidity-wall). The same trick screens whole border rings: pin a candidate border, free all 191 interior cells, and a sub-second UNSAT certifies that border can never carry a perfect interior. And within a CSP search engine, the same idea in miniature (recording hard no-goods at propagation failures so a structural dead end is never re-entered) is sound by construction and cheap to check with SAT-style watched literals. That is the division of labour: as a frontal solver of the full puzzle, CDCL is outmatched; as a fast generator of impossibility certificates for pieces of it, nothing else comes close. ## Related - [MOSAIC](https://eternity2.dev/research/lab/experiments/raphael-anjou/pipelines/mosaic) — Tile the board into small blocks, solve each one to proven optimality, and glue them together, paying for the seams instead of forbidding them. From scratch, with no record to copy, it reaches 448. - [Papers](https://eternity2.dev/research/papers) — The academic literature on Eternity II and edge-matching puzzles, drawn from the project's research notes and the community reading list, and ranked by how useful each paper actually is if your goal is to write a solver. - [Tuned to the hardness peak](https://eternity2.dev/research/why/phase-transition) — Eternity II uses 22 colors. They split 17 interior to 5 frame-only, and that 17 is exactly where this kind of puzzle is hardest to solve. - [The rigidity wall](https://eternity2.dev/research/why/rigidity-wall) — Every record board we have is frozen in place. You cannot nudge your way from a great board to a perfect one, and we can prove it. --- # Go faster > Raw throughput: the craft below the algorithm (lookup tables, cache-sized structs, generated code) and spreading the work across many machines. It decides whether a node costs 26 cycles or 2,600, and it is the clearest demonstration that speed alone does not move the wall. - Canonical page (with interactive figures/demos): https://eternity2.dev/research/build/faster/ - Updated: 2026-07-13 --- Raw throughput: the craft below the algorithm (lookup tables, cache-sized structs, generated code) and spreading the work across many machines. It decides whether a node costs 26 cycles or 2,600, and it is the clearest demonstration that speed alone does not move the wall. The pages below go technique by technique: what each is in a line, what it actually reached on the real 16×16 board, where it stops, and the labs and measurements to back it. For the whole territory at once, start with [a map of every known approach](/research/build/approaches-map). Two entry points if you want the argument end to end. [Solver engineering](/research/build/faster/solver-engineering) is the community's twenty-year ledger - every craft technique, what it cost, what it bought - and it pins down the three different things people mean by "fast" so the numbers stop sliding around. For a worked first-party demonstration, the [JIT backtracker experiment](/research/lab/experiments/raphael-anjou/jit-backtracker) takes portable Rust rung by rung to the speed of the community's fastest hand-tuned C - a tie on hard, realistic boards - then shows why even that [does not move the wall](/research/lab/experiments/raphael-anjou/going-fast). ## Pages in this section - [Solver engineering: the craft below the algorithm](https://eternity2.dev/research/build/faster/solver-engineering) — Every record solver runs the same depth-first backtracker. What separates them is the layer underneath: lookup tables, perfect hashes, cache-sized structs, generated code, compiler archaeology. That craft decides whether a node costs 26 cycles or 2,600. The community's twenty-year engineering ledger, technique by technique, and what it all bought. - [Distributed solving: swarms, syndicates, and core farms](https://eternity2.dev/research/build/faster/distributed-solving) — Every few years the community threw more computers at Eternity II: BOINC screensavers, prize-sharing syndicates, PlayStation clusters, scavenged single-board farms. What 10^19 operations bought, how a depth-first search actually gets partitioned, and the one job distribution turned out to be good at. ## Related - [A map of every known approach](https://eternity2.dev/research/build/approaches-map) — The survey the community keeps asking for and never finds: every family of attack tried on Eternity II, what each one actually reached, where it walls out, and a link to the deep page. One organising insight runs through all of them. - [The techniques](https://eternity2.dev/research/build/techniques) — The technique shelf: the algorithms and pruning ideas that recur in every serious Eternity II solver, each with what it is, what it costs, and what it actually bought when measured on this puzzle. --- # Distributed solving: swarms, syndicates, and core farms > Every few years the community threw more computers at Eternity II: BOINC screensavers, prize-sharing syndicates, PlayStation clusters, scavenged single-board farms. What 10^19 operations bought, how a depth-first search actually gets partitioned, and the one job distribution turned out to be good at. - Canonical page (with interactive figures/demos): https://eternity2.dev/research/build/faster/distributed-solving/ - Updated: 2026-07-02 - Topics: speed, backtracking - Source: eternity2.net launches on BOINC, and the skeptics answer (groups.io message 756) — https://groups.io/g/eternity2/message/756 - Source: The shutdown accounting: 1.6 TFlops, over 10^19 operations, mid-460s (groups.io message 3511) — https://groups.io/g/eternity2/message/3511 - Source: The Eternity 2 Syndicate: prize shares proportional to placements (groups.io message 3021) — https://groups.io/g/eternity2/message/3021 - Source: Verhaard releases eii with 50-50 prize terms (groups.io message 5940) — https://groups.io/g/eternity2/message/5940 - Source: François Galea's cluster and PlayStation 3s (groups.io message 6918) — https://groups.io/g/eternity2/message/6918 - Source: The 10×10 top-row list: 4,318,956 rows to reserve (groups.io message 9164) — https://groups.io/g/eternity2/message/9164 - Source: McGavin's 400+-core row farm solves the 10×10 (groups.io message 9688) — https://groups.io/g/eternity2/message/9688 - Source: The 469: a few days on about two hundred cores (groups.io message 10045) — https://groups.io/g/eternity2/message/10045 - Source: Jef Bucas's wrapper_blackwood, a job server for parameter studies — https://github.com/jfbucas/wrapper_blackwood --- The idea arrived before the puzzle did. In May 2007, two months before Eternity II went on sale, the mailing list floated a SETI@home-style community effort, and Brendan Owen's reply was the first clear statement of the thesis the next fifteen years would keep confirming: piece sets exist that "will be impossible with the current back tracking algorithms", no matter how many machines you enlist ([groups.io message 222](https://groups.io/g/eternity2/message/222), [message 226](https://groups.io/g/eternity2/message/226)). The community went ahead and built the distributed projects anyway, more than once and in two distinct shapes. Both are worth understanding, because one of them turned out to be genuinely useful. The social history (the rise and fall of eternity2.net, the contest politics around it) lives in [the history pages](/research/community/hunt); this page is the systems view. ## Volunteer swarms The first shape is the crowd: strangers download a client, donate cycles, and split any prize by contract. **eternity2.net** was the flagship. Dave Clark, author of a distributed Eternity I solver, launched it on Berkeley's BOINC infrastructure the same month the puzzle shipped, July 2007 ([message 756](https://groups.io/g/eternity2/message/756)). Skeptics said at launch that without algorithmic advances even 100,000 machines had essentially no chance ([message 763](https://groups.io/g/eternity2/message/763)); the crowd came anyway. Within six weeks it had over 1,300 signed-in members; 160 of them were in the USA, where the puzzle had not yet been released ([message 2122](https://groups.io/g/eternity2/message/2122), [message 2132](https://groups.io/g/eternity2/message/2132)). The project submitted a 462-edge partial to Tomy, then a 463 ([message 2663](https://groups.io/g/eternity2/message/2663)), the number that served as the community's public ceiling for over a year. Five months after launch, Clark shut it down and published the accounting: over 1.6 TFlops of aggregate compute, over 10¹⁹ CPU operations, best scores "in the mid 460ish range", and his own verdict that a brute-force solution "was always clearly going to be impossible" ([message 3511](https://groups.io/g/eternity2/message/3511)). He open-sourced his research solver on the way out ([message 3716](https://groups.io/g/eternity2/message/3716)), and its file formats became the community's interchange standard. **The Eternity 2 Syndicate** added the legalese. Launched in October 2007 at eternity2syndicate.co.uk, members ran a fast backtracker on partitioned search space (the same architecture as eternity2.net) but with an explicit contract: prize money shared in proportion to placements contributed. Within a week it reported ~20 machines averaging 300 million placements per second; soon 40 members were running 50 solver instances, with members-only progress statistics ([message 3021](https://groups.io/g/eternity2/message/3021), [message 3078](https://groups.io/g/eternity2/message/3078), [message 3105](https://groups.io/g/eternity2/message/3105)). A French distributed-solving site ran in parallel; Clark welcomed the "competition" ([message 1254](https://groups.io/g/eternity2/message/1254)). In May 2008 came the micro-scale version: e2dude's "E2@home", one person claiming scores above 460 per week per PC and recruiting volunteers for a share of the $10,000 lesser prize ([message 5474](https://groups.io/g/eternity2/message/5474)). None of these swarms set a record. The one volunteer campaign that won money inverted the recipe: instead of a weak client on many machines, Louis Verhaard released the *strongest solver in existence*, eii, for anyone to run, with the prize split 50-50 between him and the best-scoring user ([message 5940](https://groups.io/g/eternity2/message/5940)). The community's machines found his 467 more than forty times ([message 6275](https://groups.io/g/eternity2/message/6275)), and it won the only prize Eternity II ever paid. [The eii page](/research/lab/experiments/louis-verhaard/eii) tells that story in full; the lesson for this page is blunt: the algorithm was the asset, and the crowd was just its multiplier. ## Owned fleets The second shape is quieter and outlived the first: one researcher, many machines they personally control, aimed at a *finite* target. **François Galea's cluster.** In 2009 Galea reported solving Brendan Owen's 10×9 benchmark exactly (93 days on a 7-node cluster of dual Pentium 4s) and having the 10×10 running for ~110 days on a cluster of three PlayStation 3s, still unsolved (istarinz had given up on the same 10×10 after a month on a quad-core Xeon) ([message 6918](https://groups.io/g/eternity2/message/6918)). This is the earliest clean example of the good use case: the 10×9 has a knowable, finite tree, so more cores buy a real completion date rather than a lottery ticket. **[Peter McGavin's scavenged farm](/research/lab/experiments/peter-mcgavin/backtracker).** McGavin built his fleet out of whatever was cheap: ~20 cores at home, three ODROID XU4s, twenty-five $12 Orange Pi Lites (130+ cores), then borrowed work servers for 400+ in total. That peak was intermittent, not sustained: the work was "spread over about 4 years and intermittently using up to about 400 cores at a time" ([message 9804](https://groups.io/g/eternity2/message/9804)), the borrowed servers only in the last month or so, and by his own note the server cores "are hyperthreads, strictly speaking" ([message 9753](https://groups.io/g/eternity2/message/9753)) while the ARM boards run at about a third of a PC core. In 2017 that farm solved Brendan's set_1 10×10, the community's decade-old communal benchmark: ~2×10¹⁷ nodes, about 180 core-years, under 0.5% of the full tree, "no new methods, just systematic persistence and the law of large numbers" ([message 9686](https://groups.io/g/eternity2/message/9686), [message 9688](https://groups.io/g/eternity2/message/9688)). Three years later he pointed "about a couple of hundred" cores at Joshua Blackwood's newly released solver for a few days and landed the 469, then the all-time record on the real puzzle ([message 10045](https://groups.io/g/eternity2/message/10045)). The cloud made cameo appearances: Amazon EC2 was suggested as early as 2010 ([message 8106](https://groups.io/g/eternity2/message/8106)), and David Barr tried his search program on AWS Lambda in 2016 ([message 9642](https://groups.io/g/eternity2/message/9642)). But rented fleets never displaced owned ones; the economics of a puzzle with no deadline favour hardware you can leave running for years. ## The census | Effort | Model | Scale | Outcome | Source | | --- | --- | --- | --- | --- | | eternity2.net (Dave Clark, 2007) | Volunteer swarm (BOINC) | 1,300+ members, 1.6 TFlops | 462–463 submitted; >10¹⁹ ops; shut down after 5 months | [756](https://groups.io/g/eternity2/message/756), [3511](https://groups.io/g/eternity2/message/3511) | | French distributed site (royale_zerezo, 2007) | Volunteer swarm | unknown | Faded without a result | [1253](https://groups.io/g/eternity2/message/1253) | | Eternity 2 Syndicate (Amos, 2007) | Volunteer swarm + prize contract | ~40 members, 50 instances, ~300M placements/s | No record; faded with the site | [3021](https://groups.io/g/eternity2/message/3021), [3078](https://groups.io/g/eternity2/message/3078), [3105](https://groups.io/g/eternity2/message/3105) | | E2@home (e2dude, 2008) | Micro-syndicate | A few volunteers | Claims above 460; no verified record | [5474](https://groups.io/g/eternity2/message/5474) | | eii release (Verhaard, 2008–09) | Published binary, 50-50 prize split | Community PCs | 467 found 40+ times; the only prize ever paid | [5940](https://groups.io/g/eternity2/message/5940), [6275](https://groups.io/g/eternity2/message/6275) | | Galea's cluster + PS3s (2009) | Owned fleet | 14 CPUs + 3 PlayStation 3s | 10x9 solved exactly in 93 days; 10x10 unsolved | [6918](https://groups.io/g/eternity2/message/6918) | | Top-row reservations (2013) | Mailing-list protocol | A handful of members | 4,318,956 rows listed; known solution verified; petered out | [9164](https://groups.io/g/eternity2/message/9164), [9177](https://groups.io/g/eternity2/message/9177) | | McGavin's row farm (2016–17) | Owned fleet (scavenged) | 400+ cores at peak, intermittent over ~4 years (many are hyperthreads) | Brendan's set_1 10×10 solved, ~180 core-years | [9688](https://groups.io/g/eternity2/message/9688), [9804](https://groups.io/g/eternity2/message/9804) | | McGavin on Blackwood's solver (2020) | Owned fleet | "about a couple of hundred" cores, a few days | 469/480, the record of its day | [10045](https://groups.io/g/eternity2/message/10045) | | wrapper_blackwood (Bucas, 2021–) | Job server + per-core clients | One worker per core | Parameter maps, not records | [repo](https://github.com/jfbucas/wrapper_blackwood) | ## How do you partition a depth-first search? Backtracking looks sequential, but it distributes embarrassingly well: fix a prefix of the search and every subtree below it is an independent job needing no communication at all. The community used three concrete recipes. **Prefix bands.** Slice the space of early placements into ranges and hand each range to a worker. This is what eternity2.net and the Syndicate did, the "partitioned search space" of [message 3021](https://groups.io/g/eternity2/message/3021), and it is the weakest form, because on the full puzzle every band is equally hopeless. **First-row lists.** Enumerate every legal completion of the first row, then treat each row as one job: a bounded backtrack over the remaining board. In 2013, at McGavin's suggestion, Martin (capiman) enumerated all 4,318,956 legal top rows of Brendan's 10×10 set 1 and posted the list ([message 9164](https://groups.io/g/eternity2/message/9164)). McGavin searched the row containing the known solution, row 1,407,888, to completion in 15,310 seconds, finding exactly that solution ([message 9167](https://groups.io/g/eternity2/message/9167)), and Michel Gaillard "reserved" entries 1000002–1000035 by posting to the list ([message 9177](https://groups.io/g/eternity2/message/9177)). That 2013 effort petered out; the 2017 one added the missing ingredient: *ranking*. McGavin scored ~20 million first-row permutations by their [complex-theory](/research/why/complex-theory) chance of solution per search-tree node and farmed the best rows first. The solution arrived at row-search ~92,907 against a predicted one-per-~70,000 ([message 9688](https://groups.io/g/eternity2/message/9688)). The ranking was the difference between a lottery and a schedule. Jobs are wildly uneven in value; a good static model of which slices are promising is worth more than any amount of extra hardware. **Parameter sweeps.** The modern variant distributes *configurations* instead of subtrees. Jef Bucas's [wrapper_blackwood](https://github.com/jfbucas/wrapper_blackwood) is a small Python server that hands out jobs over HTTP, where each job is a variation of [Blackwood's solver](/research/lab/experiments/joshua-blackwood/solver) parameters; clients (one worker per core) generate the C# source from templates with that variation baked in, compile it, run it, and report back. The output is not a record but a map: which colour triples and which quota schedules reach depth, aggregated across hundreds of runs. ## Coordination and trust The coordination machinery was strikingly informal. The 2013 reservation protocol was the honour system: you claimed a range of rows by posting a message ([message 9177](https://groups.io/g/eternity2/message/9177)), and it worked because the participants numbered in the single digits. Verification, by contrast, was taken seriously, and it was always the same method: independent re-computation. When McGavin verified row 1,407,888, apal1969 re-ran the same row on separate code and confirmed it with 6.77×10¹¹ nodes ([message 9168](https://groups.io/g/eternity2/message/9168)); when the 10×10 fell in 2017, Martin independently validated the solution ([message 9725](https://groups.io/g/eternity2/message/9725)); record boards were posted with full piece lists and checked in Jef Bucas's online viewer ([message 10045](https://groups.io/g/eternity2/message/10045)). Nothing entered the community's ledger on someone's word alone. The swarm era's real coordination problem was economic, and the contest made it worse: prize entries could be disqualified if published, so eternity2.net stopped publishing scores above 463: a distributed project that could not tell its own volunteers what they had found ([message 3511](https://groups.io/g/eternity2/message/3511)). The prize-splitting contracts (the Syndicate's placement-proportional shares, eii's 50-50, E2@home's share of the lesser prize) were attempts to stop volunteers from pocketing a find for themselves, and to keep them motivated, inside that forced secrecy. When the contest died, the problem evaporated: the modern efforts publish everything, and trust rides on reproducibility instead of contracts. ## What 10^19 operations bought Nothing, and the community knew why before it started. The group's own tree estimates, converging from independent implementations in 2008, put the full search at roughly 2.2×10⁴³ nodes per solution, on the order of 10²⁷ CPU-years ([message 5193](https://groups.io/g/eternity2/message/5193), [message 5197](https://groups.io/g/eternity2/message/5197)). Against that, eternity2.net's lifetime total of 10¹⁹ operations is about 10⁻²⁴ of one solution's worth of work: multiplying your fleet by a thousand, or a million, moves a number like that not at all. Owen said it two months before the puzzle shipped ([message 226](https://groups.io/g/eternity2/message/226)); Clark's shutdown letter conceded it in almost the same words ([message 3511](https://groups.io/g/eternity2/message/3511)). The deeper point is the one this wiki keeps returning to: hardware multiplies a search, while pruning *re-shapes* it. [Prune vs speed](/research/why/prune-vs-speed) makes the general argument, and [complex theory](/research/why/complex-theory) supplies the exact arithmetic of why the full-puzzle tree dwarfs any conceivable fleet. Every distributed effort on the full puzzle confirmed the counting argument; none dented it. ## What distribution is actually good for The efforts that worked share one property: the target was finite and the mathematics said so in advance. - **Exhaustive solving at the feasibility frontier.** Galea's 10×9 and McGavin's 10×10 are trees of ~10¹⁵–10¹⁷ nodes: monstrous for one machine, tractable for a fleet. Distribution converted "someday" into 93 days and 180 core-years respectively. - **Measurement.** McGavin's 10×10 doubled as the strongest validation [complex theory](/research/why/complex-theory) ever received: the solution arrived on the predicted schedule, and the published node histograms matched the model ([message 9688](https://groups.io/g/eternity2/message/9688)). A core farm is a fine instrument for measuring a theory. - **Parameter studies.** wrapper_blackwood is the modern template: when the question is "which of these thousand configurations searches deepest?", the jobs are verifiable, bounded, and independent, which is exactly what distribution wants. - **Records only downstream of an algorithm.** The 469 came from ~200 cores running a solver that was already, by itself, record-class ([message 10045](https://groups.io/g/eternity2/message/10045)). Cores multiplied Blackwood's algorithm; at no point in this archive did they substitute for one. > **The one-line summary** > > Fifteen years of collective compute, distilled: crowds without an algorithm bought nothing; fleets pointed at finite, well-modelled targets bought exactly what the model promised. The multiplier is real; it just multiplies whatever you already have. ## Related - [The hunt, a history (part I: 2000–2009)](https://eternity2.dev/research/community/hunt) — The community's story, from a mailing list founded seven years before the puzzle existed to the $10,000 scrutiny prize won under a borrowed name, with every event sourced to its original message. Part I of a growing chronicle. - [Verhaard's eii: the solver that won the only prize](https://eternity2.dev/research/lab/experiments/louis-verhaard/eii) — The engine behind the 467, the only Eternity II score ever paid, read from Louis Verhaard's own mailing-list posts: forward pruning, comb-search fill orders, depth-gated edge slipping, a Markov-tuned slip schedule. And why his own source-less Win32 binary cannot be built or run on this machine at all. - [McGavin's C backtracker: the throughput story, built here](https://eternity2.dev/research/lab/experiments/peter-mcgavin/backtracker) — Peter McGavin's own C backtracker, the community's fastest: a 2007 optimization recipe compounded for two decades through generated code, lookup tables and counter tricks, then built on my M1 and pointed at the real 256-piece puzzle, where single core it drives past 200 of 256 pieces at ~109M placements/s. --- # Solver engineering: the craft below the algorithm > Every record solver runs the same depth-first backtracker. What separates them is the layer underneath: lookup tables, perfect hashes, cache-sized structs, generated code, compiler archaeology. That craft decides whether a node costs 26 cycles or 2,600. The community's twenty-year engineering ledger, technique by technique, and what it all bought. - Canonical page (with interactive figures/demos): https://eternity2.dev/research/build/faster/solver-engineering/ - Updated: 2026-07-02 - Topics: speed - Source: The Lebel thread dissected: the era's reference C++ solver taken apart (groups.io message 1704, 2007) — https://groups.io/g/eternity2/message/1704 - Source: Nathan's 1024-key minimal perfect hash replacing a 1M-entry array (groups.io message 1831) — https://groups.io/g/eternity2/message/1831 - Source: Mike Field's optimization recipe: 'Brute force does not work' (groups.io message 3098) — https://groups.io/g/eternity2/message/3098 - Source: Field's cycle-level budget: 75M tiles/s, ~26 cycles, half stalled on memory (groups.io message 9003) — https://groups.io/g/eternity2/message/9003 - Source: BMI/BMI2 bit-extract instructions: 78 to 90M placements/s (groups.io message 9796) — https://groups.io/g/eternity2/message/9796 - Source: Blackwood's negative results: only the heuristics ever paid (groups.io message 10056) — https://groups.io/g/eternity2/message/10056 - Source: What a 'node' is: the counting-convention thread (groups.io message 3843, 2008) — https://groups.io/g/eternity2/message/3843 - Source: The pieces-per-second convention pinned down (groups.io message 9739, 2017) — https://groups.io/g/eternity2/message/9739 - Source: Modern single-core numbers: 72.7M/s C++, 68.4M/s Rust (groups.io message 11633, 2025) — https://groups.io/g/eternity2/message/11633 - Source: McGavin's compiler playbook: clang versions, native flags, PGO (groups.io message 11751, 2026) — https://groups.io/g/eternity2/message/11751 --- Strip any record solver to its skeleton and you find the same loop: place a piece, check the edges, back up when stuck. The algorithm was settled by 2007. What the community has actually been competing on for twenty years is the layer *below* the algorithm: the craft that decides whether visiting one node of that tree costs about 26 clock cycles, as Mike Field measured on his own engine ([message 9003](https://groups.io/g/eternity2/message/9003)), or a hundred times that in a naive interpreter. Same tree, same search, two orders of magnitude apart in placements per second. This page collects that craft, technique by technique, each with its primary source in the mailing-list archive. The chronology of how one engine compounded them for two decades is told on the [McGavin page](/research/lab/experiments/peter-mcgavin/backtracker); the anatomy of the engine behind the record boards is on the [Blackwood page](/research/lab/experiments/joshua-blackwood/solver). Here is the shelf they both draw from. ## Candidate lookup tables: the universal trick Every fast backtracker shares one load-bearing idea: never *search* for candidate pieces, look them up. Fix the [fill order](/research/build/backtracking/fill-order) (a row scan, usually), and each cell exposes exactly two known constraints when its turn comes, the colour on its north edge and the colour on its west edge. So you precompute a table keyed by that colour pair, and finding all pieces that could legally go in the current cell becomes a single memory access. Field's 2007 recipe put it first in the list, together with its corollary: a **fixed** search order is what makes the two-edge key possible at all, and placing a piece then only updates its south and east neighbours ([message 3098](https://groups.io/g/eternity2/message/3098)). The same design was being dissected the same year around Marc Lebel's public C++ solver, the era's reference fast backtracker, in the thread that doubles as the community's first engineering seminar ([message 1704](https://groups.io/g/eternity2/message/1704)). Everything else on this page is a refinement of that table: making it smaller, making its entries denser, or unrolling the code around it. ## Minimal perfect hashing: the table, shrunk to fit The lookup table has a size problem when you key on more than two edges. In the Lebel thread, Nathan described the brute-force version: a 4-D array indexed by all four edge colours, `combo4[32][32][32][32]`. A million entries, mostly zeros, guaranteed cache misses. His fix built on Bob Jenkins's minimal-perfect-hash generator, a pointer he had shared with the list himself. Since the 256 pieces in 4 rotations produce only 1,024 distinct edge-quadruples, a minimal perfect hash maps the packed 32-bit key to a 1,024-entry table with no collisions: "small enough to fit in cache most of the time", with near-zero hashing overhead, and absent keys simply read a count of zero ([message 1831](https://groups.io/g/eternity2/message/1831)). A million entries down to a thousand, purely so the working set lives in L1. He drew the boundary himself: the four-edge table only earns its keep when the fill order can leave holes; a strict scan-line solver never needs it. ## Bit-packing and struct sizing: cache as the real opponent Field's cycle budget explains why so much of this craft is about memory layout: at 75M tiles per second per core, over half the time was stalled on memory access, not computation ([message 9003](https://groups.io/g/eternity2/message/9003)). The response is to make every byte the search touches count. Pack a piece's four sides into a single int ([message 3098](https://groups.io/g/eternity2/message/3098)). Keep the used-piece set as one 64-bit word per group and early-out a whole candidate loop with a single mask test, an optimization Arnaud Carré and Adam Miles discovered they had implemented independently, line for line ([message 9808](https://groups.io/g/eternity2/message/9808), [message 9809](https://groups.io/g/eternity2/message/9809)). Size the candidate-table entry so the whole table fits in cache. That is exactly the design of Blackwood's six-byte `RotatedPiece` struct, already told on [the Blackwood page](/research/lab/experiments/joshua-blackwood/solver): piece number, rotation, the two exposed sides, a break count and a heuristic count, and nothing else. ## Bipieces and metatiles: precompose, and pay in memory If one lookup gives you candidate pieces, why not precompose pairs into 1×2 "bipieces" and place two cells per node? Measured on Lebel's code in August 2007, it worked: about 20–30% faster ([message 1734](https://groups.io/g/eternity2/message/1734)). But the trade is steep and the archive documents both sides. Going to 2×2 blocks, one member measured roughly 4.2× *slower* and rejected bigger pieces outright ([message 1730](https://groups.io/g/eternity2/message/1730)). No surprise once the tables are counted: about 4 million distinct inner 2×2 combinations ([message 3044](https://groups.io/g/eternity2/message/3044)). Louis Verhaard reported bipieces helping "only very marginally" in his own fast backtracker ([message 3061](https://groups.io/g/eternity2/message/3061)). And in 2008 the list settled the theory question underneath: a metatile solver visits essentially the same constraint frontier as a 1×1 solver ("in sync every 4 pieces"), so the gain is implementation-level, never a reduction of the search space ([message 5842](https://groups.io/g/eternity2/message/5842), [message 5899](https://groups.io/g/eternity2/message/5899)). Precomposition is a speedup you buy with memory, and past 1×2 the price goes negative. ## Code generation: write the program that writes the solver The inner loop's last indirections ("which cell am I on? what are its neighbours?") can be removed by not having a loop at all. Field's recipe: procedurally *generate* monolithic straight-line code, one block per cell, each block knowing its own neighbours as constants; his generated code compiled to about 33 instructions per cell ([message 3098](https://groups.io/g/eternity2/message/3098)). The idea spread fast: by mid-2008, istarinz was generating a non-recursive C solver per puzzle and per fill path, compiled with the Intel compiler ([message 5480](https://groups.io/g/eternity2/message/5480), [message 5438](https://groups.io/g/eternity2/message/5438)), in the same season the list compared notes on non-recursive backtrackers generally ([message 4683](https://groups.io/g/eternity2/message/4683)). Peter McGavin's `body.c` is this idea compounded for twenty years: labelled blocks like `cell_9_2_next:`, `goto` chains back into the previous cell on exhaustion, the whole file regenerated for every puzzle and hint set ([message 11337](https://groups.io/g/eternity2/message/11337), [message 11782](https://groups.io/g/eternity2/message/11782)). And it works across languages: Jef Bucas's libblackwood, a Python generator emitting C, made Blackwood's C# algorithm roughly twice as fast on the same machine ([message 10065](https://groups.io/g/eternity2/message/10065), [message 10078](https://groups.io/g/eternity2/message/10078)). ## Compiler realities: the last 20%, not the missing 10²⁰ Below the source code, there is still throughput to harvest, in instructions and flags rather than ideas. Adam Miles took his solver from 78 to 90 million placements per second with BMI's `bextr` and BMI2's `pext` bit-extract instructions, while noting it was "getting increasingly difficult" to reach further ([message 9796](https://groups.io/g/eternity2/message/9796)). McGavin's 2026 playbook is the accumulated folklore: try clang, icc and icx against gcc; try *versions* (clang-15 beats clang-19 on his ARM boards); add `-march=native` and `-mtune=native`; use profile-guided optimisation. None of these tips is a silver bullet ([message 11751](https://groups.io/g/eternity2/message/11751)). His counter trick from the same post is the genre in miniature: the 64-bit placement counter is fed by a 16-bit register that rolls over, adding `0x10000` at a time, because he timed both ways years ago on 32-bit hardware and the trick won. The same realism applies to hardware. Multithreading scales the obvious way: multi-core solvers broke 100M placements/s in 2008 ([message 5804](https://groups.io/g/eternity2/message/5804)), and a single Core i7 hit 558M/s that December ([message 6212](https://groups.io/g/eternity2/message/6212)). Single-core progress, though, mostly stopped. Posting his 2025 table of nine CPU/compiler combinations (38–84M placements/s), McGavin noted that speeds on the latest CPUs "are only a little faster" than on his 2010 Phenom II ([message 11643](https://groups.io/g/eternity2/message/11643)). The engines hit Field's memory wall fifteen years ago and have been leaning on it since. ## Measurement discipline: what is a "node", anyway? An engineering culture is only as good as its benchmarks, and the archive had to build that discipline the hard way. In January 2008, comparing speed claims forced the definitional question: Txibilis counted a node as every *valid* piece committed to the board, no lookahead ([message 3843](https://groups.io/g/eternity2/message/3843)); others counted attempted placements, or steps, and the thread concluded that a metric everyone agrees on may not exist ([message 3946](https://groups.io/g/eternity2/message/3946)). The question came back in 2017 and got the standard answer: the community's "pieces per second" counts pieces *placed* per second, chess-style ([message 9739](https://groups.io/g/eternity2/message/9739), [message 9740](https://groups.io/g/eternity2/message/9740)). The standard objection came with it: the metric flatters scan-line fill orders and says nothing about search-space coverage per unit time ([message 9746](https://groups.io/g/eternity2/message/9746)). Two practical consequences. First: never compare two solvers' M/s figures without checking what they count: a "faster" solver may simply have a more generous definition. Second, the positive habit that grew out of it: publish **node counts alongside timings**. A deterministic backtracker walking a fixed tree must count the same nodes on any machine, so exact node counts became the community's checksums, the way ports, rewrites and new hardware prove they search the same tree before their speed means anything. There is a third confusion worth naming once and for all, because it recurs whenever these numbers reach a wider audience. "Fast" points at three unrelated quantities, and no two of them convert: - **Placements per second** (equivalently pieces/s or nodes/s) - how fast the search *walks*, and it depends on the board as well as the engine. McGavin's C does ~287M on an easy board but ~105M on a hard one; a [portable-Rust engine on this site](/research/lab/experiments/raphael-anjou/jit-backtracker) reaches ~110M on the same hard board - a tie there - and ~122M on the easy one. - **Matched edges out of 480** - how *good* a board is. This is the axis the [records](/research/records) live on (the ceiling is 470). It is independent of walking speed: a slow engine routinely finds a better board than a fast one. - **Aggregate placements per second** - a *fleet* total, many machines summed. The "~300M/s" figure sometimes pinned on a single engine is in fact the [Eternity 2 Syndicate swarm](/research/build/faster/distributed-solving), roughly twenty machines added together, not one core. A high number on the first axis says nothing about the second, and the third is not an engine speed at all. When this site quotes a throughput, it is always placements/s on one core unless it says otherwise; where the *trade-off* between spending a solver's budget on speed versus on judgement is the point, that argument lives on [going fast](/research/lab/experiments/raphael-anjou/going-fast). ## The shelf at a glance | Technique | What it costs | What it bought | Source | | --- | --- | --- | --- | | Per-position candidate tables (two-edge key) | memory for tables; a fixed fill order | candidates in one memory access, the baseline every fast solver shares | [3098](https://groups.io/g/eternity2/message/3098) | | Minimal perfect hashing | offline hash construction | 1M-entry lookup → 1,024 entries, cache-resident | [1831](https://groups.io/g/eternity2/message/1831) | | Bit-packing, cache-sized structs | code contortions | fewer stalls where >50% of time is memory; 64-bit used-mask early-outs | [9003](https://groups.io/g/eternity2/message/9003), [9808](https://groups.io/g/eternity2/message/9808) | | Bipieces (1×2 precomposition) | tables grow fast; no search-space reduction | +20–30% at 1×2; ~4.2× *slower* at 2×2 | [1734](https://groups.io/g/eternity2/message/1734), [5899](https://groups.io/g/eternity2/message/5899) | | Code generation (per-cell straight-line code) | a build pipeline; regenerate per puzzle | ~33 instructions/cell (2007); ~2× from libblackwood's C (2020) | [3098](https://groups.io/g/eternity2/message/3098), [10065](https://groups.io/g/eternity2/message/10065) | | BMI/BMI2 bit-extract instructions | portability | 78 → 90M placements/s | [9796](https://groups.io/g/eternity2/message/9796) | | Compiler shopping, native flags, PGO | trial and error, per machine | "significant" but unquantified single-digit-percent-to-tens gains | [11751](https://groups.io/g/eternity2/message/11751) | | Counter tricks (16-bit rollover feed) | obscurity | measurable only on 32-bit-era hardware | [11751](https://groups.io/g/eternity2/message/11751) | ## Twenty years, ~1× to 4× per core Now zoom out. Field's 2007 recipe already did 60–80 million placements per second per core ([message 3098](https://groups.io/g/eternity2/message/3098)). Twenty years of craft since have widened that range rather than uniformly multiplied it. On comparable portable code the gain is modest: 72.7M/s from a tuned C++ solver and 68.4M/s from a Rust descendant of Blackwood's in 2025 ([message 11633](https://groups.io/g/eternity2/message/11633), [message 11634](https://groups.io/g/eternity2/message/11634)), barely above the 2007 baseline. The ~4× only appears with per-cell generated C on the newest hardware: around 225–295M/s for McGavin's ([message 11751](https://groups.io/g/eternity2/message/11751), [message 11750](https://groups.io/g/eternity2/message/11750)), so it mixes a codegen gain with a hardware gain, not craft alone. Over the same twenty years, the record moved three edges: 467 to 470. A [2026 experiment on this site](/research/lab/experiments/raphael-anjou/jit-backtracker) separates those two gains directly. It takes a *portable, safe Rust* backtracker and applies the same craft - per-cell generated code, packed cells, a byte-array used-set, cell fusion - then measures it against McGavin's C on one machine, same board, both built headless, back to back. Holding the hardware fixed, the portable engine **ties the C on hard, deep boards** (≈105–110M search-nodes/s each) while the C stays ~2.3× faster on easy low-branching ones (≈287M vs ≈125M) - every rung verified to walk the identical tree. The lesson cuts both ways: the codegen craft is real and reproducible in a modern language - enough to match hand-tuned C where the search is hard - *and* it is still only the constant factor this page keeps describing. The same engine, pointed at the real puzzle, plateaus in the high-300s of 480, exactly where speed alone always leaves you. The practitioners said it themselves. Joshua Blackwood, cataloguing his dead ends after the 469 ([SAT solvers](/research/build/exact/sat-csp-encodings), [GPUs](/research/build/hardware/gpu-solving), cached 2×2 blocks, all measured and dropped), found that only refining the *heuristics* ever paid, worth another ~2× ([message 10056](https://groups.io/g/eternity2/message/10056)). And when the 2025 speed thread wound down, Razvan wrote its epitaph: regardless of how fast we can check, "we will not make a dent" in the E2 search space ([message 11657](https://groups.io/g/eternity2/message/11657)). The craft on this page is real, measurable and worth learning; it is why a hobbyist farm can walk 10¹⁷ nodes. But a constant factor is a constant factor. [Why shrinking the tree beats speeding up the walk](/research/why/prune-vs-speed) is the arithmetic of that sentence; this page is its engineering ledger. ## Related - [McGavin's C backtracker: the throughput story, built here](https://eternity2.dev/research/lab/experiments/peter-mcgavin/backtracker) — Peter McGavin's own C backtracker, the community's fastest: a 2007 optimization recipe compounded for two decades through generated code, lookup tables and counter tricks, then built on my M1 and pointed at the real 256-piece puzzle, where single core it drives past 200 of 256 pieces at ~109M placements/s. - [Blackwood's solver, decoded and run here](https://eternity2.dev/research/lab/experiments/joshua-blackwood/solver) — Joshua Blackwood's record backtracker, decoded through Jef Bucas's notes (a colour quota schedule and a late-game mismatch allowance, tuned near-optimally), then built and run on my M1: left as published it flies to 248 of 256 pieces ignoring the clues; pin the five official clues and the same engine stalls near 45. - [Why a faster computer doesn't help](https://eternity2.dev/research/why/prune-vs-speed) — The single most important idea in hard combinatorial search: shrinking the space you search beats searching it faster, by an exponential margin. Eternity II is engineered so you can barely shrink it at all. --- # Board & puzzle formats, written down > Every format an Eternity II board or puzzle travels in on this site and in the community: the board_edges letter string and the hints clue list, e2pieces.txt, the puzzle CSV, the site's Puzzle JSON, and the viewer URL, with the exact byte-level rules (how the grey border is encoded in each) and, most of all, what each format can and cannot recover. - Canonical page (with interactive figures/demos): https://eternity2.dev/research/build/formats/ - Updated: 2026-07-16 - Source: The canonical IO layer that defines these formats (e2-io: the one board format, derived everywhere) — https://github.com/raphael-anjou/eternity2/tree/main/research/experiments/common/crates/e2-io --- A board is a simple thing, 256 tiles, each with four coloured edges, each placed at a cell and a rotation, but the community has written it down a dozen ways over nineteen years, and the ways never quite line up. A letter string, a digit string, a URL, a CSV, a JSON. They say the same thing in different alphabets, and the moment you move a board between two tools you hit the seam. This page is the seam, written down: every format a board or puzzle travels in here, with the byte-level rules, including the one detail that bites everyone, **how each format encodes the grey border**, and, for each, a plain note on what it can and cannot recover. If you only take one thing away: paste any board into the [format converter](/convert) and read the others straight back. > **One input, one output** > > The IO contract is symmetric and small. **In:** one puzzle instance as JSON (the site `Puzzle` schema, below); every algorithm is invoked with `--puzzle .json`. **Out:** one board document as JSON (the `BoardDoc`, below), carrying a ready-to-open [eternity2.dev](/viewer) URL as a field. That is the whole thing: puzzle-JSON in, board-JSON out, both single self-describing files. Everything else on this page is either an *input* the tools also accept (CSV, a bare `board_edges` blob, a bucas link) or a *derived* format the [converter](/convert) can hand you. There is no `.url`-here, `.json`-there, two-files-sometimes split. ## The vocabulary A **colour** is a small integer. `0` is the grey outer border; interior colours run `1..=22` for the official puzzle (22 is exactly how many motifs exist). An **edge quad** is a cell's four colours in **URDL** order (up, right, down, left), reading the tile *as placed and rotated*, not as a catalogue tile. A cell is either filled (a real quad) or empty; an empty cell is written as if it were all border, `[0, 0, 0, 0]`. One fact follows from "as placed", and it is the source of most format confusion: a board carries **rotated** edges, not a rotation number. But this is not a loss. Eternity II pieces are **all distinct up to rotation** (the official set is, and any faithful generator keeps it that way), so a cell's edge quad identifies exactly one piece, and the rotation is the turn that maps that piece's catalogue quad onto the placed one. Matching the quad against the piece set recovers **both** the identity and the rotation. So the edges are the whole board: they render it, score it, and name every piece and its orientation. The only case where they fall short is a contrived set with two pieces sharing an edge pattern up to rotation, which real Eternity II never has, and there a piece-number channel disambiguates. That is the one job `board_pieces` exists for. ## board_edges: the letter string The lingua franca. Four lowercase letters per cell, row by row, URDL, with `letter = 'a' + colour`. So the border is **`a`**, interior colour 1 is `b`, up to colour 22 = `w`. An empty cell is **`aaaa`**, indistinguishable from a real all-border tile, which never happens on a legal board, so the ambiguity is harmless. The official 16×16 board is `256 × 4 = 1024` letters. ```text adca beaa … cell 0 = [0,3,2,0], cell 1 = [1,4,0,0], … ``` - **Border:** the letter `a` (colour 0). - **Recovers:** everything about the board, the full rendering, the exact score, and, because pieces are distinct up to rotation, each piece's identity and its rotation by matching against the set. - **Cannot recover:** which cells were *given as clues* rather than solved, that is a property of the puzzle, not the board, and it travels in `hints`. A rare wrinkle: some tools permute which glyph each letter draws (`motifs_order`). The orders `marie` and `jblackwood` are identical to each other; `jef` is a different permutation. The converter and viewer translate these back to the default alphabet on the way in, so you never have to think about it, but if you see a board whose colours look scrambled, an untranslated `motifs_order` is why. ## hints: the clue cells A board and the clues it was built from belong in one place, addressed the same way. `hints` lists the pinned clue cells, each as `pos.rot`, the row-major cell index and clockwise quarter-turn, joined by `-`. Five official clues are about thirty characters. ```text hints=34.1-45.2-135.0-210.3-221.0 ``` The piece at each hinted cell is already known from `board_edges`, so a clue needs only its position and orientation, never a piece id. This is the same `(cell, rotation)` shape every durable format uses for a pinned tile: the CSV's `x,y,rotation`, the site JSON's `{pos, rot}`. - **Recovers:** which cells are clues, so the viewer can mark them and a solver can start from them. Absent means "no clues", a plain solved or partial board. - **Pairs with:** `board_edges`. Together they carry a full *puzzle-with-clues* in one link, which a bare board never could. ## board_pieces: the interop channel Some community tools, notably e2.bucas.name links, carry an explicit piece channel: three decimal digits per cell, the **1-based** piece number, `000` for an empty cell (the official board is `256 × 3 = 768` digits). We **read** it when it is present, but never need to emit it, because `board_edges` already names every piece on a distinct-piece set. ```text 001 005 007 … piece 1 at cell 0, piece 5 at cell 1, … ``` - **Border / empty:** `000`. - **Recovers:** piece identity directly (and rotation, matched against the set), the same thing the edges recover on their own for a real board. - **On its own:** useless without the edges; it is an overlay, not a board. Its one irreplaceable use is a contrived set with pieces that repeat up to rotation, where the edges alone are ambiguous. ## e2pieces.txt: the pieces as placed The oldest interchange format, written down by the community in 2007 (see the [toolbox census](/research/build/tooling)). One line per **filled** cell, in reading order, four whitespace-separated edge integers in URDL order. ```text 0 3 2 0 1 4 0 0 … ``` - **Border:** the integer `0`. - **Recovers:** rendering and score, same as `board_edges`; it is the same data in decimal. It lists the pieces **as placed and rotated**, so it is *not* a canonical rotation-0 catalogue, and a board alone cannot turn it back into one. ## Puzzle CSV: what the standalone engines read The format McGavin's C and Blackwood's C# consume, and the shape the benchmark's `variant_NN.csv` files are written in. A size header, then one row per piece: `top,right,bottom,left` followed optionally by `x,y,rotation` for a pinned hint. ```text 16 1111111111111111,0000000000000001,0000000000000010,1111111111111111,0,0,0 … ``` Each colour is a **16-bit zero-padded binary word**. And here is the detail that trips everyone, and the reason this page exists: > **The border is all ones in the CSV** > > In the puzzle CSV, the grey border is **`1111111111111111`**, all ones, the 16-bit word `65535`, *not* all zeros. Interior colours are their small integer in binary, so colour 1 is `0000000000000001`. A reader maps the `65535` word back to interior id `0`. This is the opposite of every other format on this page, where the border is the *low* value (`a`, `0`, `000`). It is a legacy sentinel choice, kept for byte-compatibility with the engines that read it. - **Border:** the all-ones word `1111111111111111` (65535). - **Recovers:** the full puzzle, pieces and hints. This is a *puzzle* format (the tile set), not just a placed board. ## Site JSON (`Puzzle`): the canonical input The one format every algorithm is fed: `--puzzle variant_NN.json`. The site's engine, the DFS/repair studies and the single-core benchmark all read the *same* schema (byte-compatible with the web's `Puzzle` type), so every experiment runs the same instances. It carries the piece set at rotation 0 and the pinned hints explicitly, which is what makes it an input a solver can start from, rather than a board it has already filled. ```json { "name": "e2_official_variant00_pin3corners", "width": 16, "height": 16, "numColors": 22, "pieces": [[0,1,2,0], [0,0,3,1], …], "hints": [{ "pos": 34, "piece": 118, "rot": 2 }, …] } ``` - **Border:** colour `0`, as an integer in the `pieces` quads. - **Recovers:** everything about the *instance*: canonical rotation-0 tiles, colour count, and every pinned clue with its exact rotation. This is the one format that carries rotation and catalogue order by construction, because it describes the puzzle, not a placement on it. ## The canonical board JSON (`BoardDoc`): the one output What every solver on this site now writes: one self-describing `.json` per board. It folds the board, its score, its content hash, both letter strings, and the viewer URL into a single document, so a downstream tool needs nothing else. ```json { "name": "…", "size": 16, "score": 466, "breaks": 14, "board": [3, 16, 24, …], "board_hash": 2059303548241384230, "board_edges": "abda…", "board_pieces": "001005…", "url": "https://eternity2.dev/viewer?puzzle=…&puzzle_size=16&board_edges=…" } ``` `board` is the row-major **`piece*4 + rot`** placement vector (`-1` for an empty cell), the same encoding the site's `Puzzle` round-trips through. `breaks` is `max_score − score` (the unmatched interior edges; on a full board, the break count). `board_hash` is an FNV-1a hash of the placement grid, the bit-identical gate for "did these two runs produce the same board". - **Border:** as in `board_edges` (`a`) and `board_pieces` (`000`); the `board` vector uses `-1` for empty. - **Recovers:** everything a board can: rendering, score, identity and rotation (via `board_pieces` and `board`), plus provenance (`name`, `board_hash`) and a one-click view (`url`). ## The viewer URLs Two URLs, same board, two hosts. **eternity2.dev, the canonical link.** The format every algorithm here emits. The board rides entirely in `board_edges`; any pinned clues ride in `hints`. Square boards, so a single `puzzle_size` (the viewer also reads bucas's `board_w`/`board_h`), and every value stays in the URL-safe range so the link needs no percent-encoding: ```text https://eternity2.dev/viewer?puzzle=NAME&puzzle_size=16&board_edges=…&hints=135.0-210.1 ``` `hints` is omitted for a board with no clues. Because the edges carry piece identity, there is no piece channel here: the board and its clues fit in these two fields. **e2.bucas.name, the community viewer.** Jef Bucas's original, the viewer whose URL format *became* this whole vocabulary (the [toolbox](/research/build/tooling) tells that story). Fully supported as an input, and available as a derived output using its `board_w`/`board_h` pair and a `#` fragment. We emit it edges-only (bucas recovers the pieces from the edges for a distinct set), though bucas links from other tools often also carry a `board_pieces` channel, which we read on input: ```text https://e2.bucas.name/#puzzle=NAME&board_w=16&board_h=16&board_edges=… ``` The [viewer](/viewer) reads either transparently; the [converter](/convert) hands you both. The eternity2.dev form is canonical here only because it opens *this* site's viewer, with its scoring, clue overlay and piece-set verification; the bucas form remains the community's shared original, credited accordingly. ## Moving between them
| Format | Border | Carries rotation? | Carries identity? | It is a… | | --- | --- | --- | --- | --- | | `board_edges` | `a` | yes (by match) | yes (by match) | placed board | | `hints` | n/a | yes (`pos.rot`) | via edges | clue set | | `board_pieces` | `000` | with edges | yes | overlay | | `e2pieces.txt` | `0` | yes (by match) | yes (by match) | placed board | | Puzzle CSV | `1111…1` (all ones) | hints only | yes (tiles) | puzzle | | Site JSON | `0` | yes | yes | puzzle | | `BoardDoc` JSON | `a` / `000` / `-1` | yes | yes | placed board | | eternity2.dev URL | `a` | yes (by match) | yes (by match) | link to a board | | bucas URL | `a` | with pieces | with pieces | link to a board |
Every conversion in that table is one paste away in the [format converter](/convert): drop in a URL, a bare `board_edges` string, or a params blob, and read back the eternity2.dev URL, the canonical JSON, the CSV, `board_pieces`, `e2pieces.txt`, and the bucas URL, with a live preview and the score, so you can see the file is right before you trust it. ## Related - [The community's toolbox, 2007–2026](https://eternity2.dev/research/build/tooling) — Nineteen years of community software for Eternity II (manual-placement GUIs, editors, public solvers, generators and viewers), plus the quieter layer that made them interoperate: e2pieces.txt, CRC-16 checksums, and the board-in-a-URL format that became the lingua franca. A reference census, with every tool sourced to the message that announced it. - [The community's benchmarks](https://eternity2.dev/research/build/benchmarks) — How a community forbidden from sharing the pieces built a shared test culture anyway: derived-count verification protocols, the Txibilis and beginner suites, node-count duels, full enumerations, and the one benchmark that is still standing open today. - [The dataset](https://eternity2.dev/research/build/dataset) — A public, CC0 dataset for Eternity II in two parts: fourteen benchmark instances to solve, and a corpus of 7,658 distinct strong boards to learn from. Every score is recomputed from the board itself, and the corpus is checked to be genuinely diverse rather than a thousand copies of one board. --- # GPU & hardware > Throwing silicon at the wall: GPU ports, FPGA pipelines, distributed sweeps, and the perennial quantum proposal. This is the ledger of what each one actually delivered, and why the wall it meets is memory and structure, not arithmetic. - Canonical page (with interactive figures/demos): https://eternity2.dev/research/build/hardware/ - Updated: 2026-07-13 --- Throwing silicon at the wall: GPU ports, FPGA pipelines, distributed sweeps, and the perennial quantum proposal. This is the ledger of what each one actually delivered, and why the wall it meets is memory and structure, not arithmetic. The pages below go technique by technique: what each is in a line, what it actually reached on the real 16×16 board, where it stops, and the labs and measurements to back it. For the whole territory at once, start with [a map of every known approach](/research/build/approaches-map). ## Pages in this section - [GPU solving: the wall is memory, not arithmetic](https://eternity2.dev/research/build/hardware/gpu-solving) — Eternity II looks like the perfect GPU workload: millions of independent subtrees, embarrassingly parallel. Eighteen years of community attempts measured a different reality: divergent branching, per-thread state that outgrows fast memory, and a placement loop that was already memory-bound on CPUs. What the GPUs actually delivered, and the one workload where they genuinely shine. - [FPGA solving: mapped but never driven](https://eternity2.dev/research/build/hardware/fpga-solving) — If the placement loop is memory-latency-bound, an FPGA looks like the exact answer: put the lookup tables in on-chip block RAM one cycle away, and pipeline dozens of tiny backtrackers on one die. The community mapped this road in detail. Michael Field designed the solver, projected 5 billion placements per second per chip, and ran a prototype on real silicon. Then the road was never driven to the end. The complete record, and why. - [Quantum approaches: two speedups at their true price](https://eternity2.dev/research/build/hardware/quantum) — The quantum computer is the list's oldest deus ex machina, invoked in the puzzle's first month and every few years since. There are exactly two real stories to tell: Grover's quadratic speedup, and annealing on a QUBO encoding. This page tells both properly, does the arithmetic against Eternity II's actual numbers, and reports the complete community record: nineteen years of asides, one unfinished embedding attempt, zero runs. ## Related - [A map of every known approach](https://eternity2.dev/research/build/approaches-map) — The survey the community keeps asking for and never finds: every family of attack tried on Eternity II, what each one actually reached, where it walls out, and a link to the deep page. One organising insight runs through all of them. - [The techniques](https://eternity2.dev/research/build/techniques) — The technique shelf: the algorithms and pruning ideas that recur in every serious Eternity II solver, each with what it is, what it costs, and what it actually bought when measured on this puzzle. --- # FPGA solving: mapped but never driven > If the placement loop is memory-latency-bound, an FPGA looks like the exact answer: put the lookup tables in on-chip block RAM one cycle away, and pipeline dozens of tiny backtrackers on one die. The community mapped this road in detail. Michael Field designed the solver, projected 5 billion placements per second per chip, and ran a prototype on real silicon. Then the road was never driven to the end. The complete record, and why. - Canonical page (with interactive figures/demos): https://eternity2.dev/research/build/hardware/fpga-solving/ - Updated: 2026-07-02 - Topics: speed, hardware - Source: The first FPGA proposal: exact cover in hardware (groups.io message 2623, 2007) — https://groups.io/g/eternity2/message/2623 - Source: Bob Cousins's Eternity-I Altera plan and the comms bottleneck (groups.io message 3259, 2007) — https://groups.io/g/eternity2/message/3259 - Source: Mike Pringle's edge-swap VHDL: the first HDL actually written (groups.io message 5493, 2008) — https://groups.io/g/eternity2/message/5493 - Source: 'E2 in hardware...', the 2010 feasibility exchange (groups.io message 8063) — https://groups.io/g/eternity2/message/8063 - Source: Field's memory analysis: 'these problems also carry over to FPGAs' (groups.io message 9003, 2011) — https://groups.io/g/eternity2/message/9003 - Source: The 2014 design: uniform 15×15 restriction, ~4 KB tables, 5G placements/s/chip projected (groups.io message 9226) — https://groups.io/g/eternity2/message/9226 - Source: The lookup tables, bit by bit (groups.io message 9228, 2014) — https://groups.io/g/eternity2/message/9228 - Source: The hyper-pipelined redesign after the memory-bandwidth bug (groups.io message 9232, 2014) — https://groups.io/g/eternity2/message/9232 - Source: First run on real silicon: one thread, one LED (groups.io message 9236, 2014) — https://groups.io/g/eternity2/message/9236 - Source: The symmetry bug fixed; hardware walks the full benchmark tree (groups.io message 9237, 2014) — https://groups.io/g/eternity2/message/9237 - Source: Field's own retrospective: 'a fun deadend' (groups.io message 10649, 2022) — https://groups.io/g/eternity2/message/10649 - Source: The one academic FPGA attempt, ReConFig 2011 (ieeexplore 6044826; discussed in message 10651) — https://ieeexplore.ieee.org/document/6044826 --- The [GPU page](/research/build/hardware/gpu-solving) ends at a wall: an Eternity II backtracker is not compute-bound, it is a chain of tiny dependent memory lookups, and Mike Field's 2011 analysis showed both GPU branches (cooperate or work alone) ending at the external memory bus ([message 9003](https://groups.io/g/eternity2/message/9003)). An FPGA is the one piece of silicon that seems to answer that exact complaint. There is no cache hierarchy to miss: the lookup tables live in on-chip block RAM, one clock cycle away, in dozens of independent little memories that can all be read *in the same cycle*. The bit-shifts and masks that cost instructions on a CPU come free as wiring. And instead of one big fast core you lay down many small slow ones, each a complete backtracker with its own tables. The community saw this road early and mapped it thoroughly. One member designed the solver, published the datapath, projected five billion placements per second per chip, and ran a prototype on real hardware. Then, and this page exists to say it plainly, nobody ever drove the road to the end. No full-Eternity-II FPGA run was ever reported, in nineteen years of archive. The interesting part is that the reasons are on the record too, in the designer's own words. ## Why FPGAs answer the exact wall GPUs hit Recall the fork from Field's analysis (told in full on the [GPU page](/research/build/hardware/gpu-solving)): parallel searchers either share information, needing synchronization bandwidth the fabric doesn't have, or work independently, needing per-worker state that outgrows the ~8 KB of fast memory a GPU lane gets, spilling everything to one shared external bus. His 2011 post applied the same argument to FPGAs in the same breath: "either need to store too much information, pass too much information around or it choke[s] on memory bandwidth" ([message 9003](https://groups.io/g/eternity2/message/9003)). But the FPGA version of the argument has an escape hatch the GPU version doesn't. On a GPU the fast-memory budget per worker is fixed by the vendor. On an FPGA *you* draw the memory map: if you can shrink one backtracker's entire world (candidate tables, board state, used-piece set) small enough, you can instantiate it entirely in block RAM, replicate it fifty times, and no worker ever touches external memory at all. The bandwidth wall isn't climbed; it's deleted. The whole FPGA story of this archive is the pursuit of that "if": making the solver's state small and *uniform* enough to become hardware. It took one member six years of background thought to get there, and the answer required changing the problem. ## The sketches: 2007–2012 FPGAs enter the archive within weeks of the puzzle itself. In August 2007 psykowally, swearing off yet another software brute-forcer, mused about doing it "in FPGA or something" while guessing it would only "take off a few factors" ([message 2022](https://groups.io/g/eternity2/message/2022)), a guess the next seven years would keep confirming. In September, Dieter Gehrke asked whether anyone had considered exact cover in hardware, pointing at an academic FPGA implementation ([message 2623](https://groups.io/g/eternity2/message/2623)). Nobody had. The November 2007 poll thread ("purpose built electronics" got exactly one vote, its lone voter noted) produced the first real engineering talk. Bob Cousins had already bought an Altera evaluation kit *for Eternity I*, planned an FPGA accelerator for a software backtracker, and abandoned it: even at 10 million positions per second in hardware, the bottleneck was communication with the PC ([message 3259](https://groups.io/g/eternity2/message/3259)). Glen Dudley put his finger on why backtracking wastes silicon: place 200 pieces, backtrack five, and 195 cells' worth of dedicated hardware sit idle that cycle ([message 3260](https://groups.io/g/eternity2/message/3260)). Another member announced he'd "just started" a VHDL design and sought collaborators ([message 3266](https://groups.io/g/eternity2/message/3266)), and was never heard from on the subject again. A third ran the sobering numbers: trading a PC core's clock for FPGA parallelism costs 10–1000x up front, and you'd be "better off... just using multiple computers" ([message 3268](https://groups.io/g/eternity2/message/3268)). SAT-in-hardware got the same triage in 2008: millions of clause terms won't fit the largest FPGA's logic ([message 4723](https://groups.io/g/eternity2/message/4723)). One person actually wrote HDL. In May 2008 Mike Pringle described an edge-swapping local searcher whose fitness function (count the valid, unique pieces the current edge assignment implies) was designed to *swap and score in a single clock*. "I have the VHDL done for this but I ran out of FPGA resources on the evaluation board I have for anything over 8×8" ([message 5493](https://groups.io/g/eternity2/message/5493)). First HDL in the record, first resource wall in the record, same message. Then came the protagonist. In October 2010 Michael Field, the engineer whose 26-cycles-per-placement budget anchors the [solver-engineering page](/research/build/faster/solver-engineering), opened a thread titled "E2 in hardware...", having started playing with Digilent FPGA boards. His first sober estimate: a hardware backtracker would run "roughly as fast as a PC's cpu core"; the real prize would be massively parallel constraint checking, arc consistency evaluated at every step ([message 8063](https://groups.io/g/eternity2/message/8063)). Martin (capiman)'s cost/benefit reply held up: one hardware backtracker merely matches one of the four cores already in your PC, so only the parallel-logic uses are interesting, and the ~2,816 bits of board state a full arc-consistency fabric needs might not fit the biggest FPGA on the market ([message 8064](https://groups.io/g/eternity2/message/8064)). Field sketched a 256-cell fabric with 18 pattern bits per side and a piece-request bus, and signed off with the sentence that could caption this whole page: "no matter what it won't be a silver bullet" ([message 8065](https://groups.io/g/eternity2/message/8065)). By 2012 he had concluded FPGAs were "next to useless for implementing an E2 back-tracker": the feedback loop between board and bag is too tight, so "the clock speed of a CPU wins", and wondered instead about using the fabric to generate rotation sets for a CPU to check ([message 9069](https://groups.io/g/eternity2/message/9069)). ## Field's 2014 design: buy uniformity, pay in generality On 7 February 2014, Field posted "Solving Eternity II in FPGA hardware": the problem had "been sitting in my subconscious, slowly chewing over it for about 6 years. Last night I had a bit of an eureka moment" ([message 9226](https://groups.io/g/eternity2/message/9226)). His old record-class software solver couldn't become hardware for two reasons he named precisely: it needed a ~6 MB lookup table (17x17x17x17x15 32-bit entries) with truly random access, and the place-check-backtrack loop has almost no fine-grained parallelism. The eureka was to *relax the problem* until the datapath became uniform: - **Backtrack only the top-left 15×15** (never the right column or bottom row), and use no hint pieces. - Fill top-left to bottom-right, so **every** cell's candidate lookup is indexed the same way: by its top and left edge colours. No corner cases, no per-cell tables, one identical circuit, everywhere. That uniformity collapsed the memory problem. The whole lookup structure fit in about **4,096 bytes of ROM** plus ~1 KB of state per solver ([message 9226](https://groups.io/g/eternity2/message/9226)): a 1024-entry, 18-bit-wide tile table (tile number, right pattern, bottom pattern, sorted by top/left patterns) plus a 324-entry index giving each colour-pair's start and count ([message 9228](https://groups.io/g/eternity2/message/9228)). In hardware, he noted, the shifts and masks are free wiring, the two tables sit in different BRAMs so both lookups happen in parallel, and block RAM's same-cycle read-write gives an atomic test-and-set on the used-piece bit: the inner loop's entire memory traffic, one cycle away. Compare that 4 KB against the [GPU page's](/research/build/hardware/gpu-solving) fatal ">8 KB per thread": this is what deleting the bandwidth wall looks like. The projection: about **50 solver instances on a Zynq 7020 at ~200 MHz**, each place/unplace averaging ~2 cycles, "up to 5 billion tile placements per second per chip" ([message 9226](https://groups.io/g/eternity2/message/9226)). For scale, the era's best CPU cores did 70–115 million. ## What actually ran The next month is the best-documented hardware bring-up in the archive, and every step is worth recording because each one traded away a little of the projection. - **Feb 20.** Simulation places its first tiles; synthesis says >109 MHz on a Spartan-6 LX9 using ~10% of its logic; near 50M placements/s per instance early in a puzzle, degrading as more pieces are in use and cycles are spent skipping them ([message 9231](https://groups.io/g/eternity2/message/9231)). - **Feb 25.** The first casualty on the record: the design "didn't pan out, I had memory bandwidth issues during a 'tile lift'" (unplacing needs two writes at once, and a BRAM port is a BRAM port). The fix is elegant: a four-stage **hyper-pipeline**, four independent backtrackers time-sharing one datapath so each stage's memory access happens in its own cycle. Timing: 132.363 MHz; per-core cost 96 registers and 334 LUTs; an estimated 10 cores on the small LX9 or 50 on an LX45, "around 5,000M 'actions' per second" ([message 9232](https://groups.io/g/eternity2/message/9232)). - **Mar 1: real silicon.** Arnaud Carré had supplied a 16×16, 29-colour benchmark his tuned CPU solver walks completely in 34.75 s at 114.5M recursions/s on one i7-3770K core ([message 9234](https://groups.io/g/eternity2/message/9234)). Field loaded it into actual hardware at 200 MHz, output limited, for now, to a single LED that lights while any thread runs. The LED went out after 1 min 21 s; his back-of-envelope put each thread at roughly a third of an i7 thread, and a four-core, sixteen-thread build on his USB-powered board at ~800M checks/s. He published the design on his site ([message 9236](https://groups.io/g/eternity2/message/9236)). Two days later he found the flaw in that comparison and revised the figure down to 1/8; the corrected number is below. - **Mar 3: the symmetry bug.** Comparing counts with Arnaud revealed Field's fixed top-left tile was doing a quarter of the benchmark's work. Corrected, one hardware thread walks the entire tree in 199 seconds, "about an 1/8th of the speed of Arnaud's i7 solver running on one core", but 24 threads fit on a sub-$100 board, and an 8-stage pipeline should allow 48. The hardware found and printed all four solutions, timestamps and boards in the post ([message 9237](https://groups.io/g/eternity2/message/9237)). And that is where the record stops. The 8-stage pipeline, the 48 threads, the Zynq port, the full-puzzle run: none of them ever appears in the archive. mulisak asked how to get started and Field answered with toolchain links and his own free FPGA book ([message 9245](https://groups.io/g/eternity2/message/9245)); on April 1 mulisak proposed "e2coin", a cryptocurrency whose proof-of-work would be edge-matching, arguing E2 is "CPU friendly - GPU unfriendly - but... FPGA friendly" ([message 9260](https://groups.io/g/eternity2/message/9260)); the thread drifted into CPU benchmarks, and the hardware went quiet. ## Why nothing shipped **Nothing shipped, and the designer said why.** In January 2022, Jef Bucas asked whether anyone had access to an IEEE paper on FPGAs and Eternity II, and Field's reply is the retrospective this page is built on: "The E2 problem is correctly sized to make an FPGA solver hard :)". Because of the tight feedback between board and bag he "couldn't get faster than a single core on a low-end PC (~75M tiles per sec)", and the lookup-table memory "is high enough that you quickly exhaust on-chip RAM if you are trying multiple instances. It was a fun deadend for me" ([message 10649](https://groups.io/g/eternity2/message/10649)). Read that against the projection: the 5G/s figure assumed fifty instances, and the very BRAM that made one instance fast is what capped how many instances fit. The prototype's own synthesis reports had foreshadowed it: one benchmark-sized core already claimed 23 of the LX9's 64 RAM blocks ([message 9236](https://groups.io/g/eternity2/message/9236)). **The economics never closed either.** The one member who tried both worlds, valy, remembered Field's board fondly ("he was crunching 15 Mn/s on an FPGA platform. Perf/W maybe unbeatable", [message 9588](https://groups.io/g/eternity2/message/9588)), and then described the cost: FPGA work is "soooo slow to compile... code... debug... You need to be an expert or have plenty of spare time and motivation. I've tried once, that was my hardest programming experience" ([message 9590](https://groups.io/g/eternity2/message/9590)). Months of HDL bring-up bought what the [solver-engineering ledger](/research/build/faster/solver-engineering) gets from a compiler flag. That asymmetry, not any single technical wall, is why every FPGA thread in the archive ends in silence: a 2021 member's promised "FPGA custom engine in 2022" ([message 10581](https://groups.io/g/eternity2/message/10581)) is the last of the line, and it too never resurfaced. **The one completed attempt was academic, and it underperformed software.** The paper Bucas asked for, "Exploitation of Parallel Search Space Evaluation with FPGAs in Combinatorial Problems: The Eternity II Case" (ReConFig 2011, [ieeexplore 6044826](https://ieeexplore.ieee.org/document/6044826)), is the only finished, published FPGA Eternity II system anywhere in the record. Its bottom line, as the list read it: "After three months, the best available solution contained 187/196 center pieces" ([message 10651](https://groups.io/g/eternity2/message/10651)), far below what contemporary software heuristics produced. Bucas's verdict was the community's: "a bit disappointed by the results in term of speed... I would expect more from a 'dedicated' HW" ([message 10655](https://groups.io/g/eternity2/message/10655)). ## The record, at a glance | Who | When | What happened | Msg | | --- | --- | --- | --- | | psykowally | 2007 | First FPGA mention; guesses "a few factors" of speedup | [2022](https://groups.io/g/eternity2/message/2022) | | Dieter Gehrke | 2007 | Proposes exact cover in FPGA hardware; no taker | [2623](https://groups.io/g/eternity2/message/2623) | | Bob Cousins | 2007 | E1-era Altera accelerator plan, abandoned on PC-comms bottleneck; hybrid idea | [3259](https://groups.io/g/eternity2/message/3259) | | jp_yahoo | 2007 | Starts a VHDL design, seeks collaborators; never heard again | [3266](https://groups.io/g/eternity2/message/3266) | | Mike Pringle | 2008 | Edge-swap local search, VHDL written; out of resources beyond 8x8 | [5493](https://groups.io/g/eternity2/message/5493) | | Field & Martin | 2010 | Feasibility exchange: one hardware backtracker merely matches a CPU core | [8063](https://groups.io/g/eternity2/message/8063), [8064](https://groups.io/g/eternity2/message/8064) | | Mike Field | 2011–12 | Memory analysis "carries over to FPGAs"; verdict "next to useless" for backtracking | [9003](https://groups.io/g/eternity2/message/9003), [9069](https://groups.io/g/eternity2/message/9069) | | Mike Field | 2014 | The design: uniform 15x15, 4 KB tables, 50 instances @ 200 MHz, 5G/s/chip projected | [9226](https://groups.io/g/eternity2/message/9226), [9228](https://groups.io/g/eternity2/message/9228) | | Mike Field | 2014 | Built and measured: hyper-pipelined prototype walks a 16×16 benchmark on silicon; 1 thread ≈ 1/8 i7 core (his own correction of an initial 1/3) | [9237](https://groups.io/g/eternity2/message/9237) | | mulisak | 2014 | e2coin: E2 as FPGA-friendly proof-of-work; posted April 1, no uptake | [9260](https://groups.io/g/eternity2/message/9260) | | academic team | 2011 | Only completed FPGA system; 3 months → 187/196 centre pieces | [10651](https://groups.io/g/eternity2/message/10651) | | Brahim Hamadicharef | 2021 | Announces "FPGA custom engine in 2022"; never mentioned again | [10581](https://groups.io/g/eternity2/message/10581) | | Mike Field | 2022 | The retrospective: "a fun deadend", BRAM exhaustion caps instances | [10649](https://groups.io/g/eternity2/message/10649) | ## The arithmetic that still bites Grant the projection everything it asked for. Say the 50-core, 200 MHz chip had shipped at its full **5×10⁹ placements/s**, and say you filled a rack with two thousand of them: **10¹³ placements per second**, more than the whole community's combined fleet has ever fielded. A year is ~3×10⁷ seconds, so the rack walks ~3×10²⁰ nodes a year. The full puzzle's search tree is, at its plateau, on the order of **10⁴⁵ partial boards wide** ([complex theory](/research/why/complex-theory) does this measurement properly). The division: about **10²⁴ rack-years**. Every order of magnitude the hardware gains moves that exponent by one, and twenty-four of them are missing. This is the same sentence the GPU page ends on, because it is the same mathematics: hardware is a constant divisor, and E2's wall is exponential. [Why a faster computer doesn't help](/research/why/prune-vs-speed) does the general argument; the FPGA chapter is simply its cleanest case study, because here even the *projected* numbers (never mind the measured ones) concede the point before the division starts. ## What an FPGA attempt would target today The map is still on the table, and parts of it have aged well. Field's own 2022 caveat cuts the other way now: "cheaper FPGAs are now much larger" ([message 10649](https://groups.io/g/eternity2/message/10649)): a modern mid-range part carries megabytes of block RAM where his Spartan-6 had kilobytes, so the instance-count ceiling that killed the 2014 projection has genuinely lifted. But the target list that survives scrutiny is the same one the [GPU page](/research/build/hardware/gpu-solving) arrives at: - **Not search.** A record attempt needs heuristics, restarts, and the freedom to change fill order mid-campaign, everything Field traded away to make the datapath uniform. The 15×15 relaxation that made the hardware possible is exactly what a record hunter can't accept. - **Enumeration and verification.** Fixed-shape exhaustive sweeps (census re-verification, row and block counting, bounded sub-puzzles) are uniform by construction: the property Field had to buy, these workloads get free. His prototype already demonstrated the essential act, walking a complete 16×16 benchmark tree on silicon and finding exactly its four solutions ([message 9237](https://groups.io/g/eternity2/message/9237)). - **Placements per watt.** The niche nobody disputed: valy's "perf/W maybe unbeatable" ([message 9588](https://groups.io/g/eternity2/message/9588)) still stands for anyone running a years-long background census where the electricity bill, not the placement rate, is the budget. The road, in other words, leads somewhere, just not to 480. It was mapped by someone who knew both the software and the silicon better than anyone else on the list, driven one exit down, and carefully signposted on the way back: a fun dead end, correctly sized to be one. ## Related - [GPU solving: the wall is memory, not arithmetic](https://eternity2.dev/research/build/hardware/gpu-solving) — Eternity II looks like the perfect GPU workload: millions of independent subtrees, embarrassingly parallel. Eighteen years of community attempts measured a different reality: divergent branching, per-thread state that outgrows fast memory, and a placement loop that was already memory-bound on CPUs. What the GPUs actually delivered, and the one workload where they genuinely shine. - [Solver engineering: the craft below the algorithm](https://eternity2.dev/research/build/faster/solver-engineering) — Every record solver runs the same depth-first backtracker. What separates them is the layer underneath: lookup tables, perfect hashes, cache-sized structs, generated code, compiler archaeology. That craft decides whether a node costs 26 cycles or 2,600. The community's twenty-year engineering ledger, technique by technique, and what it all bought. - [Why a faster computer doesn't help](https://eternity2.dev/research/why/prune-vs-speed) — The single most important idea in hard combinatorial search: shrinking the space you search beats searching it faster, by an exponential margin. Eternity II is engineered so you can barely shrink it at all. --- # GPU solving: the wall is memory, not arithmetic > Eternity II looks like the perfect GPU workload: millions of independent subtrees, embarrassingly parallel. Eighteen years of community attempts measured a different reality: divergent branching, per-thread state that outgrows fast memory, and a placement loop that was already memory-bound on CPUs. What the GPUs actually delivered, and the one workload where they genuinely shine. - Canonical page (with interactive figures/demos): https://eternity2.dev/research/build/hardware/gpu-solving/ - Updated: 2026-07-02 - Topics: speed, hardware - Source: The first GPU-solver proposal: 'maybe 4 or 5 times' (groups.io message 351, 2007) — https://groups.io/g/eternity2/message/351 - Source: The CUDA question and a GLSL CSP solver in progress (groups.io message 5407, 2008) — https://groups.io/g/eternity2/message/5407 - Source: 'Does anyone use OpenCL for E2?', the first OpenCL discussion (groups.io message 7653, 2010) — https://groups.io/g/eternity2/message/7653 - Source: Mike Field's memory-bandwidth analysis, the definitive negative argument (groups.io message 9003, 2011) — https://groups.io/g/eternity2/message/9003 - Source: David Barr's working OpenCL solver (groups.io message 9360, 2015) — https://groups.io/g/eternity2/message/9360 - Source: Barr's solver open-sourced (github.com/david3x3x3/eternity2) — https://github.com/david3x3x3/eternity2 - Source: Adam Miles's DirectX 12 compute solver on an Xbox One X (groups.io message 9811, 2018) — https://groups.io/g/eternity2/message/9811 - Source: The payoff: 9×9 set 1 exhaustively re-verified in 25h24m (groups.io message 9822, 2018) — https://groups.io/g/eternity2/message/9822 - Source: Miles on the real parallelism problem: keeping every processor busy (groups.io message 9984, 2020) — https://groups.io/g/eternity2/message/9984 - Source: Blackwood's ledger: GPU measured during the record campaign, not kept (groups.io message 10056, 2020) — https://groups.io/g/eternity2/message/10056 - Source: Barr's rented RTX 4090: 3.17B placements/s on a 10×10, memory-limited on the full puzzle (groups.io message 11598, 2025) — https://groups.io/g/eternity2/message/11598 --- On paper, Eternity II is the perfect GPU problem. Fix the first two rows of the board and you get millions of completely independent subtrees; nothing one subtree learns matters to any other. "Embarrassingly parallel" is the textbook term, and a modern GPU offers tens of thousands of parallel lanes and teraflops of arithmetic to embarrass. The community saw this immediately (the first GPU-solver proposal dates from June 2007, weeks before the puzzle even shipped) and kept seeing it for eighteen years, in a thread literally titled "Graphic cards as CPU's?" that resurfaced in 2010, 2011 and 2019. The measured answer, across every real implementation, is that the teraflops are not the resource that matters. An Eternity II backtracker spends its life doing tiny table lookups and branching on the results: a workload that was *already* stalled on memory access on CPUs, and that GPUs make worse in two specific, well-understood ways. This page traces the argument through the people who ran it: the [dead-ends ledger](/research/build/dead-ends) carries the one-paragraph verdict; here is the why. ## Why it looks perfect The idea arrived before the hardware did. In June 2007, Simon Chapple floated brute-force solving on Nvidia's 8800 cards, and a member posting as James guessed a GPU might make a solver "maybe 4 or 5 times" faster ([message 351](https://groups.io/g/eternity2/message/351), [message 355](https://groups.io/g/eternity2/message/355)). That guess would turn out closer to the truth than the teraflop ratios suggested. (The same year, the list's first "GPU" thread was actually about a *Gnutella* Processing Unit, which is [distributed computing](/research/build/faster/distributed-solving), not graphics ([message 3020](https://groups.io/g/eternity2/message/3020)).) In May 2008 came the CUDA question (has anyone tried running backtrackers on 96–128 GPU cores?), answered by a member who was "nearly done" with a GLSL-based CSP solver and preferred GLSL for its lower hardware requirements ([message 5407](https://groups.io/g/eternity2/message/5407), [message 5409](https://groups.io/g/eternity2/message/5409)). That solver was never heard from again. In 2010 Thomas asked the first OpenCL question in the archive's most quotable form: he now owned hardware capable of more than 10¹² operations per second, "but unfortunately I miss a suitable program which can use it" ([message 7653](https://groups.io/g/eternity2/message/7653)). That sentence is the whole subject in miniature. The operations per second were real. The suitable program was the hard part, and the reasons it stayed hard were diagnosed precisely, one year later. ## Field's analysis: the fork with no good branch In November 2011, in the same recurring thread, Mike Field, whose own engine's cycle-level budget anchors the [solver-engineering page](/research/build/faster/solver-engineering), posted the archive's definitive negative analysis ([message 9003](https://groups.io/g/eternity2/message/9003), typo fix in [message 9004](https://groups.io/g/eternity2/message/9004)). His starting point was a measurement, not an opinion: his backtracker placed 75 million tiles per second per core on a 2 GHz AMD (about 26 clock cycles per tile), and the raw instruction count came to roughly half that, so **over 50% of the time the code was stalled on memory access**. The inner loop of an Eternity II solver is not arithmetic. It is a chain of dependent little loads: candidate table, piece data, board state, branch. From there, Field laid out a fork. Map the search onto a GPU and each stream processor either cooperates with its neighbours or works alone: - **If they cooperate**, they need to share information constantly, and the synchronization bandwidth that requires is exactly what GPUs don't provide. There is no "honking great crossbar" between stream processors; the fabric was built for pixels that don't talk to each other. - **If they work alone** (say, 1,024 independent backtrackers), then each needs its own problem definition and search state: the tile tables, the board, the code to process them. That bundle is small by CPU standards and still **too big for the ~8 KB of fast local memory each stream processor gets**. The state spills to the GPU's external memory, and every solver on the die now queues for the same memory bus. Either branch ends at the same wall: external memory bandwidth. And Field added the twist that makes the wall unusually stubborn for this puzzle: almost every variable an E2 solver touches fits in 16 bits, so what the search needs is more memory *transactions* at higher clocks, not wider buses: "a 128 bit memory bus will be little quicker than a 16 bit one." Widening the firehose doesn't help when you're sipping through straws. His conclusion covered [FPGAs](/research/build/hardware/fpga-solving) with the same argument, and he couldn't see any of it gaining an order of magnitude over a CPU core. His practical advice: "get a Dual Socket Hex core AMD... and get very very lucky" ([message 9003](https://groups.io/g/eternity2/message/9003)). Nothing measured since has overturned this. It is the anchor the rest of the page hangs from. ## The second wall: divergence, or the idle army Field's argument is about where the bytes live. The other wall is about how GPUs execute: lanes run in lockstep groups, and a group moves at the speed of whichever lane has work left. Backtracking is the most divergent control flow imaginable. Two searches that start from adjacent prefixes are in completely different board states within a few placements, one backtracking at depth 40 while its neighbour advances at depth 55. Adam Miles, a graphics engineer who had actually built the fastest GPU solver in the archive (below), stated the problem from experience: the hard part is "keeping every processor doing something useful on every clock cycle" (some threads simply run out of candidate tiles and wait), and since nobody has an algorithm provably better than brute force, "time spent communicating is time not spent calculating" ([message 9984](https://groups.io/g/eternity2/message/9984)). David Barr hit the same wall at scheduling granularity in 2025: divide the search among workers and some subtrees take far longer than others, so a run ends with "a dwindling number of active workers" holding the whole GPU while thousands of lanes idle ([message 11598](https://groups.io/g/eternity2/message/11598)). The embarrassingly parallel subtrees are real; they are just embarrassingly *unequal*. ## What got built anyway The community did not stop at analysis; it built the solvers and published the numbers, which is why this page can report both directions with measurements. **David Barr's OpenCL solver (2015).** The first working, published GPU solver: PyOpenCL, running on a Radeon HD 7870. It fully searched one row of Martin's 10×10 first-row list (the row containing the known solution) in 3 h 46 m, with the work divided 1,620 ways ([message 9360](https://groups.io/g/eternity2/message/9360), [message 9364](https://groups.io/g/eternity2/message/9364)); his CPU baseline was 120M placements/s across all 8 cores of an FX-8120 ([message 9366](https://groups.io/g/eternity2/message/9366)). He published the source at [github.com/david3x3x3/eternity2](https://github.com/david3x3x3/eternity2) ([message 9367](https://groups.io/g/eternity2/message/9367)), one of the few open-source E2 solvers of its era. **Adam Miles's DirectX 12 solver (2018).** Having shelved a nearly finished AVX2 solver as not worth the effort ([message 9811](https://groups.io/g/eternity2/message/9811)), Miles wrote DX12 compute shaders and ran them on an Xbox One X, a 6-teraflop part. His kernel design is a case study in working *with* the two walls rather than pretending they aren't there: a breadth-first "pre-solve" enumerates every partial solution for the first 14–18 tiles on the GPU itself (3.3 million two-row prefixes for the 7×7; 155.8 million 16-tile prefixes for the 9×9), each packed into 20 bytes (a 96-bit used-piece mask plus twelve 5-bit edge colours) before a massively parallel sweep finishes each prefix ([message 9814](https://groups.io/g/eternity2/message/9814), [message 9819](https://groups.io/g/eternity2/message/9819)). Uniform state, tiny state, no cross-talk. Brendan's 7×7 set 1 fell from 74 to 25 to 14 seconds against a 529-second optimised CPU baseline; the 8×8 took 248 seconds. Barr's OpenCL solver on a GTX 1060 ran the same 7×7 in 73 seconds, and the two traded kernel notes mapping exactly why the teraflops disappoint ([message 9818](https://groups.io/g/eternity2/message/9818)). Miles rewrote the solver again in 2020 on high-end hardware he couldn't yet name ([message 9994](https://groups.io/g/eternity2/message/9994), [message 9998](https://groups.io/g/eternity2/message/9998)). **Joshua Blackwood (2020).** The author of the record boards measured a GPU port during the campaign that produced the 468–470 family, alongside SAT solvers and cached 2×2 blocks ("I measured everything that I did"), and kept none of them. Only refined heuristics ever paid, worth about another 2x ([message 10056](https://groups.io/g/eternity2/message/10056)). The full catalogue of what he dropped is on the [dead-ends page](/research/build/dead-ends). **David Barr again (2025).** The modern data point: his Python/OpenCL depth-first searcher on a rented RTX 4090 (vast.ai, $0.25–0.34/hour) searches about **3.17 billion placements per second** on Brendan's 10×10; in his own words, though, the current code "doesn't work well with the full Eternity puzzle due to memory limitations" ([message 11598](https://groups.io/g/eternity2/message/11598)). Fourteen years after Field's post, the best GPU number in the archive still comes with Field's caveat attached. ## The attempts, at a glance | Who | Hardware | What happened | Msg | | --- | --- | --- | --- | | Simon Chapple & James (2007) | Nvidia 8800 (proposal) | First GPU proposal; "maybe 4 or 5 times" faster estimated; never built | [351](https://groups.io/g/eternity2/message/351), [355](https://groups.io/g/eternity2/message/355) | | knucklefinger (2008) | GLSL shaders | "Nearly done" with a GLSL CSP solver; no results ever posted | [5407](https://groups.io/g/eternity2/message/5407), [5409](https://groups.io/g/eternity2/message/5409) | | Thomas / trans.spam (2010) | unspecified, >10¹² op/s | First OpenCL question; experiments started, none reported back | [7653](https://groups.io/g/eternity2/message/7653), [7656](https://groups.io/g/eternity2/message/7656) | | valy / 21valy (2011) | 80-SP card, then Radeon 5770 | Toy 4x4 sub-puzzle ported to OpenCL: 4 s in single-core C vs 60 s on the GPU; code shared | [8982](https://groups.io/g/eternity2/message/8982), [8994](https://groups.io/g/eternity2/message/8994) | | Mike Field (2011) | (analysis) | The negative argument: cooperation needs bandwidth GPUs lack; independence needs >8 KB state per thread; no order of magnitude available | [9003](https://groups.io/g/eternity2/message/9003), [9004](https://groups.io/g/eternity2/message/9004) | | David Barr (2015) | Radeon HD 7870, PyOpenCL | First working published GPU solver; a 10x10 first-row fully searched in 3 h 46 m; open-sourced | [9360](https://groups.io/g/eternity2/message/9360), [9367](https://groups.io/g/eternity2/message/9367) | | Adam Miles (2018) | Xbox One X, DX12 compute | 7x7 set 1 in 14 s (CPU: 529 s); 9x9 set 1 exhaustively re-verified in 25 h 24 m, exactly the 2 known solutions | [9811](https://groups.io/g/eternity2/message/9811), [9822](https://groups.io/g/eternity2/message/9822) | | David Barr (2018) | GTX 1060, OpenCL | 7x7 set 1 in 73 s; kernel-design notes exchanged with Miles | [9818](https://groups.io/g/eternity2/message/9818) | | Adam Miles (2020) | unannounced high-end GPU | Rewrite with "quite a bit more speed"; explicit that the full 16×16 stays out of reach | [9994](https://groups.io/g/eternity2/message/9994), [9996](https://groups.io/g/eternity2/message/9996), [9998](https://groups.io/g/eternity2/message/9998) | | Joshua Blackwood (2020) | unspecified GPU | Measured during the 468–470 record campaign; not kept, only heuristics paid | [10056](https://groups.io/g/eternity2/message/10056) | | David Barr (2025) | rented RTX 4090 (vast.ai) | ~3.17B placements/s on Brendan's 10x10 at ~$0.30/h; full E2 fails on memory limits | [11598](https://groups.io/g/eternity2/message/11598) | ## What the numbers actually say Put Barr's 3.17 billion placements per second next to the community's CPU figures, roughly 70–90M/s for a tuned single core and 225–295M/s for [McGavin's](/research/lab/experiments/peter-mcgavin/backtracker) generated C on the newest hardware (the full ledger is on the [solver-engineering page](/research/build/faster/solver-engineering)), and the best GPU result equals somewhere between ten and forty CPU cores. That is a real, useful constant. It is also *only* a constant, bought on a small puzzle where the per-thread state stays tiny, and it degrades toward Field's analysis exactly when the board grows to the real 256 pieces. James's 2007 guess of "4 or 5 times" was off; the teraflop ratio, a thousandfold, was off by far more, and in the other direction. A constant factor has a precise meaning here: [why a faster computer doesn't help](/research/why/prune-vs-speed) does the arithmetic, and the [dead-ends page](/research/build/dead-ends) records the verdict: the same algorithm, faster, hits the same wall a little sooner. ## Where GPUs actually shine here Now the other half of the ledger. On February 25, 2018, Miles's Xbox One X finished walking the **entire** search tree of Brendan's 9×9 set 1 in 25 hours and 24 minutes, finding exactly 2 solutions, at 22% and 32% of the search, after which the machine spent seventeen more hours proving there were no others ([message 9822](https://groups.io/g/eternity2/message/9822)). That independently confirmed McGavin's 2014 census with a different algorithm, a different language, and radically different silicon. It is one of the strongest verification results in the archive. Notice what made it work. Exhaustive enumeration of a fixed-shape tree is uniform: every lane runs the same shallow loop over prefixes of the same size, the state fits Miles's 20-byte packing, nobody needs to talk, and nobody cares that some lanes finish early because the goal is the whole tree, not a lucky branch. Every property that breaks GPU *search* is absent from GPU *verification*. So the closing advice writes itself, and it is neither hope nor despair. A GPU will not find the solution: three record-era practitioners measured that independently, and the argument for why has held since 2011. But if your workload is re-verifying a census, enumerating rows or blocks, or sweeping a bounded sub-puzzle exhaustively (fixed shape, small state, uniform work), a rented 4090 at thirty cents an hour is the cheapest measured compute this problem has ever had. Aim the GPU at what it is: not a deeper searcher, but a very fast counter. ## Related - [Dead ends](https://eternity2.dev/research/build/dead-ends) — Approaches we tried that look promising and don't move the needle on Eternity II, written down with what we found so you can spend your time elsewhere. - [Solver engineering: the craft below the algorithm](https://eternity2.dev/research/build/faster/solver-engineering) — Every record solver runs the same depth-first backtracker. What separates them is the layer underneath: lookup tables, perfect hashes, cache-sized structs, generated code, compiler archaeology. That craft decides whether a node costs 26 cycles or 2,600. The community's twenty-year engineering ledger, technique by technique, and what it all bought. - [McGavin's C backtracker: the throughput story, built here](https://eternity2.dev/research/lab/experiments/peter-mcgavin/backtracker) — Peter McGavin's own C backtracker, the community's fastest: a 2007 optimization recipe compounded for two decades through generated code, lookup tables and counter tricks, then built on my M1 and pointed at the real 256-piece puzzle, where single core it drives past 200 of 256 pieces at ~109M placements/s. --- # Quantum approaches: two speedups at their true price > The quantum computer is the list's oldest deus ex machina, invoked in the puzzle's first month and every few years since. There are exactly two real stories to tell: Grover's quadratic speedup, and annealing on a QUBO encoding. This page tells both properly, does the arithmetic against Eternity II's actual numbers, and reports the complete community record: nineteen years of asides, one unfinished embedding attempt, zero runs. - Canonical page (with interactive figures/demos): https://eternity2.dev/research/build/hardware/quantum/ - Updated: 2026-07-02 - Topics: hardware, exact-methods - Source: Grover, A fast quantum mechanical algorithm for database search (arXiv:quant-ph/9605043, 1996) — https://arxiv.org/abs/quant-ph/9605043 - Source: Bennett, Bernstein, Brassard & Vazirani, Strengths and weaknesses of quantum computing: the quadratic limit (arXiv:quant-ph/9701001) — https://arxiv.org/abs/quant-ph/9701001 - Source: Montanaro, Quantum walk speedup of backtracking algorithms (arXiv:1509.02374) — https://arxiv.org/abs/1509.02374 - Source: Lucas, Ising formulations of many NP problems (arXiv:1302.5843, 2014) — https://arxiv.org/abs/1302.5843 - Source: Bengtsson et al., QAOA solves small exact-cover instances on two superconducting qubits (arXiv:1912.10495) — https://arxiv.org/abs/1912.10495 - Source: Ambainis, Quantum search algorithms, the survey Alan posted to the list (arXiv:quant-ph/0504012) — https://arxiv.org/abs/quant-ph/0504012 - Source: Aaronson & Ambainis, Quantum search of spatial regions (arXiv:quant-ph/0303041) — https://arxiv.org/abs/quant-ph/0303041 - Source: The 2007 'Quantum computing' thread opens (groups.io message 1446) — https://groups.io/g/eternity2/message/1446 - Source: Max reads Deutsch: the quantum speedup for E2 'would be very moderate' (groups.io message 6484, 2009) — https://groups.io/g/eternity2/message/6484 - Source: D-Wave first named on the list (groups.io message 7796, 2010) — https://groups.io/g/eternity2/message/7796 - Source: McGavin's Grover arithmetic: 3.4x10^40 nodes, sqrt, 135 qubits (groups.io message 10258, 2021) — https://groups.io/g/eternity2/message/10258 - Source: McGavin states the open question (groups.io message 10260, 2021) — https://groups.io/g/eternity2/message/10260 - Source: mulisak, 'let quantum computing save us!': QAOA on exact cover (groups.io message 10791, 2022) — https://groups.io/g/eternity2/message/10791 - Source: Quantum annealing and D-Wave's free community time suggested (groups.io message 11175, 2023) — https://groups.io/g/eternity2/message/11175 - Source: Patrick Poitras's D-Wave DQM attempt hits the connectivity wall (groups.io message 11176, 2023) — https://groups.io/g/eternity2/message/11176 - Source: mulisak sizes the circuit model: 3,000+ qubits needed, ~150 exist (groups.io message 11813, 2026) — https://groups.io/g/eternity2/message/11813 --- The quantum computer entered the Eternity II archive in the puzzle's first month. In May 2007, weeks before most members had written a solver, one proposed founding the "Homebrew Quantum Computer Club" ([message 263](https://groups.io/g/eternity2/message/263)). It was a joke, and the first appearance of a figure that would haunt the list for nineteen years: the machine from the future that dissolves the whole problem. It has been invoked as fantasy, as satire, as Santa's-list wish, and occasionally as a genuine technical question. What it has never been, anywhere in the record, is *used*: no member has ever reported running any quantum hardware or simulator against any Eternity II instance, of any size. That thin record is worth a page anyway, for two reasons. First, there are exactly two real quantum stories relevant to E2, Grover search and annealing on an Ising encoding, and both can be told with actual arithmetic, in a way the list's scattered asides never quite assembled. Second, the arithmetic is clarifying: quantum computing offers the single strongest speedup any physics currently promises for blind search, and pricing E2 against it shows sharply *why* this puzzle resists: the same walls the [structure pages](/research/why/complex-theory) map, seen from the far side. ## Story one: Grover, the square root [Grover's algorithm](https://arxiv.org/abs/quant-ph/9605043) is the headline result of quantum search. Given $N$ possibilities and a black-box test for "is this one a solution?", a quantum computer finds a solution in about $\tfrac{\pi}{4}\sqrt{N}$ evaluations of the test, where a classical machine needs on the order of $N$. Two fine-print clauses matter here: - **The speedup is quadratic, and that is a theorem, not a lower bound to be beaten.** For black-box search, [Bennett, Bernstein, Brassard and Vazirani](https://arxiv.org/abs/quant-ph/9701001) proved the square root is optimal: no quantum algorithm does better without exploiting problem structure. Quantum computers are *not* known to solve NP-complete problems in polynomial time; on unstructured search they halve the exponent, full stop. - **With $M$ solutions the cost is $\sqrt{N/M}$.** Plentiful solutions help quantum search exactly as they help classical search. Eternity II was [designed to have essentially one](/research/why/complex-theory). The adversarial design that starves classical solvers starves Grover too. Now the arithmetic, against E2's actual numbers. **Against the raw space.** The naive configuration count (every piece anywhere, any rotation) is the famous $\sim 10^{557}$ ([known facts](/research/build/known-facts)). Grover turns that into $$ \sqrt{10^{557}} \;\approx\; 10^{278.5} $$ sequential oracle calls. Halving 557 leaves 278: a number that does not care whether your machine does one operation per second or per Planck time. Nothing more needs saying about the unstructured version. **Against the structured tree.** The fair comparison is not the raw space but the tree a good backtracker actually walks, and the community did this arithmetic itself, in the one genuinely technical Grover exchange in the archive. In October 2021, prompted by Akos's estimate that a full sweep of the search space needs at minimum $3.4\times10^{40}$ operations, [Peter McGavin](/research/lab/experiments/peter-mcgavin/backtracker) asked whether Grover could search that tree in $\sqrt{3.4\times10^{40}} \approx 1.8\times10^{20}$ operations on a machine with $\log_2(3.4\times10^{40}) = 135$ qubits ([message 10258](https://groups.io/g/eternity2/message/10258)), and restated it carefully two messages later: "Could Grover's or another quantum algorithm search the E2 tree in O(sqrt(N)) operations?" ([message 10260](https://groups.io/g/eternity2/message/10260)). Nobody on the list answered. The literature does: yes, almost. [Montanaro's quantum backtracking](https://arxiv.org/abs/1509.02374) walks a classical backtracking tree of $T$ nodes in roughly $\sqrt{T}$ (times polynomial factors) quantum steps, structure and pruning included. Take this wiki's own number for the tree's plateau width, about $10^{45}$ partial boards ([complex theory](/research/why/complex-theory)): $$ \sqrt{10^{45}} \;\approx\; 3\times10^{22} \text{ quantum steps.} $$ Is $3\times10^{22}$ feasible? Grant the machine an absurd gift: one full oracle call (verifying an entire board's 480 edge constraints, reversibly) every *nanosecond*. Grover iterations are inherently sequential (running $k$ machines in parallel only buys $\sqrt{k}$, not $k$), so that is $3\times10^{13}$ seconds: **about a million years**. At the kHz–MHz logical gate rates that error-corrected machines actually project, it is longer than the age of the universe. And McGavin's 135 qubits count only the index register: the oracle must hold the board (256 cells × 10 bits of piece-rotation is already ~2,560 logical qubits), the used-piece bookkeeping, and the ancillas that make the check reversible. That adds up to thousands of logical qubits, meaning millions of physical ones at current error-correction overheads, against the roughly 150 noisy qubits accessible in 2026 ([message 11813](https://groups.io/g/eternity2/message/11813)). The remarkable thing is that the list got this right early, from an armchair. In February 2009 Max, reading a David Deutsch essay, concluded that "even if we had a large quantum computer today, the speedup for problems like chess and likely also E2 would be very moderate"; one would need new, undiscovered algorithms on top ([message 6484](https://groups.io/g/eternity2/message/6484)). That is the BBBV theorem, paraphrased on a puzzle mailing list two years into the hunt. ## Story two: annealing, and the puzzle as an energy landscape The second story is more interesting because it is closer to buildable. Quantum annealers (D-Wave's machines) do not run Grover. They physically cool a network of coupled qubits toward the ground state of a programmable energy function, a **QUBO** (quadratic unconstrained binary optimization), equivalently an Ising model. [Lucas's 2014 catalogue](https://arxiv.org/abs/1302.5843) gives Ising formulations for all of Karp's 21 NP-complete problems, and edge matching encodes exactly in its style. Take the same variable the [SAT encoding](/research/build/exact/sat-csp-encodings) uses, $x_{p,c,r} = 1$ if piece $p$ sits at cell $c$ with rotation $r$, and write $$ H \;=\; A\sum_{c}\Big(1-\!\!\sum_{p,r} x_{p,c,r}\Big)^{2} \;+\; A\sum_{p}\Big(1-\!\!\sum_{c,r} x_{p,c,r}\Big)^{2} \;+\; B \sum_{\langle c,c' \rangle} \sum_{\text{mismatching pairs}} x_{p,c,r}\,x_{p',c',r'} , $$ with $A > B > 0$: the first term punishes cells not holding exactly one placement, the second punishes pieces not used exactly once, the third adds $B$ per mismatched interior join. The ground state has energy zero exactly when the board is a perfect solution. Pleasingly, low-lying excited states *are* high-scoring partials, so the encoding natively speaks the [record ladder's](/research/records) language. Then you size it. - **Variables:** $256 \times 256 \times 4 = 262{,}144$ logical binaries. - **Couplings:** every cell's 1,024 candidate placements are mutually exclusive, which means $\binom{1024}{2} \approx 5\times10^{5}$ quadratic terms *per cell*, and again per piece: order $10^{8}$ couplings before the mismatch terms are counted. - **Hardware:** the largest annealers in 2026 carry on the order of 5,000 physical qubits, each coupled to 15–20 neighbours. Mapping a logical problem onto that sparse graph (**minor-embedding**) represents each densely connected variable by a *chain* of physical qubits; the practical ceiling for a fully connected problem is a couple of hundred logical variables per chip. A **single cell's** one-hot group (1,024 mutually coupled variables) already exceeds that several times over, and there are 256 cells. The gap is not an engineering generation; it is three-plus orders of magnitude in variables and four in couplings, before chain overhead. (D-Wave's *hybrid* solvers accept million-variable QUBOs, but there the quantum processor is a subroutine inside a classical heuristic; a hybrid "result" would not be a quantum result.) And behind the size wall stands an older one: an annealer, at any size, is a physical local-search machine descending this energy landscape, the same landscape on which the community's [simulated annealing and local search](/research/build/local-search/local-search-alns) plateaued in the 460s. Nothing in quantum annealing theory promises to tunnel through the [scarcity that was engineered into this puzzle](/research/why/complex-theory); on spin-glass-like instances the adiabatic gap closes and the anneal time blows up. Alan's cheerful 2010 remark that "Simulated Annealing is one problem QComputers are expected to be especially good at" ([message 7802](https://groups.io/g/eternity2/message/7802)) is precisely the hope, and it remains, on this problem class, a hope rather than a result. ## What the archive actually says The complete quantum record of the list, 2007–2026. It is mostly asides, and this table says so; the three genuinely technical moments are marked. | When | Who | What was said | Msg | | --- | --- | --- | --- | | 2007-05 | gfleder | "Homebrew Quantum Computer Club ???", the first joke | [263](https://groups.io/g/eternity2/message/263) | | 2007-06 | Steve Moyer | Cites the "home quantum computing" thread while doing the first permutation counts | [268](https://groups.io/g/eternity2/message/268) | | 2007-07 | Jim Witte | Analog/DNA/quantum survey question; a Q-comp "could probably spit out a solution in about a second" | [824](https://groups.io/g/eternity2/message/824) | | 2007-08 | psykowally & al. | The "Quantum computing" thread: "an obvious way to solve the puzzle... how many bits can they manage?"; Anurag: no hardware exists; Grech: a real QC is worth more than the prize; a counterfactual-computation joke | [1446](https://groups.io/g/eternity2/message/1446), [1457](https://groups.io/g/eternity2/message/1457), [1464](https://groups.io/g/eternity2/message/1464), [1535](https://groups.io/g/eternity2/message/1535), [1540](https://groups.io/g/eternity2/message/1540) | | 2008 | various | Quantum listed among "other ways" (3995), doubted for interference (4032), wished for (4850), satirized as the "time-travelling quantum computer" (5413, 5442), joked about (5542), tied to P=NP musings (5629), listed with holographic and DNA computing (5736) | [3995](https://groups.io/g/eternity2/message/3995), [4032](https://groups.io/g/eternity2/message/4032), [4850](https://groups.io/g/eternity2/message/4850), [5413](https://groups.io/g/eternity2/message/5413), [5629](https://groups.io/g/eternity2/message/5629), [5736](https://groups.io/g/eternity2/message/5736) | | 2009-02 | lukas; **Max** | "Where is the non-linear 'quantum' solver?", answered with Deutsch: **the speedup "would be very moderate"** | [6480](https://groups.io/g/eternity2/message/6480), [6484](https://groups.io/g/eternity2/message/6484) | | 2009-12 | andreas gammel | "Homemade quantum computer": double-slit musing, project the solution onto a wall | [7336](https://groups.io/g/eternity2/message/7336) | | 2010-06 | **Alan (Figjam)** & Geoff | "We either need a 2048 bit quantum computer or else buy a lottery ticket"; **D-Wave named** (first hardware pointer); the Ambainis and Aaronson–Ambainis papers posted; quantum tunnelling hopes | [7789](https://groups.io/g/eternity2/message/7789), [7796](https://groups.io/g/eternity2/message/7796), [7799](https://groups.io/g/eternity2/message/7799), [7802](https://groups.io/g/eternity2/message/7802), [7811](https://groups.io/g/eternity2/message/7811) | | 2011-02 | Johannes Lindé | Wolfram quantum-search-algorithms demo linked, "any others researching along these lines?" | [8565](https://groups.io/g/eternity2/message/8565) | | 2015-06 | void solid | Links alex1770's QUBO-Chimera (how well D-Wave's native problem solves *in software*) in an unrelated thread; no follow-up | [9417](https://groups.io/g/eternity2/message/9417) | | 2021-10 | **Peter McGavin** | **The Grover arithmetic**: $3.4\times10^{40}$ nodes $\to$ $1.8\times10^{20}$ ops, 135 qubits; the open question, never answered on-list | [10258](https://groups.io/g/eternity2/message/10258), [10260](https://groups.io/g/eternity2/message/10260) | | 2022-07 | mulisak | "Let quantum computing save us!": a QAOA paper on [exact cover](/research/build/exact/exact-cover-dlx) + cuQuantum; "convince Google/IBM/Microsoft... that this will make them famous" | [10791](https://groups.io/g/eternity2/message/10791) | | 2023-10 | Hopfer; **Poitras** | The "Pseudoquantum" processor-per-cell idea; quantum annealing + D-Wave's free community time suggested; **the one hands-on attempt**, a D-Wave DQM model stuck on embedding: 15-way connectivity vs 22 colours, "hoping they can yield a Zephyr chip soon" | [11174](https://groups.io/g/eternity2/message/11174), [11175](https://groups.io/g/eternity2/message/11175), [11176](https://groups.io/g/eternity2/message/11176) | | 2023-12 | Jef Bucas | "Anyone got a big quantum computer on Santa's list?" | [11185](https://groups.io/g/eternity2/message/11185) | | 2024 | mulisak; McGavin; Joe | IBM's 127-qubit campus machine flagged (11283); quantum listed among realms a breakthrough could come from (11346); Google's Willow announcement relayed (11407) | [11283](https://groups.io/g/eternity2/message/11283), [11346](https://groups.io/g/eternity2/message/11346), [11407](https://groups.io/g/eternity2/message/11407) | | 2026 | JSA; **mulisak** | Quantum computers named as one of the two near-term routes (11788); is the SAT work "pre-work... for an eventual quantum computer?" (11812); **the sizing answer**: ~150 noisy qubits exist, an E2 set-cover circuit needs 3,000+, a ~30-qubit QAOA/Grover proof-of-concept is the realistic ceiling; "this does not look like something that will solve Eternity II anytime soon" | [11788](https://groups.io/g/eternity2/message/11788), [11812](https://groups.io/g/eternity2/message/11812), [11813](https://groups.io/g/eternity2/message/11813) | That is everything. (The archive's remaining "quantum" hits are figurative uses like "quantum leap", or physics asides unrelated to computing.) Summed up: three technical moments in nineteen years (Max's 2009 armchair theorem, McGavin's 2021 square root, mulisak's 2026 qubit count), one unfinished D-Wave embedding, and zero reported runs of anything, on any instance. The community record is thin, and this page's job is to say so rather than inflate it. > **Quantum as a lens, not a tool** > > Here is the sober use of all this. Grover-type search is the *strongest* generic speedup any known physics offers: it halves the exponent, where every hardware story on this wiki ([FPGA](/research/build/hardware/fpga-solving), [GPU](/research/build/hardware/gpu-solving), clusters) only divides by a constant. And E2 shrugs it off: $10^{45} \to 10^{22.5}$ still loses to any conceivable clock. The argument of [why a faster computer doesn't help](/research/why/prune-vs-speed) survives even the best speedup physics has on offer, which is the strongest form of that argument. Meanwhile the annealing story lands on the other wall: as an energy landscape, E2 was [built to have one needle and no gradient toward it](/research/why/complex-theory). Quantum's real E2 relevance today is that pricing the puzzle against hypothetical hardware locates the difficulty precisely where the structure pages say it lives: in the tree, not the clock. ## What a serious attempt would look like The gap between "wished for" and "measured" is, for once, cheap to close. Annealer time is rentable by the minute, and the experiment itself is small: 1. **Encode the ladder, not the puzzle.** Write the QUBO above (or Poitras's discrete-variable form, [message 11176](https://groups.io/g/eternity2/message/11176)) for [Brendan Owen's benchmark suite](/research/build/benchmarks) starting at 4×4 and 5×5, sizes whose one-hot groups actually embed on a ~5,000-qubit chip. 2. **Run three solvers on the same $H$:** the real QPU, classical simulated annealing, and a modern tabu/SA hybrid: same energy function, same cutoff. The QPU must beat the classical anneal *on its own encoding* before any larger claim means anything. 3. **On gate hardware, do mulisak's proof-of-concept**: QAOA or Grover on a ~30-qubit set-cover toy ([message 11813](https://groups.io/g/eternity2/message/11813)), knowing in advance it demonstrates machinery, not progress. 4. **Report the scaling curve, not the anecdote:** success probability and time-to-solution versus board size, alongside the classical baseline. The realistic best case is not a solved 6×6; it is a measured crossover or, more likely, a clean, sourced entry for the [dead ends](/research/build/dead-ends) ledger, which on this wiki also counts as progress. Until someone does that, the scoreboard reads: two beautiful algorithms, one arithmetic that ends in $10^{22}$ sequential steps, one encoding three orders of magnitude too large for its hardware, and a nineteen-year archive in which the quantum computer remains what it was in May 2007: the club nobody ever built. ## Related - [SAT and CSP encodings](https://eternity2.dev/research/build/exact/sat-csp-encodings) — Write the puzzle as clauses and hand it to an industrial solver: the obvious move, tried since 2008. Why complete solvers stall on the full board, and where their verdicts still earn their keep as impossibility proofs. - [FPGA solving: mapped but never driven](https://eternity2.dev/research/build/hardware/fpga-solving) — If the placement loop is memory-latency-bound, an FPGA looks like the exact answer: put the lookup tables in on-chip block RAM one cycle away, and pipeline dozens of tiny backtrackers on one die. The community mapped this road in detail. Michael Field designed the solver, projected 5 billion placements per second per chip, and ran a prototype on real silicon. Then the road was never driven to the end. The complete record, and why. - [Complex theory: counting the search before you run it](https://eternity2.dev/research/why/complex-theory) — Brendan Owen's complex theory estimates how wide the search tree is at every depth, and even how many solutions exist at all. Many in the community consider it the single most important thing to understand about Eternity II. --- # Known facts & numbers > The numbers every Eternity II researcher ends up re-deriving, collected in one place with their provenance: the puzzle definition, the clue placements, scoring conventions, the record table, search-space sizes and the structural counts. - Canonical page (with interactive figures/demos): https://eternity2.dev/research/build/known-facts/ - Updated: 2026-07-02 - Topics: structure - Source: Wikipedia, "Eternity II puzzle" (the prize, the deadline, Verhaard's 467 and the 10^557 estimate) — https://en.wikipedia.org/wiki/Eternity_II_puzzle - Source: 469: “EternityII Solver” thread (the Blackwood & McGavin board), eternity2@groups.io, 2020-09 — https://groups.io/g/eternity2/message/10045 - Source: 470: “470 Found” (Joshua Blackwood), eternity2@groups.io, 2021-03 — https://groups.io/g/eternity2/message/10117 - Source: 460 with all five clues: “Highest points (of 480) with using all 5 (!) hints?” thread, eternity2@groups.io, 2023-03 — https://groups.io/g/eternity2/message/11074 - Source: 464 with all five clues (Benjamin Riotte): “Record of Eternity2 with 5 hints?” thread, eternity2@groups.io, 2026-07 — https://groups.io/g/eternity2/message/11919 - Source: Brendan Owen's expected-solution-count estimates (groups.io message 5197) — https://groups.io/g/eternity2/message/5197 - Source: Louis Verhaard, algorithm and score details for the 467 (shortestpath.se) — https://www.shortestpath.se/eii/eii_details.html - Source: e2.bucas.name (Jef Bucas), the community board viewer; every record board re-scores there — https://e2.bucas.name --- Every conversation about Eternity II eventually stops while someone re-derives the same handful of numbers. This page is that handful, written down once. Facts marked **computed** are re-derived exactly from the official piece set, the same data our [reference numbers](/research/reference) and [Why is it hard?](/research/why) pages are checked against, and anyone can reproduce them. Record facts come from the primary mailing-list messages; encyclopedic facts from Wikipedia. ## The puzzle by the numbers | Fact | Value | Provenance | | --- | --- | --- | | Board | 16×16 = 256 cells, framed | official | | Pieces | 256, all distinct | official; computed | | Corner pieces (2 grey sides) | 4 | computed | | Edge pieces (1 grey side) | 56 | computed | | Interior pieces (0 grey sides) | 196 | computed | | Colours (grey border excluded) | 22 | computed | | of which frame-only colours | 5 | computed | | of which interior-palette colours | 17 | computed | | Internal edges (adjacent cell pairs) | 480 = 2 · 16 · 15 | computed | | Pinned clue placements | 5 | official | | Prize | $2,000,000, unclaimed; deadline noon, 31 Dec 2010 | Wikipedia | The grey outer-border colour is not one of the 22: it never appears on an internal edge. The 5 + 17 colour split is not an accident: 17 interior colours is [exactly the hardness peak](/research/why/phase-transition) for a puzzle of this size. ## The five clues The rules sheet pins one piece; Tomy sold four smaller [clue puzzles](/research/build/clue-puzzles) whose solutions each revealed one more placement, and the remaining placements were published later. Squares use the board notation of [e2.bucas.name](https://e2.bucas.name): rows A–P from the top, columns 1–16 from the left. Piece numbers are 1–256 in the official list order, and the rotation is clockwise from the piece's stored orientation. | Square | Piece | Rotation | Which clue | | --- | --- | --- | --- | | I8 | 139 | 0° | mandatory (in the rulebook) | | C3 | 208 | 90° | clue puzzle | | C14 | 255 | 90° | clue puzzle | | N3 | 181 | 90° | clue puzzle | | N14 | 249 | 180° | clue puzzle | > **[Figure]** interactive: CluePositionsDiagram. Rendered on the canonical page (link above); not shown in this markdown export. A board that respects all five is called **strict-canonical**; most record boards respect only the mandatory centre clue ("canonical"). That distinction splits the record table in two; see below. The clues also settle a counting question: with only the mandatory piece placed, [complex theory](/research/why/complex-theory) expects ≈ 14,702 full solutions; with all five, ≈ 1. The 5-clue puzzle has, by design, a single expected solution. ## Scoring conventions - **Score = matched internal edges, out of 480.** The 60 outward-facing grey edges around the frame are not counted. This is the convention of the prize scrutiny, of every record in the table below, and of this wiki. - **"Breaks" = 480 − score.** Solver authors often report mismatch counts instead: Blackwood's 468 was announced to the mailing list as "12 breaks". - **479 is possible, but only through the border.** A launch-summer [parity argument](/research/build/analysis/parity-arguments) claimed exactly one mismatch cannot exist ([kubzpa, 2007](https://groups.io/g/eternity2/message/1640)), and it holds for interior moves (rotating an interior piece with equal opposite edges breaks two, giving 478, [msg 1642](https://groups.io/g/eternity2/message/1642)). But the parity leaks through the 60 *unscored* outward border edges: flip a border piece whose two ring-facing sides share a colour and exactly one scored edge breaks ([Verhaard, 2009](https://groups.io/g/eternity2/message/6317)). The official set has 14 such border pieces (computed), so any full solution implies a 479. - **Check the piece set before comparing scores.** Several headline "480" boards use [variant piece sets](/research/build/variants) (Clue-1/Clue-2 designs, mixed sets, the unframed TopCoder variant). They are different puzzles; see [Records & solvers](/research/records). The 480 internal edges split into three families (computed): | Edge family | Count | | --- | --- | | Border ↔ border (around the 60-piece frame ring) | 60 | | Border ↔ interior (the seam, 4 × 14) | 56 | | Interior ↔ interior (inside the 14×14 core) | 364 | | **Total** | **480** | ## The record table The full timeline, with board previews and per-record references, lives at [Records & solvers](/research/records). The numbers themselves: | Score | Who | When | Track | | --- | --- | --- | --- | | 467 | Louis Verhaard's team | Sept 2008 | canonical; won the $10,000 partial prize | | 468 | Joshua Blackwood | Aug 2020 | canonical | | 469 | Peter McGavin (Blackwood's solver) | Sept 2020 | canonical | | 469 | various (~7 boards, independent finds plus one single-swap of McGavin's) | Nov 2020 | canonical | | **470** | **Joshua Blackwood** | **Mar 2021** | **canonical, the ceiling since** | | 470 | Jef Bucas | Dec 2024 | canonical (tie of the 470) | | 460 | Bruno Gauthier | Mar 2023 | strict-canonical; best board respecting the four optional clues, 2023 until beaten Jul 2026 | | **464** | **Benjamin Riotte** | **Jul 2026** | **strict-canonical record; beat Gauthier's 460, all five clues respected** | | "480" | various | 2023 | variant piece sets, not the canonical puzzle | The 469s were long quoted as the ceiling, but board-level verification shows the 468/469/470 boards are all the same starter-only regime (the contest rules pinned only the starter piece), so the 470 is the record on the same puzzle, not an easier variant. A full canonical solution (480/480) has never been reported by anyone, in any public source. The gap of 10 edges has stood since March 2021. ## How big is the search | Count | Value | Provenance | | --- | --- | --- | | All placements, no constraints: 256! · 4²⁵⁶ | ≈ 1.15 × 10⁶⁶¹ | computed | | Corners in corners, edges on the border (orientation forced), clue pinned: 4! · 56! · 195! · 4¹⁹⁵ | ≈ 1.115 × 10⁵⁵⁷ | computed; matches the widely quoted Wikipedia figure | | Widest point of the search tree (complex-theory estimate, row scan) | ≈ 10⁴⁵ ways to extend, around depth 50–200 | Owen / McGavin, see [complex theory](/research/why/complex-theory) | | Expected full solutions, 1 clue / 5 clues | ≈ 14,702 / ≈ 1 | same | The 10⁵⁵⁷ figure is worth being able to re-derive rather than cite: the 4 corner pieces go to the 4 corners (orientation forced by the two grey sides), the 56 edge pieces to the 56 border slots (orientation forced), and the remaining 195 free interior pieces (196 minus the pinned clue) each take one of 4 rotations. ## Symmetry facts All computed from the official piece set: - **No piece is rotation-symmetric.** Every one of the 256 pieces has 4 distinct orientations, so rotation never shrinks a piece's candidate set. - **No two pieces are identical, even up to rotation.** There are no interchangeable duplicates to exploit. - **Five pairs share a colour multiset without being the same piece**: pieces 3 & 4, 6 & 15, 8 & 52, 110 & 111, 172 & 182 (1-based official numbering) carry the same four colours in a different cyclic order. - **The clues break all board symmetries.** A 16×16 board has no centre cell, so every rotation or reflection moves the mandatory clue square I8: no non-trivial symmetry maps the clued puzzle to itself, and symmetry-breaking offers no further search-space reduction. ## Colours, edge by edge The 256 pieces carry 1,024 edge stickers; 64 are grey (2 per corner piece, 1 per edge piece), leaving 960 coloured edge instances. Their census (computed; see [rare-colour geography](/research/why/rare-color-geography)): | Colour group | Colours | Edge instances each | Total | | --- | --- | --- | --- | | Frame-only ("rare") | 5 | 24 (all on frame pieces, none interior) | 120 | | Interior palette, low | 5 | 48 | 240 | | Interior palette, high | 12 | 50 | 600 | | **All** | **22** | | **960** | Two consequences researchers keep rediscovering: - **Every per-colour count is even, and the halves sum to exactly 480.** A matched internal edge consumes two instances of one colour, so a perfect solution needs $\sum_c N_c / 2 = 480$ matches, which is exactly the number of internal edges. There is **zero slack**: in a full solution every single edge instance of every colour finds its partner. - **The five rare colours live only on the frame** (24 instances each), which makes the frame ring a nearly self-contained sub-puzzle; the geometry is worked through in [rare-colour geography](/research/why/rare-color-geography). ## Local structure Exact, exhaustive counts over the official interior pieces (computed; details and live demos on the linked pages): | Fact | Value | See | | --- | --- | --- | | Random 2-cell interior placements that are infeasible | 14,890 / 38,220 ≈ 39% | [forbidden patterns](/research/why/forbidden-patterns) | | Random L-tromino placements infeasible | ≈ 83.3% | same | | Random 2×2 interior placements infeasible | 1,427,039,544 / 1,431,033,240 ≈ 99.72% | same | | Interior pieces with a forced neighbour | 0: every piece has 73–137 possible right-neighbours | [no forced moves](/research/why/no-forced-moves) | | Border↔interior colour balance in any full solution | deficit $\Delta = 0$ (a necessary condition, Hopfer 2022) | [the border balance](/research/why/border-balance) | ## Reading the provenance - **computed**: re-derived exactly from the official 256-piece set; the relevant pages carry `just research-…` reproduction commands and the raw results live in the [repository](https://github.com/raphael-anjou/eternity2). - **groups.io**: the record scores (468, 469, 470, the strict 464) exist only in mailing-list messages and on the community board viewer; the exact announcement messages are linked from [Records & solvers](/research/records), and each board can be re-scored at [e2.bucas.name](https://e2.bucas.name). - **Wikipedia**: covers only the encyclopedic layer (the prize, the deadline, and Verhaard's 467). ## Related - [Reference numbers](https://eternity2.dev/research/reference) — Exact counts of how many valid ways a small block can be filled at a given position of the official Eternity II board, under increasingly constrained rules: known-good numbers to check your solver's edge-matching and constraint code against. - [Records & solvers](https://eternity2.dev/research/records) — Eternity II has never been solved, but fifteen years of community effort have pushed the best board to 470/480. Who holds what, how they did it, and why some headline "480" boards are not actually the real puzzle. - [Tuned to the hardness peak](https://eternity2.dev/research/why/phase-transition) — Eternity II uses 22 colors. They split 17 interior to 5 frame-only, and that 17 is exactly where this kind of puzzle is hardest to solve. --- # Learn from strong boards > Most attacks on Eternity II search from first principles. A distinct family does the opposite: it mines the corpus of boards people have already found for structure, then feeds that structure back into the search. Position priors, learned move-ordering, anti-pattern mining, record decoding, and the failure mode where a learned signal collapses. - Canonical page (with interactive figures/demos): https://eternity2.dev/research/build/learning/ - Updated: 2026-07-16 --- Every other family on this shelf searches from first principles: a backtracker digs, a beam builds, a local search polishes, each reasoning only from the rules of the puzzle and the board in front of it. This family does something different. It takes the corpus of strong boards people have already found, reads it for structure, and feeds that structure back into a search as a bias. It is closer to imitation learning than to search design: the question is not "what is a good move" from first principles but "what did the boards that scored well tend to do, and can that be reused." The pages below go technique by technique. Each is genuinely its own method, so they do not share a shape the way the local-search polishers do: a position prior, a learned move-ranking, an anti-pattern miner, and a witness replay share a thesis but not a mechanism. For the whole territory at once, start with [a map of every known approach](/research/build/approaches-map). For the runnable experiments that embody these techniques, with their boards and numbers, see the [learning-from-boards experiments](/research/lab/experiments/raphael-anjou/learning). ## The thesis, and its limit A learned signal helps when it captures real, transferable structure: something true of good boards that a from-scratch search would otherwise have to rediscover by luck. Where each piece tends to sit, which pieces like to touch, which scarce demand a rare piece is the only one that can serve. Wired into a search as a gentle bias, that structure reliably carries a build to the top of its own range. The limit is the part that makes this research rather than a bag of tricks. The corpus these signals are learned from is itself sub-perfect: every board in it is stuck somewhere below 480. So a signal mined from the corpus encodes the community's *ceiling* as much as its wisdom, and a signal that merely re-encodes the plateau every strong board is already caught on raises nothing. Push a learned prior from a tiebreak into the objective and the search collapses, because it starts trading the edge in front of it against a statistical hunch. The plain through-line of this whole family: learning from strong boards helps you reach the plateau fast and reliably, but it does not, on its own, get you past it. The ceiling is the [rigidity wall](/research/why/rigidity-wall), and no amount of corpus mining moves it. ## The techniques - **[Corpus priors](/research/build/learning/corpus-priors)** are the simplest form: count where each piece sits in strong boards, or how often a piece serves a scarce demand, and use the count as a tiebreak in construction. The [PRIOR](/research/lab/experiments/raphael-anjou/learning/prior) and [LODESTONE](/research/lab/experiments/raphael-anjou/learning/lodestone) experiments. - **[Learned move-ordering](/research/build/learning/learned-value-ordering)** ranks candidate placements by several learned signals at once, and lets them vote, so no single hunch marches the search into the same dead end. The [KEYRING](/research/lab/experiments/raphael-anjou/learning/keyring) experiment. - **[Anti-pattern mining](/research/build/learning/anti-pattern-mining)** is the subtler idea: not every agreement across strong boards is good. Separate the real structure from the shared trap, and attack the trap. The [PALIMPSEST](/research/lab/experiments/raphael-anjou/learning/palimpsest) experiment, which reached this project's best board. - **[Decoding records](/research/build/learning/decoding-records)** reconstructs a known record board exactly, piece for piece, to recover the ingredient an ordinary search was missing. Reproduction as proof. The [REPLAY](/research/lab/experiments/raphael-anjou/learning/replay) experiment. - **[When learning collapses](/research/build/learning/when-learning-collapses)** is the failure-mode capstone: exactly when a learned signal stops helping, why over-trusting it wrecks the search, and why none of these methods raise the ceiling. It sets the limit for the whole section: learned signals reach the plateau faster, but none of them lift it. ## Pages in this section - [Corpus priors](https://eternity2.dev/research/build/learning/corpus-priors) — The simplest way to learn from strong boards: count where each piece tends to sit, or how often it serves a scarce demand, and use that count as a gentle tiebreak in construction. It has to stay a tiebreak; the moment it becomes part of the objective it collapses the search. - [Learned move-ordering](https://eternity2.dev/research/build/learning/learned-value-ordering) — When several pieces fit, which do you place next? Instead of one rule of thumb, carry several signals learned from strong boards and let them vote. Voting keeps the search from over-trusting any one hunch and marching into the same dead end. - [Anti-pattern mining](https://eternity2.dev/research/build/learning/anti-pattern-mining) — The subtle idea in learning from strong boards: not every agreement between them is good. Some shared placements are real structure; some are a shared trap that caps every search just short of the top. Separate the two, and attack the trap. - [Decoding records](https://eternity2.dev/research/build/learning/decoding-records) — The most literal way to learn from a strong board: rebuild it exactly, piece for piece, until your search can reproduce it. What the reconstruction forces you to add is the ingredient your search was missing, and the reproduction is the proof. - [When learning collapses](https://eternity2.dev/research/build/learning/when-learning-collapses) — The sobering half of learning from strong boards. A learned signal reaches the top of a search's own range reliably, and then stops. Over-trust it and the search collapses; even used perfectly it does not raise the ceiling, because the ceiling is not a thing the corpus knows. ## Related - [A map of every known approach](https://eternity2.dev/research/build/approaches-map) — The survey the community keeps asking for and never finds: every family of attack tried on Eternity II, what each one actually reached, where it walls out, and a link to the deep page. One organising insight runs through all of them. - [The techniques](https://eternity2.dev/research/build/techniques) — The technique shelf: the algorithms and pruning ideas that recur in every serious Eternity II solver, each with what it is, what it costs, and what it actually bought when measured on this puzzle. - [Learning from strong boards](https://eternity2.dev/research/lab/experiments/raphael-anjou/learning) — A study in five experiments of one idea: instead of searching Eternity II from first principles, mine the corpus of strong boards already found for structure and feed it back into a search. A position prior, a learned move-vote, a scarce-demand compass, an anti-pattern miner, and a record decode, ordered from the simplest signal to the subtlest, and the one wall all five reach. --- # Anti-pattern mining > The subtle idea in learning from strong boards: not every agreement between them is good. Some shared placements are real structure; some are a shared trap that caps every search just short of the top. Separate the two, and attack the trap. - Canonical page (with interactive figures/demos): https://eternity2.dev/research/build/learning/anti-pattern-mining/ - Updated: 2026-07-16 - Topics: local-search, learning - Source: Ropke & Pisinger 2006, adaptive large-neighbourhood search (the destroy-and-repair frame this steers) — https://doi.org/10.1287/trsc.1050.0135 --- Every technique so far treats agreement between strong boards as a good thing: where the good boards concur, follow them. This one takes agreement apart, because some of it is a trap. When many independent searches all reach a high but imperfect board, they agree on a great many placements, and some of that agreement is genuine structure while some of it is a shared bad habit: a local choice that looks good, feels forced, and quietly caps every search just short of the top. The whole idea is to tell the two apart, then attack the trap. ## Two frequencies, not one A single count cannot separate real structure from a trap, because both show up almost everywhere. The trick is to compute *two* frequencies for each candidate pattern and compare them. Over a corpus of boards scoring across a wide band, for every adjacent cell-pair and every piece-pair that ever sits there, measure: $$ p_\text{high} = \frac{\#\{\text{boards with the pair, score} \ge 460\}}{\#\{\text{boards} \ge 460\}}, \qquad p_\text{all} = \frac{\#\{\text{boards with the pair}\}}{\#\{\text{all boards}\}} $$ together with a *ceiling*: the best score of any board that contains the pattern. Two categories fall out. **Good consensus** is high $p_\text{all}$ with a high ceiling, a pattern that strong boards share *and* the very best boards keep: real, trustworthy structure. A **consensus trap** is high $p_\text{all}$ with a ceiling stuck just below the top, a pattern almost every board adopts but no top board does: the agreed-upon wrong choice that locks a whole family below the record. The single-frequency view cannot distinguish them; splitting by basin is the entire move. > **[Figure]** Interactive: the trap map, corner-family by corner-family — interactive: PalimpsestDiagram. Rendered on the canonical page (link above); not shown in this markdown export. ## Steering, not banning Knowing where the traps are turns the corpus into a map of which placements to trust and which to pull apart. The [PALIMPSEST](/research/lab/experiments/raphael-anjou/learning/palimpsest) experiment uses it to steer an [ALNS](/research/build/local-search/local-search-alns) search: take a board caught in the trap basin, find the wedge whose removal breaks the most trap patterns while sparing the good-consensus ones, deliberately break those cells, and hand the board back to the repair loop, whose destroy operator tears open exactly those broken regions and rebuilds them. Steered this way, it reached 463, the best board this project has produced (the [PALIMPSEST experiment](/research/lab/experiments/raphael-anjou/learning/palimpsest), whose committed board reproduces via `just research-record-boards`). The caveat is the lesson. Trying to use the trap list *directly*, forcing the search to avoid every trapped placement, did not work and made boards worse. The value was in reading the corpus to choose *where to aim* the search, not in hard-coding its conclusions as a ban. A learned map is a good place to point a search and a bad set of shackles to bolt onto it, which is the same boundary between tiebreak and objective that runs through [corpus priors](/research/build/learning/corpus-priors), seen from the other side: here the danger is not over-weighting a good signal but over-trusting a signal about what is *bad*. Even steered perfectly, this does not clear the top. Rebuilding the trapped regions tends to land back on the same known top board rather than a genuinely new one, because the trap is not a mistake a smarter search avoids; it is the [rigidity wall](/research/why/rigidity-wall) itself. That is the subject of the [collapse page](/research/build/learning/when-learning-collapses). ## Related - [Learned move-ordering](https://eternity2.dev/research/build/learning/learned-value-ordering) — When several pieces fit, which do you place next? Instead of one rule of thumb, carry several signals learned from strong boards and let them vote. Voting keeps the search from over-trusting any one hunch and marching into the same dead end. - [When learning collapses](https://eternity2.dev/research/build/learning/when-learning-collapses) — The sobering half of learning from strong boards. A learned signal reaches the top of a search's own range reliably, and then stops. Over-trust it and the search collapses; even used perfectly it does not raise the ceiling, because the ceiling is not a thing the corpus knows. - [PALIMPSEST](https://eternity2.dev/research/lab/experiments/raphael-anjou/learning/palimpsest) — Read every strong board to find the habits that quietly hold a board back, then break them. This experiment produced the project's best board: 463 of 480. - [Local search and ALNS](https://eternity2.dev/research/build/local-search/local-search-alns) — Destroy part of a board, rebuild it better, and let the algorithm learn which demolitions pay. Adaptive large-neighborhood search is the most reliable polisher this project has, and the cleanest demonstration of the wall where polishing ends. - [The rigidity wall](https://eternity2.dev/research/why/rigidity-wall) — Every record board we have is frozen in place. You cannot nudge your way from a great board to a perfect one, and we can prove it. --- # Corpus priors > The simplest way to learn from strong boards: count where each piece tends to sit, or how often it serves a scarce demand, and use that count as a gentle tiebreak in construction. It has to stay a tiebreak; the moment it becomes part of the objective it collapses the search. - Canonical page (with interactive figures/demos): https://eternity2.dev/research/build/learning/corpus-priors/ - Updated: 2026-07-16 - Topics: construction, learning - Source: Beam search (this project's concept page): the bounded-width construction a prior biases — https://github.com/raphael-anjou/eternity2/blob/main/web/content/research/build/construct/beam-search.mdx --- The simplest thing you can learn from a pile of strong boards is a count. For each cell of the board, how often does each piece sit there across the good boards? That single tally is a *prior*: a gentle statistical preference for what tends to belong where. It copies no board in particular; it reads the whole crowd of them at once and distils a bias. ## The count matrix Take every board in the corpus that scores above a threshold, and tally a matrix $M[c][p]$: how many strong boards place piece $p$ in cell $c$. Normalised per cell, $M[c][\cdot]$ is a distribution over pieces for that position, the learned preference. It costs one linear pass over the corpus to build, and nothing at search time beyond a lookup. > **[Figure]** Interactive: the position-prior heatmap — interactive: PriorDiagram. Rendered on the canonical page (link above); not shown in this markdown export. The prior is only ever used to break ties. A [beam search](/research/build/construct/beam-search) extends its partial boards cell by cell; when two candidate placements match the same number of edges, the prior tips the choice toward the piece that is more typical of strong boards in that spot. The matched-edge count still decides; the prior only speaks when the count is silent. This is the [PRIOR](/research/lab/experiments/raphael-anjou/learning/prior) experiment, which builds a competitive board from an empty grid with no board to anchor to, and reaches 460 that way. Three sharpenings of the same count are worth naming, because each trades signal strength against noise: - **Rotation-aware.** Split each piece by its four rotations, so the prior prefers not just the right piece but the right orientation. The matrix grows from $256 \times 256$ to $1024 \times 256$; the signal is finer but thinner per cell. - **Per corner-family.** Strong boards fall into families by their four corner pieces. A prior built from a single family's boards captures structure the pooled matrix averages away, which is what let PRIOR reach a fresh basin rather than the crowded common one. - **Sharper threshold.** Rebuild the prior from only the very best boards. The ceiling of the construction rises, at the cost of a thinner, noisier signal learned from fewer examples. ## A prior on demand, not position The count does not have to be over positions. A subtler prior asks, for each *piece*, how often it ends up serving a **scarce demand**: a cell whose north and west colours can be served by only one or two pieces in the whole set. The strong boards increasingly satisfy the same scarce demands as they climb, so a piece that is often the one spending itself on a rare colour earns a high weight. Ranking candidates by matched edges plus a small multiple of that weight nudges the search to commit rare pieces early, before they are stolen. This is the [LODESTONE](/research/lab/experiments/raphael-anjou/learning/lodestone) experiment, and it connects to the puzzle's [rare-colour geography](/research/why/rare-color-geography). ## Why it stays a tiebreak The load-bearing detail, for both the positional and the scarce-demand prior, is that the multiple on the prior must be *tiny*. A prior is a pure tiebreaker: it decides between equally-matching moves and nothing more. Turn the weight up even slightly and the search starts trading a real matched edge against a statistical hunch, and the score collapses, LODESTONE falls from 451 to 422 to 380 as the weight climbs. That collapse is not an implementation bug; it is the shape of the whole family, and it has its own page: [when learning collapses](/research/build/learning/when-learning-collapses). ## Related - [Learned move-ordering](https://eternity2.dev/research/build/learning/learned-value-ordering) — When several pieces fit, which do you place next? Instead of one rule of thumb, carry several signals learned from strong boards and let them vote. Voting keeps the search from over-trusting any one hunch and marching into the same dead end. - [When learning collapses](https://eternity2.dev/research/build/learning/when-learning-collapses) — The sobering half of learning from strong boards. A learned signal reaches the top of a search's own range reliably, and then stops. Over-trust it and the search collapses; even used perfectly it does not raise the ceiling, because the ceiling is not a thing the corpus knows. - [PRIOR](https://eternity2.dev/research/lab/experiments/raphael-anjou/learning/prior) — Build a board from nothing, breaking ties by where pieces tend to sit in the strong boards we already have. It reaches a high score with no starting board to copy. - [LODESTONE](https://eternity2.dev/research/lab/experiments/raphael-anjou/learning/lodestone) — A faint compass for a from-scratch search: nudge it to commit the rare pieces early, where they're needed. It doesn't raise the ceiling; it makes the search reliably reach the top of its own range. - [Beam search](https://eternity2.dev/research/build/construct/beam-search) — Keep the K most promising partial boards alive at once and grow them cell by cell. Beam search is the workhorse behind this project's from-scratch builders, and a clean illustration of why breadth alone stalls in the deep interior. - [The rare colors live on the frame](https://eternity2.dev/research/why/rare-color-geography) — Five of Eternity II's 22 colors appear only along the border ring, each on exactly 24 edges, never once in the interior. A structural split that shapes how every solver treats the frame. --- # Decoding records > The most literal way to learn from a strong board: rebuild it exactly, piece for piece, until your search can reproduce it. What the reconstruction forces you to add is the ingredient your search was missing, and the reproduction is the proof. - Canonical page (with interactive figures/demos): https://eternity2.dev/research/build/learning/decoding-records/ - Updated: 2026-07-16 - Topics: backtracking, learning - Source: Community record boards (this project's records timeline): the witnesses a replay reconstructs — https://github.com/raphael-anjou/eternity2/blob/main/web/content/research/records.mdx --- Corpus priors and anti-pattern mining learn a *statistic* from many boards. This technique learns from a *single* board, and it learns the hardest thing to see from a distance: the one move an ordinary search cannot make. The method is brutally literal. Take a known record board, and try to make your own search rebuild it exactly, piece for piece. Whatever you have to add to your search before it can walk that path is precisely the ingredient it was missing, and the exact reconstruction is the proof that the ingredient is real. ## Reproduction as proof The setup is a depth-first search run in a deliberately constrained mode, aimed at a specific witness board rather than searching freely: - **Prior-over-cost ordering.** An ordinary break-tolerant backtracker ranks candidate placements by immediate mismatch cost, cheapest first. A replay flips the priority so that the placements the witness board actually used outrank cheaper-looking ones. The search is pulled down the known good path instead of wandering off it. - **An exact tail.** The last handful of cells are solved exactly rather than heuristically, so the endgame an ordinary run fumbles is closed deterministically. - **The relaxation under test.** With the ordering and the tail fixed, you vary the one rule you suspect is the barrier, and watch for the moment the witness rebuilds. This is the [REPLAY](/research/lab/experiments/raphael-anjou/learning/replay) experiment, and what it found on the community's strict-460 boards is a clean example of the payoff. The project's own break-tolerant search had saturated at 457 or 458 no matter what, and the reason turned out to be a single rule nobody had questioned: it allowed at most *one* mismatched edge per cell. The record boards each contain four or five cells that pay *two* mismatches at once. A search capped at one break per cell literally cannot represent those boards, so it was fenced off from the very targets it was chasing. > **[Figure]** Interactive: the double-break cells — interactive: DoubleBreakDiagram. Rendered on the canonical page (link above); not shown in this markdown export. > **[Figure]** Interactive: replay the break schedule — interactive: DoubleBreakLab. Rendered on the canonical page (link above); not shown in this markdown export. Raise the per-cell budget from one to two, and both community strict-460 witnesses rebuild exactly, every piece in place, the score checking out edge by edge. The reconstruction *is* the finding: a search-completeness result dressed as a record attempt. The wall was in the move set, not the compute. ## What decoding can and cannot buy Decoding a record is the sharpest diagnostic in this family, because it turns a vague suspicion ("our search is missing something") into a specific, checkable claim ("it cannot pay two breaks at one cell"). It is also the most candid about its limits, and in the same breath. Recovering the double break lifts the strict ladder to 460, but it does not, by itself, say whether two breaks per cell open a path to 461 and beyond or merely to the known 460s. Decoding tells you the ingredient a witness used; it does not promise that ingredient carries any further than the witness did. That gap, a learned move that reaches the plateau without proving anything past it, is the theme of the [collapse page](/research/build/learning/when-learning-collapses). ## Related - [Anti-pattern mining](https://eternity2.dev/research/build/learning/anti-pattern-mining) — The subtle idea in learning from strong boards: not every agreement between them is good. Some shared placements are real structure; some are a shared trap that caps every search just short of the top. Separate the two, and attack the trap. - [When learning collapses](https://eternity2.dev/research/build/learning/when-learning-collapses) — The sobering half of learning from strong boards. A learned signal reaches the top of a search's own range reliably, and then stops. Over-trust it and the search collapses; even used perfectly it does not raise the ceiling, because the ceiling is not a thing the corpus knows. - [REPLAY](https://eternity2.dev/research/lab/experiments/raphael-anjou/learning/replay) — Rebuild the community's strict 460 boards exactly, and in doing so discover the move ordinary solvers can't make: paying two mismatches at a single cell. - [Records & solvers](https://eternity2.dev/research/records) — Eternity II has never been solved, but fifteen years of community effort have pushed the best board to 470/480. Who holds what, how they did it, and why some headline "480" boards are not actually the real puzzle. - [No-good learning: remembering why you failed](https://eternity2.dev/research/build/reduce/nogood-learning) — A failed subtree is a theorem: this partial state can never extend. Store it and never re-enter. The community tried both flavours: chess-style transposition tables over the search frontier, and mined constraints about the puzzle itself. The full ledger of what memory buys at E2 scale, and the small boards where it genuinely pays. --- # Learned move-ordering > When several pieces fit, which do you place next? Instead of one rule of thumb, carry several signals learned from strong boards and let them vote. Voting keeps the search from over-trusting any one hunch and marching into the same dead end. - Canonical page (with interactive figures/demos): https://eternity2.dev/research/build/learning/learned-value-ordering/ - Updated: 2026-07-16 - Topics: construction, learning - Source: Beam search (this project's concept page): the construction whose value-ordering is learned — https://github.com/raphael-anjou/eternity2/blob/main/web/content/research/build/construct/beam-search.mdx --- Building a board one piece at a time, the hard decision is which piece to place next when several would fit equally well. A single rule of thumb, cheapest cost first, most-constrained cell first, tends to march the search into the same dead end every run. A [corpus prior](/research/build/learning/corpus-priors) improves on that with one learned signal. This technique improves on it again by carrying *several* learned signals at once and letting them vote, so no single hunch owns the decision. ## Several signals, one vote From the corpus of strong boards you can learn more than one thing at a time, and the signals are cheap counts over the same board set: - **Piece-in-position.** How often a piece appears in a given cell across good boards, the positional prior of the previous page. - **Piece-pair adjacency.** How often two particular pieces end up touching. A neighbourliness the positional count does not see. - **The 2×2 patch prior.** For every little four-cell patch, a Laplace-smoothed log-odds ratio of how often it appears in high-scoring boards versus low-scoring ones. A patch common in strong boards and rare in weak ones scores positive; a consensus-trap patch scores negative. This is the sharpest of the three, because it is the only one that contrasts good against bad rather than merely counting good. At each step the beam scores every candidate placement by its matched-edge gain plus a weighted sum of the three signals, and keeps the top few. A little injected randomness stops the parallel beams collapsing onto one path. > **[Figure]** Interactive: the three-signal placement vote — interactive: KeyringDiagram. Rendered on the canonical page (link above); not shown in this markdown export. This is the [KEYRING](/research/lab/experiments/raphael-anjou/learning/keyring) experiment, a keyring of hunches rather than one. It reached 460 in a corner family no earlier search had cracked, which is the real payoff: because the strong boards are known to sit in isolated basins, a signal diverse enough to reach a *new* family is worth more than one that re-derives a known board. ## Why voting beats one signal A single learned signal has the same failure mode as a single hand-written rule: wherever it is wrong, it is wrong every time, and it drags every beam the same way. Three signals that were learned from different views of the corpus, position, adjacency, and patch quality, disagree in different places, and their disagreement is exactly the randomness that keeps the beams exploring different regions. The patch prior carries the most weight because it alone encodes *bad*: it can push the search away from a placement, not just toward one, which is the seed of the idea that grows into [anti-pattern mining](/research/build/learning/anti-pattern-mining). The same caveat as every learned signal applies. The three priors are mined from a corpus that is itself sub-perfect, so they encode the community's ceiling as much as its wisdom, and the vote reaches the top of the search's range reliably without lifting that range. Where that boundary sits is [its own page](/research/build/learning/when-learning-collapses). ## Related - [Corpus priors](https://eternity2.dev/research/build/learning/corpus-priors) — The simplest way to learn from strong boards: count where each piece tends to sit, or how often it serves a scarce demand, and use that count as a gentle tiebreak in construction. It has to stay a tiebreak; the moment it becomes part of the objective it collapses the search. - [Anti-pattern mining](https://eternity2.dev/research/build/learning/anti-pattern-mining) — The subtle idea in learning from strong boards: not every agreement between them is good. Some shared placements are real structure; some are a shared trap that caps every search just short of the top. Separate the two, and attack the trap. - [KEYRING](https://eternity2.dev/research/lab/experiments/raphael-anjou/learning/keyring) — Build a board from scratch, ranking each next piece by three signals learned from past strong boards. Reached 460 in a board family no earlier search had cracked. - [Beam search](https://eternity2.dev/research/build/construct/beam-search) — Keep the K most promising partial boards alive at once and grow them cell by cell. Beam search is the workhorse behind this project's from-scratch builders, and a clean illustration of why breadth alone stalls in the deep interior. - [Forbidden patterns](https://eternity2.dev/research/why/forbidden-patterns) — Almost every small patch of pieces you could build is impossible. For a 2×2 square, 99.72% of the ways to place four pieces can never be made to match. --- # When learning collapses > The sobering half of learning from strong boards. A learned signal reaches the top of a search's own range reliably, and then stops. Over-trust it and the search collapses; even used perfectly it does not raise the ceiling, because the ceiling is not a thing the corpus knows. - Canonical page (with interactive figures/demos): https://eternity2.dev/research/build/learning/when-learning-collapses/ - Updated: 2026-07-16 - Topics: learning, search-space - Source: The rigidity wall (this project): the measured ceiling every learned signal reaches and none passes — https://github.com/raphael-anjou/eternity2/blob/main/web/content/research/why/rigidity-wall.mdx --- The other four pages in this section are about what learning from strong boards *buys*. This one is about where it stops, and it is the page that keeps the family grounded, because every technique here has the same two failure modes and it is better to state them plainly than to let a reader mistake a bag of learned tricks for a way past the wall. ## Failure one: the signal becomes the objective Every learned signal in this section is safe only as a *tiebreak*. It decides between moves that are otherwise equal on the one thing that actually counts, the matched edge in front of you, and it must never outweigh that thing. The moment a learned prior is promoted from tiebreak to part of the objective, the search starts trading a real matched edge against a statistical hunch, and it collapses. [LODESTONE](/research/lab/experiments/raphael-anjou/learning/lodestone) is the cleanest measurement of this. At a tiny weight its scarce-piece-early prior lifts the median from-scratch score from 449 to 451 and tightens the spread. Turn the weight up even slightly and the score falls to 422, then 380, because chasing the corpus's scarce demands then trades directly against matching the edge in front of you. The same shape appears in [anti-pattern mining](/research/build/learning/anti-pattern-mining) from the other direction: using the trap list as a gentle steer reached 463, but hard-*banning* trapped placements made boards worse. A learned signal is a good nudge and a bad law. The collapse is not a tuning accident to be engineered away; it is the signal telling you it was only ever a hunch. ## Failure two: the ceiling is not in the corpus The deeper limit is quieter, because it looks like success. Used correctly, as a tiebreak, a learned signal reliably carries a search to the top of *its own range* and no further. LODESTONE is explicit that it "does not touch the basin ceiling that stops every method near the top." [PRIOR](/research/lab/experiments/raphael-anjou/learning/prior) and [KEYRING](/research/lab/experiments/raphael-anjou/learning/keyring) reach 460 from scratch, the top of the from-scratch range, but not past it. [PALIMPSEST](/research/lab/experiments/raphael-anjou/learning/palimpsest), the strongest of them, reaches 463 and then finds that rebuilding the trapped regions lands back on the same known top board rather than a new one. The reason is structural, and it is the thesis of the whole section turned around. Every board in the corpus is itself stuck below 480. A signal mined from that corpus encodes where the strong boards *are*, which is the plateau, so a learned signal that merely re-encodes the plateau cannot lift a search above it. The corpus knows the shape of the basin its boards are caught in; it does not know the way out, because none of its boards found one. What stops every method near the top is the [rigidity wall](/research/why/rigidity-wall): near a strong board the remaining mismatches lock into a single interlocking [σ-cycle](/research/why/sigma-cycles) that no local move can open. That wall is a property of the puzzle, not of any search's ignorance, and no amount of corpus mining moves it, because the corpus is made of boards that hit the very same wall. ## What the family is actually for None of this makes learning from strong boards worthless. It makes it *precise*. A learned signal is the fastest, most reliable way to get a search *to* the plateau: to build a competitive board from nothing (PRIOR, KEYRING), to reach it in a fresh basin (KEYRING's new corner family), to land at the top of the range every time rather than sometimes stumbling (LODESTONE's tightened spread), or to diagnose the exact move a search was missing to reach a known height ([REPLAY](/research/lab/experiments/raphael-anjou/learning/replay)'s double break). What it is not for is getting *past* the plateau, and a section on learning from strong boards that pretended otherwise would be selling the reader the one thing the corpus provably cannot contain. The construct-then-refine pipelines that reach this project's best boards divide the labour cleanly: a learned constructor to reach the top of the range fast, and then a separate reckoning with the rigidity wall, which learning from strong boards can describe but cannot dissolve. ## Related - [Corpus priors](https://eternity2.dev/research/build/learning/corpus-priors) — The simplest way to learn from strong boards: count where each piece tends to sit, or how often it serves a scarce demand, and use that count as a gentle tiebreak in construction. It has to stay a tiebreak; the moment it becomes part of the objective it collapses the search. - [Anti-pattern mining](https://eternity2.dev/research/build/learning/anti-pattern-mining) — The subtle idea in learning from strong boards: not every agreement between them is good. Some shared placements are real structure; some are a shared trap that caps every search just short of the top. Separate the two, and attack the trap. - [The rigidity wall](https://eternity2.dev/research/why/rigidity-wall) — Every record board we have is frozen in place. You cannot nudge your way from a great board to a perfect one, and we can prove it. - [Why basin-hopping looks impossible](https://eternity2.dev/research/why/sigma-cycles) — If you can't improve a great board by polishing it, maybe you can jump to a different great board. On every record pair tested, you can't, and the structural reason why is worth seeing. - [LODESTONE](https://eternity2.dev/research/lab/experiments/raphael-anjou/learning/lodestone) — A faint compass for a from-scratch search: nudge it to commit the rare pieces early, where they're needed. It doesn't raise the ceiling; it makes the search reliably reach the top of its own range. --- # Local search > Start with a full, imperfect board and improve it by moves: destroy-and-repair, annealing and tempering, evolutionary recombination. The most reliable polishers here, and the cleanest demonstrations of the rigidity wall, where every one of them stops at the same height. - Canonical page (with interactive figures/demos): https://eternity2.dev/research/build/local-search/ - Updated: 2026-07-13 --- Start with a full, imperfect board and improve it by moves: destroy-and-repair, annealing and tempering, evolutionary recombination. The most reliable polishers here, and the cleanest demonstrations of the rigidity wall, where every one of them stops at the same height. The pages below go technique by technique: what each is in a line, what it actually reached on the real 16×16 board, where it stops, and the labs and measurements to back it. For the whole territory at once, start with [a map of every known approach](/research/build/approaches-map). ## Pages in this section - [Local search and ALNS](https://eternity2.dev/research/build/local-search/local-search-alns) — Destroy part of a board, rebuild it better, and let the algorithm learn which demolitions pay. Adaptive large-neighborhood search is the most reliable polisher this project has, and the cleanest demonstration of the wall where polishing ends. - [Simulated annealing and parallel tempering](https://eternity2.dev/research/build/local-search/parallel-tempering) — Treat mismatches as energy and temperature as tolerance for making things worse. Annealing holds the puzzle's longest-standing record; parallel tempering crosses barriers annealing can't. Both stop at the same wall. - [Evolutionary and genetic approaches](https://eternity2.dev/research/build/local-search/evolutionary) — Breed a population of boards, keep the fittest, recombine the survivors. The most natural metaphor in the toolbox, and the one method whose central operator, crossover, fights the structure of Eternity II head-on. The complete record of what the community bred, measured, and abandoned. ## Related - [A map of every known approach](https://eternity2.dev/research/build/approaches-map) — The survey the community keeps asking for and never finds: every family of attack tried on Eternity II, what each one actually reached, where it walls out, and a link to the deep page. One organising insight runs through all of them. - [The techniques](https://eternity2.dev/research/build/techniques) — The technique shelf: the algorithms and pruning ideas that recur in every serious Eternity II solver, each with what it is, what it costs, and what it actually bought when measured on this puzzle. --- # Evolutionary and genetic approaches > Breed a population of boards, keep the fittest, recombine the survivors. The most natural metaphor in the toolbox, and the one method whose central operator, crossover, fights the structure of Eternity II head-on. The complete record of what the community bred, measured, and abandoned. - Canonical page (with interactive figures/demos): https://eternity2.dev/research/build/local-search/evolutionary/ - Updated: 2026-07-02 - Topics: local-search, learning - Source: simon.chapple's full GA blueprint: spiral genome, class-constrained genes, fitness (groups.io message 302) — https://groups.io/g/eternity2/message/302 - Source: Steve Moyer's two-week GA study, "Crossover seems to have no impact" (groups.io message 565) — https://groups.io/g/eternity2/message/565 - Source: cambdacambda: crossover not useful; 10x population = 10x CPU, same iterations (groups.io message 578) — https://groups.io/g/eternity2/message/578 - Source: sam_maes: mutation is obvious, a plausible crossover operator is not (groups.io message 1468) — https://groups.io/g/eternity2/message/1468 - Source: sam_maes on the real issue, good partial solutions are hard to combine (groups.io message 1492) — https://groups.io/g/eternity2/message/1492 - Source: TD: mixing two parents is mixing two permutations; duplicates, gaps, and the repair idea (groups.io message 1500) — https://groups.io/g/eternity2/message/1500 - Source: mobaladje's GA plateau near 406/480 (groups.io message 2360) — https://groups.io/g/eternity2/message/2360 - Source: mobaladje's classic recipe, and mismatches spread evenly across the board (groups.io message 2516) — https://groups.io/g/eternity2/message/2516 - Source: Lyman: two partial solutions are likely to need the same tiles in different places (groups.io message 2591) — https://groups.io/g/eternity2/message/2591 - Source: Lyman's repair-crossover sketch, with his own verdict (groups.io message 2612) — https://groups.io/g/eternity2/message/2612 - Source: antminder's backtracker+GA hybrid, 462/480 in about a day with a Munkres repair operator (groups.io message 5589) — https://groups.io/g/eternity2/message/5589 - Source: Pierre Schaus explains the optimal assignment neighborhood behind that repair (groups.io message 5601) — https://groups.io/g/eternity2/message/5601 - Source: antminder shelves it; a week to 463, and Verhaard's eii "completely blows it away" (groups.io message 5950) — https://groups.io/g/eternity2/message/5950 - Source: jagbrain's 2011 post-mortem on why GA/SA assumptions fail on this search space (groups.io message 8257) — https://groups.io/g/eternity2/message/8257 - Source: Niang, Solving the Eternity II Puzzle using Evolutionary Computing Techniques (MASc thesis, Concordia, 2011) — https://spectrum.library.concordia.ca/id/eprint/7487/1/Niang_MASc_S2011.pdf - Source: Wauters, Vancroonenburg & Vanden Berghe, A guide-and-observe hyper-heuristic approach to the Eternity II puzzle (JMMA 11, 2012) — https://link.springer.com/article/10.1007/s10852-012-9178-4 --- Ten days after the puzzle launched, the mailing list already had a complete genetic-algorithm design on the table: number the pieces, thread the board onto a spiral genome starting at the clue piece, score connectivity, breed ([groups.io message 302](https://groups.io/g/eternity2/message/302)). It is the most natural metaphor in the toolbox: a population of boards, survival of the best-matched, children that inherit good fragments from two good parents. Over the following years the community built these solvers, measured them carefully, and watched every one of them stall in the low 400s while plain backtrackers cruised past. This page teaches the recipe, then the reason it fails. That reason is worth understanding properly, because it is not "GAs are weak" but a precise structural clash between crossover and permutation problems. From there, the page follows the ideas that survived to the pages where they live now. ## The recipe on a board A genetic algorithm needs four ingredients, and Eternity II offers each one almost too easily: 1. **Genome.** A candidate solution encoded for breeding. Here: an assignment of the 256 pieces to the 256 cells, plus a rotation each (equivalently, a permutation of the piece list). Chapple's launch-week blueprint threaded the cells onto a spiral from the clue piece outward, with border and corner genes constrained to border and corner pieces ([message 302](https://groups.io/g/eternity2/message/302)); most later implementations used the flat board directly. 2. **Fitness.** Count the matched edges, the same 0-to-480 score the [record ladder](/research/records) is denominated in. mobaladje's solver was exactly this classic loop: generate a random population, evaluate, select the best, cross them, mutate a little, repeat ([message 2516](https://groups.io/g/eternity2/message/2516)). 3. **Mutation.** Swap two pieces, rotate one in place, scramble a small patch. Everyone agreed this part was easy: "the mutation operators are obvious," as the first serious GA thread put it ([message 1468](https://groups.io/g/eternity2/message/1468)). 4. **Crossover.** Take two high-scoring parents and produce a child that inherits from both. This is the ingredient that makes a GA a GA rather than a population of hill-climbers, and on this puzzle it is where everything goes wrong. ## The central problem: crossover on a permutation The promise of crossover is recombination of building blocks: a creature that excels at flying and one that excels at swimming might produce one that does both. Lyman Hurd stated the premise on the list (and his own doubt) in one sentence: two partial solutions are likely to need *the same tiles in different places* ([message 2591](https://groups.io/g/eternity2/message/2591)). Make that concrete. A genome is a permutation of 256 pieces. Take two good parents and cut them at a point (or mix them uniformly): the child keeps cells 1 to $k$ from parent A and the rest from parent B. Because the parents arrange the *same* pieces differently, the child now holds some pieces twice and lacks others entirely; it is not a board at all. TD spelled this out within hours of the question being asked: mixing two parents is mixing two permutations of 1..256, and the result "is not a valid permutation because some values are duplicated and other values are missing" ([message 1500](https://groups.io/g/eternity2/message/1500)). Watch it happen. Two *perfect* parents (the same solved board and its quarter-turn rotation, both flawless arrangements of the same pieces) produce a child that is illegal at almost every cut: > **[Figure]** Interactive: crossover clashes in recombination — interactive: CrossoverClashLab. Rendered on the canonical page (link above); not shown in this markdown export. The naive child's fitness is nearly perfect, which is the trap: each inherited half is internally solved, so an edge-counting fitness function loves a genome that isn't even a board. Every practical fix is a **repair operator**: delete the duplicates, insert the missing pieces ([message 1500](https://groups.io/g/eternity2/message/1500)), or swap duplicated entries between the two children to preserve as many "good ideas" as possible, as Lyman sketched before concluding he held "little hope that it will stumble upon the actual solution" ([message 2612](https://groups.io/g/eternity2/message/2612)). But the repaired genes land in cells whose neighbours were inherited from the *other* parent, where they match nothing. Repair converts crossover into a large, poorly aimed mutation. At that point the population is just a set of parallel mutation hill-climbers paying crossover's overhead. > **But crossover works on TSP?** > > sam_maes raised the natural objection: GAs handle the travelling-salesman problem, also a permutation problem ([message 1492](https://groups.io/g/eternity2/message/1492)). The difference is what a "building block" is. A tour's value lives in its adjacencies, and order-preserving crossovers (OX, PMX) inherit adjacency fragments meaningfully. An Eternity II board's value lives in exact piece-at-cell placements checked against 22 colours, and two good boards agree on almost none of them. sam_maes's own diagnosis was the right one: the problem is not the search space's size but that "good partial solutions are hard to combine." The deepest version of this argument was measured on this site years later: two high-scoring boards are related by large interlocking [σ-cycles](/research/why/sigma-cycles), and every *partial* application of a cycle scores worse than either endpoint. Crossover is exactly a partial application of the permutation connecting the parents. The valley between two good parents is not an accident of the operator: it is the structure of the landscape. ## What the community measured The record, in chronological order, is remarkably consistent. - **2007, the two-week study.** Steve Moyer ran a 1000-individual GA with order-preserving crossover and reported the numbers that settled the question early: "Crossover seems to have no impact," and population size barely matters, since a 100-individual population converged about as fast at a tenth of the cost ([message 565](https://groups.io/g/eternity2/message/565)). An independent reply confirmed both findings from separate experiments ([message 578](https://groups.io/g/eternity2/message/578)). - **2007, the plateaus.** insurrectors' GA on the inner 14×14 reached 326–330 of 364 edges and stuck, concluding GAs "are pretty bad at these types of combinatorial problems" ([message 1311](https://groups.io/g/eternity2/message/1311)). mobaladje's full-board GA hit its local optimum "towards 406 (/480)" ([message 2360](https://groups.io/g/eternity2/message/2360)), with the mismatches spread evenly across the board, no fixable weak region ([message 2516](https://groups.io/g/eternity2/message/2516)). JSA pointed at the underlying issue: the 480-metric is a poor guide, and nobody found a better one ([message 2683](https://groups.io/g/eternity2/message/2683)). - **2008, the serious hybrid.** antminder built the strongest evolutionary solver in the archive: a backtracker runs for ~3 minutes and fills most of the board legally, then a steady-state GA (every individual forced unique) polishes the remainder. The disruptive crossover is compensated by a repair operator he had used before on tracking problems: pop off non-adjacent pieces and let the Munkres/Hungarian algorithm re-place them *optimally*. Average, over seven runs: 462/480 in a little over a day ([message 5589](https://groups.io/g/eternity2/message/5589)). Pierre Schaus, whose JFPC paper the operator came from, confirmed the mechanism on-list ([message 5601](https://groups.io/g/eternity2/message/5601)). Note what happened to the architecture: the GA no longer breeds boards from scratch; it manages a restart loop around a backtracker and applies an exact local repair. The genetic layer became scaffolding. - **2008, the shelving.** Three months later antminder reported his program needed "a week to reach a partial score of 463" and that Louis Verhaard's backtracking-based [eii](/research/lab/experiments/louis-verhaard/eii) "completely blows it away" ([message 5950](https://groups.io/g/eternity2/message/5950)). He shelved it. eii went on to power the 467 record; no evolutionary solver appears anywhere in the record lineage after this point. - **The long tail.** A 2009 blog asked the list what crossover people used; the one substantive reply advised against expecting GAs to progress without "going backwards and ruining previous progress" ([message 6835](https://groups.io/g/eternity2/message/6835)). A 2010 neural-network-with-GA solver was shared with the plain caveat "it wont solve your puzzle anyway" ([message 7454](https://groups.io/g/eternity2/message/7454)). A 2011 solver census recorded 190 pieces by pure backtracking against 209 with a genetic hybrid ([message 8787](https://groups.io/g/eternity2/message/8787)): respectable, and some fifty pieces short of the same era's best. jagbrain wrote the community's post-mortem the same year: GA and annealing assume a landscape you can climb, and this one is huge, "fractalized," with near-random solution placement ([message 8257](https://groups.io/g/eternity2/message/8257)). - **Where a GA *did* shine.** On the smooth side-problem of rotation sets (choose a rotation per piece so all colour counts balance), antminder's GA "almost never gets stuck in a local minimum" ([message 3443](https://groups.io/g/eternity2/message/3443)) and Varga's found balanced sets in seconds where backtracking failed ([message 8900](https://groups.io/g/eternity2/message/8900)). The contrast is the lesson: evolution handles the relaxation fine; the relaxation just turned out to prune nothing. The academic record matches the list's. The one thesis-length treatment of evolutionary computing on Eternity II ([Niang 2011](https://spectrum.library.concordia.ca/id/eprint/7487/1/Niang_MASc_S2011.pdf)) surveys the GA design space without dethroning the metaheuristics of the 2008–2012 literature, and the strongest published heuristics from that line (tabu search, VLNS, [hyper-heuristics](https://link.springer.com/article/10.1007/s10852-012-9178-4)) all abandoned recombination of boards. ## Where the surviving ideas went Nothing on this wiki is deader than board-breeding, but three ideas from the GA era survived by moving out: - **The population became restarts.** Once crossover contributes nothing, a population of mutating boards is exactly a portfolio of independent restarts. Moyer's finding that population size barely matters is the restart lesson in disguise: independent draws from the same distribution, not compounding evolution. The measured case for restart portfolios is on the [restarts page](/research/build/backtracking/restarts). - **Mutation + selection + smart repair became ALNS.** antminder's Munkres-repair operator inside a destroy/rebuild loop *is* the assignment-based refill of [local search and ALNS](/research/build/local-search/local-search-alns), where it remains the most reliable polisher this project has. The winning part of the 2008 hybrid was never the genetics; it was the neighborhood. - **Evolution moved up a level.** The hyper-heuristic line ([Wauters et al. 2012](https://link.springer.com/article/10.1007/s10852-012-9178-4)) keeps selection-and-adaptation but applies it to *operators*, not boards: learn which moves are paying and lean on them. That is literally the "adapt" step of ALNS. Evolving the search's parameters survived; evolving its solutions did not. ## What it costs - **Per generation: $O(P \cdot (f + g))$** for population size $P$, fitness cost $f$ (a linear edge count, cheap) and operator cost $g$, which is cheap for swap mutations, $O(k^3)$ per Hungarian repair of $k$ cells, and worthless in between for repaired crossover. The multiplier $P$ is the painful part: the community's measurements say it buys diversity that mutation alone replicates at a tenth of the cost ([message 578](https://groups.io/g/eternity2/message/578)). - **No guarantees of any kind.** No completeness, no optimality certificate, and, unlike [ALNS](/research/build/local-search/local-search-alns), which at least polishes a good board it is handed, a GA bred from random populations spends most of its budget rediscovering what a greedy constructor produces in milliseconds. - **Where GAs actually top out.** Pure GAs plateau around 406/480 on the full board ([message 2360](https://groups.io/g/eternity2/message/2360)). The best hybrid ever reported on the list averaged 462 per day in 2008 by demoting the GA to a management layer over a backtracker and an exact repair ([message 5589](https://groups.io/g/eternity2/message/5589)), and its author shelved it the week a pure backtracking solver appeared ([message 5950](https://groups.io/g/eternity2/message/5950)). Crossover, the one idea evolution brings that nothing else in this catalogue has, is structurally wrong for a puzzle whose good solutions [share almost nothing transplantable](/research/why/sigma-cycles). What survived of the GA era is real, and none of it is genetic. ## Related - [Local search and ALNS](https://eternity2.dev/research/build/local-search/local-search-alns) — Destroy part of a board, rebuild it better, and let the algorithm learn which demolitions pay. Adaptive large-neighborhood search is the most reliable polisher this project has, and the cleanest demonstration of the wall where polishing ends. - [Dead ends](https://eternity2.dev/research/build/dead-ends) — Approaches we tried that look promising and don't move the needle on Eternity II, written down with what we found so you can spend your time elsewhere. - [Why basin-hopping looks impossible](https://eternity2.dev/research/why/sigma-cycles) — If you can't improve a great board by polishing it, maybe you can jump to a different great board. On every record pair tested, you can't, and the structural reason why is worth seeing. --- # Local search and ALNS > Destroy part of a board, rebuild it better, and let the algorithm learn which demolitions pay. Adaptive large-neighborhood search is the most reliable polisher this project has, and the cleanest demonstration of the wall where polishing ends. - Canonical page (with interactive figures/demos): https://eternity2.dev/research/build/local-search/local-search-alns/ - Updated: 2026-07-02 - Topics: local-search - Source: Pierre Schaus's JFPC paper + the Hungarian-refill neighborhood, first detailed on the list (groups.io msg 5589, June 2008) — https://groups.io/g/eternity2/message/5589 - Source: Ropke & Pisinger, An Adaptive Large Neighborhood Search Heuristic for the Pickup and Delivery Problem with Time Windows (Transportation Science, 2006) — https://doi.org/10.1287/trsc.1050.0135 - Source: Shaw, Using Constraint Programming and Local Search Methods to Solve Vehicle Routing Problems (CP 1998, the original LNS) — https://link.springer.com/chapter/10.1007/3-540-49481-2_30 - Source: Schaus & Deville, Hybridization of CP and VLNS for Eternity II (JFPC 2008) — https://hdl.handle.net/2078.5/253676 --- Once you hold a strong board, single-piece moves stop paying almost immediately. Large-neighborhood search takes the opposite bet: rip out a whole region (dozens of cells) and rebuild it with something smarter than the greedy pass that put it there. The idea is Paul Shaw's ([CP 1998](https://link.springer.com/chapter/10.1007/3-540-49481-2_30)); the *adaptive* version, ALNS, is due to Ropke and Pisinger ([Transportation Science 2006](https://doi.org/10.1287/trsc.1050.0135)), who added a portfolio of destroy and repair operators and a learning rule that steers effort toward the operators that have recently succeeded. ## The loop One ALNS iteration on a board: 1. **Destroy.** Pick a destroy operator, unplace the $k$ cells it selects. 2. **Repair.** Refill the hole (greedy fill, [constraint propagation](/research/build/reduce/arc-consistency), or an exact solve of the small subproblem). 3. **Accept.** Keep the new board if it scores better, or sometimes anyway under a simulated-annealing rule. 4. **Adapt.** Reweight the operators by their recent success, so the roulette wheel favours what has been working. Eternity II is unusually friendly to step 1, because a partial board tells you exactly where it hurts: the mismatched edges. ## Watch it run Reading the loop is one thing; watching it learn is another. Below, a real solved 8×8 from the engine has been deliberately damaged, and the full ALNS loop runs on it in slow motion: destroy, greedy refill piece by piece, accept or revert, reweight. Force an operator by hand and watch its weight bar respond; or just let the roulette drift toward whatever has been paying. > **[Figure]** Interactive: the destroy-and-repair loop — interactive: AlnsLoopLab. Rendered on the canonical page (link above); not shown in this markdown export. ## Step by step One iteration, exactly as the lab executes it: 1. **Draw an operator.** Roulette-wheel selection: operator $o$ is picked with probability $w_o / \sum_j w_j$. All weights start equal; the wheel is uniform until results arrive. 2. **Destroy.** The operator returns $k$ cells and their pieces come off the board. Picking random cells or a fixed shape is $O(k)$; conflict-guided operators (worst row, most-conflicted cells) also need the mismatch map, which costs a linear scan unless the engine maintains it incrementally. Ours does, precisely so that destroy stays $O(k)$. 3. **Repair, greedily.** Until the hole is full: take the empty cell with the most placed neighbours (most-constrained first), try every lifted piece in all four rotations, keep the placement that matches the most seams. Each of the $k$ placements scans the remaining candidates, so the pass costs $O(k \cdot |C|)$ where $|C|$ is the candidate pool (free pieces × 4 rotations). 4. **Accept or revert.** Score the rebuilt region; only the seams touching the $k$ cells changed, so re-evaluation is $O(k)$. Keep the board if $\Delta \geq 0$, else keep it anyway with probability $e^{\Delta/T}$; on rejection, restore the snapshot. 5. **Adapt.** Update the winner's weight, $w_o \leftarrow \lambda\, w_o + (1 - \lambda)\, \psi$, where the reward $\psi$ is tiered: new global best > improvement > accepted sideways move > rejection. That exponential smoothing is the whole "adaptive" in ALNS. Ropke and Pisinger's original does the same bookkeeping over segments of a few hundred iterations. ## What it costs Per iteration, with $k$ destroyed cells: $$ \underbrace{O(k)}_{\text{destroy}} \;+\; \underbrace{O(k \cdot |C|)}_{\text{greedy repair}} \;+\; \underbrace{O(k)}_{\text{evaluate}} \;+\; \underbrace{O(|\mathcal{O}|)}_{\text{adapt}} $$ Three refinements worth knowing: - **Optimal refill is an assignment problem (sometimes).** When the freed cells are pairwise non-adjacent, each hole's cost depends only on its fixed neighbours, so the refill is exactly a $k \times k$ assignment problem: the Hungarian algorithm solves it optimally in $O(k^3)$. That is Schaus's Eternity II neighborhood. The moment two holes touch, their choices couple, and optimal repair becomes a small CP/exact search, worst-case exponential in $k$, which is why large destroys stop paying. - **Anytime, and nothing more.** ALNS improves a feasible answer and can be stopped whenever; the best board so far *is* the output. It carries no completeness or optimality guarantee: it can never certify that no better board exists. On this puzzle that certificate has to come from elsewhere (the SAT oracle behind the [rigidity wall](/research/why/rigidity-wall)). - **At Eternity II scale the loop is cheap; the escape is not.** With $k = 20$–$80$ of 256 cells and a few hundred candidates per hole, an iteration costs microseconds to milliseconds, and improvement curves flatten within dozens of iterations. The binding cost is therefore not the arithmetic but the probability that a $k$-cell neighbourhood contains the one interlocking [σ-cycle](/research/why/sigma-cycles) that leads upward, and that probability is what collapses near the top. ## An operator portfolio for boards The destroy operators this project shipped are mostly geometry- and conflict-aware: random cells as a baseline, cells incident to mismatched edges, the top-$k$ most conflicted cells, the worst row or band of rows, a connected component of the mismatch graph (optionally with a one-cell halo around it), rectangles, and concentric rings. Two findings from tuning the portfolio, both measured on this project's engine and not independently replicated: - **Curation beats coverage.** A curated set of five operators outperformed the full set of eleven; spreading the adaptive weights across too many operators dilutes the learning signal. - **Temperature is not the lever.** Across a tenfold range of acceptance temperatures the end scores were identical, because near the top the landscape is dominated by equal-score plateaus where essentially every move is accepted at any temperature. That destroy-and-repair suits this puzzle is an old observation: Schaus and Deville hybridized constraint programming with large-neighborhood search on Eternity II back in [2008](https://hdl.handle.net/2078.5/253676), using CP as the repair step, the same division of labour that works here. ## What it reliably buys Final polish. On this project's engine, ALNS is the step that turns constructive output into record-class boards: [beam](/research/build/construct/beam-search) builds that land in the mid-450s consistently gain several edges under a refinement pass, and the project's strongest boards all carry an ALNS lift as their last stage. On smaller generated puzzles the effect is dramatic and repeatable: destroy-and-repair closes most of the distance between a random placement and the best reachable score, across a wide range of puzzle tightness, before saturating on the very hardest instances. (All of this is measured here, hedged accordingly.) Just as characteristic: the gains arrive early. Improvement curves flatten within the first few dozen iterations, and letting a run go ten times longer reproduces the same final score. When ALNS stops, it has stopped. ## The wall it hits Why it stops is the interesting part, and this site has two full pages on it. On every top board, the remaining mismatches are provably locked: freeing a generous neighbourhood around them and searching it exhaustively finds nothing better; that is the [rigidity wall](/research/why/rigidity-wall). And moving from one top board to a better one requires relocating a large set of pieces in one interlocking loop, where every partial application of the loop scores worse than doing nothing: the [σ-cycle structure](/research/why/sigma-cycles). ALNS is exactly the wrong shape for that. A destroy neighbourhood of 20–80 cells almost never covers the one cycle that matters, and when the destruction is large enough to cover it, the repair step faces a subproblem nearly as hard as the puzzle itself and gives back less than was torn down. Destroy-and-repair explores a basin superbly and escapes it essentially never. The summary this project's measurements support: ALNS is the best last mile we have, and it is only a last mile. ## Related - [The repair study](https://eternity2.dev/research/lab/experiments/raphael-anjou/repair-study) — The sibling of the DFS study, for the other way people attack Eternity II: destroy part of a board, rebuild it, keep the change if it helps. One question, asked carefully. What does each decision in that loop buy: which region to destroy, how to rebuild it, when to keep a move, when to restart, and what board to start from? - [PALIMPSEST](https://eternity2.dev/research/lab/experiments/raphael-anjou/learning/palimpsest) — Read every strong board to find the habits that quietly hold a board back, then break them. This experiment produced the project's best board: 463 of 480. - [The rigidity wall](https://eternity2.dev/research/why/rigidity-wall) — Every record board we have is frozen in place. You cannot nudge your way from a great board to a perfect one, and we can prove it. - [Why basin-hopping looks impossible](https://eternity2.dev/research/why/sigma-cycles) — If you can't improve a great board by polishing it, maybe you can jump to a different great board. On every record pair tested, you can't, and the structural reason why is worth seeing. - [Beam search](https://eternity2.dev/research/build/construct/beam-search) — Keep the K most promising partial boards alive at once and grow them cell by cell. Beam search is the workhorse behind this project's from-scratch builders, and a clean illustration of why breadth alone stalls in the deep interior. - [Simulated annealing and parallel tempering](https://eternity2.dev/research/build/local-search/parallel-tempering) — Treat mismatches as energy and temperature as tolerance for making things worse. Annealing holds the puzzle's longest-standing record; parallel tempering crosses barriers annealing can't. Both stop at the same wall. --- # Simulated annealing and parallel tempering > Treat mismatches as energy and temperature as tolerance for making things worse. Annealing holds the puzzle's longest-standing record; parallel tempering crosses barriers annealing can't. Both stop at the same wall. - Canonical page (with interactive figures/demos): https://eternity2.dev/research/build/local-search/parallel-tempering/ - Updated: 2026-07-02 - Topics: local-search - Source: Swendsen & Wang, Replica Monte Carlo Simulation of Spin-Glasses (Physical Review Letters, 1986) — https://doi.org/10.1103/PhysRevLett.57.2607 - Source: Earl & Deem, Parallel tempering: Theory, applications, and new perspectives (Phys. Chem. Chem. Phys., 2005) — https://arxiv.org/abs/physics/0508111 - Source: The Eternity II mailing list, where Verhaard described his 2008 annealing method (groups.io) — https://groups.io/g/eternity2 --- Simulated annealing reads a board as a physical system: unmatched edges are energy, moves that lower the energy are always accepted, and moves that raise it are accepted with probability $e^{-\Delta E / T}$. Run hot and the search wanders; cool it and the board settles into a low-energy arrangement, ideally a deep one, not merely the nearest one. The catch is the schedule: cool too fast and you freeze into a mediocre local optimum, cool slowly enough for a puzzle this size and you wait forever. ## From one temperature to a ladder Parallel tempering (replica exchange) dissolves the schedule problem by running the whole ladder at once. The method comes from spin-glass physics: Swendsen and Wang's [1986 replica Monte Carlo paper](https://doi.org/10.1103/PhysRevLett.57.2607) is the precursor, replica exchange in its modern form is usually credited to Geyer (1991) and Hukushima and Nemoto (1996), and Earl and Deem's [2005 review](https://arxiv.org/abs/physics/0508111) is the standard modern survey. $K$ copies of the board run simulated annealing at fixed temperatures $T_1 < T_2 < \dots < T_K$; periodically, adjacent replicas propose to swap states, accepted with the Metropolis rule $$ P(\text{swap}) = \min\bigl(1,\; e^{(\beta_i - \beta_j)(E_i - E_j)}\bigr) = \min\bigl(1,\; e^{\Delta\beta\,\Delta E}\bigr), $$ with $\beta = 1/T$, $\Delta\beta = \beta_i - \beta_j$ and $\Delta E = E_i - E_j$. Read it once with concrete signs: if replica $i$ is the colder one ($\Delta\beta > 0$) and the hotter replica holds the *lower* energy ($\Delta E > 0$), the exponent is positive and the swap is accepted with certainty: the good state always gets handed down the ladder for free. Hot replicas roam across barriers; cold replicas exploit; the swaps shuttle promising configurations down the ladder to be refined. No single chain ever has to survive a cooling schedule. ## See the ladder beat one cold chain The claim worth seeing is the comparison: the same cold chain, with and without a ladder above it. Below, four replicas explore a rugged synthetic landscape whose global minimum hides behind barriers; a grey ghost runs the identical cold dynamics alone. Watch the swap flashes (green for accepted) carry the right-hand basin down to the cold rung, while the ghost sits in the starting well forever. Then drag the spacing slider to both extremes and reproduce the two classic ladder failures. > **[Figure]** Interactive: the parallel-tempering ladder — interactive: TemperingLadderLab. Rendered on the canonical page (link above); not shown in this markdown export. ## Step by step One round of parallel tempering, as the lab runs it: 1. **Sweep.** Every replica performs Metropolis moves at its own fixed temperature: propose a local change, compute $\Delta E$, accept if downhill, else with probability $e^{-\Delta E / T_i}$. On a board, a single-piece move touches at most four seams, so each move's $\Delta E$ is $O(1)$. 2. **Swap attempt.** Pick an adjacent pair $(i, i{+}1)$, compute $\Delta\beta\,\Delta E$ from the two cached energies, accept with $\min(1, e^{\Delta\beta \Delta E})$. On acceptance the two replicas exchange configurations (equivalently: temperatures); nothing else moves. 3. **Bookkeeping.** Track the swap-acceptance rate per rung pair. That number *is* the ladder diagnostic: near 100%, adjacent rungs see the same landscape and one of them is wasted; near 0%, the ladder has decoupled into independent chains. Useful ladders sit in the tens of percent: frequent but not free, exactly the regime Earl and Deem recommend and the one our runs converged to. 4. **Repeat.** The good states random-walk down the rungs; the stuck states ride up, get shaken loose, and come back different. ## What it costs - **Per sweep:** $R$ replicas × $N$ sites, each move $O(1)$ local evaluation, so $O(R \cdot N)$, exactly $R$ times one chain. Memory is $O(R \cdot N)$: every replica is a full board. - **Per swap phase:** the $R{-}1$ adjacent pairs each need one exponential of cached energies: $O(R)$ total, a rounding error next to the sweeps. - **The win is mixing time, not step cost.** A lone cold chain crosses an energy barrier $\Delta E$ in roughly $e^{\Delta E / T_{\text{cold}}}$ attempts (the Arrhenius wait; our measured 76-cell crossing sat at $e^{-21}$ per attempt at $T = 1$). The ladder replaces that wait with diffusion: a configuration random-walks across $R$ rungs, and with geometric spacing tuned for constant per-rung acceptance, a round trip costs on the order of $R^2$ swap rounds. You pay a constant factor $R$ per sweep to turn an exponential wait into a polynomial shuttle. That asymmetry is the entire argument for the method. - **No guarantees, same as all samplers.** Parallel tempering is not complete and certifies nothing; it converges to the right distribution eventually, with no useful bound on "eventually". And where the landscape offers ties instead of barriers, as on the iso-score plateaus at the top of this puzzle, $\Delta E = 0$ makes every rung behave identically, and the ladder's advantage vanishes by construction, which is precisely what the verdict below reports. ## Why this puzzle needs the ladder This project's measurements (on our own engine; not independently replicated) give an unusually concrete reason. Between one strong board and a better one, the connecting move is a single interlocking relocation of dozens of pieces in which *every* strict subset of the move loses edges: the [σ-cycle structure](/research/why/sigma-cycles). One measured transition required a 76-cell move whose intermediate states sat about 21 edges below the start: at $T = 1$ the acceptance is on the order of $e^{-21}$, hopeless. With the ladder's top temperature raised to roughly 30, the crossing actually happened, and produced what was then the project's best cold-start board. Temperature, used correctly, is a real lever against real barriers. Ladder design is where practice bites. When we spaced the temperatures too closely, replica exchange accepted every swap. A 100% acceptance rate sounds healthy and means the opposite: adjacent replicas saw effectively the same landscape, and the ladder added nothing. Geometric spacing with a genuinely hot top rung, tuned so that swaps are frequent but not free, is the standard advice in Earl and Deem, and it matched what we observed. ## The community record that annealing built Annealing has a distinguished history on this puzzle. The longest-standing record on the canonical piece set (Louis Verhaard's 467 of 480 in 2008, unbeaten until the Blackwood-era backtrackers of 2020) came from an annealing method, and an unusual one: as he described it on the [community mailing list](https://groups.io/g/eternity2), he annealed the *composition* of a piece subset, swapping pieces in and out of a candidate group under a tilability score, rather than annealing positions on the board. The lesson generalizes: on Eternity II, the choice of *what to anneal* mattered more than the annealing itself. ## The verdict From this project's measurements, hedged accordingly: parallel tempering is a better barrier-crosser than plain annealing, and on the mid-range of the climb that difference is real and bankable. Near the top it dissolves. The plateaus up there are iso-score: ties everywhere, so acceptance no longer depends on temperature at all, and cranking the heat instead of climbing just randomizes the board, which then never finds its way back to record territory. Replicas launched from a top board plateau at the seed's score, every chain, every ladder we tried. Tempering moves you between hills; it does not repeal the [rigidity wall](/research/why/rigidity-wall). ## Related - [The rigidity wall](https://eternity2.dev/research/why/rigidity-wall) — Every record board we have is frozen in place. You cannot nudge your way from a great board to a perfect one, and we can prove it. - [Why basin-hopping looks impossible](https://eternity2.dev/research/why/sigma-cycles) — If you can't improve a great board by polishing it, maybe you can jump to a different great board. On every record pair tested, you can't, and the structural reason why is worth seeing. - [Local search and ALNS](https://eternity2.dev/research/build/local-search/local-search-alns) — Destroy part of a board, rebuild it better, and let the algorithm learn which demolitions pay. Adaptive large-neighborhood search is the most reliable polisher this project has, and the cleanest demonstration of the wall where polishing ends. --- # Reduce the search > Everything that throws away hopeless states before the search wastes time on them: propagation to a fixed point, the all-different matching filter, learned no-goods, and the edge-slipping invariant. - Canonical page (with interactive figures/demos): https://eternity2.dev/research/build/reduce/ - Updated: 2026-07-13 --- Everything that throws away hopeless states before the search wastes time on them: propagation to a fixed point, the all-different matching filter, learned no-goods, and the edge-slipping invariant. These prune hard on small boards; the recurring lesson here is how far that pruning reaches on the full 16×16, and where it fades. The pages below go technique by technique: what each is in a line, what it actually reached on the real 16×16 board, where it stops, and the labs and measurements to back it. For the whole territory at once, start with [a map of every known approach](/research/build/approaches-map). ## Pages in this section - [Arc consistency, from AC-3 up](https://eternity2.dev/research/build/reduce/arc-consistency) — Forward checking looks one move ahead; arc consistency makes every cell's candidate list defend itself against every neighbour's, to a fixed point. Mackworth's AC-3, the optimal refinements that followed, and what the whole family actually measured on this puzzle, including where it is unsound. - [All-different, Régin's matching filter](https://eternity2.dev/research/build/reduce/alldiff-regin) — No piece may be used twice: one global all-different constraint over 256 cells. Jean-Charles Régin showed in 1994 how bipartite matching filters it completely in polynomial time; its per-colour cousin is the strongest propagator anyone has measured on edge matching, with one sharp caveat about mismatch-tolerant searches. - [Edge slipping](https://eternity2.dev/research/build/reduce/edge-slipping) — Louis Verhaard's prize-winning move: let the backtracker place a mismatched piece, but only at chosen depths near the end of the board. Each allowed slip costs one point of score and multiplies the number of target boards astronomically. That is why his 467 was found more than fifty times, and the direct ancestor of Blackwood's breaks. - [No-good learning: remembering why you failed](https://eternity2.dev/research/build/reduce/nogood-learning) — A failed subtree is a theorem: this partial state can never extend. Store it and never re-enter. The community tried both flavours: chess-style transposition tables over the search frontier, and mined constraints about the puzzle itself. The full ledger of what memory buys at E2 scale, and the small boards where it genuinely pays. ## Related - [A map of every known approach](https://eternity2.dev/research/build/approaches-map) — The survey the community keeps asking for and never finds: every family of attack tried on Eternity II, what each one actually reached, where it walls out, and a link to the deep page. One organising insight runs through all of them. - [The techniques](https://eternity2.dev/research/build/techniques) — The technique shelf: the algorithms and pruning ideas that recur in every serious Eternity II solver, each with what it is, what it costs, and what it actually bought when measured on this puzzle. --- # All-different, Régin's matching filter > No piece may be used twice: one global all-different constraint over 256 cells. Jean-Charles Régin showed in 1994 how bipartite matching filters it completely in polynomial time; its per-colour cousin is the strongest propagator anyone has measured on edge matching, with one sharp caveat about mismatch-tolerant searches. - Canonical page (with interactive figures/demos): https://eternity2.dev/research/build/reduce/alldiff-regin/ - Updated: 2026-07-02 - Topics: search-space, exact-methods - Source: Régin 1994, "A Filtering Algorithm for Constraints of Difference in CSPs" (AAAI-94) — https://cdn.aaai.org/AAAI/1994/AAAI94-055.pdf - Source: Ansótegui, Béjar, Fernández & Mateu 2008, "Edge Matching Puzzles as Hard SAT/CSP Benchmarks" (CP 2008): the per-colour matching filter — https://doi.org/10.1007/978-3-540-85958-1_42 - Source: Hopcroft–Karp matching algorithm (Wikipedia) — https://en.wikipedia.org/wiki/Hopcroft%E2%80%93Karp_algorithm --- Underneath the colour matching, Eternity II carries a second global law: the 256 cells must take 256 *distinct* pieces. Written as a constraint, that is a single all-different over the whole board. Most solvers enforce it in the weakest possible way (when a piece is placed, cross it off everywhere else), which misses a whole class of dead positions: five cells whose remaining candidates draw on only four pieces are already unsolvable, and simple crossing-off will not notice until much later. ## Régin's 1994 filter Jean-Charles Régin showed that the all-different constraint can be filtered *completely*, in polynomial time: every candidate that appears in no valid global assignment gets removed. The construction is pure graph theory: 1. Build the bipartite graph of cells versus pieces, with an edge wherever a piece is still in a cell's domain. 2. Compute a maximum matching (Hopcroft–Karp, $O(m \sqrt{n})$). If it fails to cover every cell, the position is dead; backtrack immediately. 3. Orient the graph around the matching and compute its strongly connected components (Tarjan, linear time). A theorem of Berge then identifies, in one pass, exactly which edges belong to *some* maximum matching. 4. Every edge that belongs to none is a candidate that can be deleted from its cell's domain, soundly. This paper effectively founded the field of global constraints in constraint programming: a constraint over hundreds of variables, filtered to optimality by one combinatorial algorithm instead of being decomposed into weak pairwise checks. Incremental versions (Régin 1995; Mehlhorn & Thiel 2000) repair the matching after a few deletions instead of recomputing it, which is what makes it affordable inside a search loop. ## See the filter run The construction is easier to believe than to picture, so here it is on a six-piece instance built to contain a trap: cells C1 and C2 both draw on only pieces P1 and P2, a Hall set. Crossing-off sees nothing wrong with C3 holding P2 as a candidate; the matching argument proves it can never happen. Build the matching first (watch an augmenting path evict and re-route an earlier assignment), then run the filter and watch the strongly connected components expose every edge that no maximum matching can use. > **[Figure]** Interactive: Régin's matching filter at work — interactive: ReginMatchingLab. Rendered on the canonical page (link above); not shown in this markdown export. The payoff to notice: three edges deleted, and two cells *forced*. C3 must take P3 and C6 must take P6, conclusions that pairwise reasoning would only reach after branching. That is what "filtering to optimality" means: after Régin's pass, every surviving candidate genuinely participates in some complete assignment. ## Step by step The same run, in words: 1. **Build the bipartite graph.** Cells on one side, pieces on the other, an edge wherever a piece is still in a cell's domain: six cells, six pieces, thirteen edges in the demo. 2. **Grow a matching by augmenting paths.** C1 takes P1. C2 also wants P1: instead of giving up, follow the *alternating path* C2–P1–C1–P2. P1 is taken, but its owner C1 has a free alternative, P2. Flip every edge on the path: C1 slides to P2, C2 gets P1, and the matching has grown by one. Repeat until every cell is covered. If some cell ever exhausts its paths, there is no complete assignment and the search backtracks on the spot. 3. **Orient the graph.** Matched edges point cell → piece; unmatched edges point piece → cell. Now an alternating cycle in the original graph is a directed cycle in this one. 4. **Compute strongly connected components** (Tarjan, one linear pass). In the demo, \{C1, C2, P1, P2\} form one component (they trade their two pieces around a cycle) and \{C4, C5, P4, P5\} another. 5. **Apply Berge's rule.** An unmatched edge can join *some* maximum matching only if it lies on an alternating cycle (same SCC) or on an alternating path from a free vertex (none here; the matching is perfect). Everything else is dead: C3–P2, C4–P3 and C6–P5 each cross two components, so they are deleted, provably rather than heuristically. 6. **Read off the reductions.** C3's domain drops to \{P3\}, C6's to \{P6\}: two forced placements found without a single branch. ## What it costs One invocation from scratch is two graph passes: - **Maximum matching** via Hopcroft–Karp: $O(m \sqrt{n})$ for $m$ feasible edges over $n$ vertices, the dominant term. - **SCC decomposition** via Tarjan: $O(n + m)$, linear, plus the same again to sweep the edges and delete. For the piece-level all-different on Eternity II, $n = 512$ vertices (256 cells + 256 pieces) and $m$ at most $256 \times 256 = 65{,}536$ edges, so $m\sqrt{n} \approx 1.5$ million edge operations for a full build. That is small change on modern hardware, and it is the *worst* case, from scratch, with maximally loose domains. Inside a search nobody rebuilds: the incremental versions cited above keep the previous matching, repair it with a few augmenting paths after each domain change, and re-run the linear SCC pass, which comes to near-linear re-filtering per node in practice. The per-colour variant is smaller still: one graph per colour class over only the half-edges showing that colour, 22 little matchings instead of one big one. The polynomial label is the point: this is complete filtering of a global constraint for graph-algorithm prices, not search prices. ## Why it bites on Eternity II The same theorem applies at two different levels on this puzzle. **Per colour.** For each colour, the half-edges showing it must pair up perfectly across adjacent cells: a perfect-matching condition per colour class. Ansótegui, Béjar, Fernández and Mateu built exactly this propagator on Régin's theorem for edge-matching CSPs and called it the most powerful global constraint they had found for these puzzles. That matches this project's experience: the per-colour filter is the strongest propagator in the project's exact-matching engine, the ingredient that (together with [arc consistency](/research/build/reduce/arc-consistency)) lifts a plain backtracker to 449 of 480 edges in under a minute (measured on this project's engine, not independently replicated). It earns its keep late: the project gates it to deep positions, where domains are tight enough for matchings to fail and the cost is repaid. **Per piece.** The direct reading, remaining pieces versus empty cells, catches the Hall-style traps that crossing-off misses: whole groups of cells competing for too few pieces, detected before the pairwise machinery sees any contradiction. Since [no move is ever forced](/research/why/no-forced-moves) on this puzzle, a filter that reasons about groups rather than single cells is exactly the kind of leverage in short supply. ## The Blackwood caveat, stated plainly The per-colour filter assumes every colour must match *exactly*. A [Blackwood-style search](/research/lab/experiments/joshua-blackwood/solver) breaks that assumption on purpose: its break indices license a budget of mismatches at late depths, so a board the filter proves "impossible" may be exactly the 470 the search is hunting. Running the per-colour matching filter inside a mismatch-tolerant search is unsound, full stop. On this project's engine it is switched off in that regime, and dropping it (with the rest of the strict propagators) was part of a large single-thread speedup. The piece-level all-different is the exception, and it matters: even a mismatch-tolerant search never uses a piece twice. Piece uniqueness stays strict when colour matching does not, so Régin's filter over pieces remains sound in precisely the regime where everything else in the propagation family breaks. It is the one strong global propagator available to a record engine. ## Benefit, and what is not yet known The cost side of the ledger is above, and it is polynomial all the way down. The benefit side, though, has a hole in it: Régin's original paper benchmarks a 25-variable toy, and there is no published measurement of the filter on a 256-variable all-different shaped like Eternity II. This project has not built the piece-level version either; its promise inside mismatch-tolerant searches is an argument, not a number. Treat it as the best-reasoned open bet on the shelf: sound where nothing else strong is, cost known to be polynomial, payoff unmeasured. ## Related - [Arc consistency, from AC-3 up](https://eternity2.dev/research/build/reduce/arc-consistency) — Forward checking looks one move ahead; arc consistency makes every cell's candidate list defend itself against every neighbour's, to a fixed point. Mackworth's AC-3, the optimal refinements that followed, and what the whole family actually measured on this puzzle, including where it is unsound. - [Blackwood's solver, decoded and run here](https://eternity2.dev/research/lab/experiments/joshua-blackwood/solver) — Joshua Blackwood's record backtracker, decoded through Jef Bucas's notes (a colour quota schedule and a late-game mismatch allowance, tuned near-optimally), then built and run on my M1: left as published it flies to 248 of 256 pieces ignoring the clues; pin the five official clues and the same engine stalls near 45. - [No forced moves](https://eternity2.dev/research/why/no-forced-moves) — The usual way to crack a logic puzzle is to find a spot where only one piece fits, place it, and repeat. That lever doesn't exist here: every interior piece has between 73 and 137 possible neighbours, and not one is ever pinned to a single option. - [Dead ends](https://eternity2.dev/research/build/dead-ends) — Approaches we tried that look promising and don't move the needle on Eternity II, written down with what we found so you can spend your time elsewhere. --- # Arc consistency, from AC-3 up > Forward checking looks one move ahead; arc consistency makes every cell's candidate list defend itself against every neighbour's, to a fixed point. Mackworth's AC-3, the optimal refinements that followed, and what the whole family actually measured on this puzzle, including where it is unsound. - Canonical page (with interactive figures/demos): https://eternity2.dev/research/build/reduce/arc-consistency/ - Updated: 2026-07-02 - Topics: search-space - Source: Mackworth 1977, "Consistency in Networks of Relations" (Artificial Intelligence 8): AC-3 — https://doi.org/10.1016/0004-3702(77)90007-8 - Source: Bessière, Régin, Yap & Zhang 2005, "An Optimal Coarse-grained Arc Consistency Algorithm" (AIJ): AC-2001/AC-3.1 — https://doi.org/10.1016/j.artint.2005.02.004 - Source: AC-3 algorithm (Wikipedia) — https://en.wikipedia.org/wiki/AC-3_algorithm --- A backtracker on Eternity II spends most of its effort not placing pieces but ruling them out. Since [no cell is ever forced](/research/why/no-forced-moves) (every interior position keeps dozens of live candidates deep into the search), the only leverage available is shrinking those candidate lists as hard and as cheaply as possible. Arc consistency is the standard machine for doing that, and it has a fifty-year paper trail. ## Domains that police each other Give every empty cell a *domain*: the set of piece-and-rotation candidates still allowed there. On the full puzzle that starts at roughly 764 tuples per interior cell. **Forward checking** is the one-step discipline: when a piece is placed, delete it from every other domain and delete every candidate that clashes with the newly exposed edges. Cheap, and every serious solver does at least this. **Arc consistency** demands more. For every pair of adjacent cells, every candidate in one domain must have at least one compatible partner in the other, a *support*. When a deletion anywhere leaves a candidate unsupported, that candidate goes too, and the check ripples outward until nothing more can be removed. For edge-matching this is exactly "a piece may stay in a cell only if each neighbouring cell can still answer its colours". ## AC-3, and where it wastes work Alan Mackworth's AC-3 (1977) is the coarse-grained way to reach that fixed point: keep a queue of directed arcs, revise one arc at a time (scan a domain, delete unsupported candidates), and whenever a domain shrinks, requeue the arcs that point at it. It is short, correct, and easy to make incremental inside a search, which is why it is still the default everywhere. Worst case it costs $O(e d^3)$ for $e$ arcs and domain size $d$; on the 16×16 board $e$ is $e = 960$ (the 480 interior adjacencies, both directions) and $d \approx 764$. Its known flaw: every revision searches for supports from scratch, so the same support gets rediscovered thousands of times as the search dives and backtracks. ## Watch it run Descriptions of worklist algorithms all sound alike; watching one settle is what makes it click. Below is AC-3 on a toy version of the problem: a 4×4 board, 3 edge colours, every cell starting with all 64 candidates (16 tiles × 4 rotations). Place a piece and follow the queue: which arcs enter it, what each revision deletes, how a deletion re-arms the arcs pointing at the shrunken domain, and how the ripple dies out. The counters compare AC-3's work against the naive fixed-point loop (AC-1: re-sweep every arc until a full pass is clean) running on the exact same positions. > **[Figure]** Interactive: watch AC-3 settle to a fixed point — interactive: AcThreeLab. Rendered on the canonical page (link above); not shown in this markdown export. Two things are worth noticing. Early placements barely ripple: one ring of neighbours shrinks and the wave stops, because the second ring still finds supports for all three colours among the survivors. Late placements ripple much further: domains are tight, and single deletions strand candidates two and three cells away. That is exactly the behaviour on the real puzzle: arc consistency earns its keep in the endgame, not the opening. ## Step by step The same run, in words. This is all of AC-3: 1. **Start.** Every cell holds a domain of 64 candidates. The arc queue is empty; with no deletions yet, there is nothing to check. 2. **A piece lands on B2.** Its domain collapses to the single placed candidate. Every arc *aimed at* B2 enters the queue, one per neighbour: here (B1→B2), (C2→B2), (B3→B2), (A2→B2). Nothing else does: no other domain changed, so no other arc can have lost a support. 3. **Pop an arc, revise it.** Take (B1→B2): scan B1's 64 candidates, and for each one search B2's domain for a compatible partner, a *support*. B2 now holds one piece, so only candidates whose south edge matches its north colour survive: roughly a third. The rest are deleted. 4. **Deletions re-arm arcs.** B1's domain shrank, so candidates elsewhere that leaned on the deleted ones may be stranded: every arc pointing at B1 re-enters the queue, except the one from B2 that just fired. This is the ripple. 5. **No deletion, no requeue.** When a revision removes nothing, the arc is simply dropped. Early in the game the second ring almost always survives intact, and the queue drains in a handful of revisions. 6. **Fixed point.** The queue is empty: every candidate everywhere has a support in every neighbouring domain. No order of processing changes this final state: the fixed point is unique, and the queue discipline changes only how fast you reach it. The AC-1 comparison in the demo is the entire argument for the worklist: the naive loop re-revises all 48 arcs per sweep until one sweep is clean, doing the same deletions for several times the checks, and the gap widens as the board grows. ## What the stronger variants buy The literature spent two decades fixing that redundancy. AC-4 (Mohr & Henderson 1986) counts supports explicitly: optimal $O(e d^2)$ time, but $O(e d^2)$ memory and painful state restoration on backtrack. AC-6 and AC-7 (Bessière; Bessière, Freuder & Régin) store supports lazily and exploit bidirectionality, keeping optimal time with $O(e d)$ space at the price of fine-grained bookkeeping. The version worth knowing today is **AC-2001/AC-3.1**, found independently by Bessière & Régin and by Zhang & Yap in 2001: keep AC-3's simple loop, but remember for each candidate-arc pair the *last support found*, check that it is still alive before searching again, and resume the scan from where it stopped rather than from zero. That one integer per pair delivers the optimal $O(e d^2)$ bound with only $O(e d)$ memory; on this puzzle that is about 367,000 small integers, negligible. The 2005 journal study measures 1.5–9× less CPU than AC-3 in maintained-arc-consistency search, and shows the advantage over AC-6 *growing* with the domain size on the far side of the arc. Eternity II has huge domains on both sides of every arc, which makes AC-2001 the textbook fit. ## The ceiling: why not path consistency? Arc consistency checks pairs of cells. The next rung up, *path consistency*, checks triples: it removes any pair of assignments that no third cell can support, propagating a much stronger condition. It shrinks the search tree enormously, and the community measured exactly how much, and exactly why nobody uses it. In March 2008 Geoff ran the ladder on Brendan Owen's beginner puzzles ([msg 4827](https://groups.io/g/eternity2/message/4827)): - On the 6×6, plain nodal consistency leaves a search tree of over **40,000 nodes**. Partial path-1 consistency drops it to about 10,000. Partial path-2 consistency drops it to **138 nodes**, the bare minimum needed to walk to all eight solutions. But the runtime goes from 0.25 seconds to over **10 seconds**. - On the 8×8 the trade gets worse. Arc consistency alone solves it in under **6 million nodes and about 36 seconds**. Adding path-1 preprocessing cuts the tree to roughly 1 million nodes but costs about **14 minutes** of preprocessing; path-2 preprocessing was still running after **7 hours**. The pattern is unambiguous: each stronger level of consistency really does cut the tree by orders of magnitude, and each one costs more than it saves. Geoff's own conclusion was that path consistency is "simply not a cost-benefit positive effect" on this puzzle. That is [prune versus speed](/research/why/prune-vs-speed) stated in the language of a real algorithm: the prune is genuine and large, but here the machinery to compute it is more expensive than the search it removes, which is why the record engines stop at arc consistency (or below) and spend the saved time on raw placements instead. ## What it costs The accounting, with $e$ the number of directed arcs and $d$ the maximum domain size: - **AC-3** runs in $O(e d^3)$ time worst case: each arc can be re-enqueued up to $d$ times (once per deletion in its far domain), and each revision costs up to $d^2$ support checks. Its working memory is just the queue, $O(e)$. - **AC-2001** runs in $O(e d^2)$ time, which is *optimal* for any algorithm based on arc revision: there are $e d$ candidate–arc pairs and each may need its support walked once across a domain of size $d$. The price is the last-support table: one integer per candidate–arc pair, $O(e d)$ space. On Eternity II's scale those symbols are: $e = 960$ (480 interior adjacencies, both directions) and $d \approx 764$ candidate tuples per interior cell. So the worst-case bounds sit near $e d^3 \approx 4 \times 10^{11}$ elementary checks for AC-3 against $e d^2 \approx 5.6 \times 10^8$ for AC-2001, three orders of magnitude apart on paper. Worst cases are pessimistic (real propagations touch a few cells, as the demo above shows), but the ratio is why the literature calls AC-3's bound the thing to fix, and the fix costs only $O(e d)$ integers of memory. The catch on this puzzle is not the propagation cost per node; it is that inside a search this cost is paid at *every* node, millions of times per second, which is why constant factors and cache behaviour end up mattering as much as the exponent on $d$. ## Measured on this puzzle On this project's engine (measured here; not independently replicated): - A plain backtracker propagating AC-3 together with the [per-colour matching filter](/research/build/reduce/alldiff-regin) reaches 449 of 480 edges on the canonical puzzle in about 44 seconds single-threaded, around 2.5 seconds on 8 cores. - The best algorithmic speedup found inside AC-3 itself was mundane: a precomputed table of which rotations of the same piece share edge colours, so revisions stop re-deriving it, worth a 2.9× throughput gain on the engine's reference benchmark. - The unbuilt part: AC-2001 was recommended twice in this project's notes and never actually built, so its projected 2–5× win here is a reading of the literature, not a measurement. And the belief that AC-3 dominated the runtime profile was itself never confirmed by a profiler. Measure before porting. ## The soundness caveat Arc consistency assumes every edge must match perfectly. The record engines do not: [Blackwood-style searches](/research/lab/experiments/joshua-blackwood/solver) allow a budget of deliberate mismatches at late depths, and under that regime AC is *unsound*: it prunes boards that a licensed mismatch would make perfectly legal. On this project's engine the whole AC family is switched off in break-tolerant runs for exactly that reason. The one strong propagator that survives the mismatch regime is piece-level all-different; see [Régin's filter](/research/build/reduce/alldiff-regin). ## Verdict For any exact-matching search, arc consistency is mandatory and cheap: it is the difference between a backtracker that thrashes and one that reaches the 440s. Forward checking alone leaves prunings on the table; AC-3 collects them; AC-2001 collects the same ones for less CPU, if you first verify that propagation is where your cycles actually go. For mismatch-tolerant record hunting, leave it out; soundness comes first. ## Related - [No forced moves](https://eternity2.dev/research/why/no-forced-moves) — The usual way to crack a logic puzzle is to find a spot where only one piece fits, place it, and repeat. That lever doesn't exist here: every interior piece has between 73 and 137 possible neighbours, and not one is ever pinned to a single option. - [Blackwood's solver, decoded and run here](https://eternity2.dev/research/lab/experiments/joshua-blackwood/solver) — Joshua Blackwood's record backtracker, decoded through Jef Bucas's notes (a colour quota schedule and a late-game mismatch allowance, tuned near-optimally), then built and run on my M1: left as published it flies to 248 of 256 pieces ignoring the clues; pin the five official clues and the same engine stalls near 45. - [All-different, Régin's matching filter](https://eternity2.dev/research/build/reduce/alldiff-regin) — No piece may be used twice: one global all-different constraint over 256 cells. Jean-Charles Régin showed in 1994 how bipartite matching filters it completely in polynomial time; its per-colour cousin is the strongest propagator anyone has measured on edge matching, with one sharp caveat about mismatch-tolerant searches. - [Dead ends](https://eternity2.dev/research/build/dead-ends) — Approaches we tried that look promising and don't move the needle on Eternity II, written down with what we found so you can spend your time elsewhere. --- # Edge slipping > Louis Verhaard's prize-winning move: let the backtracker place a mismatched piece, but only at chosen depths near the end of the board. Each allowed slip costs one point of score and multiplies the number of target boards astronomically. That is why his 467 was found more than fifty times, and the direct ancestor of Blackwood's breaks. - Canonical page (with interactive figures/demos): https://eternity2.dev/research/build/reduce/edge-slipping/ - Updated: 2026-07-02 - Topics: search-space, local-search - Source: Verhaard defines edge slipping (January 2009) — https://groups.io/g/eternity2/message/6328 - Source: Verhaard details the 467 method: slipping gated at chosen depths, found 50+ times (December 2009) — https://groups.io/g/eternity2/message/7321 - Source: Verhaard's first-person 467 account: 247 flawless pieces (August 2009) — https://groups.io/g/eternity2/message/6891 - Source: Max's counting formula for N slipped edges (January 2009) — https://groups.io/g/eternity2/message/6390 - Source: Owen extends complex theory to edge slips (msg 6408; the slip table is msg 6412) — https://groups.io/g/eternity2/message/6408 - Source: Verhaard's Markov chain over (depth, slips): how the slip array was optimized (msg 6423) — https://groups.io/g/eternity2/message/6423 - Source: JSA reproduces the 467 with the public solver: the rarity ladder (msg 6687) — https://groups.io/g/eternity2/message/6687 - Source: Blackwood's no-adjacent-breaks discipline (msg 10051) — https://groups.io/g/eternity2/message/10051 --- Edge slipping is the deliberate placement of a piece that does not match one of its neighbours. Louis Verhaard, who coined the term on the mailing list, defined it in one line: "putting a piece on the board that does not match the colour of one or more of its neighbours" ([msg 6328](https://groups.io/g/eternity2/message/6328)). That sounds like a description of failure. It is in fact the single most consequential partial-score idea in the puzzle's history: because Eternity II's prize ladder scored *matched edges* rather than perfect completion, a mismatch costs exactly one point of 480, and tolerating a budget of them converts one unreachable target, the perfect board, into an astronomical number of reachable ones. The craft is in the word *budget*: slips are not allowed anywhere, but unlocked on a schedule, deep in the search, where they are cheap. Everything on this page is about that schedule. ## The mismatch that wins prizes In the summer of 2008, Verhaard was stuck the legitimate way. Without any mismatch tolerance he had found hundreds of partials with 248 pieces correctly placed (score 450) and calculated his ceiling at roughly 456. He only discovered that half-fitting pieces were *allowed* when he ran Bob Cousins's public solver (originally Dave Clark's) and watched it hit 458 within a minute; he had, by his own cheerful admission, never bothered to read the rules ([msg 5767](https://groups.io/g/eternity2/message/5767)). The same discovery struck Max independently that July: he tweaked his backtracker to tolerate single mismatched edges past piece 215 and took a 219-piece scanline partial to 461 on the spot ([msg 5691](https://groups.io/g/eternity2/message/5691)); by September he was past the community's "don't-talk-about-limit" of 463, "quite easily". Verhaard's reply, "Max, you are really a dangerous man!", opens the method exchange in which both describe the shape of the mature technique: heuristic depth-first search tuned to keep the remaining pieces tileable, with a mismatch allowance at the end ([msgs 5767–5787](https://groups.io/g/eternity2/message/5767)). Six months later, the first scrutiny paid out: $10,000 to "Anna Karlsson from Lund" (Verhaard's wife, running his program, [msg 6891](https://groups.io/g/eternity2/message/6891)) for a board with 467 of 480 edges matched. The number that matters for this page is not 467 but *fifty*: "the 467 was not a once-off; I found it more than 50 times" ([msg 7321](https://groups.io/g/eternity2/message/7321)). A score that no exhaustive argument said should be findable at all was being found repeatedly, on hobbyist hardware, and when Verhaard released the solver, JSA reproduced it from the outside, logging 4,017,182 boards at 463, 227,245 at 464, 13,637 at 465, 625 at 466 and finally two 467s over roughly eighty days of continuous running ([msg 6687](https://groups.io/g/eternity2/message/6687)). That ladder of rarity is climbable for one reason: every rung is not a single board but a combinatorially enormous class of boards, and slipping is what makes the class reachable. Most of Verhaard's 467s had a *clean* score, pieces with no mismatched edge at all, of only 247 ([msg 7321](https://groups.io/g/eternity2/message/7321)); the mismatches were not blemishes on the result, they were the mechanism. ## How it works Verhaard's own description is compact ([msg 7321](https://groups.io/g/eternity2/message/7321)). The program "searches normally" (a depth-first backtracker over a fixed fill order, with heuristics tuned to maximize the tileability of the remaining pieces) but at certain depths it *allows edge slipping*: a piece may be placed with one edge disagreeing with an already placed neighbour. He is explicit about what it is not: the solver does not first build a clean partial and then cram leftover pieces into the holes at the end, and it is a different program from his clean-score searcher, which is allowed to skip squares instead of mismatching them. The allowance is depth-gated and cumulative, structured as what his documentation calls the *slip array*: for every depth, the number of slipped edges the search is permitted to have accumulated so far. Below the first gate the solver is an ordinary exact backtracker. Past it, each placement may either fit perfectly or, if the budget at that depth allows, half-fit, and the budget unlocks one slip at a time as the depth increases. Two facts make late gates the whole game: - **Branching.** A random piece half-fits far more often than it fits. Verhaard's machinery tracks the two probabilities separately, per depth, as `fitProb` and `halfFitProb` ([msg 6423](https://groups.io/g/eternity2/message/6423)). Open the slip door at depth 40 and you multiply the width of the tree where it is already widest, drowning the search in junk prefixes. Open it at depth 210, where the surviving branches are nearly forced and candidate counts hover near zero, and the same extra option revives dying branches for almost nothing. - **Inheritance.** A depth-first search never repairs a slip; undoing it means backtracking through everything placed after it. A slip admitted at depth 41 is baked underneath 215 subsequent placements; one admitted at depth 221 sits under 35. Early slips spend the budget where it buys the least and costs the most. And the gates were not guessed. Verhaard optimized both the fill order and the slip array with a Markov chain whose states are pairs (depth, slips used so far), with transition probabilities estimated from measured fit and half-fit rates; from the chain he computed the probability of reaching the bottom of the board and the number of nodes each candidate schedule would cost ([msg 6423](https://groups.io/g/eternity2/message/6423)). The winning schedule concentrated the entire budget late: thirteen slips, a target of 467. > **[Figure]** Interactive: the edge-slipping transform — interactive: EdgeSlipLab. Rendered on the canonical page (link above); not shown in this markdown export. ## Step by step 1. **Set N = 0.** One target class: the perfect boards. Nobody has ever found one, and [complex theory](/research/why/complex-theory) explains why nobody should expect to. 2. **Slide to N = 2.** Already ≈ 1.8 × 10⁵ times more targets, at score 478. Each extra allowed slip multiplies the class again, so the bars climb by roughly two orders of magnitude per step. 3. **Mind the gap at N = 1.** There is no bar: a lone slipped interior edge is parity-forbidden, and Owen's slip table has an exact zero there ([msg 6412](https://groups.io/g/eternity2/message/6412)). The only single-mismatch boards route through the unscored border rim, the same leak that produced [the 479 story](/research/build/analysis/parity-arguments). 4. **Stop at N = 10.** Target score 470, the current record, and exactly the break budget of [Blackwood's solver](/research/lab/experiments/joshua-blackwood/solver). 5. **Stop at N = 13.** Target score 467, multiplier ≈ 6.9 × 10²⁷. This is why one hobbyist's program found the prize board more than fifty times. 6. **Toggle the gates early.** Same budget, same multiplier, but the earliest slip now sits beneath 215 later placements instead of 55, and the extra branching lands where the tree is widest. The schedule, not the budget, is what Verhaard's Markov chain was built to get right. ## What it costs Asked how many high partials exist, Max worked backwards from the full solutions and produced the community's rule-of-thumb count for boards with $N$ slipped interior edges ([msg 6390](https://groups.io/g/eternity2/message/6390)): $$ S(480-N) \;\approx\; 2^{\,N-1}\binom{420}{N}\,S(480), \qquad N \ge 2, $$ where $\binom{420}{N}$ chooses which of the 420 interior joins break, the powers of two account (roughly) for the ways each break can be realized, and $S(480)$ is the number of perfect boards. Plugging in the early complex-theory estimate $S(480) = 26{,}700$ he got about $4.7 \times 10^9$ boards at 478, $2.9 \times 10^{30}$ at 468 and $1.8 \times 10^{32}$ at 467, numbers this project has re-verified from the formula. Two consequences matter more than the absolute values, which Max himself flagged as oversimplified: - **The cost of one more matched edge.** Consecutive ratios telescope: $S(467)/S(468) = 2\binom{420}{13}/\binom{420}{12} = 2 \cdot 408/13 \approx 63$. Each edge you refuse to slip shrinks the target class by a factor of about sixty, matching, as Max noted, the observed behaviour of Verhaard's solver ([msg 6390](https://groups.io/g/eternity2/message/6390)), and of the same order as Owen's ~100×-per-edge rule of thumb, posted to the same thread the next day ([msg 6391](https://groups.io/g/eternity2/message/6391)). - **The ceiling.** The multiplication is bought with score: $N$ allowed slips cap the board at $480 - N$ forever. Slipping buys reachability, not quality; it converts an impossible search into a feasible one whose best possible outcome is strictly worse. The runtime price, by contrast, is almost nothing: per placement the solver compares a slip counter against the slip array's entry for the current depth ($O(1)$ bookkeeping, incremented on a half-fit placement and restored on backtrack). All the cost lives in the tree it unlocks, which is why the gate placement is the design problem. Owen closed the loop by extending [complex theory](/research/why/complex-theory) to slips: replace the probability that all $m$ joins match with $pm(m,v)$, the probability that exactly $v$ do, via the recursion $pm(m,v) = pm(m-1,v) - pm(m,v+1)$, then weight by the ways to position the slips ([msg 6408](https://groups.io/g/eternity2/message/6408)). His table puts boards with 13 slips at $2.05 \times 10^{35}$ times the count of perfect boards ([msg 6412](https://groups.io/g/eternity2/message/6412)), seven orders of magnitude above Max's figure, because the theory also counts near-boards that are not perturbations of any solution, while Max counted only those derived from a perfect board. Take either number: the target set explodes combinatorially, while the price is linear in score. ## From slipping to breaks For twelve years the 467 stood, and so did the design. When Joshua Blackwood arrived in 2020, an outsider whose 468 was relayed to the list from Reddit, his record solver carried a hard-coded list: ```csharp break_indexes_allowed = new List() { 201, 206, 211, 216, 221, 225, 229, 233, 237, 239 }; ``` Read it against this page and it is a slip array: mismatches ("breaks", in his vocabulary) forbidden outright for the first 200 placements, then unlocked cumulatively, one at a time, at hand-chosen depths, ten in total, for a target score of 470. The concept, the depth gating and the late-concentration of the budget are Verhaard's design of 2008, re-derived at record strength; the retuning of exactly those unlock depths is what took Blackwood from 469 to 470. He also added a discipline Verhaard's version did not have: no two breaks may ever touch, so every mismatch sits isolated among matched edges, which is why any of his runs reaching 255 placements completes to 256, and why a 469 board doubles as a 249-piece clean partial with seven holes ([msg 10051](https://groups.io/g/eternity2/message/10051)). The full machine, with its quota schedules and its parameter study, is on [the Blackwood page](/research/lab/experiments/joshua-blackwood/solver). The arithmetic of the lineage is worth saying out loud. Verhaard's thirteen slips targeted 467; Blackwood's ten target 470. By Max's ratio, each slip removed costs a factor of about sixty, so those three edges are roughly a $2 \times 10^5$ multiplier in difficulty, paid for by twelve years of hardware, a faster inner loop, and a community running the code in parallel. The technique itself did not change. On a puzzle scored by matched edges, the winning move, twice and thirteen years apart, was not a better search for perfect boards. It was a scheduled, budgeted redefinition of what counts as a target. ## Related - [Blackwood's solver, decoded and run here](https://eternity2.dev/research/lab/experiments/joshua-blackwood/solver) — Joshua Blackwood's record backtracker, decoded through Jef Bucas's notes (a colour quota schedule and a late-game mismatch allowance, tuned near-optimally), then built and run on my M1: left as published it flies to 248 of 256 pieces ignoring the clues; pin the five official clues and the same engine stalls near 45. - [Parity arguments](https://eternity2.dev/research/build/analysis/parity-arguments) — Count anything on an edge-matching board twice, once from each side, and the totals must agree, giving impossibility proofs for the price of one pass. The 479 story shows both the power and the trap: a clean parity claim, true for every interior move, defeated through the sixty border edges nobody scores. - [Complex theory: counting the search before you run it](https://eternity2.dev/research/why/complex-theory) — Brendan Owen's complex theory estimates how wide the search tree is at every depth, and even how many solutions exist at all. Many in the community consider it the single most important thing to understand about Eternity II. --- # No-good learning: remembering why you failed > A failed subtree is a theorem: this partial state can never extend. Store it and never re-enter. The community tried both flavours: chess-style transposition tables over the search frontier, and mined constraints about the puzzle itself. The full ledger of what memory buys at E2 scale, and the small boards where it genuinely pays. - Canonical page (with interactive figures/demos): https://eternity2.dev/research/build/reduce/nogood-learning/ - Updated: 2026-07-02 - Topics: search-space, exact-methods - Source: Max's frontier-index scheme: 16 unmatched edges plus a piece bitmap (groups.io message 6137, 2008) — https://groups.io/g/eternity2/message/6137 - Source: Lindström tries it, 'it learns from mistakes' (groups.io message 6138) — https://groups.io/g/eternity2/message/6138 - Source: Verhaard's chess-style advice: fixed memory, hash, overwrite (groups.io message 6144) — https://groups.io/g/eternity2/message/6144 - Source: The corrected key size: 76 bits of frontier state; hit rate 0.1% → 1% before memory ran out (groups.io message 6145) — https://groups.io/g/eternity2/message/6145 - Source: Max's count of distinct frontier signatures: 5²·17¹⁴ ≈ 4×10¹⁸ (groups.io message 6143) — https://groups.io/g/eternity2/message/6143 - Source: The improved method: tiny memory, 75–80% of branches discarded (groups.io message 6218) — https://groups.io/g/eternity2/message/6218 - Source: The restore-list saga begins (groups.io message 8854, 2011) — https://groups.io/g/eternity2/message/8854 - Source: DeVincentis's fix: one restore list per edge, plus one for used pieces (groups.io message 8886) — https://groups.io/g/eternity2/message/8886 - Source: Measured on the 6×6 border ring: 133,326,155 → 30,496,808 nodes (groups.io message 8875) — https://groups.io/g/eternity2/message/8875 - Source: Mocsi's Failure Lookup Table, abandoned over a bug (groups.io message 8887) — https://groups.io/g/eternity2/message/8887 - Source: McGavin's duplicate top rows: 40 core-hours provably wasted (groups.io message 9610, 2016) — https://groups.io/g/eternity2/message/9610 - Source: 21valy's duplicate-rate measurements: ~1% exact halfway; the relaxed table saturates in minutes (groups.io message 9618) — https://groups.io/g/eternity2/message/9618 - Source: Verhaard: eii keeps no memory of past positions, and it won the $10,000 (groups.io message 7451, 2010) — https://groups.io/g/eternity2/message/7451 - Source: Blackwood's ledger: 2×2 caching measured and dropped (groups.io message 10056, 2020) — https://groups.io/g/eternity2/message/10056 - Source: Lindström's invalid-placement mining and collaboration call (groups.io message 6743, 2009) — https://groups.io/g/eternity2/message/6743 - Source: capiman's invalid two-piece combination for the 5-hint puzzle (groups.io message 10832, 2022) — https://groups.io/g/eternity2/message/10832 - Source: The tally: ~68M invalid pairs found, ~8.1×10⁹ undecided, and a solution's ~32,000 pairs must survive them all (groups.io message 10973, 2023) — https://groups.io/g/eternity2/message/10973 - Source: An invalid 3-piece combination, dissected down to three ring-0 cells (groups.io message 11131) — https://groups.io/g/eternity2/message/11131 - Source: SAT as an invalidation service: shrinking a dead-end partial to 28 pieces (groups.io messages 10289/10292, 2021) — https://groups.io/g/eternity2/message/10289 - Source: capiman's CNF pipeline: 130,180 variables, cryptominisat, partials and rings (groups.io message 11822, 2026) — https://groups.io/g/eternity2/message/11822 --- A backtracker that gives up on a subtree has just proved a theorem: *this partial state cannot be extended to a solution*. Then it throws the theorem away and, hours later, proves it again from a different branch. No-good learning is the refusal to waste that proof: store the failed state, check the store before descending, never re-enter. Chess engines run on this idea (transposition tables), and SAT solvers industrialised it as clause learning. The Eternity II community has been trying to make it pay since 2008, in two distinct flavours, and the archive records both the attempts and the autopsies. ## Why a failed subtree is reusable at all A depth-first search over a scan-line [fill order](/research/build/backtracking/fill-order) is a function of surprisingly few inputs. When the solver stands at depth $d$, the entire subtree below is determined by two things: the **open frontier** (the colour sequence exposed along the boundary between placed and empty cells) and the **set of pieces still in hand**. Nothing else about the history matters. Two different 128-piece partials that expose the same sixteen edge colours and leave the same 128 pieces unused have *identical* subtrees. If the first failed, the second must fail, and searching it is pure waste. [Peter McGavin](/research/lab/experiments/peter-mcgavin/backtracker) caught this happening in the wild in 2016: two top-row combinations in his 10×10 [farming](/research/build/faster/distributed-solving) logs used the same ten pieces with the same permutation of colours along their lower edge, and their search trees came back with exactly the same node count: 5,602,741,481,523 nodes, twice. The roughly 40 core-hours spent on the second one "were a complete waste of time, since we could easily predict in advance that the result would be the same" ([message 9610](https://groups.io/g/eternity2/message/9610)). So the theorem is real and the waste is real. Everything else on this page is about whether *remembering* is cheaper than *re-deriving*. At E2 scale that question has a surprisingly consistent answer. ## Flavour one: transposition tables over the frontier The idea arrived on the mailing list in one thread in the autumn of 2008. Max proposed indexing every 128-piece partial (eight completed rows) by its sixteen unmatched edges, storing alongside the index a bitmap of the pieces that were available-plus-unconsidered when the subtree failed; reach another partial with the same index whose available pieces are a *subset* of the stored bitmap, and the whole subtree can be skipped ([message 6137](https://groups.io/g/eternity2/message/6137)). Michael Lindström had already been experimenting: it "does work pretty good, it learns from mistakes and will cut away more and more branches early on" ([message 6138](https://groups.io/g/eternity2/message/6138)). [Louis Verhaard](/research/lab/experiments/louis-verhaard/eii) supplied the standard engineering answer from computer chess: don't try to store everything; fix a memory budget, hash the position, overwrite old entries ([message 6144](https://groups.io/g/eternity2/message/6144)). He added a warning: the more the piece sets of two matching frontiers differ, the shorter the subtree the hit can legally cut. Then the measurements came in, and they are the heart of the story. Lindström's corrected accounting put the key at 76 bits of frontier state (3 bits for each of the two border-facing edges, 5 bits for each of the fourteen interior edges), so a direct table needs $2^{76}/8$ bytes, and Max counted roughly $5^2 \cdot 17^{14} \approx 4 \times 10^{18}$ distinct signatures for that one test line ([message 6145](https://groups.io/g/eternity2/message/6145), [message 6143](https://groups.io/g/eternity2/message/6143)). Running the real thing with the break point at 128 pieces, the discard rate started at 0.1% and climbed slowly to about 1% before memory ran out ([message 6145](https://groups.io/g/eternity2/message/6145)). Max's verdict on 1%: "we shouldn't expect wonders of this method" ([message 6152](https://groups.io/g/eternity2/message/6152)). A month later Lindström reported a refined version: no per-piece state stored, the test point movable, tiny memory, "discards about 75-80% on average" ([message 6218](https://groups.io/g/eternity2/message/6218)). The claim is striking, yet nobody else ever benchmarked it and it never surfaced in any record solver; when he returned in 2010 it was to ask the group to spot the flaw in his dynamic-reduction scheme, and no substantive reply came ([message 7938](https://groups.io/g/eternity2/message/7938)). Note what made the key so big: E2's scan-line frontier is *wide*. A chess position fits in a few dozen bytes regardless of how deep the game is; an E2 frontier is sixteen open edges of seventeen interior colours **plus** a 256-piece availability set, and the number of reachable signatures grows exponentially with the frontier's length. That is the same boundary-entropy quantity that governs the [entropy area law](/research/why/entropy-area-law): the frontier is where the puzzle's information lives, and a transposition key must carry all of it or be unsound. ## The correctness traps Unsound is exactly what the cheaper variants turned out to be, and the archive's most instructive contribution to this topic is a public autopsy. In 2011 Lindström described a backtracker where every cell keeps a live candidate list, and a piece refuted at one cell is removed from that list and parked on a "restore list" attached to the earlier cell whose undoing would make it valid again; memoized pruning, in effect ([message 8854](https://groups.io/g/eternity2/message/8854)). It cut node counts beautifully and silently lost solutions: his 8×8 runs missed some of the 52 known solutions. Over thirty-plus messages McGavin pressed objections and probing test cases ([message 8866](https://groups.io/g/eternity2/message/8866)) until Joseph DeVincentis diagnosed the flaw: a single restore list conflates *why* a piece was eliminated. Each cell needs one restore list per neighbouring edge plus one for pieces used elsewhere, restored at different moments of the backtrack ([message 8871](https://groups.io/g/eternity2/message/8871), [message 8886](https://groups.io/g/eternity2/message/8886)). The prize the scheme was chasing was real: Lindström had already measured the 6×6 border ring falling from 133,326,155 nodes to 30,496,808 ([message 8875](https://groups.io/g/eternity2/message/8875)). In the same thread Mocsi recognised his own Failure Lookup Table (spiral search, record the outer-colour arrangement at each forced retreat to the border, consult before descending), abandoned because a bug kept it from solving even 6×6 and "debugging is not so easy, when you have to wait for several thousand iterations, till the bug occurs" ([message 8887](https://groups.io/g/eternity2/message/8887)). The lesson generalises. A no-good is a *proof*, and caching proofs means your cache key must capture every hypothesis the proof used. Under-key it by forgetting a neighbour edge, a used piece or a restore moment, and you cache a falsehood that quietly deletes solutions. This is why the sound version of the idea inside CSP engines records no-goods only at propagation failures with their full reason sets, checked SAT-style with watched literals; the mechanics are on the [SAT and CSP encodings page](/research/build/exact/sat-csp-encodings). ## Flavour two: no-goods about the puzzle itself A transposition entry says "this state, in this search, is dead". A stronger kind of no-good says "this local configuration appears in **no solution of Eternity II at all**": a learned constraint about the puzzle, not the run, valid for every solver and shareable as a file. That programme also starts in 2009 with Lindström: given the corners and hints, he counted ~4,500 inherently invalid single placements, estimated 20–50 million invalid two-piece combinations, and openly called for collaborators to verify and exchange "invalid placements" files any solver could use for early branch cutting ([message 6743](https://groups.io/g/eternity2/message/6743)); comparing possibility matrices with another member ([message 6951](https://groups.io/g/eternity2/message/6951)) promptly surfaced a 618-vs-624 discrepancy ([message 6956](https://groups.io/g/eternity2/message/6956)) that Lindström chalked up to a rotation mix-up on his own side ([message 6957](https://groups.io/g/eternity2/message/6957)). The modern, industrialised form is capiman's. Using a generated CNF of the 5-hint puzzle (130,180 variables, ~4 GB, solved with an old cryptominisat; the pipeline is described first-hand at [message 11822](https://groups.io/g/eternity2/message/11822)), he mines provably-invalid two-piece placements, pairs that can co-occur at their positions in no solution ([message 10832](https://groups.io/g/eternity2/message/10832)), and even dissected an invalid *three*-piece combination down to the three ring-0 cells it strangles ([message 11131](https://groups.io/g/eternity2/message/11131)). The same machinery ran as a service for other members: handed a dead-end partial, he removed pieces one by one, keeping each removal only if the SAT solver still answered UNSAT ([message 10292](https://groups.io/g/eternity2/message/10292)), and returned a 28-piece core that is already unextendable ([message 10289](https://groups.io/g/eternity2/message/10289)). That is conflict-clause minimisation performed by hand, exactly what a CDCL solver does internally after every conflict. The accounting, though, is sobering and capiman published it himself: by February 2023 the mine held ~68 million confirmed invalid pairs, against roughly $8.1 \times 10^9$ pairs still undecided; hiding among the undecided, by his estimate, sit the ~32,000 pairs of an actual solution, the ones no invalidation campaign is allowed to touch ([message 10973](https://groups.io/g/eternity2/message/10973)). Sixty-eight million theorems, each individually true, collectively covering under 1% of the pair space, with no way to guess at the rest without risking one of the 32,000 that must survive. Learned constraints about E2 are real assets. They are just being deposited into an account with astronomical liabilities. Why CDCL's automated version of this learning also starves on the full board (flat implication chains, wide late conflicts) is covered on the [SAT and CSP encodings page](/research/build/exact/sat-csp-encodings); this is the same phenomenon met from the mining side. ## The record: measured, then dropped Now the counterweight, because on this topic the archive's negatives are better documented than its positives. **The prize-winning solver remembered nothing.** Asked in 2010 whether his public solver deduplicated the thousands of 463–465 boards it found, Verhaard answered plainly: "it does not remember them". There was no memory of past positions at all, and given the node volumes, someone had almost certainly re-encountered any given position already ([message 7451](https://groups.io/g/eternity2/message/7451)). This is the same Verhaard who had given the chess-style transposition advice two years earlier ([message 6144](https://groups.io/g/eternity2/message/6144)), whose engine held the 467 record for over a decade. He knew the technique; he shipped without it. **The record engine measured caching and dropped it.** Cataloguing what he tried after the 469, Joshua Blackwood listed SAT solvers, GPUs, "and caching all pre-solved 2 by 2s", all measured, none kept; only refining the placement heuristics paid, worth about 2× ([message 10056](https://groups.io/g/eternity2/message/10056)). His stated reasons for rejecting a related per-thread cache design are pure memory arithmetic: reconstruction cost when the search recrosses the cache boundary, and the certainty that per-thread tables would no longer fit in L3. The fastest engines spend over half their cycles stalled on memory already (see [solver engineering](/research/build/faster/solver-engineering)); a cache probe per node is a proposal to add a DRAM-latency roundtrip to a loop that lives or dies by L1. **The hit rates were measured, and they are thin.** In 2016, 21valy instrumented a 10×10 scan-line solver: exact duplicate states (same borders, same inner tiles, same exposed norths) occur at about 1% halfway through the board, prompting his "morality #1: do not care true duplicates". Relaxed keys (inner tiles only) show 30–40% repetition, but the theoretical gain tops out below 25% and his hash table "grows too rapidly … saturated in a few minutes" ([message 9618](https://groups.io/g/eternity2/message/9618)). One percent of hits, each saving a subtree, versus a probe on every node and a table whose working set exceeds RAM within minutes: that is the break-even problem in one measurement. The pattern across all three: nobody refuted the theorem. Failed subtrees *are* reusable. What failed is the exchange rate: at 16×16 the frontier key is too wide, the state space too large for any table to cover a useful fraction, and the probe cost lands on the exact resource (memory bandwidth) that fast backtrackers have already exhausted. ## Where it genuinely pays Shrink the board or close the search, and the same idea changes sign. - **Small boards and rings.** Lindström's restore-list scheme cut the 6×6 border ring by 4.4× ([message 8875](https://groups.io/g/eternity2/message/8875)). On a small state space the table *can* cover a meaningful fraction of reachable frontiers, so hit rates climb from per-mille to per-cent and beyond. - **Exhaustive enumeration and counting.** When the tree will be walked to the end, every duplicate subtree is a guaranteed revisit, not a probabilistic one: McGavin's twin top rows ([message 9610](https://groups.io/g/eternity2/message/9610)) are 40 core-hours that a signature check would have saved with certainty. Deduplicating enumerated row lists before farming them out is exactly this, applied at the tree's top, and the community's census culture (the 9×9 exhausts, the fully-enumerated hint puzzles) is where enumeration discipline visibly wins (see [benchmarks](/research/build/benchmarks)). - **Endgames.** Deep in the board the remaining-piece set is small, the frontier short, and the subproblem repeats across many top-halves: the regime where a memo table stays small, hot and reliable. - **Inside a propagation engine.** Recording a hard no-good with its full reason set at each propagation failure is sound by construction and cheap to check: the CSP-side inheritance of CDCL described on the [encodings page](/research/build/exact/sat-csp-encodings). ## What it costs - **The key: frontier entropy, paid per entry.** A sound transposition key is the open frontier plus the remaining-piece set. At a mid-board test line that is $2 \cdot 3 + 14 \cdot 5 = 76$ bits of edge state ([message 6145](https://groups.io/g/eternity2/message/6145)) plus a 256-bit piece bitmap for the subset test ([message 6137](https://groups.io/g/eternity2/message/6137)), and the number of *reachable* keys at that one line is about $5^2 \cdot 17^{14} \approx 4 \times 10^{18}$ ([message 6143](https://groups.io/g/eternity2/message/6143)). In general the key population grows like $e^{h \cdot \ell}$ for a frontier of length $\ell$: a perimeter law, the same boundary term as the [area law's](/research/why/entropy-area-law), which is why small boards are cheap and 16×16 is not. - **The table: coverage is memory over population.** A hash table of $M$ entries facing $K$ reachable keys covers $M/K$ of them; with $K \approx 4 \times 10^{18}$, a 64 GiB table ($M \approx 2^{33}$ entries) covers about $10^{-9}$ of the space. Hits then come only from short-term locality, which is what Lindström observed: 0.1% climbing to 1% and stalling at the memory wall ([message 6145](https://groups.io/g/eternity2/message/6145)). - **The probe: a DRAM roundtrip per node.** A modern engine places $\sim$70M pieces per second (about $14$ ns per node) while a random table probe costs a $\sim$100 ns memory stall, i.e. $c \approx 7$ nodes of search. The cache pays only if $$ p_{\text{hit}} \cdot \bar{S} \;>\; c \;\approx\; 7 \text{ nodes}, $$ where $\bar{S}$ is the mean size of a skipped subtree. At the measured $p_{\text{hit}} \approx 1\%$ ([message 9618](https://groups.io/g/eternity2/message/9618)) you need $\bar{S} > 700$ nodes *and* a table that actually retains those entries, the one 21valy watched saturate in minutes. At an effective $p_{\text{hit}} \sim 10^{-9}$, no realistic $\bar{S}$ balances the books. - **Correctness: the full reason set, or nothing.** Every hypothesis the failure proof used must be in the key: per-edge restore lists, used-piece lists, all of it ([message 8886](https://groups.io/g/eternity2/message/8886)), and the failure mode of under-keying is silently lost solutions, the most expensive bug an exhaustive search can have. That is the summary the archive earned over eighteen years: the theorem is free, the memory is not. A failed subtree really is a fact you own, but at full-board scale, storing facts costs more than rediscovering them, and the two solvers that set records both chose, after measuring, to forget. ## Related - [REPLAY](https://eternity2.dev/research/lab/experiments/raphael-anjou/learning/replay) — Rebuild the community's strict 460 boards exactly, and in doing so discover the move ordinary solvers can't make: paying two mismatches at a single cell. - [SAT and CSP encodings](https://eternity2.dev/research/build/exact/sat-csp-encodings) — Write the puzzle as clauses and hand it to an industrial solver: the obvious move, tried since 2008. Why complete solvers stall on the full board, and where their verdicts still earn their keep as impossibility proofs. - [Solver engineering: the craft below the algorithm](https://eternity2.dev/research/build/faster/solver-engineering) — Every record solver runs the same depth-first backtracker. What separates them is the layer underneath: lookup tables, perfect hashes, cache-sized structs, generated code, compiler archaeology. That craft decides whether a node costs 26 cycles or 2,600. The community's twenty-year engineering ledger, technique by technique, and what it all bought. - [Blackwood's solver, decoded and run here](https://eternity2.dev/research/lab/experiments/joshua-blackwood/solver) — Joshua Blackwood's record backtracker, decoded through Jef Bucas's notes (a colour quota schedule and a late-game mismatch allowance, tuned near-optimally), then built and run on my M1: left as published it flies to 248 of 256 pieces ignoring the clues; pin the five official clues and the same engine stalls near 45. --- # Run it yourself > The whole site, the engine, and every result in this section run from one repository. Here is how to get it going, rebuild the WebAssembly engine, and reproduce the numbers. - Canonical page (with interactive figures/demos): https://eternity2.dev/research/build/run-it-yourself/ - Updated: 2026-07-01 - Source: The eternity2 repository on GitHub — https://github.com/raphael-anjou/eternity2 --- The whole site, the engine, and every result in this section run from one repository. Here is how to get it going and reproduce the numbers. ## Get the code Clone the repository. Everything lives here: the Rust engine, the website, and the research topics with their compute scripts. ```bash git clone https://github.com/raphael-anjou/eternity2 cd eternity2 ``` ## What you need Three toolchains. The engine is Rust, the site is a Node app, and the engine ships to the browser as WebAssembly. - **Rust**, stable, with the `wasm32-unknown-unknown` target - **Node.js 22+ and pnpm** for the website (`corepack enable` gets you pnpm) - **wasm-pack** to compile the engine to WebAssembly - **just** (optional), a small task runner that wraps the commands below ## Build and run the site With `just` installed, two commands. The first builds the engine to WebAssembly and installs the web dependencies; the second starts the site at `localhost:5173` with hot reload. ```bash just setup just dev ``` Prefer to run things directly? Every `just` recipe is a one-line wrapper, so you can skip `just` entirely: ```bash # build the engine to WebAssembly cd engine && wasm-pack build --target web --out-dir ../web/src/engine/pkg --release # install and run the site cd ../web && pnpm install && pnpm dev ``` ## Work on the engine The engine is a normal Rust crate that also compiles to WebAssembly. Run its tests, then rebuild the WASM whenever you change it. The tests include cross-checks against real community boards, so they catch any change to the piece set, rotation, or scoring. ```bash just test # cargo test --release just wasm # rebuild the WebAssembly after a change ``` ## Reproduce a research result Each topic in this section is self-contained: an article, a compute script, and the committed output it produces. Re-running the script regenerates that output. Deterministic results come back byte-for-byte identical; runs that depend on randomness or take hours say so plainly, and ship the board they found so you can still check it in the viewer. For example, the forbidden-patterns counts (about twenty seconds): ```bash just research-forbidden-patterns # or directly: cd research/topics/forbidden-patterns/compute cargo run --release > ../results/feasibility.json ``` Running `just` with no arguments lists every task, including the other reproduce recipes (`research-subgrid`, `research-index`) and the engine's native `bench` and `stats` runs. ## Run every check One command runs what continuous integration runs: engine tests, type-check, lint, and the production build. ```bash just check # engine tests, typecheck, lint, build ``` [Browse the repository on GitHub](https://github.com/raphael-anjou/eternity2). ## Related - [Dead ends](https://eternity2.dev/research/build/dead-ends) — Approaches we tried that look promising and don't move the needle on Eternity II, written down with what we found so you can spend your time elsewhere. --- # How the record solvers search > How the solvers that hold the records actually search. They are all, at heart, depth-first backtrackers; what separates them is the order they try things and how they bend the rules near the end. - Canonical page (with interactive figures/demos): https://eternity2.dev/research/build/solvers/ - Updated: 2026-07-17 - Topics: backtracking, speed --- Every solver that holds a serious Eternity II record is, at heart, the same machine: a depth-first backtracker. What separates them is not the loop but three choices layered on top of it, the order they visit cells, the heuristics that decide which piece to try first, and how they bend the endgame when a perfect match runs out. This page is the neutral tour of those choices. The full, first-party engine story for each solver (decoded from the source and the literature, then built and measured) lives on its own lab page, linked from each section below. ## Plain backtracking Fill the board cell by cell in some fixed order. At each cell, try every piece and rotation whose edges match what's already placed; if none fit, back up and try the previous cell differently. Correct but slow: the search tree is astronomically wide. Here is exactly that, in slow motion: a real backtracker on a 3×3, one decision at a time. Step through it and watch a piece go down, a dead end appear, and the search un-place and try again. > **[Interactive: DfsDemo]** Rendered on the canonical page (link above); not shown in this markdown export. ## Order matters: the fill path The order you visit cells changes the difficulty by orders of magnitude, because some orders force conflicts to surface early (good) and others defer them until a lot of work is wasted (bad). Border-first beats row-major by a wide margin on the same puzzle. It is the single lever every record engine tunes: Verhaard's comb-search orders, Blackwood's bottom-left row scan with border pieces interspersed late, and McGavin's per-puzzle choice of scan-row, spiral-in, or border-first are all answers to the same question. ## Heuristics: which piece first A plain backtracker tries candidates in an arbitrary order. A record engine scores them, so the pieces most likely to matter go down first, and prunes any branch that falls behind a schedule. Blackwood's solver, for instance, privileges three colours and enforces a per-depth quota that must be met to keep descending; Verhaard prunes forward against hand-tuned score thresholds. The details differ, but the shape is shared: commit the constrained pieces early, cut the branches that cannot pay their way. ## Bending the endgame: breaks and edge-slipping A perfect 256-piece tiling has never been found. Every record board instead tolerates a handful of late mismatches, and the engines reach them by *scheduling* imperfection: a per-depth budget of mismatched edges that unlocks deep in the search. Verhaard called his a slip array; Blackwood calls his the break indexes. Same idea, gated by depth so the early board stays clean and the mismatches are spent only where they buy the most. The lab below lets you move that budget around and watch the reachable score change: > **[Interactive: BreakIndexLab]** Rendered on the canonical page (link above); not shown in this markdown export. ## Read the full engine story Each record engine has a dedicated page that decodes how it works and then builds and measures it on one machine, single core: - **[Blackwood's solver, decoded and run here](/research/lab/experiments/joshua-blackwood/solver)**: the schedule-and-break-index backtracker behind the standing 470, with Jef Bucas's parameter study and a build that flies unconstrained but stalls once the five clues are pinned. - **[Verhaard's eii](/research/lab/experiments/louis-verhaard/eii)**: the engine behind the 467, the only prize the contest ever paid: forward pruning, comb-search orders, a Markov-tuned slip schedule, and why its source-less binary cannot be run today. - **[McGavin's C backtracker](/research/lab/experiments/peter-mcgavin/backtracker)**: the community's fastest engine, a 2007 optimization recipe compounded for two decades, built here and pushed past 200 of 256 pieces at over 100 million placements a second. - **[The JIT backtracker](/research/lab/experiments/raphael-anjou/jit-backtracker)**: a portable-Rust engine that generates and compiles per-puzzle code, taken rung by rung to McGavin's throughput - a tie with his hand-tuned C on hard, realistic boards (his C stays faster on easy ones) - a speed result on an [axis of its own](/research/lab/experiments/raphael-anjou/going-fast) from the score the record engines chase. - **[This site's reference engine](/research/lab/experiments/raphael-anjou/engine)**: not a record machine but the Rust/WASM backtracker that runs every demo on this wiki and checks its numbers. ## See it run The playground runs a real depth-first solver in your browser. [Watch it search live](/playground/watch), or [draw your own fill order](/playground/paths) and race it against the classics to feel how much the order matters. For approaches that don't work, see the [dead ends](/research/build/dead-ends). --- # The techniques > The technique shelf: the algorithms and pruning ideas that recur in every serious Eternity II solver, each with what it is, what it costs, and what it actually bought when measured on this puzzle. - Canonical page (with interactive figures/demos): https://eternity2.dev/research/build/techniques/ - Updated: 2026-07-02 - Source: Constraint satisfaction problem (Wikipedia): the umbrella framework — https://en.wikipedia.org/wiki/Constraint_satisfaction_problem --- The technique shelf: the algorithms and pruning ideas that recur in every serious Eternity II solver, each with what it is, what it costs, and what it actually bought when measured on this puzzle. New here, or want the whole territory at once? Start with [a map of every known approach](/research/build/approaches-map): every family of attack on one page, what each reached, and where it walls out. These are not Eternity II inventions: they come from constraint programming, combinatorics and cryptanalysis, and each page names its inventor and cites the original paper. What this shelf adds is the candid part: how each technique behaves when pointed at this particular puzzle, with the project's own measurements where they exist and a plain "unmeasured" where they do not. Every page teaches by doing: an interactive lab you can poke at, a step-by-step walkthrough on the same instance, and what the algorithm actually costs. The [solver catalogue](/research/build/solvers) shows how record engines assemble these parts; the [dead ends](/research/build/dead-ends) page lists the techniques that sounded just as good and didn't survive contact. ## Related - [How the record solvers search](https://eternity2.dev/research/build/solvers) — How the solvers that hold the records actually search. They are all, at heart, depth-first backtrackers; what separates them is the order they try things and how they bend the rules near the end. - [Dead ends](https://eternity2.dev/research/build/dead-ends) — Approaches we tried that look promising and don't move the needle on Eternity II, written down with what we found so you can spend your time elsewhere. --- # The community's toolbox, 2007–2026 > Nineteen years of community software for Eternity II (manual-placement GUIs, editors, public solvers, generators and viewers), plus the quieter layer that made them interoperate: e2pieces.txt, CRC-16 checksums, and the board-in-a-URL format that became the lingua franca. A reference census, with every tool sourced to the message that announced it. - Canonical page (with interactive figures/demos): https://eternity2.dev/research/build/tooling/ - Updated: 2026-07-02 - Source: The e2pieces.txt file format written down (John Morrison), eternity2@groups.io, 2007-12 — https://groups.io/g/eternity2/message/3571 - Source: The CRC-16 checksum scheme, launch week, eternity2@groups.io, 2007-07 — https://groups.io/g/eternity2/message/1063 - Source: eii4me's Manual Placement Program, the first shared GUI tool, eternity2@groups.io, 2007-12 — https://groups.io/g/eternity2/message/3541 - Source: E2Lab is born (Fred / Eternity Blogger), eternity2@groups.io, 2009-10 — https://groups.io/g/eternity2/message/7071 - Source: Jef Bucas launches e2.bucas.name, the board viewer, eternity2@groups.io, 2019-11 — https://groups.io/g/eternity2/message/9955 - Source: libblackwood published (Jef Bucas), eternity2@groups.io, 2020-11 — https://groups.io/g/eternity2/message/10078 - Source: Survey of e2pieces.txt files: “it's a mess!” (Vasily V.), eternity2@groups.io, 2023-03 — https://groups.io/g/eternity2/message/11033 - Source: e2.bucas.name (Jef Bucas), the community viewer and today's shared board format — https://e2.bucas.name --- The Eternity II community wrote a lot of software: solvers, of course, but also manual-placement programs for hand-solvers, board editors, fill-path explorers, puzzle generators, renderers and viewers. This page is the census of that toolbox: who built each tool, when, what it did, and where it lives now. The [history pages](/research/community/hunt) tell the story these tools appear in, and the [solver pages](/research/build/solvers) cover the algorithms. Dead links are stated as dead; nothing here is a download recommendation. One constraint shaped the contest years. In August 2007 the puzzle's inventor claimed copyright on the piece designs and threatened entrants who circulated them ([msg 1342](https://groups.io/g/eternity2/message/1342)), so the norm became that community tools did not ship the pieces. Every program below expects you to type in your own set: "a rite of passage into the E2 fraternity. We ALL did it.", as Alan O'Donnell put it when the argument flared for the nth time ([msg 7578](https://groups.io/g/eternity2/message/7578)). The moderators, for their part, removed piece files from uploaded tool archives when authors slipped ([msg 7609](https://groups.io/g/eternity2/message/7609)). That is why the toolbox has a second, less visible layer: shared file formats and checksum protocols that let tools and people interoperate without anyone transmitting the piece data. Both layers are catalogued here. That norm has since eroded. Filled-in `e2pieces.txt` files circulated on GitHub for years (Vasily V. surveyed "every one he could find" in 2023, below), and open piece-set libraries followed: jwortmann's Eternity2Puzzles.jl and Dobrogost's eii-puzzles both carry the set. The edge-adjacency numbers are, in practice, public. Our own [starter kit](/research/build/toolkit) ships the set for the same reason: reproducibility without a manual transcription step. ## 2007–2008: launch tools The first tools predate the puzzle. Brendan Owen posted C++ source for generating Eternity-II-like puzzles in January 2007, six months before launch; that code is the seed of the entire benchmark culture ([msg 41](https://groups.io/g/eternity2/message/41)). Sergio "Zerjillo" Alonso uploaded a corpus of 10,080 generated test boards plus the generator and a statistics spreadsheet that spring ([msg 201](https://groups.io/g/eternity2/message/201), [msg 202](https://groups.io/g/eternity2/message/202), [msg 203](https://groups.io/g/eternity2/message/203)). Owen had also written a computer-vision program to read scanned piece panels, which digitized the real puzzle on launch eve ([msg 789](https://groups.io/g/eternity2/message/789), [msg 1054](https://groups.io/g/eternity2/message/1054)). The launch year's flagship was Dave Clark's **eternity2.net**, the BOINC-based [distributed solver](/research/build/faster/distributed-solving) ([msg 756](https://groups.io/g/eternity2/message/756)). It mattered less for its computing (the project closed in December 2007 having changed nothing, [msg 3511](https://groups.io/g/eternity2/message/3511)) than for its legacy: its client's `e2pieces.txt` / `e2hints.txt` files became the community's standard formats (below), its solver and data files were preserved in the group archive with Clark's blessing ([msg 3633](https://groups.io/g/eternity2/message/3633)), Bob Cousins shipped community-patched "rmc" builds of the solver ([msg 3654](https://groups.io/g/eternity2/message/3654)), and Clark open-sourced his personal R&D program, a research solver that could export SAT and LP encodings and generate E2-like puzzles ([msg 3716](https://groups.io/g/eternity2/message/3716)). The first fast *public* backtracker was Marc Lebel's C++ solver at squaro.fr, whose internals the list dissected in the era's best solver-engineering thread ([msg 1704](https://groups.io/g/eternity2/message/1704)). Rendering was solved early and cleverly. Henk van der Griendt photographed his own pieces and built an HTML visualiser from the pictures ([msg 2499](https://groups.io/g/eternity2/message/2499)); Ignacio Ruiz de Conejo went further with **EPiecesV2.ps**, a PostScript program that renders any 16×16 board or 256-piece set from the official edge numbering. He shipped the *renderer* rather than the piece data, precisely to stay on the right side of the copyright line ([msg 2616](https://groups.io/g/eternity2/message/2616)). Owen adopted it for his own visualisation ([msg 2617](https://groups.io/g/eternity2/message/2617)). The non-programmers got their tool in December 2007: eii4me's **Manual Placement Program** (EternManShare.EXE), a VB6 GUI for placing pieces by hand, released with source and iterated to version S3.00 within eight days on community feedback ([msg 3541](https://groups.io/g/eternity2/message/3541), [msg 3719](https://groups.io/g/eternity2/message/3719)). And in February 2008 Yannick Kirschhoffer released **Eternity II Editor 1.0.0**, a cross-platform Java board editor that would become the longest-lived tool of them all ([msg 4544](https://groups.io/g/eternity2/message/4544)). ## 2008–2010: the editor era and the open-source wave The central release of the era was Louis Verhaard's **eii**, the solver that won the only prize money Eternity II ever paid. Published in September 2008 at fingerboys.se with the words "I am stuck and my only hope to improve my best score is by using brute force" ([msg 5940](https://groups.io/g/eternity2/message/5940)), it was distributed as a binary for volunteers to run; the documentation and a decoder for its `.eii` output files followed in January 2009, along with the disclosure that users had found 467 more than forty times ([msg 6275](https://groups.io/g/eternity2/message/6275)). Its hosting is a lesson in link rot: fingerboys.se was Verhaard's band's website and folded with the band ([msg 7446](https://groups.io/g/eternity2/message/7446)), so in January 2010 the solver moved unchanged to [shortestpath.se/eii](http://www.shortestpath.se/eii/), his own site and its long-term home ([msg 7439](https://groups.io/g/eternity2/message/7439)). Hobbyists were still running it at 466-level scores in 2011 ([msg 8840](https://groups.io/g/eternity2/message/8840)), and veterans were still walking newcomers through `eii.exe` in 2021 ([msg 10202](https://groups.io/g/eternity2/message/10202)). The machine itself has [its own solver page](/research/lab/experiments/louis-verhaard/eii). Around it, a whole shelf filled in: - **E2_Manual**, trans.spam (Thomas)'s DirectX manual-placement program, at v1.0.0.18 by mid-2008 ([msg 5686](https://groups.io/g/eternity2/message/5686)), moved to a SourceForge project with binaries and source in June 2009 ([msg 6765](https://groups.io/g/eternity2/message/6765)). - **Eternity II Editor** grew from editor to solver: 1.3 in March 2009, then 1.4.0 with the real E2 patterns, a built-in solver and a random board generator ([msg 6594](https://groups.io/g/eternity2/message/6594), [msg 6679](https://groups.io/g/eternity2/message/6679)), then v1.5 within a day of a user's feature requests ([msg 6978](https://groups.io/g/eternity2/message/6978)). It lives at SourceForge (sourceforge.net/projects/eternityii); Kirschhoffer resurfaced in 2012 still offering help with the code ([msg 9064](https://groups.io/g/eternity2/message/9064)), and in 2023 Bruno Gauthier's 460 (the best five-clue board until 2026) was "made with my own program and Eternity II Editor" ([msg 11074](https://groups.io/g/eternity2/message/11074)), converted to the shared viewer format by Peter McGavin ([msg 11081](https://groups.io/g/eternity2/message/11081)). - **E2Lab.** Fred ("Eternity Blogger") published a Windows editor+solver in October 2009 and iterated almost daily ([msg 7071](https://groups.io/g/eternity2/message/7071)); it took the E2Lab name at v1.0.0.20 ([msg 7148](https://groups.io/g/eternity2/message/7148)), and v1.0.0.21 removed a "magic button" explicitly "to respect the game rules" ([msg 7150](https://groups.io/g/eternity2/message/7150)). E2Lab is also the source of the community's canonical tooling-reliability lesson: in December 2009 a user reported a popup announcing a 471 on a board that was never saved, an unverifiable claim that still haunts records discussions ([msg 7284](https://groups.io/g/eternity2/message/7284)). - **e2walker.** Philippe Coustaux's fill-path explorer, in the group Files section since August 2007 ([msg 2313](https://groups.io/g/eternity2/message/2313)), revised by Ole Knudsen ("Kron") and, when the list took inventory in 2009, still "the only program of its kind": a solver that lets you specify an arbitrary 256-step fill path ([msg 7056](https://groups.io/g/eternity2/message/7056), [msg 7067](https://groups.io/g/eternity2/message/7067)). - **WhichWayToGo.jar.** okifinoki (Benjamin)'s GUI for scoring candidate fill paths by expected options per placement; three independent implementations converged on its statistics within the thread ([msg 6572](https://groups.io/g/eternity2/message/6572)). His graphical puzzle generator E2Generator.jar had joined the Files area the previous autumn ([msg 6036](https://groups.io/g/eternity2/message/6036)). - **Open solver source** arrived in a wave: Markus Zajc's C++ constraint-propagation solver ([msg 6748](https://groups.io/g/eternity2/message/6748)); Martin Hapl's Java backtracker at hapl.net, surfaced by the list and community-profiled from 1.2M to 2.9M iterations/s ([msg 6794](https://groups.io/g/eternity2/message/6794), [msg 6916](https://groups.io/g/eternity2/message/6916)); snazzyflapper's C# task-parallel solver, promptly re-uploaded without the piece file the moderators flagged ([msg 7606](https://groups.io/g/eternity2/message/7606), [msg 7610](https://groups.io/g/eternity2/message/7610)); and doc_s_smith's **Eternity II Java Toolbox**, a five-tool suite (configurable backtracker, constraint-driven placement, mismatch-tolerant search with swap repair, Monte-Carlo node estimator, fill-strategy finder) that marked the Eternity I veteran's return in June 2010 ([msg 7755](https://groups.io/g/eternity2/message/7755)). ## 2011–2018: the quiet years' tools As the contest died, the tools got stranger and more personal. Dan Hansen, after "4 engrossing years" of E2 algorithms, shipped **Edge Match Puzzles** for iPhone, the first time the community's expertise became a consumer product ([msg 8943](https://groups.io/g/eternity2/message/8943)); Tony Wauters's academic group released an Android edge-matching app ([msg 9057](https://groups.io/g/eternity2/message/9057)). Juraj Pivovarov uploaded a scan-order visualizer, self-deprecatingly billed as a "total waste of time" ([msg 9013](https://groups.io/g/eternity2/message/9013)). Theory became a document: Peter McGavin's complex_theory.pdf, the LaTeX transcription of Owen's model, was in the group Files by 2013 ([msg 9188](https://groups.io/g/eternity2/message/9188)). The open-source torch passed to David Barr: an OpenCL solver published on GitHub in 2015 ([msg 9360](https://groups.io/g/eternity2/message/9360), [msg 9367](https://groups.io/g/eternity2/message/9367)). The repo, github.com/david3x3x3/eternity2, is still the era's most reused codebase, followed by Raspberry Pi cluster builds with a public status page ([msg 9582](https://groups.io/g/eternity2/message/9582)), a Python-in-the-browser solver via Pyodide ([msg 9854](https://groups.io/g/eternity2/message/9854)) and dancing-links experiments with visualizations ([msg 10095](https://groups.io/g/eternity2/message/10095), [msg 10100](https://groups.io/g/eternity2/message/10100)). The web got its first solver playground too: Guillaume L.'s browser backtracker at 16x16tetravex.xyz, whose instant solves collapsed to "never-ending" the moment puzzles were regenerated with E2-like colour statistics, a live demonstration of where the difficulty lives ([msg 9449](https://groups.io/g/eternity2/message/9449), [msg 9458](https://groups.io/g/eternity2/message/9458)). ## 2019–2026: the modern stack The modern toolchain begins with a rescue. When Yahoo announced it would erase Groups content in 2019, the migration to groups.io carried the messages, files and photos across with weeks to spare ([msg 9934](https://groups.io/g/eternity2/message/9934)), which is why the Files-area tools above still exist at all, behind the group's membership wall. Two weeks after the migration, Jef Bucas launched **[e2.bucas.name](https://e2.bucas.name)**: SVG-rendered boards encoded entirely in URL parameters ("since the parameters are after the '#', nothing is actually transmitted to the server"), with a drop-down of best boards that quietly became the community's record book ([msg 9955](https://groups.io/g/eternity2/message/9955)). A Clues page answering the perennial hint-piece questions followed in 2021 ([msg 10082](https://groups.io/g/eternity2/message/10082)), and a revamp with keyboard shortcuts and score display in 2022 ([msg 10590](https://groups.io/g/eternity2/message/10590)). Virtually every partial shared since is an e2.bucas.name URL. The record-solver line is a three-repo story. Joshua Blackwood open-sourced his C# **EternityII_Solver** (the code behind the 468) in September 2020, having first asked for a standard pieces file so his repo would not ship copyrighted data ([msg 10037](https://groups.io/g/eternity2/message/10037), [msg 10034](https://groups.io/g/eternity2/message/10034)). Bucas had it running under Mono within hours ([msg 10038](https://groups.io/g/eternity2/message/10038)), rewrote it in C for roughly double the speed ([msg 10065](https://groups.io/g/eternity2/message/10065)), and published the generator behind the port as **libblackwood** (Python that emits fast C) at github.com/jfbucas/libblackwood ([msg 10078](https://groups.io/g/eternity2/message/10078)). When the original repo quietly went private, a newcomer's "Where is the software you all use?" got it re-published: "It is the exact code used to find a 470" ([msg 10161](https://groups.io/g/eternity2/message/10161)). The port, the original and the viewer are the stack behind every record since 2020; the [Blackwood solver page](/research/lab/experiments/joshua-blackwood/solver) covers the algorithm itself. The rest of the modern shelf: mtmidgee's **E2Play**, an old VB manual-play board recoded in C# and open-sourced from Australian lockdown, "not a solver (in any way shape or form)" ([msg 10208](https://groups.io/g/eternity2/message/10208)); David Barr's **solveforscore**, a Python score-maximiser published in his GitHub repo, which produced a hintless 462 ([msg 11088](https://groups.io/g/eternity2/message/11088), [msg 11101](https://groups.io/g/eternity2/message/11101)); jwortmann's **Eternity2Puzzles.jl**, a Julia package extending the complexity theory with invalid joins and a slip array ([msg 11603](https://groups.io/g/eternity2/message/11603)); and Michal Dobrogost's **eii-puzzles** (github.com/michal-dobrogost/eii-puzzles), a well-tested puzzle generator with a header-only C parsing library, generating 5-hint instances à la the original ([msg 11752](https://groups.io/g/eternity2/message/11752)). ## The conventions layer The formats outlived most of the tools, and they are what a newcomer actually needs to know. **e2pieces.txt / e2hints.txt.** The piece-file format was set by eternity2.net's BOINC client (a distributed solver needs a standard input, [msg 10952](https://groups.io/g/eternity2/message/10952)), and was consciously written down as the community standard in December 2007, with John Morrison posting explicit format descriptions ([msg 3571](https://groups.io/g/eternity2/message/3571), [msg 3572](https://groups.io/g/eternity2/message/3572)). Fifteen years of drift followed: when Vasily V. surveyed every `e2pieces.txt` he could find on GitHub in 2023, his verdict was "it's a mess!". He found inconsistent numberings, palettes and at least one bad file that had been recommended to newcomers ([msg 11033](https://groups.io/g/eternity2/message/11033)). The format-confusion thread just before it had already produced the reference piece list in the de-facto standard numbering that newcomers are pointed to today ([msg 10970](https://groups.io/g/eternity2/message/10970)), verified checksum-correct in the survey's follow-up ([msg 11034](https://groups.io/g/eternity2/message/11034)). The numbering conventions themselves are launch-week decisions: edge types numbered from the booklet, agreed before the puzzle was two weeks old ([msg 983](https://groups.io/g/eternity2/message/983)); a 2009 proposal to renumber the patterns "universally" was declined precisely because de-facto standards already existed ([msg 6804](https://groups.io/g/eternity2/message/6804)). **CRC-16 checksums.** In the contest years, when the norm was not to redistribute the piece set, the community verified transcriptions instead: publish CRC-16 checksums per 8-piece block and compare. Members converged on identical CRCs within a day of launch ([msg 1063](https://groups.io/g/eternity2/message/1063), [msg 1073](https://groups.io/g/eternity2/message/1073)); checksum utilities (Checksum-v4.txt, ChecksumCalc.zip) settled into the Files section as the standard answer to "is my piece file right?" ([msg 7591](https://groups.io/g/eternity2/message/7591)), and the protocol was extended to the clue puzzles in 2009 ([msg 6769](https://groups.io/g/eternity2/message/6769)). **The board-in-a-URL format.** Since 2019, a board *is* an e2.bucas.name URL: width, height, piece list and edges in the fragment, rendered client-side, nothing sent to any server ([msg 9955](https://groups.io/g/eternity2/message/9955)). It is the format records are announced in, verified in, and archived in: today's lingua franca, the way `e2pieces.txt` was in 2008. This site is one more branch of that lineage: its [viewer](/viewer) reads the same URL format, and the community boards it bundles are catalogued in [the notable boards](/research/community/boards). ## The census | Tool | Author | Born | Status | Source | | --- | --- | --- | --- | --- | | E2-like puzzle generator (C++) | Brendan Owen | 2007-01 | group Files (members) | [41](https://groups.io/g/eternity2/message/41) | | Benchmark corpus + generator | Sergio "Zerjillo" Alonso | 2007-05 | group Files (members) | [201](https://groups.io/g/eternity2/message/201) | | eternity2.net (BOINC) + R&D solver | Dave Clark | 2007-07 | closed 2007-12; files archived | [756](https://groups.io/g/eternity2/message/756), [3716](https://groups.io/g/eternity2/message/3716) | | Public C++ solver (squaro.fr) | Marc Lebel | 2007-08 | current status unknown | [1704](https://groups.io/g/eternity2/message/1704) | | e2walker (fill-path explorer) | Philippe Coustaux | 2007-08 | group Files (members) | [2313](https://groups.io/g/eternity2/message/2313), [7056](https://groups.io/g/eternity2/message/7056) | | Photo-based HTML visualiser | Henk van der Griendt | 2007-09 | personal; never distributed | [2499](https://groups.io/g/eternity2/message/2499) | | EPiecesV2.ps (PostScript renderer) | Ignacio Ruiz de Conejo | 2007-09 | group Files (members) | [2616](https://groups.io/g/eternity2/message/2616) | | Manual Placement Program | eii4me | 2007-12 | group Files (members) | [3541](https://groups.io/g/eternity2/message/3541) | | Eternity II Editor | Yannick Kirschhoffer | 2008-02 | SourceForge; used as late as 2023 | [4544](https://groups.io/g/eternity2/message/4544), [11074](https://groups.io/g/eternity2/message/11074) | | E2_Manual | trans.spam (Thomas) | 2008-07 | SourceForge (2009) | [5686](https://groups.io/g/eternity2/message/5686), [6765](https://groups.io/g/eternity2/message/6765) | | eii (distributed solver + decoder) | Louis Verhaard | 2008-09 | shortestpath.se/eii; fingerboys.se dead | [5940](https://groups.io/g/eternity2/message/5940), [7439](https://groups.io/g/eternity2/message/7439) | | E2Generator.jar | okifinoki (Benjamin) | 2008-10 | group Files (members) | [6036](https://groups.io/g/eternity2/message/6036) | | WhichWayToGo.jar | okifinoki (Benjamin) | 2009-03 | group Files (members) | [6572](https://groups.io/g/eternity2/message/6572) | | C++ constraint solver | Markus Zajc | 2009-05 | group Files (members) | [6748](https://groups.io/g/eternity2/message/6748) | | Java backtracker (hapl.net) | Martin Hapl | 2009-07 | hapl.net; current status unknown | [6794](https://groups.io/g/eternity2/message/6794) | | E2Lab (editor + solver) | Fred ("Eternity Blogger") | 2009-10 | author's blog; current status unknown | [7071](https://groups.io/g/eternity2/message/7071) | | Eternity II Java Toolbox | doc_s_smith (Dietmar Wolz) | 2010-06 | group Files (members) | [7755](https://groups.io/g/eternity2/message/7755) | | Edge Match Puzzles (iPhone) | Dan Hansen | 2011-07 | App Store release; status unknown | [8943](https://groups.io/g/eternity2/message/8943) | | Scan-order visualizer | Juraj Pivovarov | 2012-01 | group Files (members) | [9013](https://groups.io/g/eternity2/message/9013) | | complex_theory.pdf | Peter McGavin | 2013-07 | group Files (members) | [9188](https://groups.io/g/eternity2/message/9188) | | OpenCL/CPU solvers, solveforscore | David Barr | 2015-04 | GitHub (david3x3x3/eternity2) | [9367](https://groups.io/g/eternity2/message/9367), [11088](https://groups.io/g/eternity2/message/11088) | | Browser solver (16x16tetravex.xyz) | Guillaume L. | 2015-09 | current status unknown | [9449](https://groups.io/g/eternity2/message/9449) | | e2.bucas.name (board viewer) | Jef Bucas | 2019-11 | live | [9955](https://groups.io/g/eternity2/message/9955) | | EternityII_Solver | Joshua Blackwood | 2020-09 | GitHub (public again since 2021) | [10037](https://groups.io/g/eternity2/message/10037), [10161](https://groups.io/g/eternity2/message/10161) | | libblackwood (C port generator) | Jef Bucas | 2020-11 | GitHub (jfbucas/libblackwood) | [10078](https://groups.io/g/eternity2/message/10078) | | E2Play (manual-play board) | mtmidgee | 2021-08 | open-sourced | [10208](https://groups.io/g/eternity2/message/10208) | | Eternity2Puzzles.jl | jwortmann | 2025-08 | GitHub | [11603](https://groups.io/g/eternity2/message/11603) | | eii-puzzles (generator + C library) | Michal Dobrogost | 2026-01 | GitHub (michal-dobrogost/eii-puzzles) | [11752](https://groups.io/g/eternity2/message/11752) | Where a status says "group Files (members)", the artifact survived the 2019 Yahoo-to-groups.io migration ([msg 9934](https://groups.io/g/eternity2/message/9934)) and is accessible to [group members](https://groups.io/g/eternity2). The benchmark *suites* that travelled through these tools (Txibilis's, Geoff's, Benoist's, Owen's 9×9s and 10×10s) have [their own page](/research/build/benchmarks). ## Related - [The community's benchmarks](https://eternity2.dev/research/build/benchmarks) — How a community forbidden from sharing the pieces built a shared test culture anyway: derived-count verification protocols, the Txibilis and beginner suites, node-count duels, full enumerations, and the one benchmark that is still standing open today. - [The hunt, a history (part I: 2000–2009)](https://eternity2.dev/research/community/hunt) — The community's story, from a mailing list founded seven years before the puzzle existed to the $10,000 scrutiny prize won under a borrowed name, with every event sourced to its original message. Part I of a growing chronicle. - [The notable boards](https://eternity2.dev/research/community/boards) — The famous Eternity II boards, treated as first-class citizens: Verhaard's prize-winning 467, the Blackwood record line to 470, the strict five-clue record to 464, and this project's own boards: who found each one, when, and what makes it structurally interesting. Every bundled board opens in the viewer. --- # The builder's toolkit > A ready-to-use Rust starter kit for building your own Eternity II solver: score, generate boards with real colour balance, batch-generate with pinned clues, convert every format, benchmark, and a solve→sweep→compare iteration loop, so you write only the solver. Plus a one-line setup for coding agents, and a board generator right here in the browser. - Canonical page (with interactive figures/demos): https://eternity2.dev/research/build/toolkit/ - Updated: 2026-07-20 - Source: The starter kit (this repo): the Rust workspace, examples, and agent setup files — https://github.com/raphael-anjou/eternity2/tree/main/research/starter-kit --- Everything you need to *start* building an Eternity II solver, minus the solver itself. The [starter kit](https://github.com/raphael-anjou/eternity2/tree/main/research/starter-kit) is one folder in the repo: a small Rust workspace that already does the plumbing. Scoring, board generation, batch generation with pinned clues, format conversion, benchmarking, and a full **solve → sweep → compare** iteration loop are all there. You write one `Solver`; the rest keeps working around it. Nothing in the kit re-implements scoring, generation, or formats. Those come from the same shared crates the site itself runs on, so a score from the kit is the *same* number the [viewer](/viewer) and every other engine produce: the one canonical rim-excluding matched-edge count. Copy the folder, drop in your idea, and iterate. > **[Interactive: AgentSetupBlock]** Rendered on the canonical page (link above); not shown in this markdown export. ## What's in the box - **Score and verify any board**, from an `eternity2.dev` / `e2.bucas.name` URL or a bare `board_edges` blob, through the canonical scorer, and check it against the real official piece set (all-distinct-pieces, clue compliance), which the kit now ships. - **Generate boards** with real Eternity-II colour balance: five border colours confined to the frame, the interior balanced, every piece distinct, fully deterministic per seed. - **Batch-generate** ("give me 100 boards, these seeds, five clues pinned") as reproducible site-schema JSON you can read straight back. - **Convert** between every format the community uses: `board_edges`, `board_pieces`, `e2pieces.txt`, the `eternity2.dev` and legacy bucas URLs, and CSV. See the [format reference](/research/build/formats). - **Benchmark** the plumbing single-core, so you know your solver's overhead budget. - **The iteration loop:** a stable `Solver` trait, a sweep runner that writes reproducible run directories, and a `compare` tool that diffs two runs, with the variance discipline this puzzle demands baked in. ## The one rule the kit enforces for you On Eternity II the score swings a lot from seed to seed: the standard deviation across seeds is roughly 12 to 20 points for a whole-board solver. So a one- or two-point difference in mean between two solver versions is almost always noise. The kit's `compare` tool refuses to call a sub-noise difference a win, tells you to sweep at least 40 seeds, and always reports the spread. Keep everything single-core, as the site's [benchmarks](/research/build/benchmarks) do, and your numbers stay comparable to everyone else's. ## Write your first solver The whole kit is built around one trait: ```rust use e2_kit::{Board, Budget, Instance, SolveOutcome, Solver}; struct MySolver; impl Solver for MySolver { fn name(&self) -> String { "my-solver".into() } fn solve(&mut self, instance: &Instance, start: &Board, budget: Budget) -> SolveOutcome { let mut board = start.clone(); // `start` already carries any pinned clues // ...your search here. Poll budget.expired(). SolveOutcome::complete(board) // or ::improved / ::exhausted / ::bound } } ``` Copy `examples/my_solver.rs` (a complete, working greedy baseline), replace the body of `solve`, then sweep it: ```bash cargo run --release --example sweep -- --n 40 --budget 3 cargo run --release --bin e2kit -- compare runs/ runs/ ``` Full recipes (scoring, generation, batch, convert, benchmark) are in the kit's [README](https://github.com/raphael-anjou/eternity2/tree/main/research/starter-kit#readme). Boards to test a solver against live in the CC0 [dataset](/research/build/dataset); the approaches to try are surveyed in the [map of every known approach](/research/build/approaches-map). ## Generate boards right here The kit's generator, in the browser: the same WASM engine, no install. Pick a shape and a seed range and it makes a reproducible batch; click any board to open it in the [viewer](/viewer) and score it edge by edge. > **[Interactive: BoardGenerator]** Rendered on the canonical page (link above); not shown in this markdown export. Want the same thing on the command line, or 10,000 boards with clues pinned? Use the kit's `generate_batch` example: it writes each board as JSON you can feed straight back to a solver. ## Related - [Run it yourself](https://eternity2.dev/research/build/run-it-yourself) — The whole site, the engine, and every result in this section run from one repository. Here is how to get it going, rebuild the WebAssembly engine, and reproduce the numbers. - [The dataset](https://eternity2.dev/research/build/dataset) — A public, CC0 dataset for Eternity II in two parts: fourteen benchmark instances to solve, and a corpus of 7,658 distinct strong boards to learn from. Every score is recomputed from the board itself, and the corpus is checked to be genuinely diverse rather than a thousand copies of one board. - [A map of every known approach](https://eternity2.dev/research/build/approaches-map) — The survey the community keeps asking for and never finds: every family of attack tried on Eternity II, what each one actually reached, where it walls out, and a link to the deep page. One organising insight runs through all of them. - [Board & puzzle formats, written down](https://eternity2.dev/research/build/formats) — Every format an Eternity II board or puzzle travels in on this site and in the community: the board_edges letter string and the hints clue list, e2pieces.txt, the puzzle CSV, the site's Puzzle JSON, and the viewer URL, with the exact byte-level rules (how the grey border is encoded in each) and, most of all, what each format can and cannot recover. --- # The variants and the claims that live there > Every "Eternity II" that is not the real puzzle: the TopCoder Marathon variant and the unresolved Takahashi 468, McGavin's unframed 480/480, the mixed-set boards, the no-starter challenge, and the claim quarantine, from the 2007 phantom-sets warning to the community's zero-knowledge verification ethic. Ends with a checklist for stating a score properly. - Canonical page (with interactive figures/demos): https://eternity2.dev/research/build/variants/ - Updated: 2026-07-02 - Source: The phantom-sets warning (Sergio Demian Lerner), eternity2@groups.io, 2007-07 — https://groups.io/g/eternity2/message/1210 - Source: The unsaved E2Lab "471" popup, eternity2@groups.io, 2009-12 — https://groups.io/g/eternity2/message/7284 - Source: A hand-solve worth "at least 472", never evidenced, eternity2@groups.io, 2010-01 — https://groups.io/g/eternity2/message/7383 - Source: Brendan Owen asks the 476/480 claimant to publish the grid, eternity2@groups.io, 2011-02 — https://groups.io/g/eternity2/message/8676 - Source: The $1000 no-starter challenge, quantified by Peter McGavin, eternity2@groups.io, 2011-06 — https://groups.io/g/eternity2/message/8924 - Source: The Vautrin "resolved" claim falls to duplicate-piece checks, eternity2@groups.io, 2014-10 — https://groups.io/g/eternity2/message/9300 - Source: The Takahashi 468 claim surfaces (Dima), eternity2@groups.io, 2017-09 — https://groups.io/g/eternity2/message/9694 - Source: The TopCoder rules check: randomly generated pieces (Peter McGavin), eternity2@groups.io, 2017-10 — https://groups.io/g/eternity2/message/9697 - Source: Unframed E2 solved: thousands of 480/480 boards (Peter McGavin), eternity2@groups.io, 2017-11 — https://groups.io/g/eternity2/message/9750 - Source: Why the unframed 480 is disqualified: grey edges not on the rim, eternity2@groups.io, 2017-11 — https://groups.io/g/eternity2/message/9766 - Source: The mixed-set "480": one E2 + Clue-1 + Clue-2 set (Peter McGavin), eternity2@groups.io, 2023-10 — https://groups.io/g/eternity2/message/11169 --- Over twenty years, the archive has accumulated a small zoo of puzzles that are *almost* Eternity II: same pieces with a rule dropped, same rules with different pieces, same board with donor pieces mixed in. Each variant is a legitimate object of study (some produced genuinely beautiful results), but each also became, sooner or later, the home address of a headline score that is not a record on the real puzzle. This page is the field guide: what each variant is, what was actually achieved on it, and how the community learned to keep variant scores out of the [records table](/research/records). ## Why variants matter: scores only compare within a game There is one lesson, and everything else on this page is a case study of it: **a score is only comparable to another score if both were achieved on the same piece set under the same rules regime.** The real puzzle is the board Tomy sold: 256 specific pieces, a 16×16 frame with the grey edges on the rim, and the starter piece pinned at I8 (the four other clue placements were optional aids under the contest rules, [msg 11046](https://groups.io/g/eternity2/message/11046)). The record line 467 → 468 → 469 → 470 all lives in that one regime, verified board by board ([msg 10554](https://groups.io/g/eternity2/message/10554)); the strict five-clue line (best known: 464) is tracked separately because it is a *harder* regime, not a different puzzle ([Records & solvers](/research/records)). Change the piece set and "480" can become easy. Drop the frame rule and 480/480 has actually been *achieved*. Drop the starter constraint and the expected number of solutions multiplies by 784. None of those numbers says anything about the official 480, which remains unfound. Hence the catalogue below, and the quarantine that follows it. ## The catalogue ### The TopCoder Marathon variant and the Takahashi 468 claim In 2009, TopCoder ran a Marathon Match on an Eternity-II-*style* problem. When Peter McGavin checked the contest's problem statement years later, he found that it used **randomly generated pieces**, apparently with different colour counts than E2 and possibly no distinction between border and interior edge types ([msg 9697](https://groups.io/g/eternity2/message/9697)). Each test was its own puzzle. That makes any score from the contest a statement about random instances of the puzzle *class*, not about Monckton's fixed 256 pieces: a different game, however similar the rules sheet looks. The claim attached to it surfaced in September 2017, in the afterglow of McGavin's [10×10 benchmark](/research/build/benchmarks) solve: Dima reported that "467 has been broken in 2009". Naohiro Takahashi (chokudai), a top competitive programmer, had tweeted a 468. Dima stated plainly that he had never seen the solution and it was unverified ([msg 9694](https://groups.io/g/eternity2/message/9694), [9696](https://groups.io/g/eternity2/message/9696)). The scrutiny followed the standard protocol. McGavin, surprised that a "simple" beam-search-style method would beat everything in [Verhaard's arsenal](/research/lab/experiments/louis-verhaard/eii) ([msg 9695](https://groups.io/g/eternity2/message/9695)), did the rules check above and asked for confirmation that the 468 used the original pieces ([msg 9697](https://groups.io/g/eternity2/message/9697)). David Barr argued the other side: the tweet says "Eternity 2", and Takahashi's own profile distinguishes the TopCoder contest from the real puzzle ([msg 9698](https://groups.io/g/eternity2/message/9698)). Dima undertook to contact him and ask for the solution: "This is the only way to know for sure" ([msg 9700](https://groups.io/g/eternity2/message/9700)). No resolution ever appeared in the archive, so the claim's status remains unresolved. Told in full: *if* the 468 was on the TopCoder variant, it is rule-incomparable with Verhaard's 467; *if* it was on the real pieces, no board was ever produced. Either way it stays out of the records table as a claim, not a record. ### Unframed E2: McGavin's 480/480 that isn't a solution The most beautiful non-result in the archive. In late 2017 Peter McGavin set himself a variant: place **all 256 real pieces** on the real 16×16 board, but treat the grey edges as ordinary colours (so the border pieces migrate into an interior band) and maximize internal joins. On 2 November he posted 479/480 ([msg 9736](https://groups.io/g/eternity2/message/9736)); ten days later one of his backtrackers, working from around its 4,400th 14×15 sub-solution, found not one but **thousands of full 480/480 configurations** ([msg 9750](https://groups.io/g/eternity2/message/9750), picture at [9755](https://groups.io/g/eternity2/message/9755)). Henk van der Griendt laid the pieces out physically and confirmed they fit ([msg 9754](https://groups.io/g/eternity2/message/9754)). The inevitable question came: so you have solved Eternity 2? McGavin was precise. The board scores 480/480 internal joins with original pieces on the original board, but "the competition rules say the grey edges must be around the border, which clearly they are not. From that point of view, the entry is disqualified" ([msg 9757](https://groups.io/g/eternity2/message/9757), [9766](https://groups.io/g/eternity2/message/9766)). His own summary is the model of how to report a variant result: "I set my own E2-like challenge with my own rules and then solved it" ([msg 9767](https://groups.io/g/eternity2/message/9767)). He estimated the variant's difficulty as on par with building an unframed 14×14 from the 196 middle pieces ([msg 9719](https://groups.io/g/eternity2/message/9719)). Hard, but demonstrably not E2-hard: the frame constraint the variant drops is precisely where the real puzzle's difficulty concentrates. ### Mixed piece sets: the donor-piece "480"s The third family keeps the frame rule and changes the pieces. In 2014 McGavin showed complete 16×16 boards built from *two* E2 sets, exploiting duplicate pieces ([msg 9305](https://groups.io/g/eternity2/message/9305)), and in October 2023 he built a full 480/480 board from the pieces of one E2 set, one Clue-1 set and one Clue-2 set ([msg 11169](https://groups.io/g/eternity2/message/11169)), in Vlastislav W.'s max-distinct-tiles challenge, a deliberate game whose metric is how many *distinct* official tiles such a board can carry (record: 238, [msg 11167](https://groups.io/g/eternity2/message/11167), [11170](https://groups.io/g/eternity2/message/11170)). These constructions hide nothing: clearly labelled by their makers, they are the reason the records table carries a "variant" badge on its 2023 row. The full story of the donor sets (what the clue puzzles were, and how their pieces ended up in these boards) is on [the clue puzzles page](/research/build/clue-puzzles). ### The no-starter variant and the $1000 challenge In June 2011, list member ebeternity put up $1000 for a full E2 solution **without** the piece-139 starter constraint, valid to the end of September ([msg 8922](https://groups.io/g/eternity2/message/8922)). It was the first post-contest cash on the table. McGavin immediately quantified what the relaxation buys: an estimated **1.1527 × 10⁷ solutions without the starter constraint versus 14,702 with it**, 784 times more needles, yet the expected backtracker cost per solution barely moves (9.2766 × 10⁴² nodes versus 9.2751 × 10⁴², best-known search order) ([msg 8924](https://groups.io/g/eternity2/message/8924)). Fewer constraints, proportionally bigger haystack: the variant is 784× "easier" in solution count and essentially unchanged in work. Nobody claimed the money. The only "solve" that reached the thread was a second-hand 480 claim promptly labelled bogus, occasioning Johannes Lindé's summary of a decade of such claims: claimants become "quite indignant (or silent) upon requests for proof" ([msg 8951](https://groups.io/g/eternity2/message/8951), [8952](https://groups.io/g/eternity2/message/8952)). ### A different objective: most pieces placed, zero conflicts Not every variant changes the pieces or the frame. Some change the *scoring rule*, and the cleanest example is the max-conflict-free-placement objective: instead of counting matched edges on a full board, count the most pieces you can place so that **every** placed piece matches all its neighbours, leaving holes rather than mismatches. The score is "pieces placed", not "edges matched", and the two are not comparable: a board with a handful of holes says nothing about how a full board built from the same search would score. The frontier here is old and small, and it still belongs to Louis Verhaard. His "Only seven holes" board from around 2008 places **249 of 256** pieces conflict-free, with the seven holes clustered in the top band (rows 1 to 4). In June 2026 Laurent Zamofing reached **248**, one short of it, by recombining the community's published 467-edge boards as crossover donors ([msg 11890](https://groups.io/g/eternity2/message/11890), [11901](https://groups.io/g/eternity2/message/11901)). What is striking is that both boards hit a *proven local dead-end* at their score: Verhaard's seven holes cannot be filled by the seven remaining pieces, and freeing a radius-6 neighbourhood around them still never reaches 250. That the residual holes always land in the same top band, under an objective that has nothing to do with edge count, is its own small finding, and it is [the mismatch geometry again](/research/why/mismatch-geometry): the damage collects against whichever edge the search finishes on, whatever it is optimising. ## The claim quarantine Variants are one way a false "record" is born; the other is a claim with no board attached. The community's response to both matured into a protocol, and its history is worth telling because the quarantined claims still circulate. **The earliest form: the phantom-sets warning (2007).** Within days of the launch, Sergio Demian Lerner warned the list about "phantom sets": accepting a stranger's "random" E2-like benchmark could mean unknowingly solving an isomorphic re-encoding of the real puzzle, and handing the stranger a $2M solution ([msg 1210](https://groups.io/g/eternity2/message/1210)). The community adopted the practice of publishing benchmarks with provenance and known solutions ([msg 1213](https://groups.io/g/eternity2/message/1213)). The insight generalizes: *a piece set you cannot verify is a claim you cannot score*. Set-scrutiny was part of the culture before any famous fake arrived. **The 471 that was never saved (2009).** One morning Dominique Schaltz reported that E2Lab had popped up a message box overnight saying 471, but the score did not appear on his grid and the configuration was apparently never saved ([msg 7284](https://groups.io/g/eternity2/message/7284)). Within weeks it echoed through the list as "somebody touched 471" ([msg 7317](https://groups.io/g/eternity2/message/7317), [7353](https://groups.io/g/eternity2/message/7353)). No board ever existed. The episode is the cleanest illustration of why the rule is *board or it didn't happen*: a faithfully reported software popup, once detached from its caveats, circulated as a record. **The ≥472 hand-solve (2010).** Faruk Barber reported completing the whole board by hand with none of the clue pieces on their positions; Henk van der Griendt computed the claim would be worth at least 472 after swapping the starter into compliance ([msg 7383](https://groups.io/g/eternity2/message/7383), [7385](https://groups.io/g/eternity2/message/7385)). Al Hopfer called it "just silly": a genuine 472 would dwarf the known 467 ([msg 7427](https://groups.io/g/eternity2/message/7427)). No evidence was ever posted; the claimant was simultaneously offering his clue puzzles for sale ([msg 7395](https://groups.io/g/eternity2/message/7395)). **The 476-then-480 bloom (2011).** In January 2011 Alain Bidon claimed a 476/480 achieved without the starter piece in place; the original message is missing from the archive export and survives only through replies ([msg 8247](https://groups.io/g/eternity2/message/8247)). The list immediately re-scored it under the rules (at best 472 without the starter, 468 guaranteed after compliance). By February the claim had grown to multiple hintless **480s** ([msg 8636](https://groups.io/g/eternity2/message/8636)) and hit what one member called "the good old zero knowledge test". Brendan Owen's two demands in that thread are still the model of the genre: "there is a bug in your program. Actually place the real pieces" ([msg 8670](https://groups.io/g/eternity2/message/8670)), and "could you please publish the grid of piece ids" ([msg 8676](https://groups.io/g/eternity2/message/8676)); Bruce made it concrete: just turn each piece over and post the 16×16 list of the numbers on the backs ([msg 8681](https://groups.io/g/eternity2/message/8681)). No grid ever appeared. In the same season an anonymous "new algorithm" announcement was met with the other standard challenge: prove it by solving [Brendan's hint-free 10×10 benchmark](/research/build/benchmarks) ([msg 8262](https://groups.io/g/eternity2/message/8262), [8264](https://groups.io/g/eternity2/message/8264)). **The Vautrin affair (2014): the protocol working end to end.** Nicolas Vautrin first claimed his program could prove E2 has *no* solutions, retracted (a bug), then days later posted "eternity2 resolved ;)" while withholding the solution because of a prize ([msg 9280](https://groups.io/g/eternity2/message/9280), [9286](https://groups.io/g/eternity2/message/9286), [9291](https://groups.io/g/eternity2/message/9291)). This time a checkable artifact existed, a claimed solution to one of Brendan's benchmark puzzles, and verification killed it in days: Conny Öström's editor found **115 duplicate pieces** in it ([msg 9300](https://groups.io/g/eternity2/message/9300)), McGavin exhibited one piece used five times ([msg 9301](https://groups.io/g/eternity2/message/9301)), Arnaud Carré identified the exact bookkeeping bug ([msg 9308](https://groups.io/g/eternity2/message/9308)), and Vautrin conceded ([msg 9303](https://groups.io/g/eternity2/message/9303)). Nobody had to trust anybody: the grid was posted, so the grid could be checked. The pattern across all five stories is the community's real institutional knowledge. Claims die or survive on artifacts (a grid of piece ids, a solved public benchmark, a checksum), never on reputation, enthusiasm or plausibility. The 471, the ≥472 and the 476/480s must never enter the records table; the Takahashi 468 waits outside it for a board; and the Vautrin episode shows the same machinery clearing a genuine mistake in four days. ## How to state a score properly Distilled from the twenty years above, the checklist the archive effectively enforces. A score means nothing without all four: 1. **Name the piece set.** Official 256-piece E2? A Brendan benchmark set (which one)? Random pieces? Mixed donor sets? If the set is private or unverifiable, it scores nothing; the [phantom-sets warning](https://groups.io/g/eternity2/message/1210) is about exactly this. 2. **Name the rules regime.** Framed with grey edges on the rim? Starter-only (the 467→470 record line), strict five-clue (the 464 line), no-starter (the $1000 challenge), or unframed? Scores do not transfer between regimes: 784× more solutions is still not the same game. 3. **Post the board.** The 16×16 grid of piece ids with rotations: Brendan's demand, Bruce's "turn each piece over". A board can be re-scored by anyone; a number cannot. Every board on [the notable boards page](/research/community/boards) can be loaded and re-scored edge by edge in the [viewer](/viewer). 4. **Say who and when, with a link.** The records table only carries entries with a primary source; claims that live only in a popup, a tweet or a memory stay quarantined ([Records & solvers](/research/records)). Set + regime + board, or it didn't happen. ## Related - [Records & solvers](https://eternity2.dev/research/records) — Eternity II has never been solved, but fifteen years of community effort have pushed the best board to 470/480. Who holds what, how they did it, and why some headline "480" boards are not actually the real puzzle. - [The four clue puzzles](https://eternity2.dev/research/build/clue-puzzles) — Tomy sold four small companion puzzles for Eternity II: solve one, submit the solution, and the official site revealed one piece's placement on the main board. What each puzzle was, the broken online checker, the eBay grey market, why puzzles 5 and 6 never came, and the clue puzzles' second life as complex-theory test cases and donor piece sets. - [The notable boards](https://eternity2.dev/research/community/boards) — The famous Eternity II boards, treated as first-class citizens: Verhaard's prize-winning 467, the Blackwood record line to 470, the strict five-clue record to 464, and this project's own boards: who found each one, when, and what makes it structurally interesting. Every bundled board opens in the viewer. --- # History & community > The record and the people behind it: two decades of Eternity II told as a story, the record boards themselves, the record-holders and theorists, the academic literature, and how to add your own work to the wiki. - Canonical page (with interactive figures/demos): https://eternity2.dev/research/community/ - Updated: 2026-07-13 --- Eternity II is a story before it is an algorithm. This section keeps the community's memory: how the record climbed, the boards that carry the line, the people who found them, the papers written along the way, and how to add what you know.
- [History: the big steps](/research/history) — The whole story at a glance: a scannable timeline of the turning points, from the mailing list founded in 2000 to the 470 record that still stands. - [The hunt, in full](/research/community/hunt) — The long-form account in two parts: the founding era (2000–2009) and the modern record line (2009–2026), with the posts to prove each turn. - [Records & solvers](/research/records) — The record timeline and the engines behind it: who reached 470/480, and what those boards reveal about the wall. - [The notable boards](/research/community/boards) — The record line told through the boards themselves: Verhaard's 467, the line to 470, the strict five-clue record, each with its non-matching edges marked and openable in the viewer. - [Who's who](/research/people) — The people behind two decades of research (founders, record-holders, theorists), with what each contributed and the posts to prove it. - [Papers](/research/papers) — The academic literature on Eternity II and edge-matching, ranked by how useful it actually is to a solver-builder. - [Contribute](/research/contribute) — How to add to the wiki: the sources it trusts, how findings are credited, and where to send what you know.
## The community archive Much of what this wiki draws on lives, in raw form, in the [groups.io Files area](https://groups.io/g/eternity2/files): about 300 MB built up over two decades. It is worth knowing what is in there.
- [The paper archive](https://groups.io/g/eternity2/files/00_Eternity2_articles_papers_presentations_books) — Fifteen dated PDFs, 2007 to 2020: the complexity proofs, the SAT/CSP and MILP papers, theses, and a maintained bibliography. The backbone of our [Papers](/research/papers) page. - [Puzzle theory & proofs](https://groups.io/g/eternity2/files/Puzzle%20Theory) — Sixteen more: phase-transition bounds, the shared-edge feasibility proof, French seminar notes, and cross-domain work from the SAT and physics literature. - [Decades of solvers](https://groups.io/g/eternity2/files) — Dozens of contributors' folders (Brendan, Guenter, Peter McGavin, and many more): backtrackers, SAT and exact-cover encoders, GA and GPU attempts, with source, most from before this wiki existed. - [Databases](https://groups.io/g/eternity2/databases) — Brendan Owen's ["Backtracker estimates"](/research/why/complex-theory) tabulation (the tree sizes and solution counts you'll find worked into the theory pages) and the record leaderboards, all queryable.
Sample puzzles, benchmark sets, and board images are in there too. If you find something worth a page, [say so](/research/contribute) and it can become one. ## Pages in this section - [The hunt, a history (part I: 2000–2009)](https://eternity2.dev/research/community/hunt) — The community's story, from a mailing list founded seven years before the puzzle existed to the $10,000 scrutiny prize won under a borrowed name, with every event sourced to its original message. Part I of a growing chronicle. - [The hunt, a history, part II: 2009–2026](https://eternity2.dev/research/community/hunt-part-2) — Seventeen years after the prize: the contest dies with its solution locked in a safe, 467 stands for a decade, the archive survives Yahoo's shutdown by days, and then an outsider from Reddit rewrites the record book. Every event sourced to its original message. - [The notable boards](https://eternity2.dev/research/community/boards) — The famous Eternity II boards, treated as first-class citizens: Verhaard's prize-winning 467, the Blackwood record line to 470, the strict five-clue record to 464, and this project's own boards: who found each one, when, and what makes it structurally interesting. Every bundled board opens in the viewer. --- # The notable boards > The famous Eternity II boards, treated as first-class citizens: Verhaard's prize-winning 467, the Blackwood record line to 470, the strict five-clue record to 464, and this project's own boards: who found each one, when, and what makes it structurally interesting. Every bundled board opens in the viewer. - Canonical page (with interactive figures/demos): https://eternity2.dev/research/community/boards/ - Updated: 2026-07-02 - Source: msg 6337: the January 2009 scrutiny result, $10,000 to Anna Karlsson of Lund for 467/480 — https://groups.io/g/eternity2/message/6337 - Source: msg 10032: Blackwood's 468 reaches the list from Reddit — https://groups.io/g/eternity2/message/10032 - Source: msg 10045: McGavin announces the 469 — https://groups.io/g/eternity2/message/10045 - Source: msg 10074: Fernandez's single-piece-swap 469 — https://groups.io/g/eternity2/message/10074 - Source: msg 10117: Blackwood's 470 — https://groups.io/g/eternity2/message/10117 - Source: msg 11401: Bucas ties the 470 — https://groups.io/g/eternity2/message/11401 - Source: msg 11074: Gauthier's strict five-clue 460 (the record 2023–2026) — https://groups.io/g/eternity2/message/11074 - Source: Riotte's 464, the new strict five-clue record (groups.io, July 2026) — https://groups.io/g/eternity2/message/11919 - Source: e2.bucas.name (Jef Bucas), the community viewer these boards were first shared in — https://e2.bucas.name --- The history of Eternity II is usually told through the people and the solvers. This page tells it through the boards themselves: the handful of artifacts that carry the whole record line, whoever found them. Each entry says who announced the board and where, and what is publicly known about its structure. Every board shown here is bundled with this site: click any preview to load it in the [viewer](/viewer) and re-score it edge by edge. The full timeline and method history live on the [records page](/research/records); this is the gallery. ## The record line: 467 → 468 → 469 → 470 ### Verhaard's 467 (2008): the prize board The board that won the only money Eternity II ever paid out. Louis Verhaard's [distributed *eii* solver](/research/lab/experiments/louis-verhaard/eii), released to volunteers in September 2008 with the words "I am stuck" ([msg 5940](https://groups.io/g/eternity2/message/5940)), had found 467/480 more than 40 times by different users by the time he documented it ([msg 6275](https://groups.io/g/eternity2/message/6275)). At the 31 December 2008 scrutiny the entry, submitted under the name of Anna Karlsson of Lund (Verhaard's household), took the $10,000 best-partial prize ([msg 6337](https://groups.io/g/eternity2/message/6337), with the group recognizing the winner immediately at [msg 6349](https://groups.io/g/eternity2/message/6349)). Two later footnotes change how the board reads. Re-reading Verhaard's own account, Jef Bucas noted the 467 was achieved under a self-imposed handicap: Verhaard had misinterpreted the rules and restricted the kind of board he allowed himself to submit ([msg 10582](https://groups.io/g/eternity2/message/10582)). And by 2023 the score had become a calibration target: "last week I found about 30 x 467. I use this target to calibrate the code I'm running" ([msg 11001](https://groups.io/g/eternity2/message/11001)). It stood as the record for twelve years anyway. > **[Interactive: CommunityBoard]** Rendered on the canonical page (link above); not shown in this markdown export. The viewer also bundles three sibling 467s (Verhaard 467a, 467b, 467c) from the same campaign, in its board menu. ### Blackwood's 468 (2020): the outsider board The first advance past 467 in twelve years arrived from outside the community: a Reddit post by Joshua Blackwood, then unknown to the mailing list, relayed at [msg 10032](https://groups.io/g/eternity2/message/10032). A board with only 12 breaks, 468/480. Bucas verified it, added it to the viewer, and passed on the startling claim that the author could "find a 468 every 4 days" ([msg 10033](https://groups.io/g/eternity2/message/10033)). Days later Blackwood open-sourced [the solver that found it](/research/lab/experiments/joshua-blackwood/solver) ([msg 10037](https://groups.io/g/eternity2/message/10037)). Every board below this point traces back to that code. > **[Interactive: CommunityBoard]** Rendered on the canonical page (link above); not shown in this markdown export. ### McGavin's 469 (2020): the ceiling board "Your solver is fantastic!! I ran it for a few days on about a couple of hundred cores and hit the jackpot. New record score of 469! Only 11 breaks!" So wrote Peter McGavin, running Blackwood's freshly published solver ([msg 10045](https://groups.io/g/eternity2/message/10045)). Blackwood explained the solver's break discipline in the same thread: breaks are never allowed to touch, so this 469 is equivalently a 249-piece partial with 7 holes ([msg 10051](https://groups.io/g/eternity2/message/10051)). Structurally this board has a signature you can check yourself: all eleven of its unmatched edges sit in the top five rows, leaving an eleven-row slab that is locally flawless: the damage is swept up against the edge the search finished at. That geometry, and why it flips on boards built in the other direction, is analyzed in [Where the mismatches live](/research/why/mismatch-geometry). > **[Interactive: CommunityBoard]** Rendered on the canonical page (link above); not shown in this markdown export. ### The 469 wave (October–November 2020) Bucas posted his first two 469s in October ([msg 10052](https://groups.io/g/eternity2/message/10052), "Here are 2 other 469"), ported Blackwood's algorithm to C, roughly doubling its speed ([msg 10065](https://groups.io/g/eternity2/message/10065)), and the stream kept coming: boards c through g in November, from [msg 10067](https://groups.io/g/eternity2/message/10067) ("Another one yay \o/") through [msg 10078](https://groups.io/g/eternity2/message/10078), which shipped together with the open-sourced port, *libblackwood*. All seven are in the viewer's board menu as Bucas 469a–g. The odd one out is Carlos Fernandez's. He fed McGavin's 469 to a piece-exchange program of his own and found another 469 differing by a single piece ([msg 10074](https://groups.io/g/eternity2/message/10074)), proof, in Bucas's words when he added it to the viewer, that "even at 469, there is still a little bit of flexibility left" ([msg 10075](https://groups.io/g/eternity2/message/10075)). That flexibility is thin: it is exactly the kind of isolated tie the rigidity analysis below predicts, not a path upward. ### The 470s (2021 and 2024): the current ceiling Blackwood closed his own arc with a nearly wordless message: a viewer URL, a piece list (470/480, 10 breaks), and the single line "I haven't physically put it together yet, but I found one!" ([msg 10117](https://groups.io/g/eternity2/message/10117)). He later confirmed it was found with exactly the public repo's code ([msg 10161](https://groups.io/g/eternity2/message/10161)), the retuned schedule he had published in advance, and then stopped: "I have not written a line of code or run any algorithms since I found a 470" ([msg 10185](https://groups.io/g/eternity2/message/10185)). > **[Interactive: CommunityBoard]** Rendered on the canonical page (link above); not shown in this markdown export. The score has been tied once, not beaten. In December 2024 Bucas restarted "a few threads of Joshua's code" and another 470 appeared ([msg 11401](https://groups.io/g/eternity2/message/11401)); Fernandez noticed its three unmatched border figures allowed a rearrangement and posted a 470b ([msg 11403](https://groups.io/g/eternity2/message/11403)). The 470 class remains a Blackwood-solver monopoly, and 470 remains the ceiling: "No one is even close… The best result to date, is the partial solution from Joshua Blackwood, 470/480 edges matching" ([msg 11343](https://groups.io/g/eternity2/message/11343)). > **[Interactive: CommunityBoard]** Rendered on the canonical page (link above); not shown in this markdown export. ## What the record boards share Three publicly documented facts hold across the 468/469/470 line. **Same clue regime.** All of them place the mandatory starter piece at its official spot and none of the four optional clue pieces at theirs. The community checked this for the 470 ([msg 10554](https://groups.io/g/eternity2/message/10554)), and Blackwood confirmed he had the clue tiles and deliberately did not use them ([msg 10185](https://groups.io/g/eternity2/message/10185)). Under the original contest rules only the starter was mandatory, so these boards were prize-eligible as submitted. **Banded mismatches.** The few unmatched edges are not scattered; they pack into one band of rows against the edge the search finished at. [Where the mismatches live](/research/why/mismatch-geometry) scores the real boards live and shows the band; it also shows this project's boards exhibiting the same band, mirrored. **Local rigidity.** None of these boards is an almost-solution waiting for a polish. [The rigidity wall](/research/why/rigidity-wall) uses exact integer-programming solves to prove that on record boards, freeing whole regions and refilling them optimally returns the same arrangement: the best boards sit at the bottom of their own valleys. Fernandez's single-piece-swap 469 is the exception that proves the rule: a tie next door, never a step up. ## The strict five-clue line: from Gauthier's 460 to Riotte's 464 Most published record boards keep only the mandatory starter piece. In March 2023 a thread asked the stricter question: what is the best board that respects **all five** official clues ([msg 11037](https://groups.io/g/eternity2/message/11037))? A ladder climbed in days: 412, then 452 and 457 (Carlos Fernandez), then 453/455/456/458 (David Barr), stopping at **Bruno Gauthier's 460**, "made with my own program and Eternity II Editor" ([msg 11074](https://groups.io/g/eternity2/message/11074)); McGavin converted it to the shared viewer format ([msg 11081](https://groups.io/g/eternity2/message/11081)). That 460 stood for more than three years. In late June 2026 a new thread, "Record of Eternity2 with 5 hints?", reopened the line: **Benjamin Riotte** posted a 461, then a wave of results climbing to **464/480 (only 16 broken edges)**, the first advance on the strict record since 2023 ([groups.io msg 11919](https://groups.io/g/eternity2/message/11919)). **Igor Pejic** reached the same 463–464 range independently in the same thread, using what he described as a "modified Blackwood's DFS algorithm". All of the boards respect the five clues at their official cells (starter #139, hints #208, #255, #181, #249). The strict line matters because of what the five clues imply: the community's solution-count estimate with all five clues placed is about 0.00000004 (effectively a unique target), against roughly 14,702 expected "solutions" with the starter alone ([msg 11193](https://groups.io/g/eternity2/message/11193)). A five-clue board is playing the exact game the designers set. The 464 stands sixteen edges below the full solution, and that gap is itself a datum. > **[Interactive: BoardsFoundGallery]** Rendered on the canonical page (link above); not shown in this markdown export. ## This project's boards This site's own experiments produced four boards worth keeping, labelled for what they are: experiments several steps below the community line, and documented end to end. Each links to the experiment that found it; every score is recomputed from the board's own edges. ### PALIMPSEST (463) The project's best, found by reading the whole corpus of strong boards to separate genuine shared structure from shared bad habits, then attacking the traps. The full story is in [the PALIMPSEST experiment](/research/lab/experiments/raphael-anjou/learning/palimpsest). > **[Interactive: RecordBoard]** Rendered on the canonical page (link above); not shown in this markdown export. ### KEYRING (460) Built from scratch by letting three learned signals vote on every placement, reaching 460 in a board family no earlier search here had cracked; see [KEYRING](/research/lab/experiments/raphael-anjou/learning/keyring). Its mismatches band in the bottom rows, the mirror image of McGavin's 469. That scan-order fingerprint is explained in [Where the mismatches live](/research/why/mismatch-geometry). > **[Interactive: RecordBoard]** Rendered on the canonical page (link above); not shown in this markdown export. ### PRIOR (460) From scratch plus destroy-and-repair, breaking construction ties by where pieces tend to sit in strong boards (see [PRIOR](/research/lab/experiments/raphael-anjou/learning/prior)). > **[Interactive: RecordBoard]** Rendered on the canonical page (link above); not shown in this markdown export. ### GAUNTLET (458) The same [beam search](/research/build/construct/beam-search) run across nine scan orders so it lands in different regions of board space; the zigzag order found this 458. The full run is written up in [GAUNTLET](/research/lab/experiments/raphael-anjou/pipelines/gauntlet). > **[Interactive: RecordBoard]** Rendered on the canonical page (link above); not shown in this markdown export. ## Related - [Records & solvers](https://eternity2.dev/research/records) — Eternity II has never been solved, but fifteen years of community effort have pushed the best board to 470/480. Who holds what, how they did it, and why some headline "480" boards are not actually the real puzzle. - [Where the mismatches live](https://eternity2.dev/research/why/mismatch-geometry) — A near-perfect board doesn't scatter its few errors evenly. It packs them into one band of five rows and leaves all the rest flawless. Which band is decided by the direction the search filled the board, and you can see the mirror on the real record boards. - [The rigidity wall](https://eternity2.dev/research/why/rigidity-wall) — Every record board we have is frozen in place. You cannot nudge your way from a great board to a perfect one, and we can prove it. --- # The hunt, a history (part I: 2000–2009) > The community's story, from a mailing list founded seven years before the puzzle existed to the $10,000 scrutiny prize won under a borrowed name, with every event sourced to its original message. Part I of a growing chronicle. - Canonical page (with interactive figures/demos): https://eternity2.dev/research/community/hunt/ - Updated: 2026-07-02 - Source: Monckton's copyright ultimatum and Brendan Owen's disqualification (groups.io message 1342) — https://groups.io/g/eternity2/message/1342 - Source: Brendan Owen derives the 17+5 design as the hardest possible puzzle (groups.io message 1947) — https://groups.io/g/eternity2/message/1947 - Source: eternity2.net shuts down: 1.6 TFlops, 10^19 operations, no solution (groups.io message 3511) — https://groups.io/g/eternity2/message/3511 - Source: Louis Verhaard releases the eii solver: “I am stuck” (groups.io message 5940) — https://groups.io/g/eternity2/message/5940 - Source: First scrutiny result: $10,000 to Anna Karlsson of Lund, score 467 (groups.io message 6337) — https://groups.io/g/eternity2/message/6337 - Source: Wikipedia, "Eternity II puzzle" — https://en.wikipedia.org/wiki/Eternity_II_puzzle --- Eternity II has an official history (a press release, a prize, a deadline) and it has a real one, which happened on a mailing list. The [eternity2 group](https://groups.io/g/eternity2) (originally a Yahoo group) is where the puzzle was analysed before it existed, digitized the day it launched, declared unsolvable within a fortnight, and where the only prize money ever paid out was quietly traced to one of the list's own regulars. This page tells that story from the archive itself: every event links to the message where it happened. Part I runs from the group's founding to the first scrutiny date, 2000 → February 2009. ## The group that predates its puzzle (2000–2006) The strangest fact about the Eternity II community is its birthday. Brendan Owen created the eternity_two group in October 2000, six and a half years before the puzzle was announced, "because we anticipated a follow up puzzle" to Eternity I ([msg 404](https://groups.io/g/eternity2/message/404)). The earliest surviving messages guess at what the sequel's pieces might be, betting wrongly on 3D tetrahedra ([msg 8](https://groups.io/g/eternity2/message/8)). By 2001 the group was already rehearsing the designer's problem rather than the solver's: Günter Stertenbrink asked how one would build a puzzle with a huge prize and only a ~1% chance of being solved in ten years ([msg 15](https://groups.io/g/eternity2/message/15)), almost exactly the brief Christopher Monckton's team would later execute. Eternity I veterans drifted in and waited: Dave Clark, author of the distributed E1 solver ESolve, rejoined in April 2001 ([msg 21](https://groups.io/g/eternity2/message/21)). When the first press reports arrived in December 2005, with Monckton promising the sequel would need "the lifetime of the Universe" while co-designer Oliver Riordan said "several years", Stertenbrink drew the obvious conclusion: "So we can conclude, the end of the universe is in several years." ([msg 34](https://groups.io/g/eternity2/message/34)) ## Launch summer (2007) The announcement came on 22 January 2007: 256 pieces, US$2,000,000 for the first correct solution, launch on 28 July, and a London Toy Fair stunt in which a strongman destroyed "the computer containing a solution" ([msg 36](https://groups.io/g/eternity2/message/36)). That computer, a distributor insider later admitted, contained nothing at all ([msg 148](https://groups.io/g/eternity2/message/148)). The group did not wait for the pieces. Within two days it was counting edge types on promotional photos, and Owen had derived the expected-solutions formula that made difficulty a tunable design parameter ([msg 38](https://groups.io/g/eternity2/message/38), [msg 44](https://groups.io/g/eternity2/message/44)). He published a generator for Eternity-II-like puzzles ([msg 41](https://groups.io/g/eternity2/message/41)); Alan O'Donnell had the first working solver a week later ([msg 64](https://groups.io/g/eternity2/message/64)). By 8 July, three weeks before anyone had touched a real piece, anr_56 had estimated the edge-type counts from launch photos and Owen had run the numbers on that configuration: about 10^30 times harder than the benchmarks the group was solving in minutes. "No one will solve this puzzle," he concluded ([msg 665](https://groups.io/g/eternity2/message/665)). Then came the famous 48 hours. Australia got the puzzle first, and Owen was at Kmart on launch eve, "first one to grab it off their stack" ([msg 1051](https://groups.io/g/eternity2/message/1051)). He fed the piece panels through a computer-vision program he had written in advance ([msg 789](https://groups.io/g/eternity2/message/789)), reported the edge distribution "as flat as could be" ([msg 1054](https://groups.io/g/eternity2/message/1054)), and confirmed the real parameters: 5 border colours, 17 interior colours, the group's worst-case scenario ([msg 977](https://groups.io/g/eternity2/message/977)). Then, after Dave Clark's "nice chat to Mr Monckton", he published the first solution-count estimate for the real piece set: roughly 5,930 solutions with the mandatory clue, against Monckton's own figure of about 5 million ([msg 987](https://groups.io/g/eternity2/message/987)). The puzzle was two days old and its difficulty was already measured. The same week set the community's norms. To verify piece transcriptions without sharing copyrighted data, members converged on published CRC checksums ([msg 1063](https://groups.io/g/eternity2/message/1063)); and newcomer Sergio Demian Lerner warned about "phantom sets": a stranger's benchmark could be the real puzzle re-encoded, tricking you into handing over a $2M solution ([msg 1210](https://groups.io/g/eternity2/message/1210)). ## The theory race (2007–2008) A week into August, the puzzle's inventor arrived in person; he came to disqualify someone. Posting from an unverifiable Yahoo address, Christopher Monckton declared he held copyright on the piece designs and that his "web-trawling software" had flagged Brendan Owen's website: Owen, who had been aiming for the lesser prize, was out ([msg 1342](https://groups.io/g/eternity2/message/1342), [msg 1352](https://groups.io/g/eternity2/message/1352), [msg 1358](https://groups.io/g/eternity2/message/1358)). It later emerged the flagged file did not even correspond to the real pieces ([msg 1358](https://groups.io/g/eternity2/message/1358)). Members protested that an anonymous forum account could hardly carry official weight; Monckton doubled down ([msg 1374](https://groups.io/g/eternity2/message/1374), [msg 1377](https://groups.io/g/eternity2/message/1377)). The chill was real and lasting: a year later Owen, as moderator, was still deleting derived data tables "to be safe" ([msg 5651](https://groups.io/g/eternity2/message/5651)). It was in this climate that Owen, showing that E2's flat piece statistics killed the strategy that had cracked Eternity I, drew his line: "If we cannot talk about something as fundamental as piece frequencies, then I will give up on this puzzle now" ([msg 1667](https://groups.io/g/eternity2/message/1667), [msg 1694](https://groups.io/g/eternity2/message/1694)). The theory came fast after that. kubzpa proved by a [parity argument](/research/build/analysis/parity-arguments) that a score of exactly 479 (one mismatched edge) is impossible ([msg 1640](https://groups.io/g/eternity2/message/1640)); hold that thought, because seventeen months later the argument would meet a counterexample. Owen then produced the period's signature result: assuming the designers wanted the hardest possible 16×16, with a flat distribution and about one expected solution, the interior colour count should be (196! · 4^196)^(1/392) ≈ 17.14, hence 17 interior colours and 5 border colours. Exactly the real puzzle ([msg 1947](https://groups.io/g/eternity2/message/1947)). The 17+5 split was not bad luck; it was [a bullseye on the hardness peak](/research/why/phase-transition), and the group had reverse-engineered the targeting. Theoretical claims were checked against node counts measured on shared [benchmarks](/research/build/benchmarks). Angel de Vicente, posting as Txibilis, built the standard suite of E2-like test boards ([msg 1610](https://groups.io/g/eternity2/message/1610)), and a duel began: Txibilis's hand-designed [fill orders](/research/build/backtracking/fill-order) against the automated strategy-optimizer of doc_s_smith, driving full-search node counts down by orders of magnitude; one benchmark stood at 89,794 nodes, answered within two days by 85,729 ([msg 2896](https://groups.io/g/eternity2/message/2896), [msg 2928](https://groups.io/g/eternity2/message/2928)). Mid-duel, the list discovered who doc_s_smith was: Dietmar Wolz, finder of most of the known Eternity I solutions ([msg 2972](https://groups.io/g/eternity2/message/2972)). The estimates converged too. kubzpa's paper put the solution count near 15 million ([msg 3497](https://groups.io/g/eternity2/message/3497)); Owen measured the search tree's branching depth by depth, finding the node count peaks at 161 pieces placed ([msg 3147](https://groups.io/g/eternity2/message/3147)); and in April 2008 he announced he had "nailed the theory": an exact model of the search tree whose predictions sat on top of the empirical curves, independently cross-checked by Louis Verhaard: on the order of 10^27 CPU-years per solution ([msg 5197](https://groups.io/g/eternity2/message/5197), [msg 5193](https://groups.io/g/eternity2/message/5193), [msg 5209](https://groups.io/g/eternity2/message/5209)). The group's chief theorist acted on his own numbers: he was now hunting the highest score, not 480 ([msg 4996](https://groups.io/g/eternity2/message/4996)). ## Big iron and syndicates If one computer was hopeless, perhaps thousands were not. Dave Clark's eternity2.net, a BOINC-based [distributed solver](/research/build/faster/distributed-solving), launched with the puzzle in July 2007 ([msg 756](https://groups.io/g/eternity2/message/756)) and had 1,300 members within a month, 160 of them in the USA, where the puzzle had not even been released ([msg 2122](https://groups.io/g/eternity2/message/2122), [msg 2132](https://groups.io/g/eternity2/message/2132)). The project submitted a 462-edge partial to Tomy, then 463 ([msg 2663](https://groups.io/g/eternity2/message/2663)), a number that would function as the community's public score ceiling for over a year. A prize-sharing "Eternity 2 Syndicate" followed, paying members in proportion to placements contributed ([msg 3021](https://groups.io/g/eternity2/message/3021)). It lasted five months. In December 2007 Clark shut eternity2.net down, publishing the final accounting: over 1.6 TFlops of aggregate computing, over 10^19 CPU operations, best scores in the mid-460s. His verdict: a brute-force solution "was always clearly going to be impossible" ([msg 3511](https://groups.io/g/eternity2/message/3511)). The list immediately spawned threads titled "Eternity2 Must Have Been Solved"; it had not ([msg 3554](https://groups.io/g/eternity2/message/3554)). The project's files were preserved in the group archive ([msg 3633](https://groups.io/g/eternity2/message/3633)), and Clark open-sourced his research solver ([msg 3716](https://groups.io/g/eternity2/message/3716)). He also left the archive its best primary source on the puzzle's creation: a phone call with Monckton, who described judges typing entropy into a generator built by the Eternity I winners Alex Selby and Oliver Riordan, the solution printed once and vaulted ([msg 4177](https://groups.io/g/eternity2/message/4177)), "whilst all parties were out of the room", as the Tomy distributor leaflet he had posted at launch put it ([msg 901](https://groups.io/g/eternity2/message/901)). The exact-methods flank fared no better. A published [SAT encoding](/research/build/exact/sat-csp-encodings) of the full puzzle came with a call for anyone owning a machine with more than 16 GB of RAM ([msg 4084](https://groups.io/g/eternity2/message/4084)); integer programming died at 8×8 boards ([msg 5602](https://groups.io/g/eternity2/message/5602)). Raw speed kept climbing: istarinz broke 100 million placements per second on multiple cores ([msg 5804](https://groups.io/g/eternity2/message/5804)), then measured 558 million on a brand-new Core i7 ([msg 6212](https://groups.io/g/eternity2/message/6212)). But against search spaces measured in powers of forty, throughput was a rounding error. ## The road to 467 (2008) The scores had crept up all along: 410 from Pierre Schaus in the first weeks ([msg 1568](https://groups.io/g/eternity2/message/1568)), 453 from philippe.dupond ([msg 3998](https://groups.io/g/eternity2/message/3998)), 461 from e2dude ([msg 4440](https://groups.io/g/eternity2/message/4440)), with 463 as the "current known high" ([msg 5688](https://groups.io/g/eternity2/message/5688)). The methods changed character in mid-2008: Schaus posted his constraint-programming paper, whose key move (remove a set of non-adjacent pieces and re-place them *optimally* by solving an assignment problem) became the engine of antminder's hybrid, averaging a 462 per day ([msg 5589](https://groups.io/g/eternity2/message/5589), [msg 5601](https://groups.io/g/eternity2/message/5601)). Meanwhile two people had quietly gone past the ceiling. In a long August exchange, Max reported getting "beyond the 'don't-talk-about-limit' quite easily"; Louis Verhaard ("Max, you are really a dangerous man!") matched methods with him and found they had converged on the same heuristic signature, promising full disclosure "after new-year", that is, after the 31 December scrutiny date ([msg 5767](https://groups.io/g/eternity2/message/5767), [msg 5780](https://groups.io/g/eternity2/message/5780)). Verhaard would reveal only the geometry: his best high-score fill orders looked like a "comb": most rows scanned horizontally, the rest vertically ([msg 6112](https://groups.io/g/eternity2/message/6112)). Then, on 22 September 2008, Verhaard published [his solver](/research/lab/experiments/louis-verhaard/eii) for anyone to run at fingerboys.se: "This because I am stuck and my only hope to improve my best score is by using brute force" ([msg 5940](https://groups.io/g/eternity2/message/5940)). Any prize would be split 50-50 with the best-scoring user. antminder, whose own program needed a week to reach 463, was blunt: eii "completely blows it away" ([msg 5950](https://groups.io/g/eternity2/message/5950)). The prize itself was still folklore (the rules only promised a discretionary "lesser prize") until Max traced the $10,000 figure to a Monckton interview on the French official site ([msg 6073](https://groups.io/g/eternity2/message/6073)). Verhaard, three months before winning it, claimed not to care: he was in it for the honour, and only for this year ([msg 6072](https://groups.io/g/eternity2/message/6072)). The same autumn the hand-solvers surfaced: Christine Raisin down to 21 pieces left in the box lid ([msg 5935](https://groups.io/g/eternity2/message/5935)), Verhaard sorting pieces by pattern with his seven-year-old daughter and running a solve-by-hand mini-competition, the threads coining nicknames like "pink swords" and "kipper ties" for the motifs ([msg 5933](https://groups.io/g/eternity2/message/5933), [msg 5929](https://groups.io/g/eternity2/message/5929), [msg 5958](https://groups.io/g/eternity2/message/5958), [msg 5959](https://groups.io/g/eternity2/message/5959)). The list was never only a solver bench. ## The scrutiny-date farce (December 2008 → January 2009) Going into the first scrutiny date, the community was in a holding pattern: several members refused to commit serious effort until the puzzle proved it could survive its first deadline ([msg 6216](https://groups.io/g/eternity2/message/6216)); NickB had £20 on there being no winner and considered his money safe ([msg 5979](https://groups.io/g/eternity2/message/5979)). 31 December 2008 came and went. Nothing. Members emailed Tomy's UK and US addresses and left voicemail, and got no response ([msg 6245](https://groups.io/g/eternity2/message/6245)); the consumer Careline knew of "no details as of yet, regarding whether or not there is a winner" ([msg 6295](https://groups.io/g/eternity2/message/6295)). The rules said winners would be notified within 14 days and results published in the London Times and New York Times ([msg 6296](https://groups.io/g/eternity2/message/6296), [msg 6336](https://groups.io/g/eternity2/message/6336)); no such publication ever visibly appeared. Meanwhile, on 6 January, Verhaard released his solver's documentation and disclosed its ceiling: users had found 467 more than forty times ([msg 6275](https://groups.io/g/eternity2/message/6275)). On 15 January, roughly the last day of the 14-day window, Henk van der Griendt found a statement behind an unobtrusive link on the UK site only: hundreds of entries, none complete, the $2M prize still open, and a $10,000 runner-up prize to **Anna Karlsson of Lund, Sweden, for 467 of 480** ([msg 6337](https://groups.io/g/eternity2/message/6337)). No press release, no Times, and not a word from Monckton at any point. The list needed about an hour to decode "Lund + 467": the entry was from Louis Verhaard's household, submitted in the name of his wife, who had received the congratulation email days earlier ([msg 6349](https://groups.io/g/eternity2/message/6349)). Congratulations poured in from every regular; Max revealed his own best had been 465, each extra edge costing his program a factor of ~30 in time ([msg 6348](https://groups.io/g/eternity2/message/6348)). The Swedish press ran the family photo: over a year of work, 13 "seams" from a full solution, part of the money going to the World Wildlife Fund ([msg 6374](https://groups.io/g/eternity2/message/6374), [msg 6375](https://groups.io/g/eternity2/message/6375)). The aftermath had three barbs. A researcher from the Lleida SAT group posted that reaching 470 was "rather easy" with their methods, a claim never backed by any submitted entry, as Max pointedly noted ([msg 6306](https://groups.io/g/eternity2/message/6306), [msg 6360](https://groups.io/g/eternity2/message/6360)). Tomy told a member there would be no further [clue puzzles](/research/build/clue-puzzles), which most of the list welcomed as keeping the challenge pure ([msg 6381](https://groups.io/g/eternity2/message/6381)). And Verhaard casually settled a seventeen-month-old theorem: 479 *is* reachable, by flipping a border piece whose two border edges share a colour in a 480 solution. The 2007 parity proof had missed the outward-facing border edges, which the score never counts ([msg 6317](https://groups.io/g/eternity2/message/6317)). Even the community's cleanest impossibility result had a loophole; the puzzle, unsolved, kept all of its. ## The story continues > **Part II: 2009–2026** > > The story continues in [part II](/research/community/hunt-part-2): the Hungarian "we solved it" rumor resolved, the contest's death with its solution locked in a safe, the decade of 467, the migration that saved this archive by days, and the record wave that took the board to 470. ## Related - [Records & solvers](https://eternity2.dev/research/records) — Eternity II has never been solved, but fifteen years of community effort have pushed the best board to 470/480. Who holds what, how they did it, and why some headline "480" boards are not actually the real puzzle. - [Blackwood's solver, decoded and run here](https://eternity2.dev/research/lab/experiments/joshua-blackwood/solver) — Joshua Blackwood's record backtracker, decoded through Jef Bucas's notes (a colour quota schedule and a late-game mismatch allowance, tuned near-optimally), then built and run on my M1: left as published it flies to 248 of 256 pieces ignoring the clues; pin the five official clues and the same engine stalls near 45. - [Tuned to the hardness peak](https://eternity2.dev/research/why/phase-transition) — Eternity II uses 22 colors. They split 17 interior to 5 frame-only, and that 17 is exactly where this kind of puzzle is hardest to solve. --- # The hunt, a history, part II: 2009–2026 > Seventeen years after the prize: the contest dies with its solution locked in a safe, 467 stands for a decade, the archive survives Yahoo's shutdown by days, and then an outsider from Reddit rewrites the record book. Every event sourced to its original message. - Canonical page (with interactive figures/demos): https://eternity2.dev/research/community/hunt-part-2/ - Updated: 2026-07-02 - Source: Monckton closes the contest: “Extension of time is not allowed under the rules” (groups.io message 8477) — https://groups.io/g/eternity2/message/8477 - Source: Peter McGavin solves Brendan Owen's 10×10 in ~180 core-years, inside complex theory's error bars (groups.io message 9688) — https://groups.io/g/eternity2/message/9688 - Source: McGavin's 469 with Blackwood's solver: “New record score of 469! Only 11 breaks!” (groups.io message 10045) — https://groups.io/g/eternity2/message/10045 - Source: Joshua Blackwood's 470, the standing record (groups.io message 10117) — https://groups.io/g/eternity2/message/10117 - Source: Bruno Gauthier's 460, the best five-clue board 2023–2026 (groups.io message 11074) — https://groups.io/g/eternity2/message/11074 - Source: Benjamin Riotte's 464, the new five-clue record (groups.io, July 2026) — https://groups.io/g/eternity2/message/11919 - Source: Jef Bucas ties the 470 with Blackwood's code (groups.io message 11401) — https://groups.io/g/eternity2/message/11401 --- [Part I](/research/community/hunt) ended in January 2009 with a $10,000 cheque decoded in an hour and a puzzle that had survived its first deadline untouched. Part II covers everything since: the contest's slow death, the decade in which one number, 467, refused to move, the day the archive itself nearly vanished, and the record wave that finally moved it. As before, this is the community's story told from the [eternity2 archive](https://groups.io/g/eternity2), and every event links to the message where it happened. ## The long silence and the diehards (2009–2010) The Hungarian "we solved it" rumor that part I left hanging died the way such claims always die on this list. Once properly translated (a team at ELTE university claiming a full solve via an algorithm salad that included alpha-beta pruning, for a one-player puzzle), the native speakers called the posts confused and the engineers ran the arithmetic ([msg 6575](https://groups.io/g/eternity2/message/6575)). By June the claimant's account and every comment had been deleted from the Hungarian forum ([msg 6764](https://groups.io/g/eternity2/message/6764)). The verified story of 2009 was quieter and better. JSA ran Louis Verhaard's public [eii solver](/research/lab/experiments/louis-verhaard/eii) on a single PC and logged the climb: four million 463s, 625 466s, and finally, at day ~82, a 467, independently reproducing the prize score with the public binary and quantifying just how thin the air gets above 466 ([msg 6687](https://groups.io/g/eternity2/message/6687)). In August, Verhaard himself gave the definitive first-person account of the winning entry: "Anna is my wife"; she submitted it, "it was my program that did the job", and the 467 board contained 247 flawless pieces ([msg 6891](https://groups.io/g/eternity2/message/6891)). That December he disclosed the method part I could only hint at: he had found 467 "more than 50 times", by letting the backtracker place one mismatching edge at chosen depths, the move known as [edge slipping](/research/build/reduce/edge-slipping), gated by depth ([msg 7321](https://groups.io/g/eternity2/message/7321)). The second scrutiny date, 31 December 2009, replayed the first as farce minus the payout. Weeks of silence, then a news item ("Eternity II remains unsolved") with no winner and, unlike 2008, no best-partial prize at all ([msg 7471](https://groups.io/g/eternity2/message/7471)). A member extracted a written Q&A from Tomy: no organised activity in 2009, partial solutions were not even scored, and "the year one prize was part of the initial promotion only" ([msg 7488](https://groups.io/g/eternity2/message/7488)). Verhaard confirmed he had not improved on his 467 ([msg 7494](https://groups.io/g/eternity2/message/7494)). He also republished his solver at shortestpath.se, its long-term home, after his band's website folded ([msg 7439](https://groups.io/g/eternity2/message/7439), [msg 7446](https://groups.io/g/eternity2/message/7446)). Claims bloomed in the vacuum anyway: an E2Lab popup announcing a 471 on a board that was never saved ([msg 7284](https://groups.io/g/eternity2/message/7284)), a hand-solve implying at least 472, dismissed on sight ([msg 7383](https://groups.io/g/eternity2/message/7383), [msg 7427](https://groups.io/g/eternity2/message/7427)). Neither produced a board. Meanwhile Eternity I veteran doc_s_smith returned after three years and turned the list into an algorithms workshop ([msg 7755](https://groups.io/g/eternity2/message/7755)), framing the target the era could realistically chase: solving E2 itself being hopeless, "the challenge is clear: beat 468 matching edges" ([msg 7803](https://groups.io/g/eternity2/message/7803)). When his Monte-Carlo estimator disagreed with Brendan Owen's [complexity model](/research/why/complex-theory) by five orders of magnitude, Verhaard defended the model as "the finest work that has ever been published about E2" ([msg 7810](https://groups.io/g/eternity2/message/7810)), a sentence the next fifteen years would keep proving right. ## The contest dies (December 2010 → 2011) Asked for a one-year extension of the final scrutiny date, Tomy answered in one line: "No decsions [sic] will be made until the next scrutiny date" ([msg 8006](https://groups.io/g/eternity2/message/8006)). The deadline of 31 December 2010 passed in gallows humour, with members joking about couriering a hypothetical last-minute solution to the post office ([msg 8197](https://groups.io/g/eternity2/message/8197)). Then the official site went dark, "suspended pending final scrutiny confirmation" ([msg 8270](https://groups.io/g/eternity2/message/8270)); Verhaard posted "I can honestly tell you that I didn't solve it" ([msg 8277](https://groups.io/g/eternity2/message/8277)). The end arrived via France: a Tomy France press release (deadline passed, no winner, no additional year, the $2M unclaimed) met with disbelief until the source URL surfaced and the English page followed two days later ([msg 8339](https://groups.io/g/eternity2/message/8339), [msg 8373](https://groups.io/g/eternity2/message/8373)). Monckton's emailed reply to a member closed the door in person: the competition was over, and "Extension of time is not allowed under the rules", rules which, members immediately pointed out, explicitly allowed further scrutiny dates at the promoter's discretion ([msg 8477](https://groups.io/g/eternity2/message/8477), [msg 8478](https://groups.io/g/eternity2/message/8478)). Brendan Owen, the man who had been posting since before the puzzle launched, said goodbye: "It was great fun". He also asked Verhaard to congratulate his wife on the highest score, first-party confirmation that 467 stood at the contest's close ([msg 8429](https://groups.io/g/eternity2/message/8429)). Two loose ends defined the aftermath. One was the claim vacuum: a member's 476 without the hint (the original message is missing from the archive; it survives through its replies, [msg 8247](https://groups.io/g/eternity2/message/8247)) escalated into multiple hintless-480 claims and met the community's zero-knowledge wall (Owen: publish the grid of piece ids); nothing was ever published ([msg 8676](https://groups.io/g/eternity2/message/8676)). The other was the solution itself. The group owner laid out the custody arrangement: nobody, not Tomy, not Monckton, knows the solution; it sits with independent loss adjusters ([msg 8502](https://groups.io/g/eternity2/message/8502)). Owen then gave the statement still quoted today: Alex Selby and Oliver Riordan created a solution when Monckton paid them to generate a practically impossible puzzle, and it lies "hidden amongst reams of printed text which is locked in a safe" as insurance against legal challenge ([msg 8823](https://groups.io/g/eternity2/message/8823)). In April 2011 the official site confirmed the prize had gone unclaimed ([msg 8846](https://groups.io/g/eternity2/message/8846)). What replaced the money was a ladder. Community leaderboards appeared in the group database ([msg 8222](https://groups.io/g/eternity2/message/8222), [msg 8735](https://groups.io/g/eternity2/message/8735)); Owen, prompted by a golden-ratio guess, proved that a backtracker's node counts peak at fraction (1 − 1/e) of the board: 256 × 0.632 = 161.8, the closed form behind the long-observed "magic of 161" ([msg 8125](https://groups.io/g/eternity2/message/8125)); and the first exhaustive searches of Owen's [9×9 benchmarks](/research/build/benchmarks) landed within an order of magnitude of his theory's predictions ([msg 8793](https://groups.io/g/eternity2/message/8793), [msg 8803](https://groups.io/g/eternity2/message/8803)). A new name did most of that checking: Peter McGavin, who by 2011 was running the list's complex-theory service desk and had computed the numbers that became canon, about 14,702 expected solutions with the mandatory piece placed ([msg 8924](https://groups.io/g/eternity2/message/8924)). ## The quiet years (2012–2018) Three full years, 2012 to 2014, produced fewer messages than a busy quarter of 2008. Academia arrived in person: Tony Wauters posted his group's peer-reviewed hyper-heuristic paper (best score 461/480 in an hour) and stayed to answer questions ([msg 9017](https://groups.io/g/eternity2/message/9017)); a second paper, on MILP and Max-Clique heuristics, followed in 2017 ([msg 9683](https://groups.io/g/eternity2/message/9683)). The only prize money of the era was a Czech retailer's 12,000 EUR re-run of the contest ([msg 9072](https://groups.io/g/eternity2/message/9072)), extended to July 2015 ([msg 9271](https://groups.io/g/eternity2/message/9271)); its expiry then passed without a single mention on the list. When newcomer Dima asked for the best known result in late 2014 and got the canonical answer, his reply was the era in one line: "467 still, really? But that was 6 years ago!" ([msg 9318](https://groups.io/g/eternity2/message/9318)). Under the surface, two things matured. Theory became a document: McGavin transcribed Owen's complexity model into LaTeX as complex_theory.pdf, in the group's files ([msg 9188](https://groups.io/g/eternity2/message/9188)), turning folklore into something newcomers could actually read. And speed became a culture again: Arnaud Carré posted a 114 million recursions per second single-core solver as a comparison standard ([msg 9233](https://groups.io/g/eternity2/message/9233)), Michael Field designed an FPGA backtracker ([msg 9226](https://groups.io/g/eternity2/message/9226)), and a nodes-per-watt ledger ran from Raspberry Pi clusters to an Xbox One X ([msg 9519](https://groups.io/g/eternity2/message/9519), [msg 9816](https://groups.io/g/eternity2/message/9816)). The claim-filter kept working too: a 2014 "eternity2 resolved ;)" died when verification found one piece used five times ([msg 9286](https://groups.io/g/eternity2/message/9286), [msg 9301](https://groups.io/g/eternity2/message/9301)). Then, in September 2017, the community's shared benchmark fell. Peter McGavin found the first new solution to Brendan Owen's hint-free 10×10, the "monster" that had resisted everyone since 2008, by industrialising exactly what the list had converged on: enumerate the ~20 million possible first rows, rank them by complex theory's chance-of-solution per node, and farm them to every core available, from home ODROIDs and $12 Orange Pis to borrowed work servers, 400+ cores in all ([msg 9686](https://groups.io/g/eternity2/message/9686), [msg 9688](https://groups.io/g/eternity2/message/9688)). The solution cost about 2×10^17 nodes (roughly 180 core-years) and arrived on row-search ~92,907 against a predicted one-per-70,000, inside the theory's error bars: in McGavin's words, "no new methods, just systematic persistence and the law of large numbers". John Gilbert spoke for the list: "Amazing that it is being truly just as hard as predicted" ([msg 9693](https://groups.io/g/eternity2/message/9693)). It was the strongest validation Owen's theory ever received, and the proof that the benchmark culture, not the record chase, had been the group's real achievement of the decade. The same thread raised a records question that never resolved: Dima surfaced a 2009 tweet by TopCoder star Naohiro Takahashi claiming a 468, never accompanied by a board, possibly scored under different contest rules, and left permanently unverified ([msg 9694](https://groups.io/g/eternity2/message/9694), [msg 9697](https://groups.io/g/eternity2/message/9697)). Two months later McGavin placed all 256 real pieces on the 16×16 board with all 480 internal joins matched, an "unframed E2" with gray edges buried in the interior, and was scrupulously precise that it was not a solution to the puzzle ([msg 9736](https://groups.io/g/eternity2/message/9736), [msg 9750](https://groups.io/g/eternity2/message/9750), [msg 9757](https://groups.io/g/eternity2/message/9757)). The window closed at low ebb: 2018 produced 42 messages, and to a newcomer's poll a veteran answered, "anybody still crunching with backtracking ?? no way...." ([msg 9832](https://groups.io/g/eternity2/message/9832)). ## The migration (2019) In October 2019 Yahoo announced it would erase all Groups content within weeks: twelve years of piece counts, proofs, debunkings and solver source, gone. Jef Bucas raised the alarm ([msg 9920](https://groups.io/g/eternity2/message/9920)), Robert Gerbicz proposed groups.io, founder Ole Knudsen created the new group, and JSA paid the transfer fee: "I can pay for the first 5 years" ([msg 2](https://groups.io/g/eternity2/message/2)). The automated transfer completed on 8 November 2019 with roughly 2,000 members, messages, files and photos intact ([msg 9934](https://groups.io/g/eternity2/message/9934), [msg 9937](https://groups.io/g/eternity2/message/9937)). The archive this chronicle is written from survived by days. Two weeks later, Bucas launched the other half of the modern era's infrastructure: [e2.bucas.name](https://e2.bucas.name), a board viewer whose boards live entirely in the URL (nothing is transmitted to the server), with a drop-down of best boards that quietly became the community's record book ([msg 9955](https://groups.io/g/eternity2/message/9955)). Fittingly, the year's records news was archival too: Verhaard confirmed his astonishing 249-piece flawless partial was real, "no cheating… found it after a week or so, on 1 computer" ([msg 9890](https://groups.io/g/eternity2/message/9890)). ## The record wave (2020–2021) On 31 August 2020, a member relayed a Reddit post: a new best board with only 12 breaks, 468/480, the first advance past Verhaard's 467 in twelve years ([msg 10032](https://groups.io/g/eternity2/message/10032)). The author was Joshua Blackwood, a complete outsider unknown to the list. Bucas verified the board, added it to the viewer, and passed on the detail that made veterans sit up: the author "says he can find a 468 every 4 days!" ([msg 10033](https://groups.io/g/eternity2/message/10033)). Three days later Blackwood open-sourced the solver itself, carrying heuristic changes he believed made it "twice as good" and pre-configured to hunt 469s ([msg 10037](https://groups.io/g/eternity2/message/10037)). His engineering notes were as valuable as the code: SAT solvers, GPUs and pre-solved 2×2 caches had all been measured and discarded; the magic was the heuristic schedule and a small set of allowed "break" depths ([msg 10056](https://groups.io/g/eternity2/message/10056), [msg 10076](https://groups.io/g/eternity2/message/10076)). The community did what it does with good code: it ran it. On 9 September 2020, Peter McGavin, the man who had solved the 10×10, posted: "Your solver is fantastic!! I ran it for a few days on about a couple of hundred cores and hit the jackpot. New record score of 469! Only 11 breaks!" ([msg 10045](https://groups.io/g/eternity2/message/10045)). Bucas rewrote the solver in C, roughly doubling its speed, and a wave of further 469s followed through November ([msg 10065](https://groups.io/g/eternity2/message/10065), [msg 10067](https://groups.io/g/eternity2/message/10067)); the generator behind the port was published as libblackwood ([msg 10078](https://groups.io/g/eternity2/message/10078)). Then, on 30 March 2021, a two-line message: the URL of a 470/480 board ([msg 10117](https://groups.io/g/eternity2/message/10117)). Blackwood later confirmed the public repo was "the exact code used to find a 470" ([msg 10161](https://groups.io/g/eternity2/message/10161)), then retired: "I have not written a line of code or run any algorithms since I found a 470" ([msg 10185](https://groups.io/g/eternity2/message/10185)). One clarification matters for how these records are read. The contest's own rules pinned only the starter piece, required at its specified location and rotation; the four other clues were optional aids ([msg 11046](https://groups.io/g/eternity2/message/11046)). Every record board from the 468 up sits in that same starter-only regime: piece 139 at its mandatory square, none of the four optional clues at their official positions, a claim verified at board level for the 470 ([msg 10554](https://groups.io/g/eternity2/message/10554)). The 470 is the same puzzle as the 469s long quoted as the ceiling, not an easier variant; Blackwood had the clue tiles and "deliberately didn't use" them ([msg 10185](https://groups.io/g/eternity2/message/10185)). Boards that also honour the four optional clues are a separate, stricter ladder (more on it below). The [records page](/research/records) keeps the two regimes explicitly apart. Blackwood allowed himself one encore: reconfiguring his solver for zero breaks, he pushed the consecutive-placement record from Verhaard's long-standing 226 to 227, then 230, all on "a single PC in my basement" ([msg 10536](https://groups.io/g/eternity2/message/10536), [msg 10544](https://groups.io/g/eternity2/message/10544), [msg 10547](https://groups.io/g/eternity2/message/10547)). ## The modern era (2022–2026) The post-wave years settled into a rhythm of invariants, calibration and provenance. In May 2022 Al Hopfer, a regular since 2009, stated the border condition now known on this site as the [NS-1 balance](/research/why/border-balance): the outer rim of the 14×14 interior "must have the same mixture (parity) of the internal images on all the 56 border pieces" ([msg 10754](https://groups.io/g/eternity2/message/10754), [msg 10757](https://groups.io/g/eternity2/message/10757)). In the same thread, Carlos Fernandez was solving 14×14 quadrants in about four minutes ([msg 10802](https://groups.io/g/eternity2/message/10802)). Big interior blocks had become routine; closing the frame had not. The 2008 prize score, meanwhile, was formally demoted to a regression test: "last week I found about 30 x 467. I use this target to calibrate the code I'm running", wrote Bucas ([msg 11001](https://groups.io/g/eternity2/message/11001)). The stricter ladder got its own record. A 2023 thread collecting bests that respect **all five** clue placements climbed from 412 through 452 and 458 to Bruno Gauthier's 460 ([msg 11074](https://groups.io/g/eternity2/message/11074)), which held for over three years until Benjamin Riotte's 464 in July 2026, a 461 rising to 464/480 with his own modified-Blackwood solver, with Igor Pejic reaching the same 463–464 range independently ([groups.io](https://groups.io/g/eternity2/message/11919)). The same year produced the era's canonical false positive: a complete, 480-matching 16×16 built by McGavin from pieces of one E2 set, one Clue-1 set and one Clue-2 set, a "480" that is not the puzzle, posted precisely to make that point ([msg 11169](https://groups.io/g/eternity2/message/11169)). Theory completed its long journey from posts to source code. In January 2024 McGavin restated the headline numbers: 14,702 expected solutions with just the starter, 0.00000004 with all five hints, "very strongly suggesting… a single, unique solution" ([msg 11193](https://groups.io/g/eternity2/message/11193)). The next day he published complex_theory.c, his exact C implementation of Owen's model ([msg 11197](https://groups.io/g/eternity2/message/11197)): the reference this site's own [complexity engine](/research/lab/experiments/joshua-blackwood/solver) ports. In December, Bucas tied the record: "I restarted a few threads of Joshua's code, and… another 470 appeared!" ([msg 11401](https://groups.io/g/eternity2/message/11401)), with Fernandez posting a border-rearranged variation the same week ([msg 11403](https://groups.io/g/eternity2/message/11403)). Bucas's crediting never wavered: "Joshua Blackwood is the current record holder. I humbly used his code" ([msg 11555](https://groups.io/g/eternity2/message/11555)). And his wrapper_blackwood project put the point beyond opinion: a farm that varied every parameter of Blackwood's algorithm and measured the results, concluding that within the swept parameters the author's manual tuning was already near-optimal; his notes are published on this site with his explicit permission ([msg 11905](https://groups.io/g/eternity2/message/11905)). And the founders came back, or didn't. In May 2025, Brendan Owen posted for the first time in roughly fourteen years, answering a newcomer's difficulty question ([msg 11500](https://groups.io/g/eternity2/message/11500)), telling McGavin his years of work were "very impressive" ([msg 11521](https://groups.io/g/eternity2/message/11521)), and returning to his own model with a refined calculation of edge-join probabilities ([msg 11546](https://groups.io/g/eternity2/message/11546)). The AI era arrived first as farce: ChatGPT confidently informing a member that a solution "was eventually found by a team of puzzle enthusiasts" ([msg 10993](https://groups.io/g/eternity2/message/10993)), then a vibe-coded solver app whose owner conceded "it isn't 100% guarantee because Base44 is AI", met with patient tutoring rather than ridicule ([msg 11755](https://groups.io/g/eternity2/message/11755), [msg 11818](https://groups.io/g/eternity2/message/11818)). And in February 2026, the annual welcome note opened with a tribute to Kronjuvel: Ole Knudsen, who created the group, ran it for the better part of two decades, and has been missing from the list since 2023 ([msg 11771](https://groups.io/g/eternity2/message/11771)). The archive's current edge is 31 March 2026: a SAT thread still arguing about 4 GB CNF encodings, a standing just-for-fun challenge to invalidate a border partial, and one member's line for the anniversary: "slowly we are progressing to 20 years of E2 next year ;-) Will we solve E2 in 2026...?" ([msg 11820](https://groups.io/g/eternity2/message/11820), [msg 11823](https://groups.io/g/eternity2/message/11823)). The ledger after nineteen years: the 480 has never been found; the 470 has stood since 2021; and the ten missing edges are, as ever, [where the whole problem lives](/research/records). ## Related - [The hunt, a history (part I: 2000–2009)](https://eternity2.dev/research/community/hunt) — The community's story, from a mailing list founded seven years before the puzzle existed to the $10,000 scrutiny prize won under a borrowed name, with every event sourced to its original message. Part I of a growing chronicle. - [Records & solvers](https://eternity2.dev/research/records) — Eternity II has never been solved, but fifteen years of community effort have pushed the best board to 470/480. Who holds what, how they did it, and why some headline "480" boards are not actually the real puzzle. - [Blackwood's solver, decoded and run here](https://eternity2.dev/research/lab/experiments/joshua-blackwood/solver) — Joshua Blackwood's record backtracker, decoded through Jef Bucas's notes (a colour quota schedule and a late-game mismatch allowance, tuned near-optimally), then built and run on my M1: left as published it flies to 248 of 256 pieces ignoring the clues; pin the five official clues and the same engine stalls near 45. --- # Contribute your research > This wiki is the community's research home, and there is room in it for your work. Three ways to get it published, from a mailing-list post to a pull request, plus the small set of house rules that keep every page trustworthy. - Canonical page (with interactive figures/demos): https://eternity2.dev/research/contribute/ - Updated: 2026-07-02 --- This wiki is not one person's blog with the door closed. It is meant to be the community's research home: the place where nineteen years of Eternity II work (records, methods, structural findings, [dead ends](/research/build/dead-ends) included) gets written down, sourced, and kept findable. Every page in [the lab](/research/lab) carries an author byline and gathers on that researcher's [contributor page](/research/people), today mostly [Raphaël's](/research/people/raphael-anjou), because he is the one writing things down, but the structure credits each contributor by name. Yours can sit right beside his. There is already a precedent. The page on [Blackwood's algorithm](/research/lab/experiments/joshua-blackwood/solver) is built on Jef Bucas's notes and parameter study, republished with his explicit permission, his figures, and his name on every one of them. That is the model: the work stays yours, the wiki gives it a permanent, citable home. ## Three ways in **1. Post it and flag it: the lightest path.** Share your finding where the community already talks: the [mailing list](https://groups.io/g/eternity2) or the [Discord server](https://discord.gg/Ny5xs3q8w). If you would like it on the wiki, just say so in the post. Someone (usually Raphaël) will write it up as a page, run it past you, and publish it with full credit. That is exactly how the Blackwood page came to exist from Jef's notes. You never have to touch the repository. **2. Open an issue or a pull request.** The wiki is [an open repository](https://github.com/raphael-anjou/eternity2), and a research page is nothing more than one MDX file under `web/content/research/`. Adding the file *is* the registration: the sidebar, search, and sitemap pick it up automatically. Each page starts with a small frontmatter block: ```yaml title: Your finding, in one line description: >- Two or three sentences that can stand alone in a search result. kind: finding # or experiment, concept, reference... updated: 2026-07-02 topics: [backtracking] sources: - label: Hopfer's statement of the NS-1 condition (2022) url: https://groups.io/g/eternity2/message/10754 ``` If the page is an **experiment** (a search run you measured), one more block is required: the hardware it ran on. It is what lets a reader compare your result to everyone else's, and the build refuses an experiment page without it. ```yaml kind: experiment hardware: cores: 1 # logical cores used; sum across nodes for a cluster cpu: "AMD Ryzen 9 7950X" ramGb: 64 gpus: 0 accelerator: none # none | gpu | quantum | fpga | tpu machine: "desktop, single box" wallClock: "10 × 60 s" # budget per run × repeats runs: 10 seedPolicy: "randomized corner permutation per run" measured: true # true only for the standardized single-core bench ``` The page renders this as a spec card with one derived headline: **core-hours** (cores × wall-clock hours), the true cost of the run. That single number is what puts a one-core, one-minute search and a 400-core datacenter sweep in the same table without one flattering the other. Set `measured: true` only for a standardized single-core baseline (one core, a fixed time budget); a many-core run is a `native run` and records its real kit and the best score it reached. Not sure about the plumbing? Open an issue with your draft in plain markdown and we will handle the rest. [Run it yourself](/research/build/run-it-yourself) covers getting the site running locally if you want to preview your page. **3. Share data and boards.** Not everything needs prose. A strong board, a parameter sweep, a dataset from a long run: all of it is welcome. Every board on this site is verifiable in the [viewer](/viewer), which speaks the community's standard URL format natively, so anyone can check your result in one click. Post the board or the data with a note on how it was produced, and it can back a page or become one. ## The house rules They exist for one reason: so that anyone landing on any page can trust what they read. - **Every claim links a source.** A mailing-list message, a repository, a paper: something a reader can follow. - **Every number is reproducible or labelled for what it is.** Deterministic results come with a command that regenerates them exactly. Seeded, stochastic, or heavy computations say so plainly ("won't reproduce exactly", "~40 h on 8 cores") and ship the board they found so it can still be verified. - **Every experiment says what it ran on.** A measured search is meaningless without its hardware, so an experiment page must carry the `hardware:` block above (cores, kit, time budget). The build enforces it. A score with no compute behind it is not a result anyone can compare. - **French pages are written, not translated.** Each page exists in both languages, and the French version is real French prose, not a machine pass. If you only write one language, that is fine; a maintainer can arrange the translation of the other. - **Your name stays on your work.** Credit callouts, source links, figure attributions: the Blackwood page shows what this looks like in practice. Nothing gets absorbed anonymously. ## What the wiki gives back In exchange for meeting those rules, your work gets infrastructure that a forum post never has: a stable page in the docs shell with sidebar, search and breadcrumbs; placement in the [topic hubs](/research) so it is found by theme, not just by date; a raw-markdown export of every page (append `.md` to its URL) so it stays machine-readable; and a permanent URL other researchers can cite, years from now and not just this week. The puzzle has resisted everyone so far. The least we can do is make sure nobody's progress against it gets lost. ## Related - [Run it yourself](https://eternity2.dev/research/build/run-it-yourself) — The whole site, the engine, and every result in this section run from one repository. Here is how to get it going, rebuild the WebAssembly engine, and reproduce the numbers. - [Blackwood's solver, decoded and run here](https://eternity2.dev/research/lab/experiments/joshua-blackwood/solver) — Joshua Blackwood's record backtracker, decoded through Jef Bucas's notes (a colour quota schedule and a late-game mismatch allowance, tuned near-optimally), then built and run on my M1: left as published it flies to 248 of 256 pieces ignoring the clues; pin the five official clues and the same engine stalls near 45. --- # History: the big steps > The Eternity II story at a glance, from the mailing list founded in 2000 to the 470 record that still stands. A scannable timeline of the turning points, each linking into the full two-part history and the message where it happened. - Canonical page (with interactive figures/demos): https://eternity2.dev/research/history/ - Updated: 2026-07-11 - Source: The eternity2 mailing-list archive (groups.io): every milestone below links its original message — https://groups.io/g/eternity2 - Source: Wikipedia, "Eternity II puzzle" — https://en.wikipedia.org/wiki/Eternity_II_puzzle --- Eternity II has an official story (a launch, a $2,000,000 prize, a deadline) and a real one, which played out on a mailing list. This page is the real one, compressed to its turning points: the moments that actually moved the puzzle, each one a single line you can read at a glance. For the whole account in prose, the history is told in two parts: [part I](/research/community/hunt) covers 2000 to 2009, from the group's founding to the first scrutiny prize; [part II](/research/community/hunt-part-2) covers 2009 to today. Every milestone here links into them, and to the archive message where it happened. > **[Interactive: HistoryTimeline]** Rendered on the canonical page (link above); not shown in this markdown export. ## Where to go next - The [record timeline](/research/records) plots the score itself over time, the 467 of 2008, the long silence, the fast climb to 470, and the flat line since 2021, with the full table and every board viewable edge by edge. - The [full history](/research/community/hunt) tells the same story in prose, with far more of the people, the arguments and the dead ends than fit on a timeline. - The [people behind it](/research/people) is the same story told by person: who did what, and where to read it in their own words. ## Related - [The hunt, a history (part I: 2000–2009)](https://eternity2.dev/research/community/hunt) — The community's story, from a mailing list founded seven years before the puzzle existed to the $10,000 scrutiny prize won under a borrowed name, with every event sourced to its original message. Part I of a growing chronicle. - [The hunt, a history, part II: 2009–2026](https://eternity2.dev/research/community/hunt-part-2) — Seventeen years after the prize: the contest dies with its solution locked in a safe, 467 stands for a decade, the archive survives Yahoo's shutdown by days, and then an outsider from Reddit rewrites the record book. Every event sourced to its original message. - [Records & solvers](https://eternity2.dev/research/records) — Eternity II has never been solved, but fifteen years of community effort have pushed the best board to 470/480. Who holds what, how they did it, and why some headline "480" boards are not actually the real puzzle. - [Who's who of E2 research](https://eternity2.dev/research/people) — Two decades of Eternity II research were done by named people on a mailing list. This page is the gallery: who they are, what each of them contributed, and where to read it in their own words. A thank-you as much as an index. --- # The lab > The wiki's open notebook: structural findings and named search experiments, each credited to the researcher who ran it and reproducible from source. One corner of the community's wider research. - Canonical page (with interactive figures/demos): https://eternity2.dev/research/lab/ - Updated: 2026-07-10 --- This is the open notebook: original findings and experiments on Eternity II, written up in full and credited page by page to the researcher who did the work. It is not one person's blog. The [experiments](/research/lab/experiments) are organised one section per researcher, and each person's work also gathers on their own [contributor page](/research/people). Today [Raphaël's](/research/people/raphael-anjou) section is the full one, because he is the one writing things down, but the structure is built for many hands and there is a section waiting for yours. The community's methods, records and history live across the rest of the research section. The algorithms here are experiments, not breakthroughs. Some are original ideas; others faithfully reimplement a known community technique to measure exactly what it buys. Each write-up says which it is, what it attacked, where it stopped, and what it left open, so anyone can pick up where it ended. ## Everything is reproducible No result on this site is an unbacked claim. Deterministic computations ship a runnable script and the exact output it produces. Searches that depend on randomness or take hours ship the same script plus the board they found, which you can load into the viewer and check edge by edge. The label on each result tells you which kind it is. ## How the lab publishes Every page here meets one shared editorial standard: what kind of contribution it is, whether it publishes and at what tier, and how firmly its claim is backed. [How the lab publishes](/research/lab/experiments/methodology) sets out that standard, so the same rules apply no matter who writes the page. ## Add your own The notebook is open. If you have a finding or a search worth writing down, there is [a place for it here](/research/contribute), credited to you, sitting beside the rest. ## Pages in this section - [Experiments](https://eternity2.dev/research/lab/experiments) — The lab's named search experiments, one section per researcher. Each is a real run against Eternity II with its idea, its best board, and the questions it left open. Raphaël Anjou's notebook is here in full; the notebook is open to anyone else's. --- # Experiments > The lab's named search experiments, one section per researcher. Each is a real run against Eternity II with its idea, its best board, and the questions it left open. Raphaël Anjou's notebook is here in full; the notebook is open to anyone else's. - Canonical page (with interactive figures/demos): https://eternity2.dev/research/lab/experiments/ - Updated: 2026-07-13 --- Experiments are named search runs against Eternity II, each written up with its idea, its best result, and the questions it left open. They are credited page by page to the researcher who ran them, and gathered into a section per researcher. This is one corner of the community's wider research; the methods, records and history live across the rest of the [research section](/research). > **[Interactive: ExperimentAuthors]** Rendered on the canonical page (link above); not shown in this markdown export. ## What counts as an experiment here Some are original ideas; some faithfully reimplement a known community technique to measure exactly what it buys. Each write-up says which it is, what it attacked, where it stopped, and what it left open, so anyone can pick up where it ended. And every result is reproducible: deterministic runs ship a script and its exact output; searches that depend on randomness ship the same script plus the board they found, loadable in the [viewer](/viewer) and checkable edge by edge. Every experiment also states the **hardware it ran on**, in a fixed spec card: the cores, the machine, the time budget, and one derived number, core-hours, that says what the run actually cost. It is mandatory, because a score means nothing without the compute behind it. Where a run is directly comparable it wears a **standardized bench** badge (one core, a fixed minute budget, restarted from randomized corners); a bigger run is a **native run** that records its real kit and the best score it reached. That way a from-scratch minute on one core and a datacenter sweep on four hundred cores sit in the same table, each judged against what it actually spent. ## Pages in this section - [How the lab publishes](https://eternity2.dev/research/lab/experiments/methodology) — The editorial standard for this open notebook: how a piece of Eternity II research goes from unpublished work to a published page. What kind of contribution it is, whether it publishes, at what tier, and where it lives. One shared standard, built to scale to many authors. - [Single-core benchmark](https://eternity2.dev/research/lab/experiments/single-core-benchmark) — Fifteen solvers, ours and our implementations of the community's two record backtrackers, each run once on ten corner-pinned variants of the official puzzle, single core, 60 seconds per run. The finding: node count is not score. - [Raphaël Anjou's experiments](https://eternity2.dev/research/lab/experiments/raphael-anjou) — A notebook of Eternity II search experiments, organised into the shared engines they run on, the combination pipelines that chase the score, three studies that take one search paradigm apart a decision at a time, and exact endgame solves. Each has its idea, its best board, and the questions it left open. The best reaches 463 of 480. - [Peter McGavin's engine](https://eternity2.dev/research/lab/experiments/peter-mcgavin) — Peter McGavin's own C backtracker, the fastest raw solver the community has measured. Fetched from the mailing list, built on an M1, and run on the real Eternity II. His code, his algorithm; run and written up here. - [Joshua Blackwood's solver](https://eternity2.dev/research/lab/experiments/joshua-blackwood) — Joshua Blackwood's open-source C# solver, the one that found the standing 470 record. Built and run here as he published it, then with the five official clues pinned. His code, his algorithm; run and written up here. - [Louis Verhaard's eii](https://eternity2.dev/research/lab/experiments/louis-verhaard) — Louis Verhaard's eii won the only prize the puzzle ever paid, but it shipped as a Windows binary with no source. What his method is, why the original will not run here, and where a faithful reimplementation of it lives. --- # Joshua Blackwood's solver > Joshua Blackwood's open-source C# solver, the one that found the standing 470 record. Built and run here as he published it, then with the five official clues pinned. His code, his algorithm; run and written up here. - Canonical page (with interactive figures/demos): https://eternity2.dev/research/lab/experiments/joshua-blackwood/ - Updated: 2026-07-15 --- This section is [Joshua Blackwood's](/research/people/joshua-blackwood) own solver: the open-source C# program that found the 470 that still stands. The algorithm and the code are his, public on GitHub. What is added here is the running: built as he published it, measured single core, and then tested against the real five-clue puzzle to see what its speed is actually buying. ## Pages in this section - [Blackwood's solver, decoded and run here](https://eternity2.dev/research/lab/experiments/joshua-blackwood/solver) — Joshua Blackwood's record backtracker, decoded through Jef Bucas's notes (a colour quota schedule and a late-game mismatch allowance, tuned near-optimally), then built and run on my M1: left as published it flies to 248 of 256 pieces ignoring the clues; pin the five official clues and the same engine stalls near 45. --- # Blackwood's solver, decoded and run here > Joshua Blackwood's record backtracker, decoded through Jef Bucas's notes (a colour quota schedule and a late-game mismatch allowance, tuned near-optimally), then built and run on my M1: left as published it flies to 248 of 256 pieces ignoring the clues; pin the five official clues and the same engine stalls near 45. - Canonical page (with interactive figures/demos): https://eternity2.dev/research/lab/experiments/joshua-blackwood/solver/ - Updated: 2026-07-17 - Topics: backtracking, speed - Reproduce: `git clone github.com/jblackwood345/EternityII_Solver; dotnet build -c Release` - Source: Joshua Blackwood's solver (GitHub, GPL-3.0, the original source) — https://github.com/jblackwood345/EternityII_Solver - Source: Jef Bucas's notes on the Blackwood solver (wrapper_blackwood repo) — https://github.com/jfbucas/wrapper_blackwood/blob/main/doc/Notes/Notes.md - Source: Jef's study announcement and permission to republish (groups.io message 11905) — https://groups.io/g/eternity2/message/11905 - Source: Blackwood's own tuning plan: the four levers and the 470 retune (groups.io message 10076) — https://groups.io/g/eternity2/message/10076 - Source: The repo re-published, "the exact code used to find a 470" (groups.io message 10161) — https://groups.io/g/eternity2/message/10161 - Source: Blackwood's 470 announcement (msg 10117) — https://groups.io/g/eternity2/message/10117 --- > **Whose work this is** > > The algorithm and the C# are **Joshua Blackwood's** ([EternityII_Solver](https://github.com/jblackwood345/EternityII_Solver), public on GitHub under the GPL-3.0). The decoding of the internals, along with the parameter study reported below, is Jef Bucas's, in his [wrapper_blackwood](https://github.com/jfbucas/wrapper_blackwood) project; the decoded sections rephrase and extend [his notes](https://github.com/jfbucas/wrapper_blackwood/blob/main/doc/Notes/Notes.md) with his explicit permission ([groups.io message 11905](https://groups.io/g/eternity2/message/11905)), and the figures are his, reproduced from the same notes. The final section is [Raphaël Anjou](/research/people/raphael-anjou) building and running Blackwood's code on one machine and writing up what it did; the three small edits to his source are listed there, each one his own README invites. Joshua Blackwood holds the standing 470 record, found with code he made public. His solver is, at heart, a classic depth-first backtracker running the same loop as any other: place, check, back up. What makes it the engine behind the community's best boards is a set of manually crafted heuristics layered on top: a scoring rule that decides *which* pieces to try first, a depth-by-depth quota schedule that prunes branches falling behind, a [fill order](/research/build/backtracking/fill-order) tuned to be "not too tight and not too loose", and a late-game allowance for accumulating mismatches. Every one of those choices has numbers in it, and Jef Bucas's study asked the obvious question: are Blackwood's numbers any good? They are, uncomfortably so. Because the code is a real, buildable C# program, it can then be run exactly as its author wrote it, which is what the last section here does. ## Score pieces by three colours The solver scores every piece by the colours on its sides, and it privileges exactly three of them, one border colour and two interior colours: ```csharp heuristic_sides = new List() { 13, 16, 10 }; ``` Pieces carrying those colours are sorted to the front of every candidate list, so the search commits them early. Why these three? That is one of the two knobs Jef's study turned (see below). His sampling suggests the best known scores come from two distinct pattern sets: > **[Figure]** interactive figure. Rendered on the canonical page (link above); not shown in this markdown export. ## The schedule: a quota curve over 256 depths Prioritizing three colours only helps if the search is *forced* to actually place them. So the solver carries a 256-entry array, one entry per depth, where each value is the minimum number of those three colours that must already be on the board to keep descending. Fall below the quota and the branch is cut on the spot: backtrack, no discussion. Blackwood filled that array by hand, as a piecewise-linear ramp: ```csharp heuristic_array = new int[256]; for (int i = 0; i < 256; i++) { if (i <= 16) heuristic_array[i] = 0; else if (i <= 26) heuristic_array[i] = (int)(((float)i - 16) * (float)2.8); else if (i <= 56) heuristic_array[i] = (int)((((float)i - 26) * (float)1.43333) + 28); else if (i <= 76) heuristic_array[i] = (int)(((((float)i - 56) * (float)0.9)) + 71); else if (i <= 102) heuristic_array[i] = (int)(((((float)i - 76) * (float)0.6538)) + 89); else if (i <= 160) heuristic_array[i] = (int)(((((float)i - 102) / 4.4615)) + 106); } ``` Free until depth 16, steep through the 20s, then flattening out to depth 160. This is the "schedule" in schedule-and-break-index: a pre-committed timetable for burning down the high-frequency colours, enforced as a hard prune. > **[Figure]** interactive figure. Rendered on the canonical page (link above); not shown in this markdown export. ## The fill order: not too tight, not too loose The search starts at the bottom-left of the board (the corner nearest the mandatory centre piece) and runs a standard row scan all the way to depth 180. After that, it intersperses the remaining border pieces (including the third corner) every few steps among the interior placements. That is a deliberate middle course. Spiralling in (border ring first) commits the most constrained pieces too early; a pure row scan leaves them all to the end, where they ambush you. Blackwood's order releases the border pressure progressively. Why the order matters this much, and how to score one before running it, is exactly what [complex theory](/research/why/complex-theory) formalizes. > **[Figure]** interactive figure. Rendered on the canonical page (link above); not shown in this markdown export. ## Breaks: buying the endgame with mismatches Approaching the end of the search, the solver stops demanding perfection. A budget of edge mismatches unlocks with depth, cumulatively: one break is allowed from depth 201 onward (it can be spent at 201 or any later depth), a second from 206, and so on: ```csharp break_indexes_allowed = new List() { 201, 206, 211, 216, 221, 225, 229, 233, 237, 239 }; ``` Ten breaks in total, the last unlocking at depth 239. This is what makes the [record boards](/research/records) reachable at all: a perfect 256 has never been found, but a board that tolerates a handful of late mismatches is something a backtracker can actually finish. Two details sharpen the picture. First, the budget comes with a discipline: no two breaks are ever allowed to touch: each mismatch must sit isolated among matched edges. Blackwood spells out the consequence himself: any run that reaches 255 placements automatically completes to 256, and a 469 board is equivalently a 249-piece partial with seven holes ([groups.io message 10051](https://groups.io/g/eternity2/message/10051)). Second, the ten-entry list above is itself a retune: planning the push from 469 to 470, Blackwood cut the break budget from eleven depths to ten, a change he documented, lever by lever, in his own tuning plan ([groups.io message 10076](https://groups.io/g/eternity2/message/10076)). The shifted unlock points he sketched in that plan were never adopted (the published 470 code keeps the 469-era points and simply drops the eleventh), and that tightened schedule is what found the 470. ## Restarts, randomness, and a 50-billion-node cap A row-scan backtracker rarely climbs back up to its first rows, so a bad opening can strand an entire run in an impossible region. Blackwood's answer is cheap and effective: randomize the opening (the first corner and the bottom-row pieces are shuffled on every attempt, so no two runs retrace the same prefix) and cap each attempt at 50 billion nodes explored. Hit the cap, abandon, [restart](/research/build/backtracking/restarts) with a fresh opening, and go looking for a more fertile one. ## Make it fit in cache The last ingredient is mechanical sympathy. Candidate pieces live in per-position lookup tables, and each entry is a compact struct (piece number, rotation, the two exposed sides, a break count and a heuristic count) sized so the working set fits in CPU cache: ```csharp public struct RotatedPiece { public ushort PieceNumber { get; set; } public byte Rotations { get; set; } public byte TopSide { get; set; } public byte RightSide { get; set; } public byte Break_Count { get; set; } public byte Heuristic_Side_Count { get; set; } } ``` This is the throughput half of the story: the same design that [Peter McGavin](/research/lab/experiments/peter-mcgavin/backtracker) later pushed to hundreds of millions of placements per second. ## From one 468 to a wave of records The solver's history is as instructive as its internals. Blackwood arrived a complete outsider: his 468, the first advance past [Louis Verhaard's 467](/research/lab/experiments/louis-verhaard/eii) in twelve years, reached the mailing list second-hand, relayed from a Reddit post ([groups.io message 10032](https://groups.io/g/eternity2/message/10032)). Three days later he open-sourced the solver, with heuristics he reckoned made it "twice as good" as the 468 run ([message 10037](https://groups.io/g/eternity2/message/10037)); Jef Bucas had it running under Mono on Ubuntu almost immediately ([message 10038](https://groups.io/g/eternity2/message/10038)). Within a week, Peter McGavin, running it "on about a couple of hundred cores," hit 469 ([message 10045](https://groups.io/g/eternity2/message/10045)). Bucas then rewrote the algorithm in C for roughly double the speed ([message 10065](https://groups.io/g/eternity2/message/10065)), a wave of fresh 469 boards followed within weeks, and the code generator behind the rewrite was published as [libblackwood](https://github.com/jfbucas/libblackwood) ([message 10078](https://groups.io/g/eternity2/message/10078)). When Blackwood posted his 470 in March 2021, it came from that same public code. His own words, on re-publishing the repo after it had quietly gone private: "It is the exact code used to find a 470" ([message 10161](https://groups.io/g/eternity2/message/10161)). One record, open-sourced, became a community record machine. ## Jef's parameter study: wrapper_blackwood All of the above is *how* the solver works. Jef Bucas built [wrapper_blackwood](https://github.com/jfbucas/wrapper_blackwood) to ask whether its numbers are *right*. The setup is a small [distributed experiment](/research/build/faster/distributed-solving): a Python server hands out jobs over HTTP, where each job is a variation of the solver's parameters. Clients (one worker per core) fetch a job, generate the C# source from templates with that variation baked in, compile it with Mono, run it, and report the result back to the server for analysis. Two parameters got the treatment: - **The three prioritized colours.** Sampling many different sets of three patterns, and recording how deep the algorithm got with each, his [results page](https://github.com/jfbucas/wrapper_blackwood/blob/main/doc/batch00_edge_combos_stats.html) maps every combination of one border colour and two interior colours to the depth it reached, together with a heatmap of where in the board the search spent its time. The best known scores concentrate on two distinct pattern sets. - **The quota schedule.** Running many random variations of the 256-entry heuristic array and plotting how far each one got (greener is better), Blackwood's manually crafted curve lands right in the middle of the green region. > **[Figure]** interactive figure. Rendered on the canonical page (link above); not shown in this markdown export. ## What hand-tuning got right That last result deserves emphasis. Blackwood filled his schedule by hand: five linear segments, eyeballed coefficients. When a randomized sweep explored the neighbourhood around it, the hand-tuned line sat squarely in the best-performing zone. Jef's conclusion, and ours: the original parameters were near-optimal. The decades-old advice holds. Before you redesign a record solver's heuristics, check whether its author already found the local optimum by hand. > **Blackwood's own negative results** > > Blackwood ran the same audit on himself. After the 469 he catalogued his dead ends on the mailing list ([groups.io message 10056](https://groups.io/g/eternity2/message/10056)): eliminating four colours early instead of three (no gain), saving colours for the endgame (worse), SAT solvers such as kissat, cryptominisat and Google OR-tools (poor), GPU acceleration, and caching all pre-solved 2×2 blocks (measured, then dropped). The only thing that ever paid was refining the heuristics themselves, worth another ~2x. It is the same conclusion as Jef's sweep, reached from the other direction: the schedule is the magic, not the raw technology. ## Replicate the study One caveat on the parameter study, and it is Jef's own: the sample counts behind these results are low, and he is not 100% sure of the conclusions. His notes say it plainly: it would be good to attempt to reproduce these results, to validate or invalidate them. He offers his samples, and the [wrapper_blackwood](https://github.com/jfbucas/wrapper_blackwood) harness is public: point a few machines at the server, re-run the sweeps, and post what you find on the [mailing list](https://groups.io/g/eternity2). An independent replication would confirm or refute the findings, and either outcome would be a real contribution. ## Running it here The study above audits Blackwood's parameters; this last section audits something different: what his published program does when you build it yourself and hold it to the real puzzle, single core, on my machine. ### Where the code came from The source is his public repository, [github.com/jblackwood345/EternityII_Solver](https://github.com/jblackwood345/EternityII_Solver), under the GPL-3.0. It builds unmodified on .NET 8. It is not copied here: the licence and good manners both say to link it, not vendor it, so it was cloned to a scratch directory, run, and only the numbers kept. ### What was changed to run it His program is written to run on one machine's full core count and to save only near-complete boards. To measure it single core, and to see anything short of a full solve, three edits were made, each of which his own README invites ("change the number of cores", "change the save function"): - **One search thread.** His `number_virtual_cores` constant defaults to 64. His `Parallel.For(1, N)` runs `N-1` workers, so setting it to 2 gives exactly one search thread. - **A progress line.** Unmodified, in a bounded run it prints only "Solving...". A single added line reports the deepest placement reached, so a run that does not finish still yields a number. - **A lower save threshold, and clue pinning** for the constrained run below. ### Left as published: fast, and aimed at the one clue that binds Run as his code stands, single core for 60 seconds, it is fast and it gets far: - **248 / 256 pieces placed**, a board that re-scores to **454 / 480** matched edges. - **~18.9 million nodes per second** (one node is one placement attempt). His published program has no notion of clues at all: it treats every piece, including the special ones, as ordinary and maximises raw matched edges. This is less of a compromise than it first looks, because a legal Eternity II board has exactly **one** binding constraint, the mandatory centre clue (piece 139 in its centre cell, in its given orientation); the puzzle's other four "clues" were bonus hints the maker released, not requirements. His celebrated **470** board is the proof: in the [viewer](/viewer) it verifies as clues respected **1 / 5**, the one respected being the centre, and one is all a legal board needs. Maximising edges without clue logic is not a shortcut around the puzzle; it is a legitimate way to attack the one that binds. The last eight cells of that 454 board are a genuine dead end: no arrangement of the eight leftover pieces completes them edge-perfectly. (For fun, handing that board to [our ALNS](/research/build/local-search/local-search-alns) for 30 seconds filled all eight and pushed it to 462 by rearranging the region.) ### With the clues pinned: it stalls Pinning the clue pieces into their cells forces the engine to respect them instead of placing them wherever they fit. The same code, all five official clues pinned, 120 seconds, single core: - **Deepest placement: about 45 / 256.** His scan-order heuristic has nothing to grip once the special pieces are fixed mid-board: it thrashes near the bottom rows and never climbs. Pinning all five is stricter than the puzzle strictly requires (only the centre clue is mandatory), but it is the same constraint the other engines are held to here, and Blackwood lands far below the [Verhaard reimplementation's 438](/research/lab/experiments/louis-verhaard/verhaard-reimpl) or [McGavin's 204](/research/lab/experiments/peter-mcgavin/backtracker) under the same constraint. > **A fair caveat** > > This clue pin is crude: it forbids every other piece at the five clue cells and reserves those pieces. A clue-aware redesign would search outward from the clues instead, and would do better. So 45 is a floor for "his published code with clues bolted on", not a verdict on the approach. His record 470 was found with this code plus a great deal of compute and luck, not in two minutes. ## Related - [McGavin's C backtracker: the throughput story, built here](https://eternity2.dev/research/lab/experiments/peter-mcgavin/backtracker) — Peter McGavin's own C backtracker, the community's fastest: a 2007 optimization recipe compounded for two decades through generated code, lookup tables and counter tricks, then built on my M1 and pointed at the real 256-piece puzzle, where single core it drives past 200 of 256 pieces at ~109M placements/s. - [Verhaard's eii: the solver that won the only prize](https://eternity2.dev/research/lab/experiments/louis-verhaard/eii) — The engine behind the 467, the only Eternity II score ever paid, read from Louis Verhaard's own mailing-list posts: forward pruning, comb-search fill orders, depth-gated edge slipping, a Markov-tuned slip schedule. And why his own source-less Win32 binary cannot be built or run on this machine at all. - [Single-core benchmark](https://eternity2.dev/research/lab/experiments/single-core-benchmark) — Fifteen solvers, ours and our implementations of the community's two record backtrackers, each run once on ten corner-pinned variants of the official puzzle, single core, 60 seconds per run. The finding: node count is not score. - [Records & solvers](https://eternity2.dev/research/records) — Eternity II has never been solved, but fifteen years of community effort have pushed the best board to 470/480. Who holds what, how they did it, and why some headline "480" boards are not actually the real puzzle. --- # Louis Verhaard's eii > Louis Verhaard's eii won the only prize the puzzle ever paid, but it shipped as a Windows binary with no source. What his method is, why the original will not run here, and where a faithful reimplementation of it lives. - Canonical page (with interactive figures/demos): https://eternity2.dev/research/lab/experiments/louis-verhaard/ - Updated: 2026-07-15 --- This section is about [Louis Verhaard's](/research/people/louis-verhaard) eii, the solver that found the 467 and won the puzzle's only prize. Unlike McGavin and Blackwood, he never released source, so his own program cannot be run here. This page records his method and that gap; the runnable engine is a [reimplementation](/research/lab/experiments/louis-verhaard/verhaard-reimpl), which lives here beside the method it rebuilds, bylined to Raphaël Anjou because the code is his even though the idea is Verhaard's. ## Pages in this section - [Verhaard's eii: the solver that won the only prize](https://eternity2.dev/research/lab/experiments/louis-verhaard/eii) — The engine behind the 467, the only Eternity II score ever paid, read from Louis Verhaard's own mailing-list posts: forward pruning, comb-search fill orders, depth-gated edge slipping, a Markov-tuned slip schedule. And why his own source-less Win32 binary cannot be built or run on this machine at all. - [Verhaard reimplementation](https://eternity2.dev/research/lab/experiments/louis-verhaard/verhaard-reimpl) — A from-scratch reimplementation of Louis Verhaard's eii method, since his own binary ships no source and will not run here. Set-composition swap-annealing under the 2×2-tiling metric; on the real five-clue puzzle it reaches 438 of 480, single core. --- # Verhaard's eii: the solver that won the only prize > The engine behind the 467, the only Eternity II score ever paid, read from Louis Verhaard's own mailing-list posts: forward pruning, comb-search fill orders, depth-gated edge slipping, a Markov-tuned slip schedule. And why his own source-less Win32 binary cannot be built or run on this machine at all. - Canonical page (with interactive figures/demos): https://eternity2.dev/research/lab/experiments/louis-verhaard/eii/ - Updated: 2026-07-17 - Topics: backtracking, local-search, speed - Source: Louis Verhaard's eii solver details (the original, Win32 only) — https://www.shortestpath.se/eii/eii_details.html - Source: The release: “I am stuck… my only hope is brute force” (groups.io message 5940) — https://groups.io/g/eternity2/message/5940 - Source: Decoder and internals documentation released; 467 found 40+ times (groups.io message 6275) — https://groups.io/g/eternity2/message/6275 - Source: The method disclosed: depth-gated edge slipping, clean score 247 (groups.io message 7321) — https://groups.io/g/eternity2/message/7321 - Source: JSA's independent benchmark: a 467 in 82 days with the public binary (groups.io message 6687) — https://groups.io/g/eternity2/message/6687 - Source: The solver's long-term home: shortestpath.se/eii (groups.io message 7439) — https://groups.io/g/eternity2/message/7439 - Source: Verhaard on his method (groups.io msg 6891) — https://groups.io/g/eternity2/message/6891 --- > **Whose work this is** > > The solver, called **eii**, and its documentation are **Louis Verhaard's**, hosted on his own site ([shortestpath.se/eii](http://www.shortestpath.se/eii/)). The winning entry was submitted under the name of his wife, Anna Karlsson; Verhaard's own words settle the credit: "My wife submitted my best solution last year and won 10 000 dollars" ([groups.io message 7451](https://groups.io/g/eternity2/message/7451)). This page, written up by [Raphaël Anjou](/research/people/raphael-anjou), reconstructs the machine from Verhaard's mailing-list posts of 2008–2010 and from JSA's public benchmark of the released binary, and records why the original binary cannot be run here at all. The runnable engine is a separate [reimplementation](/research/lab/experiments/louis-verhaard/verhaard-reimpl), filed here in this section beside the method, bylined to Raphaël because that code is his, not Verhaard's. Louis Verhaard's eii is the solver behind the 467/480 that won the $10,000 runner-up prize at the first scrutiny date, the only money the Eternity II contest ever paid out. The same score then stood as the record for twelve years, until Joshua Blackwood's 468 in 2020. Like [Blackwood's engine](/research/lab/experiments/joshua-blackwood/solver), it is at heart a depth-first backtracker with hand-tuned heuristics layered on top. Unlike Blackwood's, its internals were never open-sourced as code; what we have instead is unusually good testimony: Verhaard documented the heuristics and search order himself, discussed the design on the mailing list in first person, and shipped a public binary that an independent user benchmarked all the way back to the prize score. That missing source is why, of the three community engines studied in this lab, his is the one that cannot be run at all; the last section here says exactly why. ## The arc: stuck past 463, so release it Verhaard's own origin story is disarming. His first high-score program only placed perfectly matching pieces, and stalled around a 450: hundreds of 248-piece clean partials, no way forward. Only when he tried Bob Cousins' (originally Dave Clark's) solver, which found a 458 within a minute, did he grasp that the contest scored *matching edges*, so half-fitting placements count ([groups.io message 5767](https://groups.io/g/eternity2/message/5767)). He had, in his own telling, never bothered to read the rules; Jef Bucas was still pointing readers at that admission in Verhaard's documentation in 2021 ([groups.io message 10582](https://groups.io/g/eternity2/message/10582)). Through the summer of 2008 the community's publicly visible ceiling was 463 ([groups.io message 5688](https://groups.io/g/eternity2/message/5688)), and in a remarkable exchange Verhaard and Max compared notes as the only two known to be past what they called the "don't-talk-about-limit" ([messages 5767–5787](https://groups.io/g/eternity2/message/5767)). Then, on 22 September 2008, with the first scrutiny date three months away, Verhaard published the solver for anyone to run at fingerboys.se: "This because I am stuck and my only hope to improve my best score is by using brute force" ([message 5940](https://groups.io/g/eternity2/message/5940)). The terms mirrored eternity2.net's: you needed to own the real puzzle, and any prize would be split 50-50 between the best-scoring user and Verhaard. The community became his compute farm. It worked. On 6 January 2009 he released a decoder for the solver's `.eii` output files, documented the internals (heuristics and search order), and disclosed the number the farm had reached: 467, found more than 40 times by different users ([message 6275](https://groups.io/g/eternity2/message/6275)). Nine days later, Tomy's announcement surfaced: no complete solution, and a $10,000 runner-up prize to Anna Karlsson of Lund for 467 of 480 ([message 6337](https://groups.io/g/eternity2/message/6337)). The list took about an hour to decode "Lund + 467". The rest of the contest story belongs to [the history page](/research/community/hunt): the silence from Tomy, the press coverage, the aftermath. What follows here is the machine. ## Forward pruning against static thresholds The base loop is a depth-first backtracker over a fixed [fill order](/research/build/backtracking/fill-order), but one that prunes forward: branches whose heuristic score falls below a threshold are cut before they are explored. Verhaard described his thresholds as static and hand-tuned: "mostly based on pure guesswork and only on limited amount on theory or measurements," slow to tune but predictable over long runs ([groups.io message 5771](https://groups.io/g/eternity2/message/5771), quoted back at him in [message 5772](https://groups.io/g/eternity2/message/5772)). What are the thresholds *for*? The design he and Max converged on in that exchange is the interesting part: you can only influence piece selection early in the search, but what you want to maximize is the **tileability of the remaining pieces** deep in the fill, around pieces 160–200, where the branching factor collapses toward forced moves. So the early thresholds are tuned, semi-manually, to answer: which heuristic score must early partials reach so that the survivors carry a leftover piece set that still tiles well? Verhaard's verdict on Max's description: "I think we work in a very similar way after all" ([message 5780](https://groups.io/g/eternity2/message/5780)). ## The dashboard: where the node distribution peaks How do you know a heuristic is strong? The measure the two settled on (proposed by Max, adopted by Verhaard) is where the peak of the node-depth distribution sits. An unheuristic full search on E2 spends most of its time around depth 161, Brendan Owen's baseline figure ([message 6112](https://groups.io/g/eternity2/message/6112)); both of their heuristic searches had pushed the peak to just under 170 ([message 5780](https://groups.io/g/eternity2/message/5780)). Max supplied the interpretation: a peak at 170 is roughly equivalent to eliminating one interior colour from the puzzle entirely; a "killer heuristic" that eliminates two seemed out of reach ([message 5787](https://groups.io/g/eternity2/message/5787)). ## Comb search: a fill order for high scores A full-solution search wants a row-by-row scan; a high-score search lives deeper in the board, and wants a different frontier. When Brendan Owen posed exactly that question, Verhaard revealed the shape of his answer: the best orders he had found resemble a **comb search** (most rows searched horizontally, then the remaining rows searched vertically), with the tooth length tied to the target: "The lower the score you aim for, the longer the teeth of the comb become" ([groups.io message 6112](https://groups.io/g/eternity2/message/6112)). Max had independently converged on nearly the same geometry (twelve rows of scanline, then column scan) and reported his scores ran about one edge below "the results that Louis solver accomplishes" ([message 6126](https://groups.io/g/eternity2/message/6126)). ## Edge slipping, gated by depth The lever that actually bought the 467 is deliberate imperfection. Asked about it directly a year later, Verhaard was precise: the 467 program searches "normally," but at certain depths it allows **edge slipping**: placing a piece with one mismatching edge against an already-placed neighbour. It does not first build a clean partial and then patch holes; the mismatches are budgeted *into the descent*, unlocked at chosen depths. And the anatomy of the result is telling: most of the 467 boards he examined had a clean score of only 247, with thirteen slipped edges spent where the schedule allowed them ([groups.io message 7321](https://groups.io/g/eternity2/message/7321)). The 467 was no fluke, either: he found it more than 50 times ([same message](https://groups.io/g/eternity2/message/7321)). The technique itself has [its own page](/research/build/reduce/edge-slipping): why scheduled mismatches reach boards a clean search never could, and the counting theory behind the cost of each extra matched edge. What belongs here is the solver-side machinery: the per-depth mismatch budget is a **slip array**, one entry per depth, and it is a tuned object, not a guess. ## The slip array's optimizer: a Markov chain In January 2009, in the thread where Owen was extending [complex theory](/research/why/complex-theory) to cover slips, Verhaard posted the outline (with Java snippets) of the algorithm he used to optimize eii's search order and slip array ([groups.io message 6423](https://groups.io/g/eternity2/message/6423)). The input is a candidate search order plus a slip array. For every depth he estimates two numbers from experimental runs (theory would do to start, he noted): the probability that a random remaining piece fits perfectly, and the probability that it fits with one slipped edge. From these he builds a Markov chain whose state is *(depth, slipped edges so far)*, with transitions for a clean placement and, where the slip array permits, for a slipped one. Running the chain end to end yields the probability of reaching the bottom and the expected node count: a cheap, closed-loop evaluator for any (order, slip-schedule) pair, memoized for efficiency. He flagged its limit himself: the simple model ignores slip parity, so it gets unreliable at very high target scores. The family resemblance to what came a decade later is hard to miss: Blackwood's break indexes are also a depth-gated mismatch budget, and his quota schedule is also a pre-committed, per-depth curve, hand-tuned rather than chain-optimized. The lineage runs through this solver. ## The clean-score sibling The same heuristics powered a second program with a different late-game move: instead of slipping an edge, it may *skip a square*, that is, leave a cell empty and keep going. The name is his own ([message 7321](https://groups.io/g/eternity2/message/7321)). That is the clean-score (no mismatches) hunter. With it, Verhaard filled 14 complete rows plus two pieces, a 226-piece flawless partial and the record he knew of at the time ([groups.io message 6303](https://groups.io/g/eternity2/message/6303)). In a one-day return in December 2009, after estimating ~2,000 248s per 249, he landed three 249s in a row and stopped, putting a 250 at roughly 4,000 times harder ([message 7306](https://groups.io/g/eternity2/message/7306)). Asked about it a decade later, he confirmed the 249 on his site is real: about a week of compute on one machine ([message 9890](https://groups.io/g/eternity2/message/9890)). ## The public reproduction: 82 days to a 467 Because the binary was public, the 467 is the rare contest-era record with an independent, quantified reproduction. JSA ran eii continuously on one PC and logged the score distribution as it accumulated: - **43 days:** 2,008,484 463s · 109,195 464s · 6,048 465s · 250 466s · nothing higher ([groups.io message 6571](https://groups.io/g/eternity2/message/6571)) - **62 days:** 427 466s, arriving at roughly 5–6 per day, and still no 467 ([message 6653](https://groups.io/g/eternity2/message/6653)) - **82 days:** two 467s, alongside 4,017,182 463s · 227,245 464s · 13,637 465s · 625 466s ([message 6687](https://groups.io/g/eternity2/message/6687)) That last log is the cleanest public measurement of the exponential rarity ladder near the top: four million 463s for every couple of 467s, and a 466→467 step that took a single machine nearly three months. JSA's sign-off, "Congratulations to Louis on a well-thought-out algorithm", doubles as the verification verdict. ## What it taught the community Beyond the score, eii set a precedent: when you are stuck, release the solver and let the community's machines hunt, with the prize split as the contract. The 467 was found by *users* of a published binary, 40+ times, before it won anything. Twelve years later [Joshua Blackwood repeated the pattern](/research/lab/experiments/joshua-blackwood/solver), posting a 468 and open-sourcing the engine days later, and got the same reward: a wave of community records on his own algorithm. The other lesson is methodological and runs through this whole page: Verhaard tuned his solver against *models* rather than raw vibes (the node-peak dashboard, the Markov-chain evaluator), at a time when that discipline was rare. ## Where the code lives, and why it won't run here The original home, fingerboys.se, was his band's website; when the band gave up maintaining the site, the solver went offline with it for months. In January 2010 Verhaard republished it, unchanged, at [shortestpath.se/eii](http://www.shortestpath.se/eii/) ([groups.io message 7439](https://groups.io/g/eternity2/message/7439)); that address is still its home, and the first-party source behind the 467 row in [the records table](/research/records). One operational footnote from the Q&A that followed: the solver keeps no memory of past positions, so its thousands of 463–465 boards are not deduplicated ([message 7451](https://groups.io/g/eternity2/message/7451)). What "the code lives there" hides is that no *source* lives anywhere. What Verhaard shipped is `eii-1.0-win32.zip`: a Windows `eii.exe`, a readme, and some `.bat` files. There are **zero source files**, and it is Win32 only. It does not run on Apple silicon, and there is no Windows or emulation layer on this machine to run it under. His artifact is, here, unrunnable, and there is nothing of his to fetch and build. The comb-search fill orders and depth-gated slip schedule described above became community canon precisely because they were recovered from his posts and, where numeric, byte-exact from the strings inside `eii.exe`, since that binary is the only surviving record of them. So "running Verhaard" at all means rebuilding his method from that documentation. That is what the [Verhaard reimplementation](/research/lab/experiments/louis-verhaard/verhaard-reimpl) does, and on the real five-clue puzzle it reaches 438 of 480, single core. That engine is filed here beside this page, bylined to Raphaël, because it is a reading of Verhaard's method rewritten as Raphaël's code. Naming that distinction is part of the finding: of the three community engines studied here, his is the one that cannot be run at all. ## Related - [Verhaard reimplementation](https://eternity2.dev/research/lab/experiments/louis-verhaard/verhaard-reimpl) — A from-scratch reimplementation of Louis Verhaard's eii method, since his own binary ships no source and will not run here. Set-composition swap-annealing under the 2×2-tiling metric; on the real five-clue puzzle it reaches 438 of 480, single core. - [Blackwood's solver, decoded and run here](https://eternity2.dev/research/lab/experiments/joshua-blackwood/solver) — Joshua Blackwood's record backtracker, decoded through Jef Bucas's notes (a colour quota schedule and a late-game mismatch allowance, tuned near-optimally), then built and run on my M1: left as published it flies to 248 of 256 pieces ignoring the clues; pin the five official clues and the same engine stalls near 45. - [Edge slipping](https://eternity2.dev/research/build/reduce/edge-slipping) — Louis Verhaard's prize-winning move: let the backtracker place a mismatched piece, but only at chosen depths near the end of the board. Each allowed slip costs one point of score and multiplies the number of target boards astronomically. That is why his 467 was found more than fifty times, and the direct ancestor of Blackwood's breaks. - [Records & solvers](https://eternity2.dev/research/records) — Eternity II has never been solved, but fifteen years of community effort have pushed the best board to 470/480. Who holds what, how they did it, and why some headline "480" boards are not actually the real puzzle. --- # Verhaard reimplementation > A from-scratch reimplementation of Louis Verhaard's eii method, since his own binary ships no source and will not run here. Set-composition swap-annealing under the 2×2-tiling metric; on the real five-clue puzzle it reaches 438 of 480, single core. - Canonical page (with interactive figures/demos): https://eternity2.dev/research/lab/experiments/louis-verhaard/verhaard-reimpl/ - Updated: 2026-07-15 - Topics: speed, local-search - Reproduce: `just experiments single-core-benchmark` - Source: Runnable engine + committed results + scripts (this experiment's backing directory) — https://github.com/raphael-anjou/eternity2/tree/main/research/experiments/single-core-benchmark - Source: Louis Verhaard's eii solver details (the original, Win32 only) — https://www.shortestpath.se/eii/eii_details.html --- > **Whose work this is** > > The **method** is [Louis Verhaard's](/research/lab/experiments/louis-verhaard/eii). The **code** here is a from-scratch reimplementation by [Raphaël Anjou](/research/people/raphael-anjou). It is filed here, in Verhaard's section beside the method it rebuilds, as a reconstruction: a reading of his method, not his program. The byline stays Raphaël's because the code is his; the section is Verhaard's because the idea is. Verhaard's own eii is a source-less Windows binary that [will not run here](/research/lab/experiments/louis-verhaard/eii). The only way to run his approach is to rebuild it, and this is that rebuild: the same engine that appears as `verhaard` on the [grid](/research/lab/experiments/single-core-benchmark). ## What it reimplements Verhaard's documented method: **set-composition swap-annealing** under the 2×2-tiling metric. Pick a roughly 180-piece interior subset, swap-anneal its composition until the number of achievable 2×2 sub-tilings is locally maximised, front-load the worst performers, then search the rest under that scaffold. The engine's numeric constants were recovered byte-exact from the strings inside `eii.exe`, because that binary is the only surviving record of them. Calling this "running Verhaard" is a stretch worth naming: it is a reading of his method, not his code. That it is the only way to run his approach at all is part of the finding. ## What it does on the real five-clue puzzle Single core, 120 seconds, all five official clues pinned: - **438 / 480** matched edges, a **fully placed** board (256 of 256 pieces). - All five clues respected (a strict clue solution), 42 broken edges, at roughly 40 million nodes a second. The run and its output board are committed in the engine's [backing directory](https://github.com/raphael-anjou/eternity2/tree/main/research/experiments/single-core-benchmark), and `just experiments single-core-benchmark` reruns it, so the 438 is checkable rather than asserted. This is the five-clue instance, a harder puzzle than the corner-pinned variants the [leaderboard](/research/lab/experiments/single-core-benchmark) scores, where the same engine reaches a best of 451. It found 438 within about twelve seconds and then plateaued for the rest of the budget: a genuine local optimum for that seed and time. It is the only one of the three community reimplementations here that solves the real, five-clue puzzle well rather than an easier version of it, but the three are not measuring the same thing, so the comparison needs care. [Blackwood](/research/lab/experiments/joshua-blackwood/solver) is measured on the same footing, matched edges with the clues pinned, and stalls near 45. [McGavin](/research/lab/experiments/peter-mcgavin/backtracker) is not: its figure is a placement *depth* (about 204 of 256 pieces reached), not a matched-edge score, so it cannot be read on the same axis as the 438 here, and the two numbers are not directly comparable. What the three share is only the verdict that the constrained puzzle is far harder than the unconstrained one; the numbers behind that verdict are on different scales. ## Related - [Verhaard's eii: the solver that won the only prize](https://eternity2.dev/research/lab/experiments/louis-verhaard/eii) — The engine behind the 467, the only Eternity II score ever paid, read from Louis Verhaard's own mailing-list posts: forward pruning, comb-search fill orders, depth-gated edge slipping, a Markov-tuned slip schedule. And why his own source-less Win32 binary cannot be built or run on this machine at all. - [Single-core benchmark](https://eternity2.dev/research/lab/experiments/single-core-benchmark) — Fifteen solvers, ours and our implementations of the community's two record backtrackers, each run once on ten corner-pinned variants of the official puzzle, single core, 60 seconds per run. The finding: node count is not score. - [Local search and ALNS](https://eternity2.dev/research/build/local-search/local-search-alns) — Destroy part of a board, rebuild it better, and let the algorithm learn which demolitions pay. Adaptive large-neighborhood search is the most reliable polisher this project has, and the cleanest demonstration of the wall where polishing ends. --- # How the lab publishes > The editorial standard for this open notebook: how a piece of Eternity II research goes from unpublished work to a published page. What kind of contribution it is, whether it publishes, at what tier, and where it lives. One shared standard, built to scale to many authors. - Canonical page (with interactive figures/demos): https://eternity2.dev/research/lab/experiments/methodology/ - Updated: 2026-07-15 --- This page is the editorial standard behind everything in the lab. It exists so that a finding reaches a reader as an authored artifact, not a raw note, and so the same rules apply no matter who writes it. ## Published, and unpublished The ground rule everything rests on: - **Unpublished work does not appear here.** Where a researcher keeps their work in progress is their own business. It is simply not in this repository. There is no half-finished draft sitting in the published notebook. - **Published work lives in the lab.** Public, distilled, written for a reader. It got here through review. Publishing happens by pull request. A researcher opens a PR that adds or promotes a page, and the review on that PR is where the decision to publish, and at what tier, is made. Nothing enters the public record without a PR, and the PR is where a second reader checks it against the standard below. This keeps review collegial rather than a heavyweight gate, and it scales to many authors. ## Three axes describe every page Keeping these separate is the whole method. It is easy to blur "polished," "reproducible," and "reviewed" into one vague notion of "done." They are not the same thing. 1. **Contribution:** what kind of result is this? 2. **Tier:** how far through review has it come? 3. **Rigor and reproducibility:** how firmly is the claim backed? Plus attribution: who did what. ## Axis 1: contribution Not every result is a solver, and the notebook stopped pretending otherwise. A page declares its contribution: - **solver:** produces a competitive board by searching. Its score is a real search result. Only these earn a row on the leaderboard. - **analysis:** proves or computes a property of an existing board or of the instance. It does not produce a new board. - **reconstruction:** decodes or rebuilds the community's known work to extract an insight. The number is theirs, decoded. - **theory:** a mathematical property, law, or impossibility proof. - **method:** a technique described for reuse, not a scored run. - **measurement:** a benchmark or empirical observation about solvers or instances. - **negative:** a rigorously-run dead end. First-class, not a footnote. - **tool** and **exposition:** a software artifact, or an explainer. The load-bearing distinction is solver versus everything else. A meet-in-the- middle band solver that proves an endgame is optimal is an analysis, not a solver, and it does not belong on a score chart even though it emits a number. Getting this axis right is what lets the leaderboard mean one thing. ## Axis 2: tier Once a page is published, it carries a tier that says how firmly it has been reviewed: - **Technical report:** public, but the review confirmed only that it is sound and fairly stated, not that it has been independently checked. The page carries a "technical report" badge, the way a preprint is stamped "not yet reviewed." A legitimate resting state: not everything needs to go further. - **Reviewed finding:** a second reader, or the same author after a cooling-off, confirmed it holds. Cited, treated as close to immutable; corrections happen in place, annotated. Two principles carry over from how research publishing works elsewhere. The tier is stamped on the page, so a reader always knows what they are looking at. And promotion turns on rigor, not on outcome: a sound method that found nothing gets published as a negative result, while a striking result on an unsound method does not. ## Axis 3: rigor and reproducibility Every page states how firmly its central claim is established (proven, measured, or conjectured) and how re-runnable it is. For anything quantitative the gate is simple: a number publishes only when its exact configuration and seed are archived and it can be re-run from the documentation. A benchmark score with no re-runnable config does not get published. Cheaper contributions carry a lighter bar: a negative result or an explainer needs sound reasoning and clearly stated limits, not a reproduction script. ## Attribution, built for more authors Each researcher's pages gather automatically on their contributor page, derived from the byline, never hand-listed. Adding an author is adding an entry to the registry and writing pages under their name. When a page has more than one hand, a light contributor role (who ran it, who analysed it, who validated it, who wrote it) records the split, so credit stays accurate as the lab grows. ## The decision, in short When a piece of work is done: 1. **Name the contribution.** Solver, analysis, reconstruction, theory, method, measurement, negative, tool, or exposition. 2. **Decide if it publishes.** Publish on rigor, not on excitement. A sound dead end publishes. A number with no re-runnable config waits. 3. **Open a PR at a tier.** Technical report if it is written up but not yet independently checked; reviewed finding once a second reader signs off. 4. **Place it.** Solvers and their kin under the experiments; structural results under why it is hard; techniques under building a solver; cross-solver measurements with the benchmarks. 5. **Chart it only if it is a solver.** That is the whole standard. It is deliberately light, because the point is to raise the floor on every page without slowing the notebook down. ## Related - [The lab](https://eternity2.dev/research/lab) — The wiki's open notebook: structural findings and named search experiments, each credited to the researcher who ran it and reproducible from source. One corner of the community's wider research. - [Experiments](https://eternity2.dev/research/lab/experiments) — The lab's named search experiments, one section per researcher. Each is a real run against Eternity II with its idea, its best board, and the questions it left open. Raphaël Anjou's notebook is here in full; the notebook is open to anyone else's. - [Contribute your research](https://eternity2.dev/research/contribute) — This wiki is the community's research home, and there is room in it for your work. Three ways to get it published, from a mailing-list post to a pull request, plus the small set of house rules that keep every page trustworthy. --- # Peter McGavin's engine > Peter McGavin's own C backtracker, the fastest raw solver the community has measured. Fetched from the mailing list, built on an M1, and run on the real Eternity II. His code, his algorithm; run and written up here. - Canonical page (with interactive figures/demos): https://eternity2.dev/research/lab/experiments/peter-mcgavin/ - Updated: 2026-07-15 --- This section is [Peter McGavin's](/research/people/peter-mcgavin) own solver: the C backtracker he posted to the mailing list, which by the community's measurements is the fastest raw engine anyone has run. The algorithm and the code are his. What is added here is the running: fetched from source, built on one machine, and pointed at the real puzzle, with the numbers written up. ## Pages in this section - [McGavin's C backtracker: the throughput story, built here](https://eternity2.dev/research/lab/experiments/peter-mcgavin/backtracker) — Peter McGavin's own C backtracker, the community's fastest: a 2007 optimization recipe compounded for two decades through generated code, lookup tables and counter tricks, then built on my M1 and pointed at the real 256-piece puzzle, where single core it drives past 200 of 256 pieces at ~109M placements/s. --- # McGavin's C backtracker: the throughput story, built here > Peter McGavin's own C backtracker, the community's fastest: a 2007 optimization recipe compounded for two decades through generated code, lookup tables and counter tricks, then built on my M1 and pointed at the real 256-piece puzzle, where single core it drives past 200 of 256 pieces at ~109M placements/s. - Canonical page (with interactive figures/demos): https://eternity2.dev/research/lab/experiments/peter-mcgavin/backtracker/ - Updated: 2026-07-17 - Topics: speed, backtracking - Reproduce: `fetch genbody71.zip from groups.io msg 11749; gcc -Ofast -DG then without -DG` - Source: Peter McGavin's genbody71.zip (groups.io msg 11749, the original source) — https://groups.io/g/eternity2/message/11749 - Source: Mike Field's optimization recipe: 'Brute force does not work' (groups.io message 3098, 2007) — https://groups.io/g/eternity2/message/3098 - Source: McGavin rediscovers Field's thread: 'I found the old thread' (groups.io message 11338) — https://groups.io/g/eternity2/message/11338 - Source: The 10×10 method and statistics: 180 core-years (groups.io message 9688) — https://groups.io/g/eternity2/message/9688 - Source: The 469 announcement: a few days on a couple of hundred cores (groups.io message 10045) — https://groups.io/g/eternity2/message/10045 - Source: Multi-core throughput table, Raspberry Pi to dual Xeon (groups.io message 11369) — https://groups.io/g/eternity2/message/11369 - Source: Single-core speeds across nine CPU/compiler combos (groups.io message 11643) — https://groups.io/g/eternity2/message/11643 - Source: The counter trick and the compiler playbook (groups.io message 11751) — https://groups.io/g/eternity2/message/11751 - Source: 295M placements/s measured on McGavin's code (groups.io message 11750) — https://groups.io/g/eternity2/message/11750 --- > **Whose work this is** > > The algorithm and the C are **Peter McGavin's** own auto-generated engine, posted to the mailing list. By his own account it is built on an optimization recipe Mike Field posted in 2007 ([message 3098](https://groups.io/g/eternity2/message/3098)), a debt he acknowledged twice ([message 11338](https://groups.io/g/eternity2/message/11338), [message 11780](https://groups.io/g/eternity2/message/11780)). One record is deliberately excluded from that lineage: his 469 came from running [Joshua Blackwood's solver](/research/lab/experiments/joshua-blackwood/solver), not his own ([message 10045](https://groups.io/g/eternity2/message/10045)). This page is [Raphaël Anjou](/research/people/raphael-anjou) building and running McGavin's code on one machine and writing up what it did; the only changes to his source are the two small ones described below. From late 2010 to today, Peter McGavin has been the mailing list's theory desk and its stopwatch. He is the person who typeset Brendan Owen's [complex theory](/research/why/complex-theory) into a LaTeX paper ([message 9188](https://groups.io/g/eternity2/message/9188)), reimplemented it as a C reference in 2024 ([message 11197](https://groups.io/g/eternity2/message/11197)), solved the community's hardest open [benchmark](/research/build/benchmarks), and set the 469 record that stood until Blackwood's 470. But under all of that runs a quieter, twenty-year project: a plain row-scan backtracker in C, tuned until it counts tile placements by the hundreds of millions per second. This page traces that project through his own posted numbers (where the speed came from, what it bought, and what he himself said it never could), then builds it here and points it at the real puzzle. ## The recipe is from 2007, and he says so In October 2007, answering the question "where have you heard of 70 million pieces per second?", Mike Field posted a complete optimization playbook under the pointed title "Brute force does not work" ([message 3098](https://groups.io/g/eternity2/message/3098)). Its ingredients: a lookup table keyed by a cell's north and west colours, so finding candidate pieces is one memory access; a **fixed** search order exploited ruthlessly (placing a piece only updates its south and east neighbours); no loops at all, but procedurally *generated* monolithic code, one straight-line block per cell; minimal state (reconstruct the pretty output later, don't store it in the hot path); piece sides packed into a single int; and reading the generated assembler to hunt pipeline flushes and L1 misses. Field's code compiled down to about 33 instructions per cell and ran 60–80 million placements per second per core on a 2007 desktop, peaking near 100 million when the working set stayed in L1 cache. That post is the genome of McGavin's engine. When he showed a snippet of his "awful auto-generated source code" in 2024, it was recognisably the same organism: a labelled block per cell (`cell_9_2_next:`), a `LookupNW` table indexed by the north and west colours, a `tileFree` array, `register` hints, and a `goto` back into the previous cell's block on exhaustion ([message 11337](https://groups.io/g/eternity2/message/11337)). He went looking for the origin minutes later and posted the link: "I found the old thread" ([message 11338](https://groups.io/g/eternity2/message/11338)); in 2026 he repeated the attribution: his optimised backtracker C code "is based on" Mike's 2007 post ([message 11780](https://groups.io/g/eternity2/message/11780)). Field himself supplies the era's baseline. In 2011 he reported his own backtracker at 75 million tiles placed per second per core on a 2 GHz AMD, about 26 clock cycles per tile, with over half the time stalled on memory access ([message 9003](https://groups.io/g/eternity2/message/9003)). That number, roughly 40 to 80 million per core, is what a serious community engine did for the next decade, McGavin's included. ## What he added, in his own words The recipe was public; the compounding was McGavin's. The refinements he has described on the list, roughly in the order they surface: - **A code generator, not a program.** The per-cell C is regenerated for each puzzle, hint set and [placement path](/research/build/backtracking/fill-order). His 2026 workflow is a compile/run/compile/run cycle: the first pass rebuilds `body.c`, the straight-line cell code, and the second compiles the solver that embeds it. Skip a step after changing an input file and the program "won't be doing anything sensible" ([message 11751](https://groups.io/g/eternity2/message/11751), [message 11782](https://groups.io/g/eternity2/message/11782)). In January 2026 he posted the whole thing to the list as `genbody71.zip`: 1,455 lines of `genbody.c` plus a README, compiled with `-DG` to emit `body.c` and again without it to build the solver that includes it. His own warning leads the README: "This is experimental development code that evolved over several years --- not nice, elegant code at all" ([message 11749](https://groups.io/g/eternity2/message/11749)). - **A counter that costs almost nothing.** `ntpll` ("number of tile placements per second long long", in his own gloss) is not incremented directly. A 16-bit register is bumped on every placement, and `0x10000` is added to the 64-bit counter each time it rolls over: a throwback to 32-bit machines where a 64-bit increment wasted registers or hit slow RAM. He timed both approaches years ago; the trick won. On early 64-bit machines it was even faster to install 32-bit compatibility libraries and compile with `gcc -m32` ([message 11751](https://groups.io/g/eternity2/message/11751)). - **Compiler archaeology.** Compiling with clang instead of gcc gave "a significant speed boost" ([message 11330](https://groups.io/g/eternity2/message/11330)); on ARM, clang-15 beats clang-19 and gcc; add `-march=native` and `-mtune=native`; try icc and icx; use profile-guided optimisation ([message 11751](https://groups.io/g/eternity2/message/11751)). None of this changes the search. It changes how many searches a dollar of electricity buys. - **The placement path as a measured choice.** Scan-row is best for E2, but spiral-in wins on clue puzzles 1 and 3, border-first on 2 and 4, and spiral-out on unframed variants; he checks by running the solver or by asking complex theory, having found himself "poor at judging solving orders" by eye ([message 9703](https://groups.io/g/eternity2/message/9703), [message 9713](https://groups.io/g/eternity2/message/9713)). ## The numbers, 2007 to 2026 Every figure below is from the archive, in its author's own units. | When | Figure | Setting | Source | | --- | --- | --- | --- | | 2007-10 | 60–80M placements/s/core, ~100M peak | Mike Field's recipe, AMD X2 3800+ | [3098](https://groups.io/g/eternity2/message/3098) | | 2011-02 | ~38M placements/s/core (2,300 × 10⁶/min) | McGavin counting 5x5 corners of Brendan's 10x10, 4 cores; 8672 is his own correction of the units (placements, not solutions) | [8672](https://groups.io/g/eternity2/message/8672) | | 2011-06 | ~50M nodes/s, single core | AMD Phenom II, scan-row, Brendan's 8x8 | [8863](https://groups.io/g/eternity2/message/8863) | | 2011-11 | 75M/s/core (~26 cycles/tile) | Field's baseline, 2 GHz AMD, memory-stalled | [9003](https://groups.io/g/eternity2/message/9003) | | 2013-06 | 44.6M nodes/s sustained | one 683-billion-node 10x10 first-row test | [9167](https://groups.io/g/eternity2/message/9167) | | 2014-04 | 67M placements/s, single core | Arnaud Carré's benchmark: all 4 solutions in under a minute | [9263](https://groups.io/g/eternity2/message/9263) | | 2024-10 | 60–140M placements/s per backtracker | "depending on CPU type" | [11329](https://groups.io/g/eternity2/message/11329) | | 2024-11 | 99M → 10,160M nodes/s per machine | Raspberry Pi 4 (4 processes) to dual Xeon Gold 6338 (128) | [11369](https://groups.io/g/eternity2/message/11369) | | 2025-09 | 38–84M placements/s, single core | nine OS/compiler/CPU combos on Brendan's 8x8 | [11643](https://groups.io/g/eternity2/message/11643) | | 2026-01 | ~225M placements/s, single core | Orange Pi 6 Plus on small puzzles; "halves on 16x16" | [11751](https://groups.io/g/eternity2/message/11751) | | 2026-01 | 295M placements/s, single core | Joe running McGavin's code on a newer CPU, vs his own C# at 27–37M | [11750](https://groups.io/g/eternity2/message/11750) | | 2026-02 | 44.0M vs 105.1M tiles/s | identical 2.12-trillion-node tree: 2010 Phenom II vs Ryzen 5 5600H | [11782](https://groups.io/g/eternity2/message/11782) | Two readings of that table. First, the headline: the ~295M/s figure (the one our [records page](/research/records) quotes) is real, but it is Joe's measurement, made in January 2026 when McGavin shared his source and Joe ran it on hardware newer than anything McGavin owns; Joe's own C# solver managed 27–37M/s on the same machine, and the best speed he had seen mentioned on the list was 70–90M/s ([message 11750](https://groups.io/g/eternity2/message/11750)). McGavin's own best figure is the Orange Pi's ~225M/s on small puzzles ([message 11751](https://groups.io/g/eternity2/message/11751)). Second, the quieter and more instructive reading: single-core speed barely moved for fifteen years. McGavin said so himself when he posted the 2025 table: speeds on the latest CPUs "are only a little faster" than on his 2010 Phenom II ([message 11643](https://groups.io/g/eternity2/message/11643)). The engine was already near the memory wall Field described in 2011. What actually grew was the number of cores he could point at a problem. ## Hundreds of cores on a hobby budget McGavin's chapter of the community's [distributed-solving story](/research/build/faster/distributed-solving) is charmingly domestic. For the 10×10 campaign he started with about 20 cores at home, then added three octa-core Odroid XU4s and twenty-five quad-core Orange Pi Lites at 12 dollars each (over 130 cores, each ARM core about a third the speed of a PC core) and, when allowed, multi-core servers at work for a total of over 400 ([message 9688](https://groups.io/g/eternity2/message/9688)). The Orange Pis ran off 12-port USB chargers (he permanently killed one charger by plugging in twelve boards running 48 backtrackers, and cut back to eight per charger) with WiFi networking: one cable per board, for power ([message 9690](https://groups.io/g/eternity2/message/9690)). Orchestration is two shell scripts: one starts as many backtrackers as a node has cores, the other launches it on ~20 nodes over ssh, each with 16 to 48 cores, though "well, they are hyperthreads, strictly speaking" ([message 9753](https://groups.io/g/eternity2/message/9753)). At peak, "more than 400 backtrackers running at once" ([message 9751](https://groups.io/g/eternity2/message/9751)). ## What the speed bought **Verified counts, first.** Fast full enumerations are what let the community check theory against reality. In 2011, an overnight run counted 4,739,821,621,743 5×5 corner blocks of Brendan's 10×10, against a complex theory estimate of 5.0077 × 10¹², "pretty close… if I do say so myself" ([message 8672](https://groups.io/g/eternity2/message/8672)). In 2014 his single core swept Arnaud Carré's 256-piece benchmark tree (3,979,209,754 placements, all 4 solutions) in under a minute ([message 9263](https://groups.io/g/eternity2/message/9263)). In 2026, two different machines walked the same 2,120,424,701,160-node tree of an E2-like puzzle and found the same lone solution: determinism as a feature, node counts as a checksum ([message 11782](https://groups.io/g/eternity2/message/11782)). **The 10×10, above all.** Brendan's set_1 10×10, a benchmark that had stood open for a decade, fell in September 2017 to exactly this machinery: enumerate ~20 million candidate first rows, rank them by complex theory's solutions-per-search-node, and let the farm test them one by one, about a core-day each. The solution arrived on row-test ~92,907 of a predicted one-in-70,000, after nearly 2 × 10¹⁷ nodes, about **180 core-years**, less than 0.5% of the whole tree ([message 9686](https://groups.io/g/eternity2/message/9686), [message 9688](https://groups.io/g/eternity2/message/9688)), spread over about four years ([message 9804](https://groups.io/g/eternity2/message/9804)). His summary: "no new methods, just systematic persistence and the law of large numbers." The [benchmarks page](/research/build/benchmarks) tells that story as complex theory's strongest validation; here it stands as the throughput story's high-water mark. **And one record, on someone else's engine.** In September 2020, days after Joshua Blackwood open-sourced his solver, McGavin ran it "for a few days on about a couple of hundred cores and hit the jackpot. New record score of 469!" ([message 10045](https://groups.io/g/eternity2/message/10045)), with run statistics to match (2,832 boards reaching 252 pieces, one 255, one 256: [message 10049](https://groups.io/g/eternity2/message/10049)). Note what combined there: [Blackwood's heuristics](/research/lab/experiments/joshua-blackwood/solver) supplied the shape of the search; McGavin's farm supplied the placements. His own C engine holds no E2 score record; his row-scan 226s of February 2020 equalled [Verhaard's](/research/lab/experiments/louis-verhaard/eii) old consecutive-placement mark, no more ([message 10523](https://groups.io/g/eternity2/message/10523)). ## What the speed could not buy McGavin is also the archive's most consistent witness *against* raw speed. His own numbers make the case. With scan-row order, complex theory puts E2's full search tree at about 1.6 × 10⁴⁷ placements ([message 9710](https://groups.io/g/eternity2/message/9710)), some 9.3 × 10⁴² per expected solution ([message 9713](https://groups.io/g/eternity2/message/9713)). Even on his best 5-hint placement path (a far smaller tree, about 3.1 × 10⁴⁰ nodes) he computed 4.9 × 10³² years at 100 million nodes per second, and adding billions of cores still leaves you "orders of magnitude longer than the age of the Universe" ([message 11201](https://groups.io/g/eternity2/message/11201)). He had drawn the conclusion long before, in 2013: "It seems clear to me that E2 will not be solved by brute force. If it is to be solved at all, it will be by deep analysis and/or clever insight, in my opinion" ([message 9117](https://groups.io/g/eternity2/message/9117)). Which is why the biggest single speedup he ever reported was not a speedup at all. For the unframed sub-solution hunts, he used complex theory as a chess-style lookahead: estimate solutions-per-node at every leaf 13 or 14 plies ahead, cache the repeated statistics, and steer into the best branch. Overall gain: a factor of about 25 by depth 81 ([message 9751](https://groups.io/g/eternity2/message/9751)). No compiler flag ever gave him 25×. Shaping the tree beat shrinking the nanoseconds. That is this site's [core lesson](/research/why/prune-vs-speed), reported here as one practitioner's twenty-year experiment: he built the fastest engine in the community's history, measured everything, and concluded the gap to 480 was never on the clock. ## Running it here All of the above is drawn from the archive. The rest of this page is that same engine, built on my machine and pointed at the real puzzle, so the throughput story carries a first-party measurement and not only a relayed one. ### Where the code came from The source is `genbody.c`, attached as `genbody71.zip` to [groups.io message 11749](https://groups.io/g/eternity2/message/11749). It is 1,455 lines of C, with a README, a piece file, and a hint file. It is not copied into this repository: it stays on the list, where its author put it. It is a two-pass program, and the README is candid about the style ("dreadful C source code ... it really needs a lot of work to clean it up"). Compiled with `-DG`, it generates a second C file, `body.c`, specialised to one puzzle. Recompiled without `-DG`, it includes that generated file and runs the search. That two-pass workflow is exactly the code-generator design described above, now in front of me. ### What was changed to run it Two things, both small: - **Nothing, to build it.** It compiles clean on Apple silicon with `clang` (one unused-variable warning). The POSIX status display it uses, `setitimer` and `termios`, works on macOS with no shim. - **The puzzle it reads.** The filenames were hardcoded to Joe's test puzzle. I made them read from the command line so it could be fed the real Eternity II, and wrote the official pieces and clues into his `.puz` / `.hnt` format from the canonical puzzle file. His search path is built generically (clue cells first, then a row scan), so no other change was needed. ### What it does on Joe's puzzle Configured as shipped, on Joe's 18-hint 16×16 test puzzle, it is very fast and it finishes: - **~279 million tile placements per second**, single core. - Solves the puzzle to completion in about 13 seconds (3.577 billion placements to the first solution), identically on every run. That is the number the community means by "McGavin is fast." It is real, and it is on current hardware, not a seven-year-old machine: right in line with the ~295M/s Joe measured, and comfortably past McGavin's own ~225M/s Orange Pi. ### What it does on the real Eternity II Fed the actual 256-piece puzzle, once with only the mandatory centre clue and once with all five official clues: his solver only saves a board when it finds a **complete** solution, and the real puzzle has never been solved, so it saves nothing and runs without stopping. What it does report, live, is the deepest it has placed: | Puzzle | Deepest placement, 30 s | Rate | Solutions | | --- | --- | --- | --- | | Real E2, 1 clue | **205 / 256** | ~108 M placements/s | 0 | | Real E2, 5 clues | **204 / 256** | ~109 M placements/s | 0 | Two things are worth saying plainly. First, this is a **depth** (how far the search reached before backtracking), not an edge score out of 480: his program does not emit a partial board to re-score. Second, the rate on the real puzzle is about 109 million placements a second, roughly 40% of its speed on Joe's puzzle, because the real puzzle's constraints prune harder. The clue count barely moves it: 205 with one clue, 204 with five. This is the same lesson his own posts reach, now on my own hardware: the raw engine is superb at walking a tree and says nothing, on its own, about where a high-scoring board hides. ### Single core, confirmed The binary links only the system library, has no threading primitives in its source, and holds one CPU at 100% (not 800%) with a single thread throughout. The speed is one core's. That is the fair unit for comparing engines, and it is the one the [single-core benchmark](/research/lab/experiments/single-core-benchmark) uses to put this engine next to [Blackwood's](/research/lab/experiments/joshua-blackwood/solver) and the [Verhaard reimplementation](/research/lab/experiments/louis-verhaard/verhaard-reimpl). The three are not measuring the same axis (McGavin's number is a placement depth, not a matched-edge score), so read the comparison with care. One first-party postscript on the throughput itself. Rebuilt headless (its live terminal display, it turns out, costs it ~2.7×) and pointed at both an easy and a hard board, this C engine sets the bar a [portable-Rust codegen backtracker](/research/lab/experiments/raphael-anjou/jit-backtracker) was then measured against on the same M1: the Rust ties it on hard, deep boards like the real puzzle (~105–110M each) and trails by ~2.3× on easy low-branching ones (~287M vs ~122M). A useful calibration of how much of this engine's edge is portable craft and how much is the shape of the board it runs on. ## Related - [Blackwood's solver, decoded and run here](https://eternity2.dev/research/lab/experiments/joshua-blackwood/solver) — Joshua Blackwood's record backtracker, decoded through Jef Bucas's notes (a colour quota schedule and a late-game mismatch allowance, tuned near-optimally), then built and run on my M1: left as published it flies to 248 of 256 pieces ignoring the clues; pin the five official clues and the same engine stalls near 45. - [Single-core benchmark](https://eternity2.dev/research/lab/experiments/single-core-benchmark) — Fifteen solvers, ours and our implementations of the community's two record backtrackers, each run once on ten corner-pinned variants of the official puzzle, single core, 60 seconds per run. The finding: node count is not score. - [Complex theory: counting the search before you run it](https://eternity2.dev/research/why/complex-theory) — Brendan Owen's complex theory estimates how wide the search tree is at every depth, and even how many solutions exist at all. Many in the community consider it the single most important thing to understand about Eternity II. - [The community's benchmarks](https://eternity2.dev/research/build/benchmarks) — How a community forbidden from sharing the pieces built a shared test culture anyway: derived-count verification protocols, the Txibilis and beginner suites, node-count duels, full enumerations, and the one benchmark that is still standing open today. --- # Raphaël Anjou's experiments > A notebook of Eternity II search experiments, organised into the shared engines they run on, the combination pipelines that chase the score, three studies that take one search paradigm apart a decision at a time, and exact endgame solves. Each has its idea, its best board, and the questions it left open. The best reaches 463 of 480. - Canonical page (with interactive figures/demos): https://eternity2.dev/research/lab/experiments/raphael-anjou/ - Updated: 2026-07-17 --- This is [Raphaël Anjou's](/research/people/raphael-anjou) notebook of Eternity II search experiments. Some are original ideas; some faithfully reimplement a known community technique to measure exactly what it buys. Every one records its idea, the board it reached, and the questions it left open, and every board is real and checkable in the [viewer](/viewer). The best reaches **463 of 480** matched edges; the community's best on the same puzzle is 470. Methods and boards are here in full, nothing withheld. It is a notebook, not a single result, so it is worth knowing how it is laid out before diving in. ## What's in this section Two kinds of thing live here: the **apparatus** the experiments run on, and the **experiments** themselves. The experiments come in three flavours: pipelines that chase the whole-board score, studies that isolate one search decision at a time, and exact solves that *prove* a small region rather than guess it. Start wherever the question you care about lives.
- [The engines](/research/lab/experiments/raphael-anjou/engines) — The shared machinery the experiments run on: a constructive beam producer, a destroy-and-repair local search, and a family of CSP presets. Documented once here so each study can point back instead of re-explaining the machine. Start here if you want to know how a search works before reading what a study did with it. - [Combination pipelines](/research/lab/experiments/raphael-anjou/pipelines) — The named runs that push the score. Each is a pipeline, not a single algorithm: build a board with one engine, then lift or finish it with another. The interest is in the division of labour between construction, repair and an exact endgame. This is where the record-approaching boards come from. - [The DFS study](/research/lab/experiments/raphael-anjou/dfs-study) — Depth-first backtracking, dissected. A family of from-scratch backtrackers, each one change apart (fill order, heuristic, break policy), run on the same ten variants under a fixed budget, to price what each idea is worth. - [The repair study](/research/lab/experiments/raphael-anjou/repair-study) — Its sibling, for destroy-and-repair local search: which region to destroy, how to rebuild it, when to keep a move, what board to start from. The loop the records actually reach the top with, taken apart one decision at a time. - [Learning from strong boards](/research/lab/experiments/raphael-anjou/learning) — The third study, turned inward: instead of varying the search, vary what it is allowed to *know*. Five experiments mine the corpus of strong boards for structure and feed it back in, and all five hit the same wall. - [Meet in the middle](/research/lab/experiments/raphael-anjou/meet-in-the-middle) — Exact endgame solves: enumerate a region from two ends and join on the seam to find the true best completion, with a proof nothing scores higher. These measure a small region exactly rather than chase the whole-board score. - [Going fast](/research/lab/experiments/raphael-anjou/going-fast) — The other lever: not a smarter search, a faster one. A portable-Rust backtracker that generates and compiles per-puzzle Rust, taken rung by rung to McGavin-class throughput - a tie with the community's fastest hand-tuned C on hard, realistic boards, from a safe language. A speed result, on an axis of its own from the scores above.
The two constructive engines, the beam producer and the ALNS polish stage, do not yet have their own write-ups; where a pipeline steers one, its own page says what that engine does at the level the study needs. The CSP presets are the one engine documented and measured in full. ## How to read the scores The chart and table below carry two kinds of number that must never be conflated, so they are drawn as separate groups. - **Explore** is the best board each method reached in exploratory runs on 8 cores, wall-clock not logged. These are the headline numbers the write-ups quote, and they top out at PALIMPSEST's 463. - **Bench** is the standardized single-core benchmark: one core, sixty seconds, every board re-scored by the same canonical scorer. Lower, and *directly comparable* across methods in a way the explore numbers are not. Not every experiment earns a row. The three studies vary a knob across a grid rather than producing one board, so the [DFS](/research/lab/experiments/raphael-anjou/dfs-study) and [repair](/research/lab/experiments/raphael-anjou/repair-study) studies carry their own leaderboards instead of a chart row; only their single best bench result appears here. The five [learning](/research/lab/experiments/raphael-anjou/learning) experiments each reach one scored board, so they keep their rows as well as their study home. The bench rows above are study results, not standalone pages, so they appear only on the chart. > **[Interactive: ExperimentScoreChart]** Rendered on the canonical page (link above); not shown in this markdown export. The named experiments as a sortable table (click a column head to reorder by score, name, method, or month). Author, month, rigor and reproducibility are read from each experiment's own page, so this summary stays in step with them. s.group !== "bench")} /> ## Pages in this section - [The reference engine behind this site](https://eternity2.dev/research/lab/experiments/raphael-anjou/engine) — The Rust-to-WebAssembly backtracker that runs every live demo and checks every number on this wiki. Not a record machine but a reference engine, ported four times and parity-tested byte-for-byte, built so the claims here can be re-run. - [Learning from strong boards](https://eternity2.dev/research/lab/experiments/raphael-anjou/learning) — A study in five experiments of one idea: instead of searching Eternity II from first principles, mine the corpus of strong boards already found for structure and feed it back into a search. A position prior, a learned move-vote, a scarce-demand compass, an anti-pattern miner, and a record decode, ordered from the simplest signal to the subtlest, and the one wall all five reach. - [The engines](https://eternity2.dev/research/lab/experiments/raphael-anjou/engines) — The shared engines under Raphaël Anjou's experiments. The named experiments are studies that run on these; this is the apparatus they share. The CSP presets and the Verhaard reimplementation are documented here; the constructive engines are not yet published. - [The JIT backtracker: portable Rust that ties hand-tuned C on hard boards](https://eternity2.dev/research/lab/experiments/raphael-anjou/jit-backtracker) — A safe, portable Rust depth-first backtracker, specialised at runtime by emitting and compiling per-puzzle Rust, taken from 43 to 123 million search-nodes per second on one core. Measured fairly against Peter McGavin's C on the same machine: a tie on hard, deep boards like the real Eternity II, and about 44% of its speed on easy ones. Every rung searches the identical tree; the whole gain is code, not algorithm. - [Going fast: when a solver spends its budget on speed](https://eternity2.dev/research/lab/experiments/raphael-anjou/going-fast) — Some Eternity II engines pour their effort into walking the search tree as fast as possible; others spend it on judgement about where to walk. This is the case for the first kind - what raw throughput buys, the three different things people mean by "fast", and why the fastest engine ever built still cannot solve the puzzle. - [Combination pipelines](https://eternity2.dev/research/lab/experiments/raphael-anjou/pipelines) — The named search experiments that chase score. Each is a pipeline rather than a single algorithm: it builds a board with one engine, then lifts or finishes it with another. Each records its idea, its best board, and the questions it left open. - [The DFS study](https://eternity2.dev/research/lab/experiments/raphael-anjou/dfs-study) — One question, asked carefully: among depth-first backtrackers for Eternity II, what does each fill order, each heuristic, and the break mechanism actually buy? A family of from-scratch backtrackers, each one change apart, run on the same ten corner-pinned variants, single core, sixty seconds. - [The hint study](https://eternity2.dev/research/lab/experiments/raphael-anjou/hint-study) — Give a backtracker five correct pieces for free, in the puzzle's own clue geometry. It turns out not to help, and depending on the fill order it can hurt badly, because a pinned piece is a hard constraint a fixed fill order must satisfy on arrival. A family of fill paths, run on the same hinted boards, single core, measured against no hints at all. - [The repair study](https://eternity2.dev/research/lab/experiments/raphael-anjou/repair-study) — The sibling of the DFS study, for the other way people attack Eternity II: destroy part of a board, rebuild it, keep the change if it helps. One question, asked carefully. What does each decision in that loop buy: which region to destroy, how to rebuild it, when to keep a move, when to restart, and what board to start from? - [Meet in the middle](https://eternity2.dev/research/lab/experiments/raphael-anjou/meet-in-the-middle) — Exact endgame experiments that meet in the middle: enumerate a region from two ends and join on the seam, to find the true best completion with a proof rather than a heuristic's best guess. These measure a small region exactly instead of chasing the whole-board score. --- # The DFS study > One question, asked carefully: among depth-first backtrackers for Eternity II, what does each fill order, each heuristic, and the break mechanism actually buy? A family of from-scratch backtrackers, each one change apart, run on the same ten corner-pinned variants, single core, sixty seconds. - Canonical page (with interactive figures/demos): https://eternity2.dev/research/lab/experiments/raphael-anjou/dfs-study/ - Updated: 2026-07-16 - Topics: backtracking, search-space, speed - Reproduce: `just experiments dfs-study` - Source: Runnable engine + committed results + scripts (this study's backing directory) — https://github.com/raphael-anjou/eternity2/tree/main/research/experiments/dfs-study --- Every record-holding Eternity II solver (Blackwood, Verhaard, McGavin) is a depth-first backtracker. What separates them from a first-week homework backtracker is not their kind but a handful of decisions: which order they fill cells in, which look-ahead they run, and whether they let an edge *break*. This study takes those decisions apart. It builds a family of depth-first backtrackers from scratch, each one exactly one change away from a sibling, and runs them all on the same ten corner-pinned variants of the official puzzle, single core, sixty seconds a run. The maximum score is 480 matched edges. The point is not to win. The strongest variant here averages the low 430s, well short of the community's 464 on these five clues, because sixty seconds on one core is a small fraction of the compute the records took. The point is to isolate *what each idea is worth* by changing one thing at a time and measuring the result with the same canonical scorer for every board. > **[Interactive: StartingPuzzleCarousel]** Rendered on the canonical page (link above); not shown in this markdown export. ## The family, and the leaderboard Four families, laid out so that neighbours differ by a single decision. **Baseline** is the rawest possible backtracker, alongside a hand-specialised twin that prices the low-level engineering. **Path order** fixes everything but the sequence in which cells are filled. **Heuristic** fixes the order and adds one propagator at a time. **Break** is the elite axis: the depth-gated edge-break mechanism the records rely on. The community record engines, McGavin's C and Blackwood's C#, are themselves break backtrackers, so they sit in the break family too, not in a category of their own. Whose code an engine is stays a matter of labelling, not colour. Both appear on the leaderboard at their corner-pinned score, badged where they collapse, and again on a fair unpinned grid further down where they run as designed. > **[Interactive: DfsStudyLeaderboard]** Rendered on the canonical page (link above); not shown in this markdown export. ## What the study found - **Path order is the largest free lever, and the wrong order is catastrophic.** Plain row-major averages 377; a strict border-first or spiral fill, with no heuristic to rescue it, stalls near 67. Same engine, same budget, a swing of more than 300 points from the fill order alone. - **The most-constrained-cell heuristic (MRV) is what makes border-first viable.** It lifts a stalled border-first from the sixties to a mean of 324, at a cost of three orders of magnitude in node throughput. Node rate and score are different axes, a distinction the study returns to throughout. - **More propagation did not buy more score at this budget.** Forward-checking, arc-consistency and per-colour reasoning land within a point of each other (322, 321, 321), a gap far inside the run-to-run spread, so heavier look-ahead neither helped nor clearly hurt. It spends the sixty seconds proving small regions rather than reaching deeper. - **Breaks reach deeper than any strict search.** Strict backtrackers top out in the low 200s (the fastest, NAIVE-CODEGEN, at 216); a depth-gated break budget reaches past 245 and averages the low 430s, because it can push past a locally unmatchable edge instead of backtracking out of it. The decisive factor is the break *schedule*: unlocking breaks too early (Verhaard's ladder, mean 399) scores well below the later Blackwood ladder (mean 431). Raising the per-cell cap from one to two did not help at this budget, a null result reported as measured. Each of these has its own page: how the engine is built and what every raised statistic means is on the [method page](/research/lab/experiments/raphael-anjou/dfs-study/method), and the path, heuristic and break comparisons are worked through on the [findings page](/research/lab/experiments/raphael-anjou/dfs-study/findings). ## How to read the numbers Every board is re-scored by one canonical scorer, and no engine's self-reported score is trusted. Throughput is reported in search-nodes per second and is **never compared across families**, because a node that runs full arc-consistency is not the same unit of work as a naive placement. Depth is the deepest placement a variant reached, out of 256. The break count deserves a precise definition, because it is easy to state loosely. A board's *score* is its matched interior edges, and the gap `480 − score` is the board's total unmatched-edge deficit. On a **completed** board every unmatched edge is a genuine break, so there the score is exactly `480 − #breaks`. Sixty seconds is rarely enough to fill the board, however, so most break-variant boards here are partial, and their deficit is dominated by edges that are simply still empty rather than broken. This study therefore reports the **true break count**, meaning the interior mismatches the search actually committed under its budget, tracked by the search itself rather than inferred from the score. That number stays small even when the deficit is large. Every board carries a bucas `.url` that opens in the [viewer](/viewer), so both the score and the broken edges can be checked directly. The whole apparatus (the engine workspace, the ten variants, the committed per-run results and the grid scripts) lives under the study's [backing directory](https://github.com/raphael-anjou/eternity2/tree/main/research/experiments/dfs-study), and `just experiments dfs-study` rebuilds the engine and reruns the whole grid. ## Pages in this section - [How the study is built](https://eternity2.dev/research/lab/experiments/raphael-anjou/dfs-study/method) — The engine behind the DFS study: one composable backtracker where a variant is a declared change over a parent, a shared IO layer every algorithm speaks, and the definitions of every statistic the study raises: node rate, depth, breaks. - [What each idea buys](https://eternity2.dev/research/lab/experiments/raphael-anjou/dfs-study/findings) — The three comparisons at the heart of the DFS study, worked through: fill order (row-major wins, a bad order is catastrophic), heuristics (MRV rescues border-first but costs throughput; more propagation did not help), and breaks (they smash the depth wall; the break schedule is the lever, not the per-cell cap). ## Related - [Raphaël Anjou's experiments](https://eternity2.dev/research/lab/experiments/raphael-anjou) — A notebook of Eternity II search experiments, organised into the shared engines they run on, the combination pipelines that chase the score, three studies that take one search paradigm apart a decision at a time, and exact endgame solves. Each has its idea, its best board, and the questions it left open. The best reaches 463 of 480. - [Single-core benchmark](https://eternity2.dev/research/lab/experiments/single-core-benchmark) — Fifteen solvers, ours and our implementations of the community's two record backtrackers, each run once on ten corner-pinned variants of the official puzzle, single core, 60 seconds per run. The finding: node count is not score. - [Fill orders](https://eternity2.dev/research/build/backtracking/fill-order) — The order in which a backtracker visits the 256 cells is its one free choice: it costs nothing at runtime and moves the size of the search tree by orders of magnitude. Twenty years of community science, from the fixed-vs-dynamic wars and the strategy races to the magic 10×16 square and Verhaard's comb search, all answer the same question: which path through the board is cheapest? --- # What each idea buys > The three comparisons at the heart of the DFS study, worked through: fill order (row-major wins, a bad order is catastrophic), heuristics (MRV rescues border-first but costs throughput; more propagation did not help), and breaks (they smash the depth wall; the break schedule is the lever, not the per-cell cap). - Canonical page (with interactive figures/demos): https://eternity2.dev/research/lab/experiments/raphael-anjou/dfs-study/findings/ - Updated: 2026-07-16 - Topics: backtracking, search-space, speed - Source: Committed per-run results (results.jsonl) and per-family report (report.md) — https://github.com/raphael-anjou/eternity2/tree/main/research/experiments/dfs-study/results --- Three comparisons carry the [DFS study](/research/lab/experiments/raphael-anjou/dfs-study). Each isolates one decision by holding everything else fixed. All scores are the mean matched-edge count over the ten corner-pinned variants, single core, sixty seconds. Throughput is search-nodes per second and is never compared across families. ## What low-level specialisation buys: throughput, and only that The two baselines run the *same* strict row-major algorithm: `NAIVE-CLEAN` as a readable general engine, `NAIVE-CODEGEN` as a hand-specialised, row-major-only 16×16 hot loop. The specialisation delivers what it should on the axis it targets. `NAIVE-CODEGEN` is meaningfully faster per node, by up to a third on some instances. On *score* the two are a wash, a point or two apart at sixty seconds and well inside the run-to-run spread, which is the fair reading rather than a claim that specialisation *hurts*. At a fixed wall-clock a faster engine reaches a different point of the same tree, and a backtracker's best partial does not move monotonically with how fast it got there. The baselines are therefore a clean *speed* comparison and are deliberately not presented as a *score* comparison. The score effects worth studying are all on the axes below, where the search itself changes. ## Fill order: row-major wins, and the wrong order is catastrophic Fix the engine (strict, no heuristics) and change only the order cells are filled. The six orders differ only in where the search sends its frontier, shown below. > **[Figure]** The six fill orders, traced as the path the search walks — interactive: PathOrderDiagram. Rendered on the canonical page (link above); not shown in this markdown export. - **Row-major** is the strong baseline, averaging 377. Its damage zone stays constant, since every new cell has the same two placed neighbours, so it reaches deep before the strict wall. - **A strict border-first or spiral fill collapses.** Filling the border ring first, with no look-ahead, walks straight into the hardest corner and edge constraints and stalls almost at once, near a mean of 67 at depth 66 or so. The spiral pays the same closure tax. - **Bottom-up row-major fares worse still on this clue geometry** (mean 226, but as low as 18 on some variants), because the pinned clues sit in rows the bottom-up fill reaches early and cannot satisfy. Same engine, same sixty seconds, a swing of more than 300 points from the fill order alone. This is the measured form of a piece of community wisdom: border-first is only good *with* a heuristic to choose cells within the ring. On its own it is one of the worst orders available. ## Heuristics: MRV rescues border-first, but throughput craters Now fix the path near the frame and add one thing at a time. The largest lever is **MRV**, filling the most-constrained empty cell next, chosen dynamically. It turns the stalled border-first (mean 67) into a search that averages 324 (best 341) at depth 190 or so. It also recomputes the most-constrained cell over the whole frontier at every step, so node throughput falls by three orders of magnitude, from tens of millions of nodes per second to a few thousand. Each node is worth far more, and far fewer of them are visited. Node rate and score are different axes. Adding heavier look-ahead on top did **not** buy more score at this budget. - **Forward-checking** (reject a placement that empties a neighbour's domain) averaged 322. - **Arc-consistency** and the **per-colour supply check** averaged 321 each. With a per-variant score spread of about 11 points over the ten instances, that one-point gap is well within the noise: the three propagators are statistically indistinguishable here, so the fair reading is that heavier look-ahead neither helped nor clearly hurt, rather than that forward-checking won. - A **rare-colour-first** value ordering was inert, no better than plain insertion order, echoing the community's repeated negative result on within-bucket value orders. The lesson is not that propagation is useless. It is that at a small fixed budget, on this instance, the cheapest useful prune (forward-checking) already captures whatever benefit is available, and more expensive reasoning does not recover its extra per-node cost within sixty seconds. ## Breaks: past the wall, and the schedule is the lever Strict backtracking, whatever its order or heuristic, hits a wall well short of a full board: row-major tops out around depth 208 of 256, and even the fastest strict variant (NAIVE-CODEGEN) only reaches 216. The record engines get past it by *breaking*: allowing a bounded number of interior edge mismatches, released on a depth schedule, with a rule that no cell may carry too many broken edges. The score of a full board is then `480 − #breaks`. - **Breaks clear the wall.** A depth-gated break budget reaches past depth 245 and averages the low 430s (break-1 means 431 of 480, best 435), a large gain over the strict high-370s on the same instances and budget. This is the mechanism behind the community's record backtrackers, not a different paradigm but a depth-gated relaxation of the matching rule. - **Allowing a second break per cell did not help here.** One-break and two-break reach the same best board (435), and their means (431.3 against 428.5) sit within the two-break variant's own spread, so neither leads on average. What does separate them is consistency: the one-break variant is tightly clustered (never below 427), while the two-break variant ranges down to 402. The double-break geometry the community's 460-boards use appears to need more than sixty seconds to pay off; at this budget the extra freedom mostly widens the branching without reaching better boards. This is a null result, reported as measured rather than the gain one might expect. - **The schedule is the decisive lever.** Verhaard's slip ladder unlocks breaks much earlier than Blackwood's (depth 193 against 201) and here scores markedly worse (mean 399 against 431), because unlocking early spends the budget on shallow breaks. When and how fast breaks open is a tuning decision rather than a detail. These break numbers sit alongside the sibling benchmark's from-scratch Blackwood-style and Verhaard-style reimplementations, which reach the high 430s on the same five clues. The agreement from an independent engine cross-validates the break machinery here. ## Where the community engines sit: two grids Blackwood and McGavin are the high end of this same family, and both build and run on this machine, so this study ran them on both a pinned and an unpinned grid, with every score canonically rescored from the engine's own board. The result is a finding in its own right, and it has two halves. **On the pinned grid, they collapse.** McGavin's C, built with its author's own ARM flags (native tuning plus link-time optimisation), reaches depth 211 on the plain centre-clue puzzle at about 85 million tiles per second, well ahead of our fastest strict engine, yet pinning three corners collapses it to depth 21, a canonical score of 13. Its generated scan path never visits the corners early, so a pinned corner constrains its neighbourhood at once and dead-ends the fixed path almost immediately. Blackwood's C# hardcodes its piece set and scan, so it cannot even express an arbitrary corner pin; on the matching five-clue constraint its break heuristic thrashes to depth 47, a canonical score of 75, because it is tuned for the near-unconstrained one-clue instance where its 470 record was set. > **[Figure]** The corner-pin collapse: cells placed out of 256 — interactive: PinCollapseDiagram. Rendered on the canonical page (link above); not shown in this markdown export. That collapse is the point. A record engine built around one clue configuration does not transfer to another, and a fixed scan path cannot absorb an arbitrary pin. Our from-scratch engines treat a pin as a pre-placed cell the scan simply skips, which is why they, rather than the community binaries, are the stand-ins on the pinned grid. **On a fair unpinned grid, they run as designed.** Give every engine the official pieces with only the one mandatory centre clue, and nothing dead-ends on a corner. In sixty seconds on one core, McGavin reaches 392, our strongest break engine 344, the Verhaard reimplementation 286, and Blackwood 214. Read those as what a single core buys in a minute from a cold start, not as any engine's ceiling: Blackwood's 470 and McGavin's deep runs came from days on hundreds of cores, which this budget cannot show. What the grid does show is that all four run properly once the pins that break a fixed scan path are gone, which is exactly what the pinned grid denied the two foreign engines. Both grids are on the study's leaderboard above. ## The through-line One theme runs through all three comparisons: **node count is not score.** The fastest variants per node (the codegen baseline and the strict row-major engine) do not reach the best boards; the slowest per node (MRV with propagation) reaches far better ones; and the breaks that win do so by changing *which* branch is legal, not by visiting branches faster. Raw speed is a constant factor, while where and whether the search is allowed to go is the exponential one. ## Related - [The DFS study](https://eternity2.dev/research/lab/experiments/raphael-anjou/dfs-study) — One question, asked carefully: among depth-first backtrackers for Eternity II, what does each fill order, each heuristic, and the break mechanism actually buy? A family of from-scratch backtrackers, each one change apart, run on the same ten corner-pinned variants, single core, sixty seconds. - [How the study is built](https://eternity2.dev/research/lab/experiments/raphael-anjou/dfs-study/method) — The engine behind the DFS study: one composable backtracker where a variant is a declared change over a parent, a shared IO layer every algorithm speaks, and the definitions of every statistic the study raises: node rate, depth, breaks. - [Fill orders](https://eternity2.dev/research/build/backtracking/fill-order) — The order in which a backtracker visits the 256 cells is its one free choice: it costs nothing at runtime and moves the size of the search tree by orders of magnitude. Twenty years of community science, from the fixed-vs-dynamic wars and the strategy races to the magic 10×16 square and Verhaard's comb search, all answer the same question: which path through the board is cheapest? --- # How the study is built > The engine behind the DFS study: one composable backtracker where a variant is a declared change over a parent, a shared IO layer every algorithm speaks, and the definitions of every statistic the study raises: node rate, depth, breaks. - Canonical page (with interactive figures/demos): https://eternity2.dev/research/lab/experiments/raphael-anjou/dfs-study/method/ - Updated: 2026-07-16 - Topics: backtracking, speed - Source: The engine workspace (dfs-engine, dfs-run) on the shared e2-core / e2-io library — https://github.com/raphael-anjou/eternity2/tree/main/research/experiments/dfs-study/engine --- This page is the apparatus behind the [DFS study](/research/lab/experiments/raphael-anjou/dfs-study): how the engine is built, why a new variant is cheap to add, and what every number on the results means. None of it depends on the sibling [single-core benchmark](/research/lab/experiments/single-core-benchmark)'s engine. The whole point was to reimplement the family from scratch, keeping the software engineering clean and the "what stacks on what" story explicit. ## A variant is a declared change over a parent Every algorithm in the study is the *same* recursive depth-first backtracker, parameterised by four independent choices: - **path order**: the sequence cells are filled in (row-major, spiral, border-first, Verhaard's comb, or dynamic most-constrained-cell); - **value order**: the order a cell's candidate pieces are tried; - **propagator**: the look-ahead run after each placement (none, forward-checking, arc-consistency, per-colour reasoning); - **break policy**: whether an edge may mismatch, and under what depth-gated budget. A variant is a small record naming those four choices, together with **the parent it derives from and a one-line description of the single change it adds**. Adding a variant means adding one record to the registry, with no new search code unless the idea is a genuinely new strategy. The "what stacks on what" matrix on the results page is generated from those descriptions, so it cannot drift from the code that ran. That is what keeps an extensive study, with dozens of one-change-apart variants, maintainable rather than a pile of copy-pasted solvers. ## One IO layer, and conversions between engines Every algorithm in the study consumes one instance type and emits one output: the best board, its canonical score, and a bucas URL. Around that sits a shared IO layer with lossless converters between the formats the site's other engines speak: the benchmark's site-schema JSON, the standalone community engines' CSV, bucas URLs, and hint files. The study reads the *same* ten corner-pinned variants the single-core benchmark uses, through this layer, so the two experiments are directly comparable. A small `dfs-convert` utility exposes the conversions from the shell, so any blog engine's output can be fed to any other. ## The scorer is the single source of truth No engine's self-reported score is trusted. Every board, strict or broken, is re-scored by one canonical scorer: matched, non-border, interior adjacencies, counted right and down per cell. It is byte-for-byte the same formula the site's scorer and the benchmark use, checked by a test that re-scores a known 469-board and asserts 469. This is what lets scores from different variants, and from the sibling benchmark, sit on one axis. ## The statistics the study raises For every run the engine records, and the results carry all the way to the page: - **score**: canonical matched edges (of 480). For a full board with breaks, this equals `480 − #breaks`. - **node throughput**: search-nodes per second, one node per attempted placement. Reported per variant and **never compared across families**, because a node that runs full arc-consistency is not the same unit of work as a naive placement. Heavy propagation trades throughput for node quality, and the study measures both axes rather than collapsing them into one. The slowest variants carry a caveat worth stating plainly: the MRV engine picks the most-constrained cell by scanning every empty cell's candidate list at each node, which is inherently heavier than a fixed fill order. Two behaviour-preserving optimisations bring it within a few times of the fast engines rather than the thousands it once was: the most-constrained search stops counting a cell's candidates the moment they exceed the best cell found so far (a minimum search never needs the exact count of a cell that cannot win), and it skips re-checking the edges the candidate list is already indexed on. What it still does not do is maintain each cell's candidate count fully incrementally across placements, which a production CSP solver would; that last step would need to track how a newly-used piece affects every cell's count, and it is left out here to keep the engine legible. The ranking by score does not depend on any of this, since throughput is a separate axis, but the MRV node rate should be read as this clean engine's rather than as MRV's best possible. - **max depth reached**: the deepest placement the search made, out of 256, the study's measure of how far a variant got. Strict backtracking hits a wall in the low 200s (row-major 208, the fastest strict variant 216); breaks push well past it, to 243 to 245. - **depth at timeout**: where the search frontier stood when the clock struck, so a variant that never completes still records where it was working. - **number of breaks**: the interior edges the search actually *broke* on the best board. This is zero for a strict variant, and for a break variant it is the count its own budget accounting committed rather than the score deficit. On a completed board it equals `480 − score`; on a timed-out partial the deficit also counts still-empty edges, so the study reports the true break count instead. Every board's bucas URL makes both checkable in the [viewer](/viewer). - **backtracks**: retreats out of a cell after its candidates are exhausted. ## The two baselines, and what specialisation costs The rawest variant, `NAIVE-CLEAN`, is a readable general engine: sentinel-free per-cell candidate lists indexed by the two already-placed neighbours, a resolved edge cache so no rotation is recomputed on the hot path, and no allocation inside the search. Its twin, `NAIVE-CODEGEN`, is the *same algorithm* re-expressed as a hand-specialised, 16×16-only, row-major hot loop, kept as a separate program so the general engine stays clean. Running them head to head prices the low-level engineering: on this puzzle it buys a modest, instance-dependent throughput gain and, notably, no better score. The numbers are on the [findings page](/research/lab/experiments/raphael-anjou/dfs-study/findings). ## Soundness of the propagators Forward-checking, arc-consistency and the per-colour supply check are sound *by construction*. Each only ever rejects a state in which some cell already has an empty domain, a cell that no unused piece can fill, so none of them can remove a branch that leads to a real completion. The arc-consistency revise is deliberately conservative where it is imprecise: wherever it might be unsure it prunes *less* rather than more, staying on the safe side. The propagators are sound only under strict placement, because under a break budget a local look-ahead can prune a branch the global budget could still rescue, so the break variants deliberately run no propagator. The registry enforces this: a variant that pairs breaks with a strict-only propagator fails to build. The engine tests check that constraint and the score and break bookkeeping, though the soundness of the prune itself rests on the argument above rather than on a test. ## Reproducibility The engine workspace, the ten variants, the committed per-run results and the grid scripts all live under the study's [backing directory](https://github.com/raphael-anjou/eternity2/tree/main/research/experiments/dfs-study). `just experiments dfs-study` rebuilds the engine and reruns the whole grid; the run is deterministic at a fixed seed, and the corner arrangement is the only diversity axis. ## Related - [The DFS study](https://eternity2.dev/research/lab/experiments/raphael-anjou/dfs-study) — One question, asked carefully: among depth-first backtrackers for Eternity II, what does each fill order, each heuristic, and the break mechanism actually buy? A family of from-scratch backtrackers, each one change apart, run on the same ten corner-pinned variants, single core, sixty seconds. - [What each idea buys](https://eternity2.dev/research/lab/experiments/raphael-anjou/dfs-study/findings) — The three comparisons at the heart of the DFS study, worked through: fill order (row-major wins, a bad order is catastrophic), heuristics (MRV rescues border-first but costs throughput; more propagation did not help), and breaks (they smash the depth wall; the break schedule is the lever, not the per-cell cap). - [Fill orders](https://eternity2.dev/research/build/backtracking/fill-order) — The order in which a backtracker visits the 256 cells is its one free choice: it costs nothing at runtime and moves the size of the search tree by orders of magnitude. Twenty years of community science, from the fixed-vs-dynamic wars and the strategy races to the magic 10×16 square and Verhaard's comb search, all answer the same question: which path through the board is cheapest? --- # The reference engine behind this site > The Rust-to-WebAssembly backtracker that runs every live demo and checks every number on this wiki. Not a record machine but a reference engine, ported four times and parity-tested byte-for-byte, built so the claims here can be re-run. - Canonical page (with interactive figures/demos): https://eternity2.dev/research/lab/experiments/raphael-anjou/engine/ - Updated: 2026-07-17 - Topics: backtracking, speed - Source: The eternity2 repository on GitHub — https://github.com/raphael-anjou/eternity2 --- > **Whose work this is** > > This page is about the engine behind the site you are reading, written by the person who wrote it, [Raphaël Anjou](/research/people/raphael-anjou). It is not a community record solver: those are studied elsewhere in this lab ([Blackwood](/research/lab/experiments/joshua-blackwood/solver), [McGavin](/research/lab/experiments/peter-mcgavin/backtracker), [Verhaard](/research/lab/experiments/louis-verhaard/eii)). This one sits among them as a peer, and a modest one: the record solvers hold the records; this one holds the receipts. Where the [named experiments](/research/lab/experiments/raphael-anjou) each ask a question and the [shared engines](/research/lab/experiments/raphael-anjou/engines) are the apparatus those studies run on, this page is a third thing: the small reference engine that powers the site itself, checks the numbers the other pages quote, and animates every live demo. It scores no records. Its job is verifiability and teaching. ## What it is A small Rust crate compiled to WebAssembly, running live in your browser on every interactive page of this wiki. It implements the classics, plainly: the official 16×16 piece set, a generator that builds solvable puzzles of any size (with an optional real-E2-style mode that restricts border colours to the frame band), nine cell-visit orders, a strict depth-first backtracker, a scorer, and a break-tolerant variant of the search, a reimplementation of the break-index idea from [Blackwood's solver](/research/lab/experiments/joshua-blackwood/solver), built so the labs here can demonstrate it. One design choice matters more than the algorithms: the solver is a step-able machine, not a recursive function. Callers run it one bounded step at a time, one placement or one backtrack, and read the board between steps. That is what lets a web page animate a real search instead of a canned recording: [the watch page](/playground/watch) is stepping this exact engine, not a video of it. ## One engine, many ports The site runs one engine: the Rust/WASM crate, the canonical reference. But the repository keeps a whole collection of faithful reimplementations of it in other languages: a pure TypeScript port (zero WASM), a C port, a C++ port, and smaller studies in Python, Lua, COBOL, even Brainfuck. Each is validated byte-for-byte against golden data the Rust crate emits: generated puzzles down to the RNG output, all nine fill paths at several sizes, and full solver runs with exact node, attempt, and backtrack counts. That discipline exists for one reason: an interactive demo you cannot cross-check is just an animation. Two independent implementations that agree to the last backtrack are much harder to get wrong the same way twice, and eight are harder still. The ports are a study exhibit, not build options (the site always runs Rust), and they live together in the repo's `engine-ports/` collection. Some of them (the Brainfuck backtracker especially) are there for joy. ## What it does not claim This is not a record machine, and it would be misleading to dress it as one. The strict solver carries none of the hand-tuned quota schedules or restart strategies that make [Blackwood's solver](/research/lab/experiments/joshua-blackwood/solver) the engine behind the community's best boards. The best score produced by [the experiments here](/research/lab/experiments) is 463 of 480; the community's best on the same puzzle is 470. The record solvers studied in this lab are simply better at finding boards. Throughput is a separate axis, and one this reference engine deliberately does not chase - but a sibling experiment does. The [JIT backtracker](/research/lab/experiments/raphael-anjou/jit-backtracker) asks how fast a *portable* Rust search can go, and reaches [McGavin-class throughput](/research/lab/experiments/peter-mcgavin/backtracker) on the hard, deep boards that resemble the real puzzle - a tie with his hand-tuned C on the same machine (his C stays ~2.3× faster on easy boards). That is a speed result, not a solving one: it still plateaus where every strict backtracker does. Speed and score are [different axes](/research/lab/experiments/raphael-anjou/going-fast), and this page's engine optimises for neither - only for being checkable. This engine's job is different: verifiability and teaching. When this wiki states a node count, a feasibility number, or a score, the claim is checked by this engine, and because it runs in your browser and its source is public, you can check it too. ## How it powers the wiki Every interactive element in this research section is this engine: the live DFS demos, the fill-order races on [the paths page](/playground/paths), the break-index lab on [the solver hub](/research/build/solvers), the board viewer's scoring and verification, and the committed reference counts that research pages quote. The engine's own test suite cross-checks against real community boards, so a change that broke scoring or rotation conventions would fail loudly rather than silently corrupting the site's numbers. ## Where to get it Everything is in one repository, [github.com/raphael-anjou/eternity2](https://github.com/raphael-anjou/eternity2), and [run it yourself](/research/build/run-it-yourself) walks through building the engine, running its tests, and reproducing the published results command by command. ## What drives it The engine does not grow on its own schedule; it grows when [an experiment](/research/lab/experiments) needs something. The break-tolerant solver exists because demonstrating break indices required one; the frame-restricted generator exists because a lab needed puzzles that behave like the real E2 border. That keeps the engine small, and it keeps every feature attached to a question someone actually asked. ## Related - [The engines](https://eternity2.dev/research/lab/experiments/raphael-anjou/engines) — The shared engines under Raphaël Anjou's experiments. The named experiments are studies that run on these; this is the apparatus they share. The CSP presets and the Verhaard reimplementation are documented here; the constructive engines are not yet published. - [Run it yourself](https://eternity2.dev/research/build/run-it-yourself) — The whole site, the engine, and every result in this section run from one repository. Here is how to get it going, rebuild the WebAssembly engine, and reproduce the numbers. - [Blackwood's solver, decoded and run here](https://eternity2.dev/research/lab/experiments/joshua-blackwood/solver) — Joshua Blackwood's record backtracker, decoded through Jef Bucas's notes (a colour quota schedule and a late-game mismatch allowance, tuned near-optimally), then built and run on my M1: left as published it flies to 248 of 256 pieces ignoring the clues; pin the five official clues and the same engine stalls near 45. --- # The engines > The shared engines under Raphaël Anjou's experiments. The named experiments are studies that run on these; this is the apparatus they share. The CSP presets and the Verhaard reimplementation are documented here; the constructive engines are not yet published. - Canonical page (with interactive figures/demos): https://eternity2.dev/research/lab/experiments/raphael-anjou/engines/ - Updated: 2026-07-15 --- The [experiments](/research/lab/experiments/raphael-anjou) are studies: each one asks a question and reports the board it reached. But most of them are not built from nothing. They run on a small set of shared engines, and the same engine turns up under experiment after experiment. This page documents that apparatus once, so the studies can point here instead of re-explaining the machine each time.
- [The CSP presets, measured](/research/lab/experiments/single-core-benchmark/csp-presets) — A single constraint-propagation engine with interchangeable orderings and propagators: arc-consistency, colour-graph matching, several fill orders. Faithful reimplementations of known community techniques, run under a dozen presets on the ten variants so the exact cost of each knob is on the leaderboard rather than argued about. - [The Verhaard reimplementation](/research/lab/experiments/louis-verhaard/verhaard-reimpl) — A from-scratch reimplementation of Louis Verhaard's eii method, since his own binary ships no source and will not run here. Set-composition swap-annealing under the 2×2-tiling metric; on the real five-clue puzzle it reaches 438 of 480, single core.
The two constructive engines these studies also lean on, the beam producer and the ALNS polish stage, do not yet have their own write-ups here; those pages are held back for now, and neither is on the benchmark leaderboard. Where an experiment steers one of them, its own page says what that engine does at the level the study needs, so nothing below depends on reading a page that is not here yet. The two engines documented and measured in full are the CSP presets and the Verhaard reimplementation. ## Why document the engines apart from the experiments A study and its engine answer different questions. The engine answers *how the search works*, the data structures, the fill order, the propagators, and it is reused unchanged across many studies. The study answers *what happens when you point that engine at a particular idea*: a learned prior, a fixed border, a break mask. Keeping them apart means a reader who wants to understand PRIOR's prior does not have to re-read how a beam works, and a reader who wants the engine gets it in one place, current and complete. Where these engines race head to head under a fixed budget, they appear on the [single-core benchmark](/research/lab/experiments/single-core-benchmark). The general theory behind each method lives in the [build-a-solver](/research/build) section; these pages are the specific engines as built and measured here. --- # Going fast: when a solver spends its budget on speed > Some Eternity II engines pour their effort into walking the search tree as fast as possible; others spend it on judgement about where to walk. This is the case for the first kind - what raw throughput buys, the three different things people mean by "fast", and why the fastest engine ever built still cannot solve the puzzle. - Canonical page (with interactive figures/demos): https://eternity2.dev/research/lab/experiments/raphael-anjou/going-fast/ - Updated: 2026-07-20 - Topics: speed, backtracking - Source: McGavin: even at 100M nodes/s, the 5-hint tree is 4.9×10³² years (groups.io msg 11201) — https://groups.io/g/eternity2/message/11201 - Source: Razvan's epitaph for the 2025 speed thread: 'we will not make a dent' (groups.io msg 11657) — https://groups.io/g/eternity2/message/11657 --- Every Eternity II solver has a fixed budget of human effort and machine time, and it spends that budget in one of two places. It can spend it on **speed** - walking the search tree as fast as the hardware allows, trying billions of placements a second - or on **judgement** - being cleverer about *which* placements to try, so it walks a smaller, better tree. This page is the case for the first kind: what going fast actually buys, what it doesn't, and how to talk about it without fooling yourself. It is also the conceptual home of a specific result: a [portable Rust backtracker that ties McGavin's hand-tuned C on hard boards](/research/lab/experiments/raphael-anjou/jit-backtracker) - the fastest engine in the community's history - and runs at about 44% of its speed on easy ones. That page is the engineering diary; this one is what the diary *means*. ## Three things people mean by "fast" The single biggest source of confusion in twenty years of speed talk is that "fast" names three unrelated quantities. Keeping them apart is most of the battle. > **The three axes, and why they don't convert** > > **1 · Placements per second (a.k.a. pieces/s, nodes/s).** How fast the search *walks*. This is an engine-*and-board* number: McGavin's C does ~287 M on an easy board but ~105 M on a hard one; the [JIT engine here](/research/lab/experiments/raphael-anjou/jit-backtracker) does ~122 M on the easy board and ~110 M on the hard one - tying the C exactly where the puzzle is hard. Bigger is faster, but only ever *on the same board*. **2 · Matched edges out of 480.** How *good* a board is. This is where [records](/research/records) live - the ceiling is 470. It has nothing to do with axis 1: a slow engine can find a better board than a fast one, and routinely does. **3 · Aggregate placements per second.** A *fleet* number - many machines summed. The community's "~300 M/s" figure that sometimes gets attached to a single engine is actually the [Eternity 2 Syndicate swarm](/research/build/faster/distributed-solving): ~20 machines added together, not one core. A high number on axis 1 tells you nothing about axis 2, and axis 3 is not an engine speed at all. Every speed claim worth trusting says which axis it is on. For the precise, sourced history of how the community settled its definition of a "node" - pieces *placed*, chess-style, and why even that flatters scan-line fill orders - see the measurement-discipline section of the [solver-engineering ledger](/research/build/faster/solver-engineering). This page takes that vocabulary as given and asks what the speed is for. ## What speed buys Real things, and it is worth being concrete, because the case *against* speed only lands once you respect the case *for* it. - **Verified enumeration.** A fast, deterministic engine can walk a benchmark tree to the last node and *count* it, turning theory into checked fact. The community's [benchmarks](/research/build/benchmarks) - census protocols, the 10×10 that finally fell after ~180 core-years - are throughput victories. You cannot verify what you cannot finish. - **Determinism as a checksum.** Two fast engines that walk the same tree must report the same node count. That equality is how ports, rewrites and new hardware prove they search the same tree before their speed means anything - it is the backbone of the [JIT engine's optimization ladder](/research/lab/experiments/raphael-anjou/jit-backtracker), where every rung halts at the identical node count. - **More attempts per second under a heuristic.** Speed is a multiplier on judgement: a good repair loop that runs twice as fast gets twice as many shots at a better board in the same wall-clock. Speed does not *replace* judgement, but it amplifies whatever judgement you already have. ## What speed cannot buy The wall. And no engine-builder has been clearer about this than the person who built the fastest engine. On his best five-hint placement path - already a far smaller tree than the raw puzzle - McGavin worked out that even at 100 million nodes per second the search would take about **4.9 × 10³² years**, and that throwing billions of cores at it still leaves you "orders of magnitude longer than the age of the Universe" ([msg 11201](https://groups.io/g/eternity2/message/11201)). When the community's 2025 speed thread wound down, Razvan wrote its epitaph: however fast we can check, "we will not make a dent" in the space ([msg 11657](https://groups.io/g/eternity2/message/11657)). The arithmetic is unforgiving and it is the site's [core lesson](/research/why/prune-vs-speed): a constant-factor speed-up, however hard-won, is *multiplied against* a number so large that no constant factor matters. Doubling the walking speed of a search that would take 10³² years gives you a search that takes 5 × 10³¹ years. Shrinking the *tree* is the only lever with exponents on it. ## The controlled experiment This is exactly why the [JIT backtracker result](/research/lab/experiments/raphael-anjou/jit-backtracker) is framed as a speed experiment and nothing more. It answers a clean, bounded question - *can portable, safe Rust reach hand-tuned-C throughput?* - and the answer is board-dependent: on hard, deep boards like the real puzzle it **ties** the C, walking the identical tree; on easy low-branching boards the C is about 2.3× faster. It settles a smaller open question the community had left standing: whether the famous ~4× edge of McGavin's engine over "typical" solvers was **codegen craft** or merely **newer hardware**. Holding the hardware fixed and reaching his speed *on hard boards* from portable code shows it was craft - the same craft, reproducible in a safe language, and written down rung by rung. (It also shows where the craft pays most: on easy boards, where per-node work is nearly free, his tighter codegen still wins.) And then it stops, plainly, at the same place every fast engine stops: pointed at the real puzzle it plateaus in the high-300s of 480, because a strict backtracker is a superb tree-walker and a poor solver. The records belong to engines that spend their budget the *other* way - on [destroy-and-repair judgement](/research/lab/experiments/raphael-anjou/repair-study) and [what a search is allowed to learn](/research/lab/experiments/raphael-anjou/learning) - and they get there at a small fraction of the speed. That is the whole trade. Speed is real, learnable, and worth mastering; the JIT engine is proof you can master it in a safe language. But on Eternity II, the fast lane and the winning lane are not the same lane. Which is why the interesting engineering question is never only "how fast" - it is "fast *at what*, and is that the thing in the way?" ## Related - [The JIT backtracker: portable Rust that ties hand-tuned C on hard boards](https://eternity2.dev/research/lab/experiments/raphael-anjou/jit-backtracker) — A safe, portable Rust depth-first backtracker, specialised at runtime by emitting and compiling per-puzzle Rust, taken from 43 to 123 million search-nodes per second on one core. Measured fairly against Peter McGavin's C on the same machine: a tie on hard, deep boards like the real Eternity II, and about 44% of its speed on easy ones. Every rung searches the identical tree; the whole gain is code, not algorithm. - [McGavin's C backtracker: the throughput story, built here](https://eternity2.dev/research/lab/experiments/peter-mcgavin/backtracker) — Peter McGavin's own C backtracker, the community's fastest: a 2007 optimization recipe compounded for two decades through generated code, lookup tables and counter tricks, then built on my M1 and pointed at the real 256-piece puzzle, where single core it drives past 200 of 256 pieces at ~109M placements/s. - [Solver engineering: the craft below the algorithm](https://eternity2.dev/research/build/faster/solver-engineering) — Every record solver runs the same depth-first backtracker. What separates them is the layer underneath: lookup tables, perfect hashes, cache-sized structs, generated code, compiler archaeology. That craft decides whether a node costs 26 cycles or 2,600. The community's twenty-year engineering ledger, technique by technique, and what it all bought. - [Why a faster computer doesn't help](https://eternity2.dev/research/why/prune-vs-speed) — The single most important idea in hard combinatorial search: shrinking the space you search beats searching it faster, by an exponential margin. Eternity II is engineered so you can barely shrink it at all. --- # The hint study > Give a backtracker five correct pieces for free, in the puzzle's own clue geometry. It turns out not to help, and depending on the fill order it can hurt badly, because a pinned piece is a hard constraint a fixed fill order must satisfy on arrival. A family of fill paths, run on the same hinted boards, single core, measured against no hints at all. - Canonical page (with interactive figures/demos): https://eternity2.dev/research/lab/experiments/raphael-anjou/hint-study/ - Updated: 2026-07-21 - Topics: backtracking, search-space, structure - Reproduce: `just experiments hint-study` - Source: Runnable generator + committed results + scripts (this study's backing directory) — https://github.com/raphael-anjou/eternity2/tree/main/research/experiments/hint-study --- There is a folk answer to how you make Eternity II easier: hand the solver some correct pieces. The natural next question is *how many*, and the community's own [hint-geometry discussion](/research/why/hint-geometry) already sharpened it to *where*. This study asks something more basic that both questions skip past: on our own generated boards, do the hints help *at all*? For a chronological backtracker, the answer is **no**. Seed one with the five official clue pieces at their real board positions, then measure it against the very same board with no hints, and it does worse on every fill order tested, without exception. On a compact row-major sweep the five correct pieces cost only ten to twenty matched edges; on the fill order a newcomer would reach for first, "get to the clues and connect them up", they cost around three hundred and forty-five, turning one of the best no-hint orders into the worst. The reason is simple once seen: to a solver that fills cells in a fixed order, a pinned piece is not free information but a **hard constraint it must satisfy the moment it arrives**, and sometimes it cannot. ## See it: five hints, four orders Each board below fills along a different order, on a loop. Nothing is being *solved*; this is only the order the search would visit cells, made visible. The bright cell is the one just placed, and the trail behind it is the recent **wavefront**, so you can see how much boundary each order keeps open as it runs. That open boundary, the frontier, is what a backtracker pays for: its branching grows with the frontier, and a small frontier is also what leaves the search room to route around a hostile pin. > **[Interactive: HintPathFill]** Rendered on the canonical page (link above); not shown in this markdown export. A row-major sweep keeps one thin frontier and rolls it down the board, so when it meets a pinned piece it can adjust the single row it is building. The hint-seeking orders do the opposite. Spiralling in or out drags a whole ring as its frontier, and tracing the hints scatters its wavefront across the board from the very first move, committing everywhere before it can know whether the commitments are consistent. The compact sweep survives the five hints; the hint-seeking orders are undone by them. ## What the study measures Two paired comparisons, run on the same generated boards: - **Do the hints help, and which order survives them?** Fix the hints (five, in the shape of Eternity II's own five clues) and vary only the fill order, measured against the identical board with no hints. This is the study's spine: it shows the hints never help, and that how much they hurt is set by the fill order and its open frontier. - **Count.** Does adding *more* hints help? Some, but the naive way of measuring it is *confounded*. A block of clustered hints banks a pile of correct edges for free just by being pinned; that free "floor" flatters clustered layouts on raw score while saying nothing about whether the board got easier to *finish*. The [method page](/research/lab/experiments/raphael-anjou/hint-study/method) defines the floor and the floor-immune metrics (solved-rate and earned score) that see past it. Everything here is built and measured from scratch: our own parametric board generator, our own family of backtrackers, our own canonical scorer, and a beam solver as a non-backtracker contrast. No community board, puzzle, or engine is used; only the *shape* of the five-clue arrangement is borrowed from the list discussion, as a geometry to test. ## How to read the numbers Every board is re-scored by one canonical matched-edge scorer that never counts a border-facing (grey) seam, the same convention as the [benchmark](/research/lab/experiments/single-core-benchmark) and the [DFS study](/research/lab/experiments/raphael-anjou/dfs-study). The maximum is 480. Each of the fifteen seeds is a genuinely distinct generated instance, not merely a different solver seed, so the spread across seeds is real instance-to-instance variance and is reported as such. No self-reported score is trusted. The comparisons are worked through on the [findings page](/research/lab/experiments/raphael-anjou/hint-study/findings); how the boards are generated, why the colour recipe stays faithful across sizes, and what every metric means are on the [method page](/research/lab/experiments/raphael-anjou/hint-study/method). ## Pages in this section - [How the study is built](https://eternity2.dev/research/lab/experiments/raphael-anjou/hint-study/method) — The apparatus behind the hint study: a parametric board generator faithful to Eternity II's colour recipe at every size, the family of fill-path backtrackers, the one canonical scorer, and the piece of arithmetic that keeps the count axis meaningful, the pinned-seam floor. - [What the study found](https://eternity2.dev/research/lab/experiments/raphael-anjou/hint-study/findings) — The results, worked through: on these boards the five clue-shaped hints never help a backtracker, they range from a mild cost to a catastrophe, and the fill order decides how much damage they do; the scores are bimodal, not a smooth gradient; and the hint-count question is confounded by a free pinned-seam floor. ## Related - [Raphaël Anjou's experiments](https://eternity2.dev/research/lab/experiments/raphael-anjou) — A notebook of Eternity II search experiments, organised into the shared engines they run on, the combination pipelines that chase the score, three studies that take one search paradigm apart a decision at a time, and exact endgame solves. Each has its idea, its best board, and the questions it left open. The best reaches 463 of 480. - [The DFS study](https://eternity2.dev/research/lab/experiments/raphael-anjou/dfs-study) — One question, asked carefully: among depth-first backtrackers for Eternity II, what does each fill order, each heuristic, and the break mechanism actually buy? A family of from-scratch backtrackers, each one change apart, run on the same ten corner-pinned variants, single core, sixty seconds. - [Where you place the hints beats how many](https://eternity2.dev/research/why/hint-geometry) — On a 16×16 puzzle built like Eternity II, eighteen hints scattered across the board solve it in minutes, while the same puzzle needs eighty or more hints piled into contiguous rows to be as easy. Position, not count, is the lever, and it points straight at the endgame. --- # What the study found > The results, worked through: on these boards the five clue-shaped hints never help a backtracker, they range from a mild cost to a catastrophe, and the fill order decides how much damage they do; the scores are bimodal, not a smooth gradient; and the hint-count question is confounded by a free pinned-seam floor. - Canonical page (with interactive figures/demos): https://eternity2.dev/research/lab/experiments/raphael-anjou/hint-study/findings/ - Updated: 2026-07-21 - Topics: backtracking, structure, search-space - Source: Committed per-run results (results.jsonl) and the analysis script — https://github.com/raphael-anjou/eternity2/tree/main/research/experiments/hint-study --- The study fixes five hints in the shape of Eternity II's own five clues, runs eight fill orders on the identical boards, and asks a simple question: what are those five hints worth? Every number below is over fifteen distinct generated instances, single core, eight seconds a run, re-scored out of 480 by one canonical scorer. The comparison is paired, every fill order sees the same boards, and the per-instance spread is shown rather than averaged away, because it turns out to matter more than any median. ## The hints don't help, and the fill order decides how much they hurt Start with the distribution. Each dot is one board; the tick is the median. > **[Interactive: HintStudyCharts]** Rendered on the canonical page (link above); not shown in this markdown export. Two things are visible at once. First, the scores are **bimodal**: on most orders a board either climbs into the 360s or stalls in the double digits, with little in between. A median drawn through that is a summary of a gap, not a centre, which is exactly why the dots are shown. Second, the orders split hard: the three compact sweeps (row-major, its bottom-up mirror, Verhaard's comb) sit high on most boards; the fragmenting orders sit low throughout. But the compact-beats-fragmenting split is not the real finding, because it invites the wrong question, "which order best *uses* the hints?" The question that matters is whether the hints help *at all*. The second chart answers it, and the answer is no. It shows the **paired change** from adding the five hints: each order's score on a board minus its score on the *same board with no hints*. Every bar is at or below zero. The five clue-shaped hints do not help a single fill order. On the compact sweeps they cost only ten to twenty points. On spiral-out they cost about ninety. And on the two hint-seeking orders they are ruinous: the `trace-hints` order, which draws a skeleton between the clues before filling, loses about three hundred and twenty-five, and the `connect-hints-first` flood loses roughly **three hundred and forty-five**, taking an order that scores among the *best* of all eight with no hints to the *worst* with them. The more deliberately an order chases the hints, the more they cost it. Handing the solver five correct pieces, in the puzzle's own clue geometry, made every version of it worse. ## Why a correct hint hurts A pinned piece is not free information to a chronological backtracker; it is a **hard constraint the fixed fill order must satisfy on arrival**. When a compact sweep rolls down to a pinned interior cell, the piece is already there, and the row it just built has to match that piece's edges. Most of the time it can, at a small cost: the sweep steers around the constraint and loses a few tens of points. But on some boards the pinned piece contradicts what the frontier has committed to, and there is no local repair: the search hits a wall it cannot pass and thrashes below it. That is the stalled mode, and it is the hints that create it. On row-major, the boards that collapse into the double digits are precisely the ones where a clue-shape pin lands where the sweep cannot honour it; the same board with no pins climbs into the 360s and 370s. This reframes the fill-order result. The order still matters (a compact sweep survives the hint constraints with a scar of ten to twenty points while `connect-hints-first` is destroyed by them), but what the order is buying is not "using the hints well." It is **surviving them**. The frontier is why: an order that keeps a single tight frontier has room to route around a bad pin; an order that has already fragmented into five open blobs has committed everywhere at once and cannot. That frontier relationship, across the eight orders, is strikingly clean, and it is worth showing precisely because the frontier can be computed from an order's geometry with no solver at all, then checked against the measured scores: > **[Interactive: FrontierPhaseChart]** Rendered on the canonical page (link above); not shown in this markdown export. The average open frontier an order holds predicts its median score closely across these eight orders. It is a strong descriptive relationship, not a law proved on eight points, and it stops settling the ranking among the fragmenting orders on the right (spiral-in holds a larger frontier than spiral-out yet scores higher). But the direction is exactly what the mechanism predicts: branching cost is multiplicative in the frontier, so an order that keeps the frontier small keeps the room to absorb a hostile pin. For contrast, the beam solver, which is not a chronological backtracker and does not pay the frontier cost the same way, reaches a median in the 450s on these same hinted boards. The hints and boards are nowhere near unsolvable. It is specifically the *chronological, fixed-order* backtracker that cannot turn five correct pieces into progress. ## Count: a threshold, not a gradient, and a floor that hides it The same question one level out: does adding *more* hints help? The answer is not a smooth "more is better", and the raw number hides which part is real. The lower chart above splits each layout's score into two parts. The **floor** is the seams the pins complete for free, because both their endpoints are pinned to the true solution; the **earned** part is what the search actually found. A solid clustered block banks a tall floor (five 4×4 blocks pin a quarter of the whole board's seams before the search takes a single step), while a spread lattice, whose hints never touch, banks nothing. So a raw-score comparison hands clustered layouts a hundred-point head start that says nothing about whether the search made headway. Read the earned column across the spread lattices, whose floor is zero so earned *is* the score, and a threshold appears. A sparse spread, four to sixteen hints, earns almost nothing (in the twenties): the pins are just scattered constraints the sweep keeps tripping over, exactly the five-clue effect. But keep adding them and the picture flips. Twenty-five spread hints earn 127, and thirty-six, a six-per-line lattice, **solve the board outright on most instances**. Below the threshold the spread hints only get in the way; above it there are finally enough of them to carve the board into pieces small enough for the sweep to finish. It is not a gradient of help, but a wall the count has to clear. The clustered blocks show the mirror image. Their raw score is mostly *floor*: five 4×4 blocks (eighty hints, a quarter of the board) do solve every instance, but they have pinned so much of the board that they have half-solved it by hand. Strip the floor away and the clustered layouts short of that extreme earn only double digits, coasting on the free seams. So the real count story is not "more hints help" or "more hints hurt", but: it takes a *lot* of correct hints, spread or clustered, to move a chronological backtracker at all, and until you reach that amount the extra pins are as likely to trip the search as to speed it. The [method page](/research/lab/experiments/raphael-anjou/hint-study/method) works the floor arithmetic through in full. ## Scattered versus contiguous: we get the opposite The community's [hint-geometry write-up](/research/why/hint-geometry) makes a sharper version of the placement claim: eighteen hints *scattered* on a lattice solve a 16×16 E2-like puzzle in minutes, while eighteen piled into *contiguous* top rows barely help, and you need eighty or more contiguous hints to match the scattered eighteen. That result was measured on one specific puzzle with one specific engine. We put its two exact layouts, the scattered rows-{1,3,5} lattice and the eighteen-cell top block, on our own generated boards and solvers to see whether the direction holds. > **[Interactive: HintGeoComparison]** Rendered on the canonical page (link above); not shown in this markdown export. It does not. On our boards the **contiguous** eighteen score *higher* than the scattered eighteen for seven of the eight fill orders, and by a wide margin: a row-major sweep reaches a median of 377 with the contiguous block and only 138 with the scattered lattice. This looks like a flat contradiction, and it is worth being precise about why it is not quite one. The two studies measure different things. The community result is about *time to a full solution*: scattered hints reach into the deep endgame where a backtracker spends almost all of its time, so they prune the expensive part, while a contiguous top block prunes only the cheap opening. Our number is *matched-edge score at a short budget*, and at eight seconds none of these strict backtrackers reaches the endgame at all. What a top-anchored contiguous block does buy, immediately, is a large correct region for the row-major sweep to build against, so the score climbs fast even though the hard part of the board is untouched. Scattered hints, by contrast, fragment the early fill exactly the way the five-clue shape did. So the two results are consistent once you separate "solves the whole board eventually" from "scores well in the first eight seconds": scattered placement helps the former and hurts the latter. The next section makes that split visible. ## Solving it: where scattered finally wins At 16×16 nothing solves in eight seconds, so the score is always a snapshot of a search still in its opening. To see the *endgame* effect the community reported, we need a board that fully solves. An 8×8 built to the same colour recipe does, in well under a second, so on it we can measure the quantity that actually matters: the number of search nodes a row-major backtracker needs to reach a complete solution. Fewer nodes means the hints did real pruning work. Below, a spread lattice and a matched contiguous block, at rising hint counts. > **[Interactive: SolveSpeedChart]** Rendered on the canonical page (link above); not shown in this markdown export. This is the whole story in one chart, and it finally lines up with the community claim. At four hints the scattered lattice is *worse* than useless, solving only two of thirty boards, the same sparse-hints-trip-the-search effect from every other axis, while the matched contiguous block solves almost all of them. But cross a threshold around sixteen hints and the lines swap hard: a sixteen-hint scattered lattice solves in about four thousand nodes, while the matched contiguous block still grinds through nearly two million, a five-hundred-fold difference at the same hint count. Push further and both layouts become easy (by thirty-six hints a quarter of the board is pinned and either one solves in a few hundred nodes), so the scattered advantage is a window, widest where the count is enough to reach the deep search but not so large that the board is half-solved by hand. In that window, spread hints reach into the part of the search a backtracker actually struggles with and cut it off, exactly as Joe and Peter McGavin described; a contiguous block only ever prunes the easy opening. The 16×16 score comparison looked like it contradicted them only because at a short budget the search never lives long enough to reach the region where scattered placement pays off. ## What it does and does not say This is a result about **strict, chronological depth-first backtrackers** on generated 16×16 boards built to Eternity II's colour recipe, at a short (eight second) budget. Each of those scoping words earns its place. *Chronological*: the result is specifically about solvers that fill cells in a fixed order and must satisfy a pinned piece when they reach it, a beam solver, which does not, reaches the 450s on the same boards. *Generated*: the boards share E2's colour recipe and its five-clue *shape*, but they are not the official puzzle, and the study transfers no number to it. *Short budget*: none of these strict backtrackers solves within eight seconds, so this measures how far each reaches, not a race to 480; whether the "hints hurt" effect survives at much longer budgets is untested here. Within that scope the lesson is sturdy and, we think, counterintuitive: for a chronological backtracker, five correct pieces placed in the puzzle's own clue geometry are not a gift but a constraint, and can cost far more than they give. What decides the damage is not the hints but the fill order that has to live with them and the order pays for a hint the way it pays for everything else, in the size of the frontier it keeps open. It is one more reading of [why the puzzle resists](/research/why/hint-geometry): even correct information helps only a solver built to receive it. ## Related - [The hint study](https://eternity2.dev/research/lab/experiments/raphael-anjou/hint-study) — Give a backtracker five correct pieces for free, in the puzzle's own clue geometry. It turns out not to help, and depending on the fill order it can hurt badly, because a pinned piece is a hard constraint a fixed fill order must satisfy on arrival. A family of fill paths, run on the same hinted boards, single core, measured against no hints at all. - [How the study is built](https://eternity2.dev/research/lab/experiments/raphael-anjou/hint-study/method) — The apparatus behind the hint study: a parametric board generator faithful to Eternity II's colour recipe at every size, the family of fill-path backtrackers, the one canonical scorer, and the piece of arithmetic that keeps the count axis meaningful, the pinned-seam floor. - [Where you place the hints beats how many](https://eternity2.dev/research/why/hint-geometry) — On a 16×16 puzzle built like Eternity II, eighteen hints scattered across the board solve it in minutes, while the same puzzle needs eighty or more hints piled into contiguous rows to be as easy. Position, not count, is the lever, and it points straight at the endgame. - [The DFS study](https://eternity2.dev/research/lab/experiments/raphael-anjou/dfs-study) — One question, asked carefully: among depth-first backtrackers for Eternity II, what does each fill order, each heuristic, and the break mechanism actually buy? A family of from-scratch backtrackers, each one change apart, run on the same ten corner-pinned variants, single core, sixty seconds. --- # How the study is built > The apparatus behind the hint study: a parametric board generator faithful to Eternity II's colour recipe at every size, the family of fill-path backtrackers, the one canonical scorer, and the piece of arithmetic that keeps the count axis meaningful, the pinned-seam floor. - Canonical page (with interactive figures/demos): https://eternity2.dev/research/lab/experiments/raphael-anjou/hint-study/method/ - Updated: 2026-07-21 - Topics: backtracking, structure, search-space - Source: The parametric generator and the fill-path engine (this study's backing directory) — https://github.com/raphael-anjou/eternity2/tree/main/research/experiments/hint-study --- This page is the apparatus behind the [hint study](/research/lab/experiments/raphael-anjou/hint-study): how the boards are generated, why they stay faithful to Eternity II across sizes, the family of fill paths, and the piece that matters most for reading the results correctly, the arithmetic of the *pinned-seam floor*, which is what separates a real effect from a measurement artifact on the count axis. ## The boards: a faithful, size-parametric generator Every instance is generated from scratch, seeded, and deterministic: the same `(size, colours, seed)` produces the same board on any machine. A generated board is a *solved* board, piece $i$ sits at cell $i$ at rotation zero, whose piece IDs are then relabelled by a seeded permutation, so a hint for cell `pos` pins the (relabelled) true piece, and a solver cannot simply walk the identity placement. The colour recipe mirrors the official puzzle's structure exactly. On an $n\times n$ board there are $$ E(n) \;=\; 2\,n\,(n-1) $$ interior seams (the matched edges; $E(16) = 480$). These split into a **frame band**, the seams joining two border pieces along the rim, and the deep interior. The five *border colours* are confined to the frame band and never appear in the interior; the *interior colours* appear both in the deep interior and on the inward-facing edge of border pieces. This is the defining structural fact of a real Eternity II board, and the generator reproduces it and is tested against it. ### Why the census is automatically balanced (a claim to state carefully) It is tempting, and the earlier write-ups did this, to present Eternity II's *even* colour census as a specially tuned gift: every colour appears an even number of times, so a perfect solution's $\sum_c N_c / 2$ matches land with zero slack. The even parity is real, but it is **not** a tuning achievement. It is forced. A colour painted on $k$ interior seams appears on exactly $2k$ piece-edges, one on each side of every seam. So for every colour $c$, $$ N_c \;=\; 2\,k_c \quad\text{is even, for any seam colouring whatsoever.} $$ Zero-slack parity is therefore automatic for *any* board built by colouring seams; it says nothing special about Eternity II. The properties that are genuinely load-bearing, and that the generator must get right, are three: border colours confined to the frame band, the per-colour counts kept **balanced** (so no colour is rare enough to over-constrain), and every piece **distinct up to rotation** (so a pinned hint names a unique piece). The study's write-up is precise about this where the earlier framing was not. ### Scaling the recipe without changing the difficulty The generator and the solver are both size-parametric, the board can be $8\times8$ or $12\times12$ as readily as $16\times16$, which opens a natural follow-up: does the placement effect *strengthen* as the board grows? Answering that cleanly needs a colour recipe that does not change the puzzle's *difficulty* as the size changes. Simply keeping the colour *counts* fixed while growing $n$ would make the puzzle structurally *easier* at large $n$: with more seams and the same palette, each colour repeats more often, so the average cell accepts more neighbours and the constraint loosens. That would confound size with difficulty. Instead the recipe holds the **per-colour multiplicity** roughly constant. Writing $F(n)$ for the frame-band seam count and $E(n) - F(n)$ for the interior, the number of border and interior colours is chosen as $$ b(n) \;=\; \operatorname{round}\!\Big(\tfrac{F(n)}{12}\Big), \qquad i(n) \;=\; \operatorname{round}\!\Big(\tfrac{E(n) - F(n)}{24}\Big), $$ targeting the multiplicities Eternity II itself uses at $n=16$ (border $\approx 12$, interior $\approx 24$). At $n=16$ this returns exactly the official recipe, five border colours and seventeen interior. Getting this right on small boards took one fix to the generator. Eternity II's palette is *interior-dominant*, five border colours to seventeen interior, but the default generator caps the border count at five and takes everything else as interior, which on a small board inverts the ratio: at $8\times8$ the recipe wants eight colours, and the cap would split them five border to one interior, a near-uniform interior sea that behaves nothing like E2. The generator now accepts an explicit border-colour count, and the recipe holds the interior at roughly three times the border at every size ($8\times8 \to$ two border, six interior; $16\times16 \to$ five, seventeen, unchanged). With that, small boards are faithful *and* fully solvable, which is what the solve-speed comparison on the [findings page](/research/lab/experiments/raphael-anjou/hint-study/findings) relies on. The main path and count results on this page are all at $16\times16$; the $8\times8$ board is used only where a full solve is needed. ## The hint geometries Each layout is a pure function of the board size, so the same geometry can be drawn, measured, and scaled consistently. The gallery below renders them all from the one shared board primitive. > **[Interactive: HintLayoutGallery]** Rendered on the canonical page (link above); not shown in this markdown export. ## The pinned-seam floor: keeping the count axis meaningful Here is the subtlety that reshaped the study. Ask "do more hints help?" and the obvious move is to compare final scores at different hint counts. But a hint does two different things at once, and score conflates them: 1. it **removes a piece** from the search (the useful part, it prunes the tree); 2. it **may complete a seam for free**, if a neighbouring cell is also pinned. The second effect is a pure bookkeeping gift. Define the **pinned-seam floor** of a layout as the number of interior seams with *both* endpoints pinned: $$ \text{floor} \;=\; \#\{\, \text{interior seams } (u,v) : u \text{ and } v \text{ both hinted} \,\}. $$ Because the pins are true-solution pieces, every such seam is guaranteed correct before the solver runs. A solid $k\times k$ clustered block contributes $2k(k-1)$ of them; five $k{=}4$ blocks bank $5 \cdot 24 = 120$ correct seams, a **quarter of the whole 480**, for free. A spread lattice, whose hints never touch, has a floor of **zero**. So a raw-score comparison systematically **flatters clustered layouts**: they start a hundred-plus points ahead on bookkeeping alone, regardless of whether the board became any easier to *finish*. This is the same family of error as counting rim seams in a partial board, a floor that inflates the number without reflecting progress. The toggle in the gallery above draws these banked seams so the free score is visible. The study therefore does not rank layouts by raw score on the count axis. It uses two floor-immune metrics: - **solved-rate**, the fraction of instances a path actually completes to 480; - **reached depth**, how far past the pinned cells the search got, out of 256. Both measure whether the search made *progress the pins did not hand it*. On the path axis, where every compared layout shares the *same* hints and hence the same floor, raw score is directly comparable and is used. ## Measuring against no hints, paired per instance The question "what are the hints worth?" only has an answer relative to *not* having them. So the path axis is run twice on every board: once with the five clue-shape hints, once with none (`baseline_00`), and the reported effect is the **paired difference**, the hinted score minus the no-hint score on the *same* generated board. Pairing per instance removes the board-to-board difficulty variance, which on these bimodal boards is large enough to swamp the effect if the two conditions were compared across different seeds. A negative paired difference means the hints made that fill order worse than it was with a blank interior, which is what the findings report. All comparisons use the common set of seeds that ran to completion, so every path and layout is aggregated over the identical instances. ## The fill paths, and why the frontier is the lever The engine is the study's sibling [DFS backtracker](/research/lab/experiments/raphael-anjou/dfs-study), run strict (no breaks, no propagation) so that the **fill order is the only thing changing**. The orders tested are row-major, its bottom-up mirror, spiral-in, spiral-out, border-first, Verhaard's comb, a clue-rows-first control, and the study's own hint-seeking order, `connect-hints-first`. Why does the order matter so much? A backtracker's cost is governed by the **open frontier**: the set of already-filled cells still adjacent to an empty one. When the next cell is placed against a frontier of size $f$, the number of partial boards the search may have to consider grows multiplicatively in $f$, branching is exponential in the frontier, not in the board. A single compact sweep keeps $f$ to about one row ($\approx n$); an order that opens blobs around $k$ scattered hints runs $k$ frontiers at once, and $$ \text{work} \;\sim\; \prod_{j} b^{\,f_j} \;=\; b^{\sum_j f_j}, $$ so fragmenting the fill into disconnected regions multiplies, not adds, the cost. This is exactly why `connect-hints-first`, the order that *seeks* the hints, is the worst performer: reaching the hints early is worth far less than keeping the frontier small, and connecting scattered anchors does the opposite of keeping it small. ## How to read the numbers Every board is re-scored by one canonical matched-edge scorer that never counts a border-facing (grey) seam. The maximum is $E(n)$ ($480$ at $16\times16$). Each of the fifteen seeds is a distinct generated instance, so across-seed spread is genuine instance variance. Throughput, where reported, is search-nodes per second and is never compared across different path orders, since a node under one order is not the same unit of work as under another. The whole apparatus, generator, layouts, per-run results, and the grid script, lives in the study's [backing directory](https://github.com/raphael-anjou/eternity2/tree/main/research/experiments/hint-study), and `just experiments hint-study` reruns it. ## Related - [The hint study](https://eternity2.dev/research/lab/experiments/raphael-anjou/hint-study) — Give a backtracker five correct pieces for free, in the puzzle's own clue geometry. It turns out not to help, and depending on the fill order it can hurt badly, because a pinned piece is a hard constraint a fixed fill order must satisfy on arrival. A family of fill paths, run on the same hinted boards, single core, measured against no hints at all. - [What the study found](https://eternity2.dev/research/lab/experiments/raphael-anjou/hint-study/findings) — The results, worked through: on these boards the five clue-shaped hints never help a backtracker, they range from a mild cost to a catastrophe, and the fill order decides how much damage they do; the scores are bimodal, not a smooth gradient; and the hint-count question is confounded by a free pinned-seam floor. - [Where you place the hints beats how many](https://eternity2.dev/research/why/hint-geometry) — On a 16×16 puzzle built like Eternity II, eighteen hints scattered across the board solve it in minutes, while the same puzzle needs eighty or more hints piled into contiguous rows to be as easy. Position, not count, is the lever, and it points straight at the endgame. --- # The JIT backtracker: portable Rust that ties hand-tuned C on hard boards > A safe, portable Rust depth-first backtracker, specialised at runtime by emitting and compiling per-puzzle Rust, taken from 43 to 123 million search-nodes per second on one core. Measured fairly against Peter McGavin's C on the same machine: a tie on hard, deep boards like the real Eternity II, and about 44% of its speed on easy ones. Every rung searches the identical tree; the whole gain is code, not algorithm. - Canonical page (with interactive figures/demos): https://eternity2.dev/research/lab/experiments/raphael-anjou/jit-backtracker/ - Updated: 2026-07-20 - Topics: speed, backtracking - Reproduce: `cargo run --release -p dfs-codegen --bin run_dfs_codegen_jit -- --puzzle P.json --chain2 --opt native` - Source: Peter McGavin's genbody71.zip — the C reference this engine chases (groups.io msg 11749) — https://groups.io/g/eternity2/message/11749 - Source: rust-lang/rust#80630 — LLVM cannot lower loop+match to a computed goto (why the function-chain design exists) — https://github.com/rust-lang/rust/issues/80630 - Source: The eternity2 repository on GitHub — https://github.com/raphael-anjou/eternity2 --- > **What this experiment is, and is not** > > This is a **speed** experiment, not a solving one. It asks a single question: can a *safe, portable* Rust backtracker reach the throughput of the community's fastest engine - [Peter McGavin's hand-tuned C](/research/lab/experiments/peter-mcgavin/backtracker) - without leaving Rust or dropping to hand assembly? The answer turns out to depend on the board: on **hard, deep boards like the real Eternity II it ties his C**; on easy low-branching boards his C is about **2.3× faster**. It says nothing about *scores*: a fast walk of the tree and a high-scoring board are [different axes entirely](/research/lab/experiments/raphael-anjou/going-fast). The best this engine reaches on the real puzzle is in the high-300s of 480, exactly what a strict backtracker should reach - the record boards come from metaheuristics, not from walking faster. Every fast Eternity II engine is, underneath, the same depth-first backtracker: fill cells in a fixed order, try each piece that fits, recurse, back out on a dead end. [McGavin's page](/research/lab/experiments/peter-mcgavin/backtracker) tells the throughput story of the C engine that has held the community's single-core speed crown for years. This page is the other side of that story: how close *portable Rust* can get to it, and where the line really falls. The result is board-dependent, and that turns out to be the interesting part. Measured on my Apple M1, single core, both engines built headless with native codegen and run back to back: | Board | McGavin's C (headless) | This engine | Result | | --- | --- | --- | --- | | Easy (Joe's 18-hint 71.puz) | ~287 M/s | ~122 M/s | McGavin **~2.3×** | | **Hard (deep 16×16, like real E2)** | **~102–105 M/s** | **~104–111 M/s** | **~tie** | On the boards that actually resemble Eternity II - deep, densely constrained, where the search spends its time backtracking - a safe, portable Rust engine **matches hand-tuned C**. On easy, low-branching boards, where there is almost nothing to do per node, McGavin's straight-line generated C is more than twice as fast. Both numbers are real; the engineering below is what pulled Rust up to the tie on hard boards. Everything that follows is **code generation and data layout**, not a smarter search: every rung walks the *identical* tree and, on a solvable test board, halts at the *identical node count*. That invariant is the backbone of the whole experiment, so it is worth stating first. > **Measure the reference at full speed, or you will fool yourself** > > An earlier version of this work reported that we *beat* McGavin outright. That was wrong, and the reason is instructive. McGavin's engine ships with a live terminal display (`#define INTERACTIVE`): a status readout it redraws constantly. That display costs it about **2.7× of its throughput** - his headless speed is ~287M on the easy board, but with the display on it reads ~106M. The first comparison pitted our headless engine against his *throttled* one and produced a phantom win. Rebuilt headless (`-mcpu=native`, display off), the true picture is the table above: he wins the easy board comfortably, and we tie on hard ones. The lesson is general - always build the reference the way it runs at full speed before trusting any ratio. ## The rule of the game: same tree, every rung A depth-first backtracker is deterministic. Given a board and a fixed fill order, it visits exactly one sequence of nodes, on any machine, in any language. So there is a hard test for whether an "optimization" is really just a speed-up and not a silent change to the search: **the node count must not move.** Throughout this work the oracle was a 60-hint solvable 16×16. Every version of the engine solves it to 480 and reports **251,815 nodes** - the same number, to the digit, from the slowest baseline to the fastest fused build. Any change that moved that number was a bug in disguise and was reverted. That single discipline is what lets the speed ladder below be read as an apples-to-apples comparison rather than a collection of differently-behaving programs. > **Correctness is a baseline invariant here, not a milestone** > > The engine checks all four edges of every placement against every already-fixed neighbour (placed piece or the frame rim), and it forbids a border/grey edge from facing into the interior. Those are not optimizations that were "added later" - they are the definition of a legal Eternity II placement, present in every version on this page. The ladder varies *only* how fast a fixed, correct search runs. ## The core idea: generate the program, don't interpret the puzzle A generic backtracker pays, at every single node, for questions whose answers never change during a run: *which cell am I on? where are its neighbours? which candidate pool do I read?* A table-driven loop looks those up from arrays, per node, forever. McGavin's C answers them **once, at build time**, by generating a program specialised to one puzzle: `genbody -DG` writes a second C file with one straight-line block per cell, neighbour addresses baked in as constants, and `goto` chains threading the blocks together. That specialisation is the source of its speed - same algorithm, run near the metal. This engine does the same thing in Rust, at runtime: 1. `emit_program(&instance)` writes a **self-contained, puzzle-specialised Rust program** - pieces, candidate buckets, pins and fill order all baked in as `const` data, no external crates. 2. The wrapper compiles it with `rustc -O` (about 0.15 s for the plain build, ~1.7 s for the fused one). 3. The generated binary runs the search and prints its result. It is McGavin's `genbody -DG → compile → run` flow, in Rust, invoked as a library. Nothing exotic - just moving the puzzle's fixed facts out of the hot loop and into the compiler's hands. Everything after this is squeezing constant factors out of the generated code, and each squeeze is a small, self-contained change best shown as a diff. ## The ladder, one change at a time The diffs below are **simplified for reading**: the real engine emits its inner loop as machine-generated Rust (constants like a cell's position and neighbours are baked per cell, and the source is a few hundred lines per puzzle). Each diff shows the idea of the change, not the literal generated text - run the engine with `--emit-src out.rs` to see the actual code for a given board. ### 1 · Pack each candidate into one word The first generated loop still chased a pointer: read a `u32` index, follow it into an `oriented[]` array for the piece's `(id, rotation, edges)`, *then* test whether the piece was already used. Three dependent loads to consider one candidate. ```diff - let idx = pool[i]; // load an index … - let (pid, rot, edges) = oriented[idx as usize]; // … chase it into a second array … - if !used[pid] { /* consider */ } // … then test usage + let cand = pool[i]; // one contiguous load: pid<<48 | rot<<40 | edges<<8 + let pid = (cand >> 48) as usize; + if free[pid] != 0 { let edges = (cand >> 8) as u32; /* consider */ } ``` Each candidate becomes a single packed `u64` stored directly in its `(up, left)` bucket. The hot loop does **one** load, extracts the piece id, and tests usage *before* unpacking the edges - McGavin's "check `tileFree` first" pattern. **+12 %**, and it set up the packed representation the rest of the work depends on. ### 2 · Store board cells as one `u32`, not four bytes The board stored each cell's four edges as `[u8; 4]`. Reading a neighbour's edge to match against meant four separate byte loads. McGavin keeps each placed tile's edges as **one `u32`** and pushes them to neighbours with shifts. ```diff - let cell: [[u8; 4]; N]; // four byte loads to read one neighbour - let up_edge = cell[up_pos][2]; // …and index arithmetic each time + let cell: [u32; N]; // one u32 per cell, URDL packed, empty = 0xFFFF_FFFF + let up_edge = (cell[up_pos] >> 8) as u8; // one load + one shift ``` This was the single biggest data-layout lever: **34 → 57 M nodes/s, +67 %**. Node count unchanged. Representing the hottest data structure well mattered more than any micro-optimization that came after it. ### 3 · Emit one function per cell - the pivot Here is the move that made "match McGavin" plausible. The remaining tax was the data-driven loop itself: `free_order[level]`, `cursor[level]`, `score_at[level]` - indexed array loads *every node* for values McGavin has as compile-time constants. The obvious way to bake them - one giant `loop { match level { …256 arms… } }` - does not work: `rustc` takes over a minute to compile one enormous function, and [LLVM cannot lower a `loop`/`match` to a computed goto](https://github.com/rust-lang/rust/issues/80630) anyway, so it would not even reproduce McGavin's `goto` structure. The way that *does* work is to emit **one small `#[inline(never)]` function per cell**: ```diff - // one generic loop, indexing arrays by depth on every node - loop { - let pos = free_order[level]; - let (up_pos, left_pos) = neigh[level]; - // …scan, place, advance level, or back out… - } + // one function per cell; its position and neighbours are baked constants + fn cell_37(st: &mut St, left_arg: u8) -> bool { + const POS: usize = 138; const UP: usize = 122; // this cell's facts, as constants + for cand in POOL_UL[/* up*COLORS+left */] { // its exact candidate pool + // place … + if cell_38(st, right_edge) { return true; } // advance = call the next cell + // unplace … + } + false // exhausted = plain return (backtrack) + } ``` Advancing is a call to the next cell's function; backtracking is a bare `return`. Roughly 256 *small* functions compile in about two seconds (a 200-function chain compiles in ~1 s; the one giant function took >60 s). This is McGavin's per-cell straight-line code, expressed as a chain of tiny functions Rust will actually compile. **58 → 92 M nodes/s, +56 %** - the single largest lever in the ladder. Node count unchanged. ### 4 · Stop re-deriving what you already loaded Two smaller changes, same theme: never read from memory something you already have in a register. The **left neighbour** of a cell is, 94 % of the time (240 of 256 cells, all but the row boundaries), exactly the piece the *calling* cell just placed. So the caller passes its own right edge down as an argument, and the cell derives its left constraint with no board read at all: ```diff - let left_edge = (cell[LEFT] >> 24) as u8; // re-read the neighbour we just placed + fn cell_38(st: &mut St, left_arg: u8) -> bool { // caller handed us its right edge + let left = left_arg; // …no board read ``` And the **match gain** - how many new matched edges a placement adds - was re-reading all four neighbours. But the up and left edges were *already loaded* to pick the candidate pool, and in row order those neighbours are always placed (or a frame edge, worth no gain). So up/left gain becomes two branchless `bool → u32` adds on values already in hand; only genuinely-pinned down/right neighbours cost a read: ```diff - let gain = matched(up) + matched(left) + matched(down) + matched(right); // 4 reads + let gain = u32::from(e_up == up) + u32::from(e_left == left) // 0 reads: cached + + need_down_read + need_right_read; // only if pinned ``` Together: **92 → 106 M nodes/s** - on the hard board this pulled level with McGavin's headless C (~102–105 M there). Node count unchanged. ### 5 · A byte array for the used-set The engine tracked placed pieces as a `u64` bitset: shift, mask, and, test. McGavin uses a flat `unsigned char tileFree[256]`; his check is one byte load and a compare-to-zero. ```diff - if used[pid >> 6] & (1u64 << (pid & 63)) == 0 { /* free */ } // shift, mask, and, test + if free_pc[pid] != 0 { /* free */ } // one byte load + compare ``` **106 → 108 M.** Node count unchanged. ### 6 · Fuse cells to amortise the call - the win The last thing standing between the function-chain and McGavin's `goto` was the call itself: a `goto` back to the previous cell is a bare jump; a function `return` restores callee-saved registers first. So **fuse several cells into one function** - nest the second cell's scan *inside* the first's placement loop, the third inside the second, and so on, so there is one `call` per *group* of placed cells instead of one per cell: ```diff - fn cell_37(st){ for c in pool { place; if cell_38(st, r) {return true} unplace } } - fn cell_38(st){ for c in pool { place; if cell_39(st, r) {return true} unplace } } + fn cells_37_38_39(st){ // three cells, one function, one call in/out + for c37 in pool37 { place37; + for c38 in pool38 { place38; + for c39 in pool39 { place39; + if next_group(st, r) {return true} + unplace39 } + unplace38 } + unplace37 } ``` Fusion trades fewer calls for more register pressure, so there is an optimum, and it is a shallow one. Sweeping the group size on `bench-hard`, three trials each, back to back: | group | 1 | 2 | 4 | 6 | 8 | | --- | --- | --- | --- | --- | --- | | nodes/s | ~102 M | ~107 M | **~110 M** | ~108 M | ~108 M | Fusion clearly beats no fusion (group 1), but past group 2 the differences are within run-to-run noise: the peak wanders between group 4 and 6 depending on the board and the LLVM register allocator's mood, and it is never more than a couple of percent. The `--chain2` default is group 6; group 4 edged ahead on this particular board. What matters is the jump from group 1, not the exact winner. Node count is preserved through the nesting either way. ## The ladder at a glance Three anchors are re-verified today on the committed `bench-*.json` boards; the steps between them are the development-time deltas from the build diary (each a self-contained commit), which drift a few percent with machine state, so read the middle rows as the *shape* of the climb, not lab-grade constants. | Rung | Engine | Change | status | | --- | --- | --- | --- | | **naive-clean** | recursive | plain portable Rust DFS, the true baseline | **~44 M, verified** | | **data-driven JIT** | codegen | generated program, table-driven inner loop | **~61 M, verified** | | u32 board cells | codegen | one load + shift per neighbour | +~65 % (diary) | | function-chain | codegen | one function per cell | +~55 % (diary) ★ | | cached up/left + byte used-set | codegen | stop re-reading placed neighbours | +~15 % (diary) | | **fusion (group 4–6)** | codegen | **one call per several cells** | **~108–110 M hard / ~122 M easy, verified** | | *McGavin's C (headless)* | C | *same machine, for reference* | *~102 M hard / ~287 M easy* | Two engines share this table: `naive-clean` is a separate recursive backtracker (runnable with `run_dfs --algo naive-clean`), and everything from "data-driven JIT" down is the codegen path this page is about (`run_dfs_codegen_jit`). The headline, stated plainly, is a **~2.5× lift from the naive-clean baseline to the fused champion on the hard board** (~44 M → ~110 M), and **~2.8× on the easy board** (~44 M → ~122 M) - landing, on the hard board, level with McGavin's headless C. Three meta-lessons fall out of it, the transferable part: 1. **Representation beats micro-ops.** The two biggest single wins - u32 cells (+67 %) and the function-chain (+56 %) - were both about the *shape* of the data and the code, not about shaving instructions. No branch-fiddling came close. 2. **Reuse what you have already computed.** Cached-gain and left-as-argument were pure "stop re-loading it" wins. 3. **Structure beats cycles.** Fusion attacked the *call structure*, not any single cycle - and that is what brought Rust level with hand-tuned C on hard boards. ## Reproduce it The engine and two committed benchmark boards live in the public repo under `research/experiments/dfs-study/engine/crates/dfs-codegen` (`bench/bench-easy.json`, `bench/bench-hard.json`, and a `bench/README.md` with the full recipe). The three anchors of the ladder - the naive-clean baseline, the codegen floor, and the fused champion - are each runnable directly, so anyone can re-run them on their own machine, back to back, and see the same tree walked at different speeds. From `research/experiments/dfs-study/engine`: ```bash # naive-clean: the honest baseline (a separate plain recursive backtracker) ~44 M cargo run --release -p dfs-run --bin run_dfs -- \ --puzzle crates/dfs-codegen/bench/bench-hard.json --algo naive-clean --seed 1 --budget-s 10 # data-driven JIT floor: the codegen path with no chain/fusion ~61 M cargo run --release -p dfs-codegen --bin run_dfs_codegen_jit -- \ --puzzle crates/dfs-codegen/bench/bench-hard.json --budget-s 15 --opt native # fused champion (group = 6): the engine this page is about ~108–110 M hard, ~122 M easy cargo run --release -p dfs-codegen --bin run_dfs_codegen_jit -- \ --puzzle crates/dfs-codegen/bench/bench-hard.json --budget-s 15 --chain2 --opt native # any fusion width, to walk the group sweep yourself cargo run --release -p dfs-codegen --bin run_dfs_codegen_jit -- \ --puzzle crates/dfs-codegen/bench/bench-hard.json --budget-s 15 --group 4 --opt native ``` Point `--puzzle` at `bench-easy.json` and every configuration prints `score=480` at the **same node count** (3,577,121,570) - the equality that proves the ladder is a speed ladder and nothing more. On the non-terminating `bench-hard.json` they print the same partial score at different `nps`. (Give it a real budget: a very short one reports compile warm-up, not throughput. The easy board wants ≥30 s to solve.) The three intermediate micro-steps in the ladder table below - packed candidates, cached gain, the byte used-set - are not separate flags; they are the commit sequence in `bench/README.md`, reproducible with `git checkout`. To reproduce the McGavin comparison fairly, build **his** engine headless - comment out `#define INTERACTIVE` near the top of `genbody.c` so the live display does not throttle it - then read the true throughput: ```bash # McGavin, headless + native: emit the puzzle-specialised C, then link and run gcc -o genbody genbody.c -lm -Ofast -mcpu=native -DG # emits body.c for this puzzle ./genbody PUZZLE.puz HINTS.hnt gcc -o solve genbody.c -lm -Ofast -mcpu=native # links body.c, runs the search ./solve PUZZLE.puz HINTS.hnt # read the "Rate:" line (= placements / elapsed) on a hard board, or the final # "tiles/second" summary on a solvable one — that is his real speed ``` With the display left on, the same binary reads roughly a third of that - which is exactly the trap that produced the earlier false "we beat him." > **First: are we even counting the same thing?** > > A speed comparison is meaningless unless both engines count the same events, so before trusting any ratio we read McGavin's source. His counter (`ntp`, the famous 16-bit-rollover trick) increments **once per piece committed to the board** - after the candidate has passed the colour-fit lookup and the used-check, at the moment it is placed (`genbody.c`, the `ntp++` right after `square[x][y].tile = t`). Our `st.nodes` does exactly the same: it increments after a candidate passes the edge-fit and used checks, as the piece is placed. Neither counts candidates that fail those checks; both count placements that will later backtrack. So McGavin's "tiles placed per second" and our "search-nodes per second" are **the same measurement** - committed placements, not attempts. (The one asymmetry: he counts the handful of forced hint placements and we bake those out - ≤18 on a count of billions, i.e. nothing.) The number to be wary of is a *third* engine's "M/s": that is where "placements attempted" vs "placements committed" can differ by an order of magnitude, which is the community's own long-standing caution about [what a "node" is](/research/build/faster/solver-engineering). > **Measure carefully, or don't measure** > > Absolute nodes/s drifts with machine load and thermals, and - as the correction above shows - with how the *reference* engine is built. **Only same-state, back-to-back, headless, otherwise-idle ratios are trustworthy.** Every comparison on this page was taken with nothing else running, both engines built headless with native codegen and run seconds apart. The early "McGavin is 5× faster" folklore was also a phantom, in the other direction: it compared his run on an easy puzzle to ours on a hard one. Match the board, match the build, measure back to back - or the number means nothing. ## The easy-board gap is a real, open lever Why does McGavin's C win the easy board by 2.3× yet only tie on hard ones? Because on a low-branching board there is almost nothing to do per node - pick the one or two candidates, place, move on - and his straight-line generated code, with each cell's candidate list baked to a minimal-perfect-hash lookup, does that with the fewest possible instructions. Our per-node work (index the pool, compute the gain, check the rim) is cheap but not *nothing*, and when the tree is shallow-and-wide that overhead shows. On a hard board the same nodes are dominated by backtracking and cache misses, where the two engines converge. Closing the easy-board gap would mean adopting his tighter candidate-list codegen - a concrete next step, not a wall. It is logged here as open rather than papered over. ## What the speed is worth Pointed at the real 256-piece Eternity II - six cores, fifteen minutes, the mandatory centre clue pinned - this engine walks the tree at tens of millions of nodes per second per core and plateaus, across seeds, in the high-300s of 480. That is not a disappointment; it is the [whole point of the site's core lesson](/research/why/prune-vs-speed). A strict backtracker is a superb tree-walker and a poor puzzle-solver: the search space is so vast that no achievable speed makes a dent in it, which is precisely why the records come from [heuristics and repair](/research/lab/experiments/raphael-anjou/repair-study), not from raw throughput. So the result here is deliberately narrow and, I think, worth stating plainly: a *safe, portable* Rust engine can **match hand-tuned C on the hard, deep boards that resemble the real puzzle**, walking the same tree on the same hardware - while the C still wins by ~2.3× on easy ones. And even at parity it cannot solve Eternity II, because speed was never the thing standing in the way. The longer argument about that trade-off - why some algorithms spend their budget on speed and others on judgement - is its own page: [going fast](/research/lab/experiments/raphael-anjou/going-fast). ## Related - [McGavin's C backtracker: the throughput story, built here](https://eternity2.dev/research/lab/experiments/peter-mcgavin/backtracker) — Peter McGavin's own C backtracker, the community's fastest: a 2007 optimization recipe compounded for two decades through generated code, lookup tables and counter tricks, then built on my M1 and pointed at the real 256-piece puzzle, where single core it drives past 200 of 256 pieces at ~109M placements/s. - [Going fast: when a solver spends its budget on speed](https://eternity2.dev/research/lab/experiments/raphael-anjou/going-fast) — Some Eternity II engines pour their effort into walking the search tree as fast as possible; others spend it on judgement about where to walk. This is the case for the first kind - what raw throughput buys, the three different things people mean by "fast", and why the fastest engine ever built still cannot solve the puzzle. - [Solver engineering: the craft below the algorithm](https://eternity2.dev/research/build/faster/solver-engineering) — Every record solver runs the same depth-first backtracker. What separates them is the layer underneath: lookup tables, perfect hashes, cache-sized structs, generated code, compiler archaeology. That craft decides whether a node costs 26 cycles or 2,600. The community's twenty-year engineering ledger, technique by technique, and what it all bought. - [Why a faster computer doesn't help](https://eternity2.dev/research/why/prune-vs-speed) — The single most important idea in hard combinatorial search: shrinking the space you search beats searching it faster, by an exponential margin. Eternity II is engineered so you can barely shrink it at all. --- # Learning from strong boards > A study in five experiments of one idea: instead of searching Eternity II from first principles, mine the corpus of strong boards already found for structure and feed it back into a search. A position prior, a learned move-vote, a scarce-demand compass, an anti-pattern miner, and a record decode, ordered from the simplest signal to the subtlest, and the one wall all five reach. - Canonical page (with interactive figures/demos): https://eternity2.dev/research/lab/experiments/raphael-anjou/learning/ - Updated: 2026-07-16 - Topics: learning, construction --- Most of this notebook searches Eternity II from first principles: a beam builds a board from an empty grid, a backtracker digs and retreats, a repair loop polishes a full board by moves. Each reasons only from the rules of the puzzle and the board in front of it. This study is the exception, and it is a study rather than a loose set of runs because all five experiments in it ask one question from different angles: **what can a search learn from the boards people have already found, and how far does that carry it?** The raw material is a corpus of strong boards, every arrangement the community and this project have pushed above 400 of 480. The move, in every experiment here, is to read that corpus for structure (where pieces sit, which pieces touch, which local patterns recur, which agreements are traps) and feed the structure back into a search as a bias. It is closer to imitation learning than to search design, and it earns its own home because the same handful of ideas keep returning, each a little sharper than the last. The corpus itself is [published](/research/build/dataset): 7,658 distinct boards scoring 400 to 469, released under CC0, with the diversity check that stops a learned signal from merely re-encoding one board. The method-agnostic write-up of each technique lives in the theory section on [learning from strong boards](/research/build/learning); the pages here are the lab side, the runs that put each technique on the real 16×16 board, with their scores and the questions they left open. ## The five experiments, simplest signal to subtlest The study reads as a sequence. Each experiment adds one turn of the screw over the one before it, and the pages are ordered to be read in that order. | # | Experiment | The learned signal | Reached (of 480) | |---|---|---|---| | 1 | [PRIOR](/research/lab/experiments/raphael-anjou/learning/prior) | where each piece tends to sit, a single position count | 460 | | 2 | [KEYRING](/research/lab/experiments/raphael-anjou/learning/keyring) | three signals (position, adjacency, 2×2 patch) voting together | 460 | | 3 | [LODESTONE](/research/lab/experiments/raphael-anjou/learning/lodestone) | which pieces serve a scarce colour demand, a faint compass | 451 | | 4 | [PALIMPSEST](/research/lab/experiments/raphael-anjou/learning/palimpsest) | the shared bad habits that cap boards, mining the trap not the structure | 463 | | 5 | [REPLAY](/research/lab/experiments/raphael-anjou/learning/replay) | the one move a single record board used that our search could not | 460 | **[PRIOR](/research/lab/experiments/raphael-anjou/learning/prior)** is the simplest form the idea can take, a count: over the strong boards, how often does each piece sit in each cell? Used as a construction tiebreak it builds a competitive board from nothing and reaches 460. **[KEYRING](/research/lab/experiments/raphael-anjou/learning/keyring)** adds signals rather than trusting one, letting a position count, an adjacency count, and a learned 2×2-patch quality vote on each placement, which carries a build into a corner family no earlier search had cracked. **[LODESTONE](/research/lab/experiments/raphael-anjou/learning/lodestone)** goes the other way, to a single deliberately faint signal (a per-piece scarce-demand weight) and, in doing so, finds the knife-edge that runs through the whole study: the moment a learned signal stops being a tiebreak and starts being the objective, the search collapses. **[PALIMPSEST](/research/lab/experiments/raphael-anjou/learning/palimpsest)** is the subtle turn. Every experiment before it trusts agreement between strong boards; this one asks which agreements are *traps*, placements every board adopts but no top board keeps, and steers a repair search to attack them. It produced this project's best board, 463. **[REPLAY](/research/lab/experiments/raphael-anjou/learning/replay)** learns from a single board rather than a statistic: rebuild a community record exactly, and whatever you must add to your search to make it walk that path is the ingredient it was missing. Here that was the double break, the move that lifted the strict ladder from 458 to 460. ## The one wall all five reach The through-line is what makes this a study and not a bag of tricks, and it is a sobering one. Every signal here is safe only as a gentle bias: over-trust it and the search falls apart (LODESTONE drops from 451 to 380 as its weight climbs; PALIMPSEST's trap list helps as a steer and hurts as a ban). And even used perfectly, none of these signals raises the ceiling. They reach the top of a search's own range, fast and reliably, and stop, because the corpus they learn from is made of boards that all hit the same [rigidity wall](/research/why/rigidity-wall). Learning from strong boards is the fastest way *to* the plateau and, on its own, no way *past* it. That failure mode is the subject of the theory section's [collapse capstone](/research/build/learning/when-learning-collapses), and it is the note the whole study resolves on. This is one of three studies in the [experiments notebook](/research/lab/experiments/raphael-anjou). Its siblings, the [DFS study](/research/lab/experiments/raphael-anjou/dfs-study) and the [repair study](/research/lab/experiments/raphael-anjou/repair-study), take a single search paradigm apart one decision at a time; this one holds the paradigm loose and varies what the search is allowed to *know*. ## Pages in this section - [PRIOR](https://eternity2.dev/research/lab/experiments/raphael-anjou/learning/prior) — Build a board from nothing, breaking ties by where pieces tend to sit in the strong boards we already have. It reaches a high score with no starting board to copy. - [KEYRING](https://eternity2.dev/research/lab/experiments/raphael-anjou/learning/keyring) — Build a board from scratch, ranking each next piece by three signals learned from past strong boards. Reached 460 in a board family no earlier search had cracked. - [LODESTONE](https://eternity2.dev/research/lab/experiments/raphael-anjou/learning/lodestone) — A faint compass for a from-scratch search: nudge it to commit the rare pieces early, where they're needed. It doesn't raise the ceiling; it makes the search reliably reach the top of its own range. - [PALIMPSEST](https://eternity2.dev/research/lab/experiments/raphael-anjou/learning/palimpsest) — Read every strong board to find the habits that quietly hold a board back, then break them. This experiment produced the project's best board: 463 of 480. - [REPLAY](https://eternity2.dev/research/lab/experiments/raphael-anjou/learning/replay) — Rebuild the community's strict 460 boards exactly, and in doing so discover the move ordinary solvers can't make: paying two mismatches at a single cell. ## Related - [Learn from strong boards](https://eternity2.dev/research/build/learning) — Most attacks on Eternity II search from first principles. A distinct family does the opposite: it mines the corpus of boards people have already found for structure, then feeds that structure back into the search. Position priors, learned move-ordering, anti-pattern mining, record decoding, and the failure mode where a learned signal collapses. - [The dataset](https://eternity2.dev/research/build/dataset) — A public, CC0 dataset for Eternity II in two parts: fourteen benchmark instances to solve, and a corpus of 7,658 distinct strong boards to learn from. Every score is recomputed from the board itself, and the corpus is checked to be genuinely diverse rather than a thousand copies of one board. - [Raphaël Anjou's experiments](https://eternity2.dev/research/lab/experiments/raphael-anjou) — A notebook of Eternity II search experiments, organised into the shared engines they run on, the combination pipelines that chase the score, three studies that take one search paradigm apart a decision at a time, and exact endgame solves. Each has its idea, its best board, and the questions it left open. The best reaches 463 of 480. - [The DFS study](https://eternity2.dev/research/lab/experiments/raphael-anjou/dfs-study) — One question, asked carefully: among depth-first backtrackers for Eternity II, what does each fill order, each heuristic, and the break mechanism actually buy? A family of from-scratch backtrackers, each one change apart, run on the same ten corner-pinned variants, single core, sixty seconds. - [The repair study](https://eternity2.dev/research/lab/experiments/raphael-anjou/repair-study) — The sibling of the DFS study, for the other way people attack Eternity II: destroy part of a board, rebuild it, keep the change if it helps. One question, asked carefully. What does each decision in that loop buy: which region to destroy, how to rebuild it, when to keep a move, when to restart, and what board to start from? - [The rigidity wall](https://eternity2.dev/research/why/rigidity-wall) — Every record board we have is frozen in place. You cannot nudge your way from a great board to a perfect one, and we can prove it. --- # KEYRING > Build a board from scratch, ranking each next piece by three signals learned from past strong boards. Reached 460 in a board family no earlier search had cracked. - Canonical page (with interactive figures/demos): https://eternity2.dev/research/lab/experiments/raphael-anjou/learning/keyring/ - Updated: 2026-07-10 - Topics: construction, learning - Reproduce: `just research-record-boards` - Source: Beam search as bounded-width best-first construction (this project's concept page) — https://github.com/raphael-anjou/eternity2/blob/main/web/content/research/build/construct/beam-search.mdx --- [PRIOR](/research/lab/experiments/raphael-anjou/learning/prior) trusted one learned signal, a position count, to break its ties. KEYRING is the next step in the [study](/research/lab/experiments/raphael-anjou/learning): what if one signal is not enough? Building a board one piece at a time, the hard part is deciding which piece to place next when several would fit, and a single rule of thumb, even a learned one, tends to march the search into the same dead ends every time. KEYRING carries three different learned hunches at once, a keyring of them, and lets them vote, which keeps the search from over-trusting any one signal. ## How it works From the library of strong boards, KEYRING learns three things. First, where each piece likes to sit: how often a piece appears in each position across good boards. Second, which pieces like to be neighbours: how often two pieces end up touching. Third, which little 2×2 patches show up in good boards versus bad ones. It then fills the board with a beam search, keeping many partial boards alive at once. When it has to choose the next piece, it scores each option by how many edges it matches, nudged by the three learned signals together. A small amount of randomness keeps the many parallel attempts from collapsing onto the same path. > **[Figure]** Interactive: the three-signal placement vote — interactive: KeyringDiagram. Rendered on the canonical page (link above); not shown in this markdown export. ## The board > **[Interactive: RecordBoard]** Rendered on the canonical page (link above); not shown in this markdown export. ## The result KEYRING reached 460 of 480, and did it in a corner arrangement where no board had reached that level before, so it's not just another route to a known board but a genuinely new region. Across repeated runs it landed a strong board far more often than the simpler single-signal version it grew out of. It is not the project's top score (that's 463), but finding a high board in a fresh family matters: the strong boards are known to be isolated from each other, so each new family is its own foothold. ## Method The three signals, made precise, then how they steer the beam. The strongest of the three is the **2×2 patch prior**. Over the corpus, split boards into *high* (score ≥ 460) and *low* (< 460), and for every 2×2 patch $q$ (four pieces with their rotations) score it by a Laplace-smoothed log-odds ratio: $$ \text{score}(q) = \log\big(\text{count}_\text{high}(q) + \alpha\big) - \log\big(\text{count}_\text{low}(q) + \alpha\big), \quad \alpha = 0.5 $$ A patch that shows up in strong boards and not weak ones scores positive; a consensus-trap patch scores negative. (In the run that found the 460, the corpus split 23 high boards against 1255 low.) The other two signals are simpler counts: a **piece-in-position** frequency and a **piece-pair adjacency** frequency, each tallied over the same strong-board set. The build is a **beam search**: keep $W$ partial boards alive, and at each step extend every beam by scoring each candidate placement as its matched-edge gain plus a weighted sum of the three priors, then keep the top $W$. A little injected randomness stops the $W$ beams from collapsing onto one path, which is what let KEYRING reach a *new* corner family rather than re-deriving a known board. Patches pack into a `u64` key (piece ≤ 8 bits, rotation 2 bits, ×4 cells = 40 bits) so the prior lookup is a hash hit. As with [PRIOR](/research/lab/experiments/raphael-anjou/learning/prior), the beam build reaches the high 450s on its own; the committed 460 board takes that construction and a local-refinement tail on top, the same construct-then-refine split the record pipelines use. The three signals are what carry the *construction* into a fresh family; the last few edges are the refinement's. One limit worth stating: the priors are learned from a corpus that is itself sub-perfect, so they encode the community's ceiling as much as its wisdom: the same double edge that [PALIMPSEST](/research/lab/experiments/raphael-anjou/learning/palimpsest) turns into a feature by separating good consensus from traps. ## Reproduce `just research-record-boards` verifies the committed 460 board's score byte-for-byte from its stored Bucas string. The search is stochastic (beam search with injected randomness), so a re-run will not reproduce the same board; the board is the artifact of record. The engine is the shared beam producer; the change this page describes is the three learned ranking signals. Those signals are mined from a corpus of strong boards, so the run is not reproduced from scratch here. ## Open questions Would grading the patch signal by degree, rather than treating patches as simply good or bad, help further? Could the weights on the three signals shift as the board fills, trusting structure more late in the build? And can this new family be pushed past 460 with a longer refinement? ## Related - [Learned move-ordering](https://eternity2.dev/research/build/learning/learned-value-ordering) — When several pieces fit, which do you place next? Instead of one rule of thumb, carry several signals learned from strong boards and let them vote. Voting keeps the search from over-trusting any one hunch and marching into the same dead end. - [Learning from strong boards](https://eternity2.dev/research/lab/experiments/raphael-anjou/learning) — A study in five experiments of one idea: instead of searching Eternity II from first principles, mine the corpus of strong boards already found for structure and feed it back into a search. A position prior, a learned move-vote, a scarce-demand compass, an anti-pattern miner, and a record decode, ordered from the simplest signal to the subtlest, and the one wall all five reach. - [PRIOR](https://eternity2.dev/research/lab/experiments/raphael-anjou/learning/prior) — Build a board from nothing, breaking ties by where pieces tend to sit in the strong boards we already have. It reaches a high score with no starting board to copy. - [Why basin-hopping looks impossible](https://eternity2.dev/research/why/sigma-cycles) — If you can't improve a great board by polishing it, maybe you can jump to a different great board. On every record pair tested, you can't, and the structural reason why is worth seeing. - [Forbidden patterns](https://eternity2.dev/research/why/forbidden-patterns) — Almost every small patch of pieces you could build is impossible. For a 2×2 square, 99.72% of the ways to place four pieces can never be made to match. - [Beam search](https://eternity2.dev/research/build/construct/beam-search) — Keep the K most promising partial boards alive at once and grow them cell by cell. Beam search is the workhorse behind this project's from-scratch builders, and a clean illustration of why breadth alone stalls in the deep interior. --- # LODESTONE > A faint compass for a from-scratch search: nudge it to commit the rare pieces early, where they're needed. It doesn't raise the ceiling; it makes the search reliably reach the top of its own range. - Canonical page (with interactive figures/demos): https://eternity2.dev/research/lab/experiments/raphael-anjou/learning/lodestone/ - Updated: 2026-07-10 - Topics: construction, search-space, learning - Reproduce: `just research-record-boards` - Source: Rare-colour geography (this project): where the scarce (N,W) demands live — https://github.com/raphael-anjou/eternity2/blob/main/web/content/research/why/rare-color-geography.mdx --- [KEYRING](/research/lab/experiments/raphael-anjou/learning/keyring) added signals; LODESTONE, the third experiment in the [study](/research/lab/experiments/raphael-anjou/learning), pares back to a single deliberately faint one, and in doing so exposes the knife-edge every learned signal here balances on. The strong boards quietly agree on something: as the score rises, they increasingly satisfy a particular set of scarce demands, places where only one or two pieces in the whole set can serve a cell's north-and-west colours. LODESTONE asks whether telling a from-scratch search about those demands helps it commit the right rare pieces before they're stolen. ## How it works From the corpus of strong boards, LODESTONE builds a prior: for each piece, how often it ends up serving one of those scarce north-west demands in a good board, weighted up sharply for the rarest, so a piece that is the only possible server gets the biggest boost. The beam search then ranks its candidate placements by the usual matched-edge score plus a small multiple of this prior, so among otherwise-equal moves it prefers to place the pieces the good boards learned to spend early. The crucial detail is the size of that multiple. The prior has to be a pure tiebreaker, not part of the objective: it breaks ties between equally-matching moves and nothing more. > **[Figure]** Interactive: rare-colour attraction map — interactive: LodestoneRarityLab. Rendered on the canonical page (link above); not shown in this markdown export. ## The result At a tiny weight the prior gives a small, consistent gain: across five seeds the median from-scratch score rises from 449 to 451, and, more usefully, the spread tightens, from a 446–451 scatter to a reliable 450–451. It makes the constructor land at the top of its range instead of sometimes stumbling. Turn the weight up even slightly and it collapses (422, then 380) because chasing the corpus's scarce demands then trades directly against matching the edge in front of you. That failure is itself the finding: scarcity is a real signal for *which* piece to prefer, but a weak one, and only safe as a tiebreaker. LODESTONE is modest about its size: it improves construction quality and consistency by a couple of edges, and does not touch the basin ceiling that stops every method near the top. ## Method The signal comes first, then the deliberately-tiny way it is used. **The measurement.** A *scarce demand* is a cell whose north-and-west colours can be served by only one or two pieces in the whole set. Over the corpus, the count of scarce demands satisfied in at least half the boards rises *monotonically* with score, roughly 1 → 2 → 3 → 10 as boards climb toward 458+. Strong boards don't just happen to place rare pieces well; they increasingly satisfy the *same* scarce demands. That is a real, score-correlated structure that no earlier constructor had wired in. **The prior.** For each piece, weight how often it serves one of those scarce north-west demands in a good board, boosted sharply for the rarest (a piece that is the *only* possible server gets the biggest weight). The beam ranks candidates by the usual matched-edge gain plus a small multiple of this weight. **The knob is the whole story.** The multiple must be a pure *tiebreaker*: it decides between equally-matching moves and nothing else. At a tiny weight: median from-scratch score 449 → 451 across five seeds, and the spread tightens from 446–451 to a reliable 450–451. Nudge the weight up and it collapses (422, then 380), because chasing scarce demands then trades directly against matching the edge in front of you. The collapse *is* the result: scarcity says *which* piece to prefer, but weakly, safe only as a tiebreak. ## Reproduce Seeded; the reproducible artifact here is the tiebreak *effect* (a tighter spread and a +2 median across five seeds), not a single board. The engine is the shared beam producer; the change this page describes is a faint scarce-piece-early tiebreak. That tiebreak weight is derived from the piece set and a corpus, so the run is not reproduced from scratch here. ## Open questions Could the prior be made position-aware without becoming part of the objective, strong only in the regions where scarce demands actually concentrate? Does combining it with KEYRING's three signals add a fourth useful vote, or just more noise? And is the consistency gain worth more than the median gain, given that a tighter search is easier to build a ladder on? ## Related - [Corpus priors](https://eternity2.dev/research/build/learning/corpus-priors) — The simplest way to learn from strong boards: count where each piece tends to sit, or how often it serves a scarce demand, and use that count as a gentle tiebreak in construction. It has to stay a tiebreak; the moment it becomes part of the objective it collapses the search. - [When learning collapses](https://eternity2.dev/research/build/learning/when-learning-collapses) — The sobering half of learning from strong boards. A learned signal reaches the top of a search's own range reliably, and then stops. Over-trust it and the search collapses; even used perfectly it does not raise the ceiling, because the ceiling is not a thing the corpus knows. - [Learning from strong boards](https://eternity2.dev/research/lab/experiments/raphael-anjou/learning) — A study in five experiments of one idea: instead of searching Eternity II from first principles, mine the corpus of strong boards already found for structure and feed it back into a search. A position prior, a learned move-vote, a scarce-demand compass, an anti-pattern miner, and a record decode, ordered from the simplest signal to the subtlest, and the one wall all five reach. - [Piece theft, where solvers die](https://eternity2.dev/research/why/piece-theft) — A solver fills a few rows for free, then hits a wall in the middle of the board. Here's the mechanism: a scarce piece spent in the wrong place, rows ago. - [KEYRING](https://eternity2.dev/research/lab/experiments/raphael-anjou/learning/keyring) — Build a board from scratch, ranking each next piece by three signals learned from past strong boards. Reached 460 in a board family no earlier search had cracked. - [PRIOR](https://eternity2.dev/research/lab/experiments/raphael-anjou/learning/prior) — Build a board from nothing, breaking ties by where pieces tend to sit in the strong boards we already have. It reaches a high score with no starting board to copy. - [The rare colors live on the frame](https://eternity2.dev/research/why/rare-color-geography) — Five of Eternity II's 22 colors appear only along the border ring, each on exactly 24 edges, never once in the interior. A structural split that shapes how every solver treats the frame. --- # PALIMPSEST > Read every strong board to find the habits that quietly hold a board back, then break them. This experiment produced the project's best board: 463 of 480. - Canonical page (with interactive figures/demos): https://eternity2.dev/research/lab/experiments/raphael-anjou/learning/palimpsest/ - Updated: 2026-07-10 - Topics: local-search, learning - Reproduce: `just research-record-boards` - Source: Ropke & Pisinger 2006, adaptive large-neighbourhood search (the destroy-and-repair frame this steers) — https://doi.org/10.1287/trsc.1050.0135 --- Every experiment in the [study](/research/lab/experiments/raphael-anjou/learning) so far has trusted agreement between strong boards: where the good boards concur, follow them. PALIMPSEST is the turn where that trust is examined, and it produced this project's best board. When many independent searches all reach a high but not perfect board, they tend to agree on a lot of placements. Some of that agreement is genuine structure, and some of it is a shared bad habit: a local choice that looks good and keeps every search stuck just short of the top. The idea behind this experiment is to read the whole corpus of strong boards, separate the helpful agreement from the trap, and attack the traps. ## How it works Take every board anyone has found that scores reasonably well, and for each pair of neighbouring positions count how often a given pair of pieces sits there, weighted by how good the board was. Two patterns fall out. Some adjacencies show up again and again in the very best boards: those are safe, real structure. Others show up almost everywhere but never in the top boards: those are the traps, the choices that feel right and cap the score. The traps cluster in particular regions of the board rather than spreading evenly. Knowing where they are turns the corpus into a map: which placements to trust, and which to pull apart and rebuild. Grouping boards by how their corners are arranged then points the search at the most promising family to attack. > **[Figure]** Interactive: the trap map, corner-family by corner-family — interactive: PalimpsestDiagram. Rendered on the canonical page (link above); not shown in this markdown export. ## The board > **[Interactive: RecordBoard]** Rendered on the canonical page (link above); not shown in this markdown export. ## The result Used as a map to steer the search, this reached 463 of 480 matched edges, the best board this project has produced. For comparison, the community's best on this puzzle is 470, and a complete solution is 480. One caveat worth stating: trying to use the trap list directly, by forcing the search to avoid trapped placements, did not work on its own and tended to make boards worse. The value was in reading the corpus to choose where to focus, not in hard-coding its conclusions into the search. ## Method For the reader who wants the exact procedure. It runs in two passes. **1. Score-weighted, basin-separated consensus mining.** Over a corpus of boards scoring 400–480, for every adjacent cell-pair $(i, j, \text{dir})$ and every piece-pair that ever sits there, compute two frequencies rather than one: $$ \begin{aligned} p_\text{high}(\text{pair}) &= \frac{\#\{\text{boards with the pair, score} \ge 460\}}{\#\{\text{boards with score} \ge 460\}} \\[4pt] p_\text{all}(\text{pair}) &= \frac{\#\{\text{boards with the pair}\}}{\#\{\text{all boards}\}} \end{aligned} $$ together with a *ceiling*: the maximum score of any board containing that pair. The ceiling, not $p_\text{high}$, is what separates the two categories. **Good consensus** is high $p_\text{all}$ with a ceiling that reaches the top family, boards at or within a point of this project's best (463): patterns the strongest boards keep, so trustworthy structure. **Consensus traps** are high $p_\text{all}$ with a ceiling that stalls a couple of points short, no board carrying the pair breaking past the low-460s: the agreed-upon wrong choice that locks a whole family below the record. The cut sits between "reaches the top" and "stalls just below"; on this small corpus (a 463 ceiling, boards clustered from the high 450s to low 460s) it is set by hand rather than swept, and $p_\text{high}$ (score $\ge$ 460) is reported alongside but is not the discriminant. The single-frequency view (persistence alone) cannot tell these apart; splitting by ceiling is the whole trick. **2. Trap-destroy ALNS.** Take a 461 board (it lives *inside* the trap basin by construction), locate the ~50 highest-ranked trap pairs it contains, and find the wedge: the position whose removal breaks the most trap pairs while preserving the good-consensus ones. Then perturb those trap cells, swap them to non-trap pieces, introducing 4–8 deliberate mismatches, and feed the board back to [adaptive large-neighbourhood search](/research/build/local-search/local-search-alns). ALNS's worst-band destroy operator preferentially tears open exactly those intentionally-broken regions and rebuilds them. Run: 30 minutes × 6 seeds. The complexity is unremarkable: the mining pass is linear in the corpus size, and the real cost is the ALNS search it steers. The contribution is *where* it aims that search, not a new search. ## Reproduce The verifier `just research-record-boards` recomputes the matched-edge score of the committed 463 board from its raw Bucas edges and checks it equals the claim, so the board is reproducible and checkable byte-for-byte in the viewer. The search that *found* it is a stochastic run of the shared ALNS engine (30 min × 6 seeds), steered by the trap map described above. It will not reproduce the same board, which is why the artifact of record is the board, not a re-run. The steering is read from a corpus of strong boards, so the run is not reproduced from scratch here. ## Open questions Why does rebuilding the trapped regions tend to land back on the same known top board rather than a genuinely new one? Would a separate map per corner family reveal structure that the combined map hides? And could a gentle penalty for trapped placements help where a hard ban hurt? ## Related - [Anti-pattern mining](https://eternity2.dev/research/build/learning/anti-pattern-mining) — The subtle idea in learning from strong boards: not every agreement between them is good. Some shared placements are real structure; some are a shared trap that caps every search just short of the top. Separate the two, and attack the trap. - [Learning from strong boards](https://eternity2.dev/research/lab/experiments/raphael-anjou/learning) — A study in five experiments of one idea: instead of searching Eternity II from first principles, mine the corpus of strong boards already found for structure and feed it back into a search. A position prior, a learned move-vote, a scarce-demand compass, an anti-pattern miner, and a record decode, ordered from the simplest signal to the subtlest, and the one wall all five reach. - [The rigidity wall](https://eternity2.dev/research/why/rigidity-wall) — Every record board we have is frozen in place. You cannot nudge your way from a great board to a perfect one, and we can prove it. - [KEYRING](https://eternity2.dev/research/lab/experiments/raphael-anjou/learning/keyring) — Build a board from scratch, ranking each next piece by three signals learned from past strong boards. Reached 460 in a board family no earlier search had cracked. - [Local search and ALNS](https://eternity2.dev/research/build/local-search/local-search-alns) — Destroy part of a board, rebuild it better, and let the algorithm learn which demolitions pay. Adaptive large-neighborhood search is the most reliable polisher this project has, and the cleanest demonstration of the wall where polishing ends. --- # PRIOR > Build a board from nothing, breaking ties by where pieces tend to sit in the strong boards we already have. It reaches a high score with no starting board to copy. - Canonical page (with interactive figures/demos): https://eternity2.dev/research/lab/experiments/raphael-anjou/learning/prior/ - Updated: 2026-07-10 - Topics: construction, learning - Reproduce: `just research-record-boards` - Source: Beam search (this project's concept page): bounded-width best-first construction — https://github.com/raphael-anjou/eternity2/blob/main/web/content/research/build/construct/beam-search.mdx --- PRIOR opens the [learning-from-strong-boards study](/research/lab/experiments/raphael-anjou/learning) with the simplest thing the idea can be: a count. Most strong boards on this site are found by taking an existing good board and improving it. PRIOR asks a harder question: can you build a competitive board from an empty grid, with no board to anchor to? The trick is to let the crowd of past good boards quietly guide the construction without copying any single one of them, and the guidance is nothing more than a tally of where pieces tend to sit. ## How it works From the library of boards scoring well, PRIOR learns one simple thing: for each position on the board, how often each piece shows up there. That gives a gentle preference, a prior, for what tends to belong where. Then it builds with a beam search, keeping many partial boards alive at once and extending them cell by cell. When two options match the same number of edges, the prior breaks the tie toward the piece that's more typical of strong boards in that spot. A diversity rule keeps the many parallel attempts from collapsing onto the same path. No single board is copied; the guidance is statistical. > **[Figure]** Interactive: the position-prior heatmap — interactive: PriorDiagram. Rendered on the canonical page (link above); not shown in this markdown export. ## The board > **[Interactive: RecordBoard]** Rendered on the canonical page (link above); not shown in this markdown export. ## The result From scratch, PRIOR reaches the mid-450s, and with a sharper prior built from only the very best boards it climbs higher. Followed by local refinement it reaches 460, the board shown here. That a from-nothing build lands this close to the records is the point: the structure of good boards is partly learnable, and you don't need to start from one to get there. It is not the project's top score (463), and the final lift here leans on a refinement step, which the board's label notes. But as a clean-slate result it's the strongest the project has, and it's the foundation the later multi-signal builders grew from. ## Method The prior is deliberately the simplest thing that could work: a count. Over every corpus board scoring above a threshold (440 for the base prior), tally a $256 \times 256$ matrix $M[p][c]$, how many strong boards place piece $p$ in cell $c$. Normalized per cell, that is the preference used to break ties. Three sharpenings, each a variant of the same tally: - **Rotation-aware.** Split each piece by its four rotations: a $1024 \times 256$ tensor ($256 \times 4$ rows). The prior now prefers not just the right piece but the right orientation, 262,144 entries against the base 65,536. - **Per corner-family.** The strong boards fall into families by their four corner pieces. Building a *separate* prior from just one family's boards gives a signal the pooled matrix averages away, this is what let the from-scratch build reach a fresh 460 rather than the crowded common basin. - **Sharper threshold.** Rebuilding the prior from only the very best boards (a higher cutoff) raises the ceiling of the construction, at the cost of a thinner, noisier signal. Construction is a [beam search](/research/build/construct/beam-search): keep $W$ partial boards, extend cell by cell, and when candidates tie on matched edges let $M$ break the tie; a diversity rule keeps the $W$ beams apart. The 460 here takes a from-scratch beam build to the mid-450s, then a short local-refinement tail to 460. **Novelty was checked, not assumed.** The resulting board is compared against every 460-tier board already known by corner-permutation and Hamming distance on (piece, position); a match only counts as a new basin when the corner family differs or the Hamming distance is large. PRIOR's board passed that test, it is a genuinely distinct basin, not a re-discovery. ## Reproduce `just research-record-boards` verifies the committed 460 board's score exactly, edge by edge, from its stored Bucas string, so the result is checkable even though the search that found it is not deterministic (its final lift uses a stochastic refinement tail). The board is the artifact of record. The search that produced it is the shared beam producer, with the one change this page describes: the learned positional prior that breaks its ties. That prior is a matrix mined from a large corpus of strong boards, which is why the run is not reproduced here from scratch. ## Open questions How sharp can the prior get before it overfits? Built from only a handful of top boards the signal is strong but thin. Could a separate prior per board-family capture structure the combined one averages away? And how much of the final gap is the construction versus the refinement that follows it? ## Related - [Corpus priors](https://eternity2.dev/research/build/learning/corpus-priors) — The simplest way to learn from strong boards: count where each piece tends to sit, or how often it serves a scarce demand, and use that count as a gentle tiebreak in construction. It has to stay a tiebreak; the moment it becomes part of the objective it collapses the search. - [Learning from strong boards](https://eternity2.dev/research/lab/experiments/raphael-anjou/learning) — A study in five experiments of one idea: instead of searching Eternity II from first principles, mine the corpus of strong boards already found for structure and feed it back into a search. A position prior, a learned move-vote, a scarce-demand compass, an anti-pattern miner, and a record decode, ordered from the simplest signal to the subtlest, and the one wall all five reach. - [KEYRING](https://eternity2.dev/research/lab/experiments/raphael-anjou/learning/keyring) — Build a board from scratch, ranking each next piece by three signals learned from past strong boards. Reached 460 in a board family no earlier search had cracked. - [GAUNTLET](https://eternity2.dev/research/lab/experiments/raphael-anjou/pipelines/gauntlet) — Run the same beam search across nine different scan orders, so it lands in different regions instead of always converging to the same one. The zigzag order found a brand-new 458 board. - [Piece theft, where solvers die](https://eternity2.dev/research/why/piece-theft) — A solver fills a few rows for free, then hits a wall in the middle of the board. Here's the mechanism: a scarce piece spent in the wrong place, rows ago. - [Beam search](https://eternity2.dev/research/build/construct/beam-search) — Keep the K most promising partial boards alive at once and grow them cell by cell. Beam search is the workhorse behind this project's from-scratch builders, and a clean illustration of why breadth alone stalls in the deep interior. --- # REPLAY > Rebuild the community's strict 460 boards exactly, and in doing so discover the move ordinary solvers can't make: paying two mismatches at a single cell. - Canonical page (with interactive figures/demos): https://eternity2.dev/research/lab/experiments/raphael-anjou/learning/replay/ - Updated: 2026-07-10 - Topics: backtracking, learning - Source: Community strict-460 boards (records timeline): the witnesses REPLAY reconstructs — https://github.com/raphael-anjou/eternity2/blob/main/web/content/research/records.mdx --- REPLAY closes the [study](/research/lab/experiments/raphael-anjou/learning) with a different kind of learning. Every experiment before it mined a *statistic* from the whole corpus; REPLAY learns from a *single* board, and it learns the one thing a statistic cannot show, the exact move a record used that our search could not make. The public fully-clued boards this project was measured against reach 460 (the community record has since advanced to 464), but this project's own break-allowing search stalled at 457 or 458 no matter what. REPLAY set out to reproduce those 460 boards exactly, piece for piece, to learn what they were doing that our search could not. The answer turned out to be a single overlooked move. ## How it works A break-allowing search normally lets a cell carry at most one mismatch as it's placed. REPLAY relaxes that to allow two at certain cells, and reorders how candidate placements are ranked so that the moves a known good board actually used outrank cheaper-looking ones. With those two changes it can walk the same path the witness board took. Played back this way, the community 460 boards rebuild exactly, every piece in place, and the score checks out. The reproduction is the proof that the missing ingredient was real. > **[Figure]** Interactive: the double-break cells — interactive: DoubleBreakDiagram. Rendered on the canonical page (link above); not shown in this markdown export. > **[Figure]** Interactive: replay the break schedule — interactive: DoubleBreakLab. Rendered on the canonical page (link above); not shown in this markdown export. ## The result Both community strict-460 boards replay exactly to 460. The discovery: each contains four or five cells that pay two mismatches at once. A search that allows only one mismatch per cell literally cannot reach those boards, which is exactly why the project's earlier runs saturated at 457 to 458. Allowing the double break lifts the strict ladder to 460. It's a clean explanation of a long-standing plateau, and a caution: a reasonable-looking rule (one break per cell) silently fenced off the very boards we were chasing. ## Method The replay is a depth-first search run in a deliberately constrained mode. - **Prior-over-cost ordering.** Ordinary break-tolerant DFS ranks candidate placements by immediate mismatch cost, cheapest first. REPLAY flips the priority to *prior-over-cost*: candidates the witness board actually used are ranked ahead of cheaper-looking ones, so the search is pulled down the known good path instead of wandering off it. This is the `--prior-over-cost` flag driving off the witness board's own schedule. - **Exact tail.** The last 14 cells are solved exactly (`--exact-tail 14`) rather than heuristically, so the endgame that ordinary runs fumble is closed deterministically. - **The relaxation that mattered.** The per-cell mismatch budget is raised from one to two. That single change is what admits the witness boards at all. Run on a fixed 460 frame, 8 threads, a 5-second restart cadence and a per-run budget, both community strict-460 witnesses rebuild piece-for-piece and the score checks out, the reproduction *is* the proof that the missing ingredient was the double break. **The finding.** Each witness contains four or five cells that pay two mismatches at once. A search capped at one break per cell cannot represent those boards, which is precisely why the project's earlier break-tolerant runs saturated at 457–458. It is a search-completeness result dressed as a record attempt: the wall was in the move set, not the compute. ## Reproduce This one is seeded and closer to deterministic than the stochastic builders: the DFS replay off a fixed frame and witness schedule rebuilds the 460 boards reliably. The targets it reconstructs are the community's own strict-460 [records](/research/records), so the boards themselves are on the record timeline; what this experiment adds is the replay that rebuilds them. The replay needs two inputs beyond the puzzle, a border frame and the community witness board it reconstructs; a runnable backing directory that ships both is planned. ## Open questions Does allowing two breaks per cell open a path to 461 and beyond, or just to the known 460s? Are there boards needing a triple break? And can the double-break cells be predicted from a partial board rather than discovered by replay? ## Related - [Decoding records](https://eternity2.dev/research/build/learning/decoding-records) — The most literal way to learn from a strong board: rebuild it exactly, piece for piece, until your search can reproduce it. What the reconstruction forces you to add is the ingredient your search was missing, and the reproduction is the proof. - [Learning from strong boards](https://eternity2.dev/research/lab/experiments/raphael-anjou/learning) — A study in five experiments of one idea: instead of searching Eternity II from first principles, mine the corpus of strong boards already found for structure and feed it back into a search. A position prior, a learned move-vote, a scarce-demand compass, an anti-pattern miner, and a record decode, ordered from the simplest signal to the subtlest, and the one wall all five reach. - [LADDER](https://eternity2.dev/research/lab/experiments/raphael-anjou/pipelines/ladder) — Throw hundreds of cheap short searches at the board, keep only the deepest starts, and promote the survivors through longer and longer rounds. - [Records & solvers](https://eternity2.dev/research/records) — Eternity II has never been solved, but fifteen years of community effort have pushed the best board to 470/480. Who holds what, how they did it, and why some headline "480" boards are not actually the real puzzle. - [The rigidity wall](https://eternity2.dev/research/why/rigidity-wall) — Every record board we have is frozen in place. You cannot nudge your way from a great board to a perfect one, and we can prove it. - [No-good learning: remembering why you failed](https://eternity2.dev/research/build/reduce/nogood-learning) — A failed subtree is a theorem: this partial state can never extend. Store it and never re-enter. The community tried both flavours: chess-style transposition tables over the search frontier, and mined constraints about the puzzle itself. The full ledger of what memory buys at E2 scale, and the small boards where it genuinely pays. --- # Meet in the middle > Exact endgame experiments that meet in the middle: enumerate a region from two ends and join on the seam, to find the true best completion with a proof rather than a heuristic's best guess. These measure a small region exactly instead of chasing the whole-board score. - Canonical page (with interactive figures/demos): https://eternity2.dev/research/lab/experiments/raphael-anjou/meet-in-the-middle/ - Updated: 2026-07-17 --- Heuristic search guesses; it never knows it has the best possible finish. The experiments here take the opposite stance for a small region: enumerate it from two ends, join the halves wherever their seam colours agree and their piece sets don't overlap, and come away with the *exact* best completion plus a proof that nothing scores higher. It is the classic [meet-in-the-middle](/research/build/exact/meet-in-the-middle) time-for-space trade, pointed at the puzzle's endgame. These are not attempts on the score. They answer a different question from the [combination pipelines](/research/lab/experiments/raphael-anjou/pipelines) and the two search [studies](/research/lab/experiments/raphael-anjou): not *how high can a heuristic climb*, but *what is the true best ending of this region, and where do exact methods stop being affordable*. An exact answer about a small region is worth more here than another near-miss on the whole board. This is the first experiment of that kind; the section is named for the technique rather than the one page, because more exact endgame ideas belong alongside it as they land. ## Pages in this section - [BANDSAW](https://eternity2.dev/research/lab/experiments/raphael-anjou/meet-in-the-middle/bandsaw) — Solve a band of rows exactly by meeting in the middle, to find the true best ending and to measure how far ahead an endgame can be decided. --- # BANDSAW > Solve a band of rows exactly by meeting in the middle, to find the true best ending and to measure how far ahead an endgame can be decided. - Canonical page (with interactive figures/demos): https://eternity2.dev/research/lab/experiments/raphael-anjou/meet-in-the-middle/bandsaw/ - Updated: 2026-07-10 - Topics: exact-methods - Source: Meet-in-the-middle (this project's concept page): the two-halves-and-join technique — https://github.com/raphael-anjou/eternity2/blob/main/web/content/research/build/exact/meet-in-the-middle.mdx --- Heuristic search guesses; it never knows it has the best possible finish. BANDSAW is the opposite experiment: for a band of rows near the bottom, it computes the exact best completion, with a proof that nothing scores higher. The aim isn't speed, it's certainty, and the certainty doubles as a ruler for how hard the endgame really is. ## How it works Split the band into a top half and a bottom half. Enumerate every way to fill the top half up to a small mismatch budget, keyed by two things: which pieces it used, and the row of colors it leaves dangling at the seam. Enumerate the bottom half the same way, but only from the pieces the top half didn't use. Then join the two halves wherever their seam colors agree and their piece sets don't overlap. That meet-in-the-middle join finds the exact best completion without walking the whole tree. Exact lower-bound tables, computed by working backwards column by column, let it prune branches that already can't beat the budget, and it raises the budget step by step until a round finds nothing new, which proves the best score for that band. > **[Figure]** Interactive: the meet-in-the-middle endgame tree — interactive: MeetInMiddleDiagram. Rendered on the canonical page (link above); not shown in this markdown export. ## The result On a 10×10 testbed BANDSAW settles the endgame exactly and pins the budget where exactness stops being affordable: the search tree grows about twenty-fold per extra mismatch, on both sides, so meeting in the middle stops paying off at full board size. That negative is the useful part: it tells you exactly where exact methods give out and heuristics must take over. The exact pieces that survived, the suffix lower-bound tables and the pruned branch-and-bound, became reusable instruments. A frame-free board scoring 437 came out of the same machinery. ## Method The join is the idea; the pruning is what makes it affordable. - **Meet in the middle.** Split the band into a top and bottom half. Enumerate every top-half fill up to a mismatch budget, keyed by (piece-set used, seam colour row). Enumerate the bottom half the same way, drawing only from the pieces the top half left. Join two halves wherever their seam colours agree *and* their piece-sets are disjoint. That join finds the exact best completion without ever walking the full tree, the classic [meet-in-the-middle](/research/build/exact/meet-in-the-middle) time-for- space trade. - **Suffix lower bounds.** Working backwards column by column builds exact lower-bound tables, so a partial that already cannot beat the current budget is pruned before it is extended. - **Budget ratchet.** Raise the mismatch budget one step at a time and re-solve; when a round finds nothing better, the previous best is *proven* optimal for that band. That proof is why this page is tagged **proven**, not measured: the result is a certificate, not a sample. The measured ceiling: each half grows ~20× per extra unit of budget, so at full 16×16 board size the top-half table no longer fits, memory, not time, is the wall. That negative is the deliverable: it pins exactly where exact methods give out and heuristics must take over. The frame-free 437 board fell out of the same machinery. ## Reproduce Deterministic (`kind: exact`): the meet-in-the-middle solve and its optimality proof reproduce byte-for-byte for a given band, and the 437 board is checkable in the viewer. The MITM enumerator and suffix-bound tables are committed with the research code. ## Open questions Can the lower-bound tables scale to the full 16×16 endgame, or does the seam state space grow too large? At what band size does memory rather than time become the limit? And can the rare cases where the middle join does fire be spotted in advance and finished exactly? ## Related - [STAGED](https://eternity2.dev/research/lab/experiments/raphael-anjou/pipelines/staged) — Build the whole board from scratch with no pre-set frame, in stages, letting the border emerge last from whatever pieces are left. - [Entropy and the area law](https://eternity2.dev/research/why/entropy-area-law) — Eternity II has two rules: edges must match, and each piece is used once. The first is generous. All the hardness lives in the second. - [Meet in the middle](https://eternity2.dev/research/build/exact/meet-in-the-middle) — Enumerate two halves of a problem and join them on a shared interface, trading memory for an exponent cut in half. The classic Horowitz–Sahni trick, what it looks like on bands of the board, and what this project's BANDSAW experiment measured, including the one-sided method that beat it. --- # Combination pipelines > The named search experiments that chase score. Each is a pipeline rather than a single algorithm: it builds a board with one engine, then lifts or finishes it with another. Each records its idea, its best board, and the questions it left open. - Canonical page (with interactive figures/demos): https://eternity2.dev/research/lab/experiments/raphael-anjou/pipelines/ - Updated: 2026-07-16 --- Every page here is one named experiment with an idea and a board, and nearly every one is a *pipeline*: it builds a board with one engine, then lifts or finishes it with another. That is what sets this group apart from the two studies that take a single paradigm apart, the [DFS study](/research/lab/experiments/raphael-anjou/dfs-study) and the [repair study](/research/lab/experiments/raphael-anjou/repair-study). These chain engines together, and the interest is as much in the *combination*, the division of labour between construction, repair and an exact endgame, as in any one stage. They share the [engines](/research/lab/experiments/raphael-anjou/engines); what differs is how each one composes and steers them: what it seeds, what it forbids, what it tears up and rebuilds. Each page's method section walks its stages in order. Several of the from-scratch builders lean on the beam producer, and two on the ALNS repair loop, engines that do not yet have their own write-ups here (see the [engines page](/research/lab/experiments/raphael-anjou/engines)); where a pipeline does, its page says so plainly rather than pointing at a page that is not up yet. They are ordered by what they taught, not by score. A pipeline that ended lower but explained why is worth more here than one that scraped a point and could not say how. ## Pages in this section - [GAUNTLET](https://eternity2.dev/research/lab/experiments/raphael-anjou/pipelines/gauntlet) — Run the same beam search across nine different scan orders, so it lands in different regions instead of always converging to the same one. The zigzag order found a brand-new 458 board. - [CLOISTER](https://eternity2.dev/research/lab/experiments/raphael-anjou/pipelines/cloister) — Fix a perfect border, then search the interior with the border's edges treated as hard constraints from the very first cell. - [MIDDEN](https://eternity2.dev/research/lab/experiments/raphael-anjou/pipelines/midden) — Decide in advance not when a board may break, but where: confine every mismatch to a chosen shape of cells, and search for the best shape. - [LADDER](https://eternity2.dev/research/lab/experiments/raphael-anjou/pipelines/ladder) — Throw hundreds of cheap short searches at the board, keep only the deepest starts, and promote the survivors through longer and longer rounds. - [MOSAIC](https://eternity2.dev/research/lab/experiments/raphael-anjou/pipelines/mosaic) — Tile the board into small blocks, solve each one to proven optimality, and glue them together, paying for the seams instead of forbidding them. From scratch, with no record to copy, it reaches 448. - [STAGED](https://eternity2.dev/research/lab/experiments/raphael-anjou/pipelines/staged) — Build the whole board from scratch with no pre-set frame, in stages, letting the border emerge last from whatever pieces are left. --- # CLOISTER > Fix a perfect border, then search the interior with the border's edges treated as hard constraints from the very first cell. - Canonical page (with interactive figures/demos): https://eternity2.dev/research/lab/experiments/raphael-anjou/pipelines/cloister/ - Updated: 2026-07-10 - Topics: local-search, backtracking - Source: Rare-colour border geography (this project): why the frame is the natural cut — https://github.com/raphael-anjou/eternity2/blob/main/web/content/research/why/rare-color-geography.mdx --- The border and the interior are usually solved together, which wastes effort: the interior keeps proposing pieces that can't possibly meet the border later. CLOISTER pins a perfect 60-piece frame first, then searches the 14×14 interior with the frame's inward-facing edges as real constraints from cell one, so a doomed interior is rejected immediately instead of at the end. ## How it works Start from a complete, perfectly-matched border. The interior search is a break-allowing depth-first fill, but the cells along the inner edge of the frame must match the frame, and that requirement is live from the first placement, not checked only when the interior is finished. Exact endgames score the last region, including how well it seals against the rim. Because the border is fixed, the search collects something a post-hoc interior can't: the handful of extra edges that come from the interior actually fitting the rim it was built against, rather than being grafted onto a rim later. > **[Figure]** Interactive: how the frame anchors the interior — interactive: BorderAnchorDiagram. Rendered on the canonical page (link above); not shown in this markdown export. Try it live: fix a frame and watch the interior search run against it in your browser. > **[Figure]** Interactive: solve the standalone interior live — interactive: CloisterLiveLab. Rendered on the canonical page (link above); not shown in this markdown export. ## The result As a standalone interior solver CLOISTER reaches an interior score of 453 unhinted, in minutes, and confirms a real effect: an interior built against its own rim attaches with a few more matched edges than the same-quality interior attached after the fact. With all five official clues forced it settles in the high 440s to low 450s. It doesn't break the top records, and it saturates like everything else does near the wall. But it cleanly isolates and measures the border-interior coupling that whole-board search blurs together. ## Method The search is a break-tolerant DFS over the interior, but the leverage is in the framing and a two-phase campaign over *many* frames. - **Frame as hard constraint.** A complete 60-piece border is fixed, and the frame's inward-facing colours become hard constraints on the rim cells from the very first interior placement, not a check deferred to the end. A doomed interior is pruned immediately. - **Exact tail.** The endgame region is solved exactly (a 14-cell exact tail), including how it seals against the rim, so the last few cells are closed deterministically rather than by heuristic. - **Frame-breadth campaign.** Rather than one border, sweep a directory of candidate frames in two phases: a cheap ~6-second hint-compatibility probe drops frames that can't host the clues, then a 30-second tail recipe runs over each surviving frame with 8 seeds. The best interior wins. The measured effect is small but real, and it comes from one thing: the border-interior coupling that whole-board search averages away, but that a rim-first build gets to exploit while it still can. 453 unhinted; high-440s to low-450s with all five clues forced. ## Reproduce Seeded and close to deterministic given a frame: the DFS interior solve off a fixed frame reproduces its score reliably, and the committed board is checkable edge by edge in the viewer. The solve needs one input beyond the puzzle, a pre-solved perfect border frame; a runnable backing directory that ships that frame alongside the engine is planned. ## Open questions How much of the rim-compatibility bonus can be collected without fixing the border first? Does scanning many borders, rather than one, find an interior that attaches better still? And where exactly does the strict-clue version's ceiling come from? ## Related - [STAGED](https://eternity2.dev/research/lab/experiments/raphael-anjou/pipelines/staged) — Build the whole board from scratch with no pre-set frame, in stages, letting the border emerge last from whatever pieces are left. - [The rare colors live on the frame](https://eternity2.dev/research/why/rare-color-geography) — Five of Eternity II's 22 colors appear only along the border ring, each on exactly 24 edges, never once in the interior. A structural split that shapes how every solver treats the frame. - [MIDDEN](https://eternity2.dev/research/lab/experiments/raphael-anjou/pipelines/midden) — Decide in advance not when a board may break, but where: confine every mismatch to a chosen shape of cells, and search for the best shape. - [Meet in the middle](https://eternity2.dev/research/build/exact/meet-in-the-middle) — Enumerate two halves of a problem and join them on a shared interface, trading memory for an exponent cut in half. The classic Horowitz–Sahni trick, what it looks like on bands of the board, and what this project's BANDSAW experiment measured, including the one-sided method that beat it. --- # GAUNTLET > Run the same beam search across nine different scan orders, so it lands in different regions instead of always converging to the same one. The zigzag order found a brand-new 458 board. - Canonical page (with interactive figures/demos): https://eternity2.dev/research/lab/experiments/raphael-anjou/pipelines/gauntlet/ - Updated: 2026-07-10 - Topics: construction - Reproduce: `just research-record-boards` - Source: Beam search (this project's concept page): the construction this varies the scan order of — https://github.com/raphael-anjou/eternity2/blob/main/web/content/research/build/construct/beam-search.mdx --- A beam search that always fills the board in the same order tends to discover the same kind of board, no matter the random seed. The order you visit the cells quietly decides which region you end up in, and across sixteen seeds, a single scan order produced just one distinct corner-arrangement family. GAUNTLET turns that into a tool: run the search across nine genuinely different scan orders, and you sample genuinely different regions. ## How it works GAUNTLET forks the constructive PRIOR beam and gives it a scan order it can swap: row, row-reversed, column, column-reversed, zigzag, zigzag-reversed, spiral-in, spiral-out, and diagonal, nine in all. Because the order of cells changes which partial boards survive at each step, each order explores a different trajectory rather than crowding into one. A sweep of 9 scans × 4 seeds produced **18 distinct corner-arrangement signatures**, against just one across sixteen seeds of the single-scan beam it grew from. Each full run produces a complete board; the strongest are then polished by a 30-minute ALNS lift. The finding is sharp: *scan order is a stronger diversity axis than the random seed.* That is the lever, and it is what the later KEYRING and PRIOR build on. > **[Figure]** Interactive: the construction-order schedule — interactive: GauntletDiagram. Rendered on the canonical page (link above); not shown in this markdown export. Step through one scan to see how the visit order steers the beam. > **[Figure]** Interactive: step through the build order — interactive: GauntletStepThrough. Rendered on the canonical page (link above); not shown in this markdown export. Or race the nine orders against each other, live, in your browser. > **[Figure]** Interactive: race the construction strategies — interactive: GauntletLiveRace. Rendered on the canonical page (link above); not shown in this markdown export. ## The board The search is stochastic, so it won't reproduce this exact board, but the board it found is fixed, bundled here, and checkable edge by edge. > **[Interactive: RecordBoard]** Rendered on the canonical page (link above); not shown in this markdown export. ## The result The zigzag order at seed 99, lifted, reached 458 of 480 in the corner arrangement cp=(3,0,1,2), the first board at or above 458 ever found in that arrangement in our database. It is at least 246 of 256 cells away from anything we had at that level: a genuinely new basin, not another route to a known one. So GAUNTLET's contribution is reach rather than a record: it opened a new region of strong boards. A second round (32 more lifts) topped out at 457 with no 461, which says the new family saturates like the others, but the family itself was the prize. ## Method The pipeline is three stages, and the parameters are the point. **Stage 1: diverse construction.** Fork PRIOR's beam and give it a swappable scan order over the 256 cells: `row`, `row_rev`, `col`, `col_rev`, `zigzag`, `zigzag_rev`, `spiral_in`, `spiral_out`, `diagonal`, nine orders, crossed with seeds `{1, 7, 42, 99}`. All share one prior (the `high459` matrix) at a low softmax temperature (0.05), so the beam is prior-guided but not deterministic. The order changes which partial boards survive each step, so each (scan, seed) walks a different trajectory. **Stage 2: lift.** Each strong build gets an ALNS lift (prior-escape + `basic_lkh` destroy/repair operators), 5 minutes per build in the sweep, longer for the finalists. **Stage 3: cluster.** Group all outputs by corner-permutation and flag the signatures absent from the existing database. That is how the 9×4 sweep surfaced **18 distinct corner families** where sixteen seeds of a single scan had surfaced one, the measured claim that *scan order is a stronger diversity axis than the seed.* The winning board, zigzag, seed 99, lifted, sits at cp = (3, 0, 1, 2), Hamming distance ≥ 246/256 from anything previously at that level: a new basin by the same corner-perm-plus-Hamming test [PRIOR](/research/lab/experiments/raphael-anjou/learning/prior) uses. ## Reproduce `just research-record-boards` verifies the committed 458 board's score exactly from its stored Bucas string. The sweep is stochastic (nine scans × four seeds, then a polish pass), so it will not reproduce the same board; the board is the artifact of record. The engine is the shared beam producer run across nine fill orders; it uses the same corpus-mined prior as [PRIOR](/research/lab/experiments/raphael-anjou/learning/prior), so the run is not reproduced from scratch here. ## Open questions Does this new family have the same rigid local structure as the others, or a different shape? And can a longer refinement lift it past 458, the way a fresh family sometimes has more room than a well-worn one? ## Related - [PRIOR](https://eternity2.dev/research/lab/experiments/raphael-anjou/learning/prior) — Build a board from nothing, breaking ties by where pieces tend to sit in the strong boards we already have. It reaches a high score with no starting board to copy. - [KEYRING](https://eternity2.dev/research/lab/experiments/raphael-anjou/learning/keyring) — Build a board from scratch, ranking each next piece by three signals learned from past strong boards. Reached 460 in a board family no earlier search had cracked. - [Beam search](https://eternity2.dev/research/build/construct/beam-search) — Keep the K most promising partial boards alive at once and grow them cell by cell. Beam search is the workhorse behind this project's from-scratch builders, and a clean illustration of why breadth alone stalls in the deep interior. --- # LADDER > Throw hundreds of cheap short searches at the board, keep only the deepest starts, and promote the survivors through longer and longer rounds. - Canonical page (with interactive figures/demos): https://eternity2.dev/research/lab/experiments/raphael-anjou/pipelines/ladder/ - Updated: 2026-07-10 - Topics: local-search - Source: Successive halving / restart strategies (this project's restarts concept page) — https://github.com/raphael-anjou/eternity2/blob/main/web/content/research/build/backtracking/restarts.mdx --- Most of a long search is wasted on starts that were doomed early. LADDER spends almost nothing to find out which beginnings are worth pursuing. It runs a flood of very short probes, keeps the few that got deepest, and only then pays for longer runs, on those alone. It's tournament selection for search starts. ## How it works Round one is hundreds of five-second probes from different random seeds, each trying to lay down a long run of perfectly-matched cells. Keep the deepest prefixes, and throw out ones that are near-duplicates of each other so the survivors stay diverse. Promote those to a longer round with tighter quality gates, then promote the best of those to a full-length run. Each rung spends more time on fewer, better candidates, the way successive-halving tournaments allocate effort to the contenders that keep winning. > **[Figure]** Interactive: the rung-by-rung progression — interactive: LadderDiagram. Rendered on the canonical page (link above); not shown in this markdown export. > **[Figure]** Interactive: run the ladder search live — interactive: LadderLiveLab. Rendered on the canonical page (link above); not shown in this markdown export. ## The result LADDER produced a 451 board obeying all five official clues, with no guidance from any known record, the first time the project escaped the band of 444 to 450 that unguided search kept landing in. The finishes are determined by their prefix: once a strong enough opening is banked, the rest follows. A longer run later touched 452, one edge more, though 451 is the board committed and reproducible here. It also mapped the limits: the supply of perfect openings runs out, and beyond a point the rungs all converge to the same ceiling. So LADDER is a good way to find the best start, not a way past the structural walls that stop every method near the top. ## Method The ladder is a recursive successive-halving tournament over search *starts*, scored by prefix depth. - **Round one: flood.** Hundreds of 5-second probes from different seeds, each laying down as long a run of perfectly-matched cells as it can. Rank by the depth of that perfect prefix; keep the deepest, and drop near-duplicates (prefixes too similar to a survivor) so the kept set stays diverse. - **Ratchet.** Each subsequent round pins the previous round's deepest banked prefix (a depth-15 pin in the recorded run) and probes *beyond* it, pushing the perfect-prefix frontier one notch further. The recursion stops when a round gains fewer than four cells of depth, the supply of deeper openings has run dry. - **Finish.** From the three deepest distinct prefixes, run long exact-tail-14 rungs (300 s × 8 seeds each) to convert the banked opening into a full board. The finding is that *the finish is determined by the prefix*: once a deep enough perfect opening is banked, the endgame follows. That is why concentrating compute on finding the best start, rather than spreading it across full runs, escaped the 444–450 band unguided search kept landing in. A longer finishing round later touched 452; the committed, reproducible board here is the 451. ## Reproduce Seeded; the probe-and-promote structure reproduces the *behaviour* reliably though the exact board depends on seeds. The committed 451 board is checkable in the viewer. The climb needs no corpus, frame, or witness, it runs from the puzzle alone, so a runnable backing directory for it is planned alongside the other from-scratch experiments. ## Open questions What's the real ceiling of prefix-first selection given more compute on the early rungs? Could the diversity rule be smarter about which near-duplicates to keep? And does combining the deepest prefixes from different families beat promoting within one? ## Related - [REPLAY](https://eternity2.dev/research/lab/experiments/raphael-anjou/learning/replay) — Rebuild the community's strict 460 boards exactly, and in doing so discover the move ordinary solvers can't make: paying two mismatches at a single cell. - [PRIOR](https://eternity2.dev/research/lab/experiments/raphael-anjou/learning/prior) — Build a board from nothing, breaking ties by where pieces tend to sit in the strong boards we already have. It reaches a high score with no starting board to copy. - [Restarts and heavy tails](https://eternity2.dev/research/build/backtracking/restarts) — Run the same backtracker on the same puzzle twice and the runtimes differ by powers of ten. The community measured this in 2007; the CSP literature had already named it. The cure (cut off, reshuffle, restart) is why every record solver since has been a restart portfolio. --- # MIDDEN > Decide in advance not when a board may break, but where: confine every mismatch to a chosen shape of cells, and search for the best shape. - Canonical page (with interactive figures/demos): https://eternity2.dev/research/lab/experiments/raphael-anjou/pipelines/midden/ - Updated: 2026-07-10 - Topics: local-search - Source: Piece theft (this project): the spatial view of where boards fail that MIDDEN gates against — https://github.com/raphael-anjou/eternity2/blob/main/web/content/research/why/piece-theft.mdx --- Most break-allowing solvers control when a mismatch is permitted: at certain depths, past a certain fill. MIDDEN controls where instead. It fixes a mask, a chosen set of cells, and rules that mismatches may only be paid inside it; everywhere else must match perfectly. Then it searches over the shape of that mask. Existing methods say when to take damage; this experiment asks where damage should live. ## How it works Pick a mask: a couple of rows, a couple of columns, a scattered lattice of cells, or a set chosen by color. Run the search forcing perfect matches outside the mask and allowing mismatches only inside it. Different mask shapes lead the search into different parts of the space, so the mask becomes a design knob rather than a fixed rule. Comparing shapes shows which geometry of allowed damage lets a board grow a long perfect run before it has to spend a mismatch. > **[Figure]** Interactive: the damage-geometry break masks — interactive: MaskShapeDiagram. Rendered on the canonical page (link above); not shown in this markdown export. ## The result A dispersed lattice of allowed-damage cells extends the longest perfect run markedly further than concentrating the damage in a row or two, pushing the perfect wall from around 150 cells to the 170s. The mechanism is clear; what stays open is the economics: turning a longer perfect run into a higher final score once the endgame has to absorb the deferred damage. So the mask is a real lever, the spatial complement to the usual timing controls, with a measured effect on how far a board stays perfect, but not yet a finished route to a record. ## Method Every other break-tolerant search gates damage by *when*, a depth, a fill fraction. MIDDEN gates by *where*. It is the first cell-set (WHERE) damage control against everyone else's depth (WHEN) gates. - **The mask.** A chosen set of cells (a 256-bit mask) is passed as `--break-cells`. Inside the mask, mismatches are allowed; everywhere else must match perfectly. The search is otherwise a standard break-tolerant DFS off a fixed frame. - **The sweep.** Mask *shape* becomes the design variable: a couple of rows, a couple of columns, a dispersed lattice, or a colour-chosen set, swept over shapes and densities, each 300 s × 8 seeds. The measured result is a graded-density design rule: a **dispersed lattice** of allowed-damage cells extends the longest perfect run from ~153 cells to 167–174 (**+21**), far more than concentrating the damage into a row or two. The mechanism is clear; the open economics is the endgame, a longer perfect run only helps if the tail can absorb the deferred damage, and the dispersed mask that maximizes the wall does not by itself seal the finish. The natural next step (composing a dispersed body-mask with an open tail) is exactly what the MIDDEN-v2 sweep set out to test. ## Reproduce Seeded off a fixed frame; the wall-extension effect reproduces across masks, though the exact board depends on seeds, and the committed 452 board is checkable in the viewer. Like [CLOISTER](/research/lab/experiments/raphael-anjou/pipelines/cloister) it needs a pre-solved border frame (plus the break-cell mask, which is a literal input); a runnable backing directory that ships the frame is planned. ## Open questions Which mask shapes convert a longer perfect run into actual matched edges at the end, rather than just deferring the damage? Can spatial masks be combined with timing controls so a board is gated in both where and when it may break? And is there a mask that mirrors where the best known boards actually carry their mismatches? ## Related - [LADDER](https://eternity2.dev/research/lab/experiments/raphael-anjou/pipelines/ladder) — Throw hundreds of cheap short searches at the board, keep only the deepest starts, and promote the survivors through longer and longer rounds. - [The rigidity wall](https://eternity2.dev/research/why/rigidity-wall) — Every record board we have is frozen in place. You cannot nudge your way from a great board to a perfect one, and we can prove it. - [CLOISTER](https://eternity2.dev/research/lab/experiments/raphael-anjou/pipelines/cloister) — Fix a perfect border, then search the interior with the border's edges treated as hard constraints from the very first cell. - [Piece theft, where solvers die](https://eternity2.dev/research/why/piece-theft) — A solver fills a few rows for free, then hits a wall in the middle of the board. Here's the mechanism: a scarce piece spent in the wrong place, rows ago. --- # MOSAIC > Tile the board into small blocks, solve each one to proven optimality, and glue them together, paying for the seams instead of forbidding them. From scratch, with no record to copy, it reaches 448. - Canonical page (with interactive figures/demos): https://eternity2.dev/research/lab/experiments/raphael-anjou/pipelines/mosaic/ - Updated: 2026-07-10 - Topics: exact-methods - Source: RC2 MaxSAT (the exact block solver): a core-guided weighted-MaxSAT algorithm — https://doi.org/10.3233/SAT190116 --- Eternity II has no local structure you can exploit globally, but a small window of it, a 4×4 block, solves to perfect optimality in seconds. MOSAIC is an experiment built on that single fact: if you can solve a block exactly, can you compose sixteen exact blocks into a whole board? ## How it works The 16×16 board is cut into sixteen 4×4 blocks, filled one at a time. Each block is handed to an exact MaxSAT solver, which finds the best possible placement of pieces in it. The trick is in how a block meets its already-placed neighbours: those shared edges are not hard requirements but *soft* targets the block is rewarded for matching. So a block can never become impossible; it simply pays for any seam it can't match, and always completes. The second idea fights piece theft directly. Before filling a block, MOSAIC holds back the globally scarcest pieces, so the last blocks aren't starved of the rare pieces their seams will demand. Tuning how much to reserve is the one real knob; too little and the corner starves, too much and the early blocks suffer. > **[Figure]** Interactive: the block-assembly search — interactive: MosaicBlockLab. Rendered on the canonical page (link above); not shown in this markdown export. ## The result The window primitive does what it promises: a 4×4 block solves to its 24-edge optimum in about thirty seconds, a 3×3 in eleven, confirming the puzzle really is tractable in the small. Composed across the whole board, from scratch and with no warm start, MOSAIC reaches 448 of 480. The reservation sweet spot is around eight percent of the pool. The shortfall is informative: almost all of it is in the last three blocks of the bottom-right corner, where the pool finally runs thin: piece theft again, now visible as a single bright spot on the board. Exact-in-the-small does compose, but the composition order spends its freedom early and pays for it at the end, the same shape every method here runs into. ## Method The exactness is genuine, and so is the backtracking that stitches it together. - **Exact blocks.** Each 4×4 block is encoded as a *weighted MaxSAT* problem and solved by RC2, a core-guided solver, to a provably-optimal fill. Shared edges with already-placed neighbours are *soft* clauses (rewarded, not required), so a block can never be infeasible, it pays for any seam it can't match and always completes. - **Backtracking over solutions.** MOSAIC is not a one-shot glue. Each block level keeps an *enumerator* of MaxSAT solutions, best-first, via RC2 plus blocking clauses that rule out already-seen fills. When a later block is starved or a level exhausts, it backtracks and pulls the *next* solution of the previous block (freeing a different set of pieces). It is a coarse 16-level backtracking search where each node is a whole optimal block. - **Scarcity reservation.** Before filling, MOSAIC holds back the globally scarcest pieces so the final blocks aren't starved of the rare pieces their seams demand. That reservation fraction is the one real knob; the measured sweet spot is ~8% of the pool. The window primitive is real: a 4×4 block reaches its 24-edge optimum in ~30 s, a 3×3 in ~11 s, the puzzle *is* tractable in the small. Composed from scratch it reaches 448, with the residual shortfall concentrated in the last three bottom-right blocks: [piece theft](/research/why/piece-theft) made visible as a single bright spot. ## Reproduce Deterministic: the MaxSAT block solves and the backtracking composition are exact, so `kind: exact`, the 448 board reproduces and is checkable edge by edge in the viewer. The block engine runs from the puzzle alone, with no corpus or seed board, its only external dependency being a MaxSAT solver, so a runnable backing directory for it is planned alongside the other exact experiments. ## Open questions Would a non-row-major block order, spiralling in or solving the constrained corner first, move the depletion off the hardest block? Could blocks overlap, so seams are solved twice and reconciled? And does a faster (Rust) primitive make a larger block size, with its stronger exact guarantee, affordable? ## Related - [BANDSAW](https://eternity2.dev/research/lab/experiments/raphael-anjou/meet-in-the-middle/bandsaw) — Solve a band of rows exactly by meeting in the middle, to find the true best ending and to measure how far ahead an endgame can be decided. - [Piece theft, where solvers die](https://eternity2.dev/research/why/piece-theft) — A solver fills a few rows for free, then hits a wall in the middle of the board. Here's the mechanism: a scarce piece spent in the wrong place, rows ago. - [Which wall stops which method](https://eternity2.dev/research/why/walls-and-methods) — The research section has two halves: the structural walls that make Eternity II hard, and the algorithms built to climb them. This page is the bridge: each method lined up against the wall it actually attacks, and the score where that wall stopped it. - [SAT and CSP encodings](https://eternity2.dev/research/build/exact/sat-csp-encodings) — Write the puzzle as clauses and hand it to an industrial solver: the obvious move, tried since 2008. Why complete solvers stall on the full board, and where their verdicts still earn their keep as impossibility proofs. --- # STAGED > Build the whole board from scratch with no pre-set frame, in stages, letting the border emerge last from whatever pieces are left. - Canonical page (with interactive figures/demos): https://eternity2.dev/research/lab/experiments/raphael-anjou/pipelines/staged/ - Updated: 2026-07-10 - Topics: construction - Reproduce: `just research-record-boards` - Source: Beam search (this project's concept page): the staged construction primitive — https://github.com/raphael-anjou/eternity2/blob/main/web/content/research/build/construct/beam-search.mdx --- Almost every solver starts by locking down the border, because the border is the most constrained part and pinning it shrinks the search. STAGED is an experiment in refusing that crutch. It builds the board in stages from the top down with all 256 pieces free, and never commits to a border until the very end, when the border simply falls out of what remains. The question it answers: can you reach a strong board without ever anchoring to a frame? ## How it works The build runs in four stages. The first two fill the top half of the board with a fast plain search, banking the partial boards that survive. At the handoff, a cheap admissible estimate throws out any partial that clearly can't be finished well, so later stages only work on promising starts. The third stage grows the next band of rows from those survivors. The fourth is an exact finisher on the bottom rows that minimizes mismatches, and it chooses the bottom border last, against whatever pieces are still unused. So the frame is not designed up front; it emerges as a consequence of everything above it. > **[Figure]** Interactive: the stage-by-stage build — interactive: StageBuildDiagram. Rendered on the canonical page (link above); not shown in this markdown export. ## The result STAGED reaches 436 of 480 from scratch, with an emergent border and all five official clues respected, built end to end with no frame to lean on. That's well below the records, and that gap is the finding: it measures how much the usual frame-first anchor is worth, and it showed the frame-free machinery works at full scale. Along the way it pinned down the anatomy of the very best boards: they are a perfect block of most of the board plus a thin band of mismatches concentrated in a few top rows. That shape is what later builders aim to reproduce on purpose. ## Method Four stages, each handing survivors to the next through an admissible filter. 1. **Top-half beams (stages 1–2).** Fill the top half with a fast plain search, banking the partial boards that survive. All 256 pieces are free, no frame is pinned. 2. **Admissible handoff.** At each stage boundary, a cheap *admissible* estimate (an optimistic upper bound on the best possible finish) discards any partial that provably can't be completed well. Because the estimate never under-counts the achievable score, discarding is safe, it only removes partials that cannot win. 3. **Band grow (stage 3).** Extend the surviving partials down the next band of rows. 4. **Exact finisher (stage 4).** Solve the bottom rows exactly, minimizing mismatches, and *choose the border last* from whatever pieces remain. The frame is not designed up front; it falls out of everything above it. The result is 436 from scratch with an emergent border, all five clues respected, well below the records, and that gap is the measurement: it prices what the usual frame-first anchor is worth. The by-product mattered more than the score: STAGED pinned the anatomy of the best boards, a large perfect block plus a thin band of mismatches in a few top rows, the target shape later builders aim at deliberately. ## Reproduce Stochastic (the top-half beams use randomized tie-breaking), so a re-run won't reproduce the exact board; the committed 436 board is the artifact of record and is checkable in the viewer. The engine is the shared beam producer, run in stages so the border emerges last rather than being fixed first. It needs no corpus or seed board, so a runnable backing directory for the full staged pipeline is planned alongside the other from-scratch builders. ## Open questions Can a generator that deliberately spends its mismatches in the top rows, to keep the rest perfect, reach the 450s frame-free? How much of the 436-to-record gap is the missing frame anchor versus the harder endgame? And does a learned finish-quality estimate pick better survivors than the cheap admissible one? ## Related - [CLOISTER](https://eternity2.dev/research/lab/experiments/raphael-anjou/pipelines/cloister) — Fix a perfect border, then search the interior with the border's edges treated as hard constraints from the very first cell. - [BANDSAW](https://eternity2.dev/research/lab/experiments/raphael-anjou/meet-in-the-middle/bandsaw) — Solve a band of rows exactly by meeting in the middle, to find the true best ending and to measure how far ahead an endgame can be decided. - [Beam search](https://eternity2.dev/research/build/construct/beam-search) — Keep the K most promising partial boards alive at once and grow them cell by cell. Beam search is the workhorse behind this project's from-scratch builders, and a clean illustration of why breadth alone stalls in the deep interior. --- # The repair study > The sibling of the DFS study, for the other way people attack Eternity II: destroy part of a board, rebuild it, keep the change if it helps. One question, asked carefully. What does each decision in that loop buy: which region to destroy, how to rebuild it, when to keep a move, when to restart, and what board to start from? - Canonical page (with interactive figures/demos): https://eternity2.dev/research/lab/experiments/raphael-anjou/repair-study/ - Updated: 2026-07-16 - Topics: local-search, search-space, speed - Reproduce: `just experiments repair-study` - Source: Runnable engine + committed results + scripts (this study's backing directory) — https://github.com/raphael-anjou/eternity2/tree/main/research/experiments/repair-study --- There are two ways people actually attack Eternity II. One is to build a board cell by cell and backtrack when it fails; the [DFS study](/research/lab/experiments/raphael-anjou/dfs-study) takes that apart. The other is to hold a whole board and *repair* it: rip out a region, rebuild it, keep the change if it helped, and repeat. Repair is the last stage of the construct-then-refine pipelines behind this project's own record-approaching boards, and it is the method the literature reaches for once a board is too good for a single-piece move to improve. This study takes the repair loop apart the same way its sibling took backtracking apart: one decision at a time, on the same ten corner-pinned variants, single core, sixty seconds a run. The maximum score is 480 matched edges. The loop itself is short. One iteration, walked through below. > **[Figure]** One destroy-and-repair iteration, step by step — interactive: RepairLoopDiagram. Rendered on the canonical page (link above); not shown in this markdown export. The point is not to win. Most variants finish in the 360s and 370s, and the one that does best (446) does so by starting from a strong backtracked board rather than a constructed one, which is itself the study's central lesson. Repairing a plain greedy board on one core for a minute is a small thing next to the pipelines the records use; what the study measures is *what each decision in the loop is worth* by changing one at a time and measuring the result with the same canonical scorer the DFS study and the rest of the site use. ## The family, and the leaderboard Five families, laid out so that neighbours differ by a single decision, all branching off one plain anchor loop (greedy start, destroy the mismatched cells, greedy refill, keep the result unless it loses score, never restart). **Starting board** changes where the loop begins. **Destroy operator** changes which cells each iteration lifts. **Repair** changes how the hole is rebuilt. **Acceptance** changes when a non-improving move is kept. **Restart** changes what happens once the loop stalls. > **[Interactive: RepairStudyLeaderboard]** Rendered on the canonical page (link above); not shown in this markdown export. ## What the study found - **Starting from a strong backtracked board wins the whole study.** The variant that spends its first twenty seconds running the DFS study's break-DFS, then repairs the resulting low-440s board, finishes highest of all, at a mean of 446 (best 449). Repair adds only a handful of edges on top of that board, but the board it starts from is a hundred points better than a greedy construction, and that carries through. This is the construct-then-refine division of labour the records use, reproduced end to end on one core in one minute. - **Among the greedy-start variants, random destroy wins and targeting the breaks backfires.** A geometry-blind destroy that lifts twelve *random* cells finishes at a mean of 402 (best 409) and keeps improving deep into the run. Every operator that targets the broken cells finishes below it, and the more precisely it fixates, the worse it does: the mismatched-cells anchor lands at 366, a larger connected-component destroy at 350. On a mediocre board there is improvement available everywhere, so exploring beats attacking where it already hurts. That inverts on a near-record board, where the few remaining mismatches are the only thing left to fix. - **The starting board sets the floor.** A greedy construction starts around 348; a random one starts near 18, and although the loop lifts it a spectacular 308 points, it still finishes below where the greedy start *began*. Construction is the lever, repair is the polish. - **The acceptance rule is the other real lever.** Simulated annealing, which steps downhill occasionally to leave a plateau, is the strongest acceptance rule by a clear margin (mean 377, best 394), well ahead of a strict hill-climb (361). How much a non-improving move is allowed is worth a sixteen-point swing on the same loop. - **The clever refinements buy nothing here.** A whole-band destroy is inert (zero improvements on nine of ten instances). A bounded *exact* refill of a small hole does not beat a plain greedy refill of the same hole, a clean negative result: its locally-perfect rebuilds cost enough iterations that more, cheaper greedy rebuilds reach just as far. Neither a random kick nor a revert-to-best on a stall moves the score off the no-restart baseline. Each of these has its own treatment: how the engine is built and what every raised statistic means is on the [method page](/research/lab/experiments/raphael-anjou/repair-study/method), and the destroy, repair, acceptance, restart and starting-board comparisons are worked through on the [findings page](/research/lab/experiments/raphael-anjou/repair-study/findings). ## How to read the numbers Every board is re-scored by the one canonical scorer, and no engine's self-reported score is trusted. The loop maintains its score incrementally as it places and lifts pieces, but the published number is always a fresh canonical re-score of the output board. Throughput is reported in repair-iterations per second and is **never compared across families**, because an iteration that runs an exact refill is not the same unit of work as one that runs a greedy fill. The axis to watch is the *stall*: the iteration at which the global best last improved, against the total iterations run. When the first is a few thousand and the second is hundreds of thousands, the run found its answer early and then ground the same basin for the rest of the minute. That gap is the measured form of a long-standing observation about this puzzle, that destroy-and-repair is a superb basin-explorer and essentially never escapes the basin it lands in. The whole apparatus (the engine, the ten variants, the committed per-run results and the grid scripts) lives under the study's [backing directory](https://github.com/raphael-anjou/eternity2/tree/main/research/experiments/repair-study), and `just experiments repair-study` rebuilds the engine and reruns the whole grid. The board, scorer and IO layer come from a [shared library](https://github.com/raphael-anjou/eternity2/tree/main/research/experiments/common) the DFS study uses too, so a repaired board and a backtracked one are scored by exactly the same code. ## Pages in this section - [How the study is built](https://eternity2.dev/research/lab/experiments/raphael-anjou/repair-study/method) — The engine behind the repair study: one composable destroy-and-repair loop where a variant is a declared change over a parent, the shared IO and scorer it sits on with the DFS study, an incrementally-maintained mismatch map, and the definitions of every statistic the study raises. - [What each decision buys](https://eternity2.dev/research/lab/experiments/raphael-anjou/repair-study/findings) — The five comparisons at the heart of the repair study, worked through: blind random destroy wins while every conflict-targeting operator loses; construction sets the floor; simulated annealing is the strongest acceptance rule; and the clever refinements (exact refill, restarts) buy nothing at this budget. ## Related - [Raphaël Anjou's experiments](https://eternity2.dev/research/lab/experiments/raphael-anjou) — A notebook of Eternity II search experiments, organised into the shared engines they run on, the combination pipelines that chase the score, three studies that take one search paradigm apart a decision at a time, and exact endgame solves. Each has its idea, its best board, and the questions it left open. The best reaches 463 of 480. - [The DFS study](https://eternity2.dev/research/lab/experiments/raphael-anjou/dfs-study) — One question, asked carefully: among depth-first backtrackers for Eternity II, what does each fill order, each heuristic, and the break mechanism actually buy? A family of from-scratch backtrackers, each one change apart, run on the same ten corner-pinned variants, single core, sixty seconds. - [Local search and ALNS](https://eternity2.dev/research/build/local-search/local-search-alns) — Destroy part of a board, rebuild it better, and let the algorithm learn which demolitions pay. Adaptive large-neighborhood search is the most reliable polisher this project has, and the cleanest demonstration of the wall where polishing ends. --- # What each decision buys > The five comparisons at the heart of the repair study, worked through: blind random destroy wins while every conflict-targeting operator loses; construction sets the floor; simulated annealing is the strongest acceptance rule; and the clever refinements (exact refill, restarts) buy nothing at this budget. - Canonical page (with interactive figures/demos): https://eternity2.dev/research/lab/experiments/raphael-anjou/repair-study/findings/ - Updated: 2026-07-16 - Topics: local-search, search-space, speed - Source: Committed per-run results (results.jsonl) and per-family report (report.md) — https://github.com/raphael-anjou/eternity2/tree/main/research/experiments/repair-study/results --- Five comparisons carry the [repair study](/research/lab/experiments/raphael-anjou/repair-study). Each isolates one decision by holding the other four fixed at a plain anchor loop: greedy start, destroy the mismatched cells, greedy refill, keep the result unless it loses score, never restart. All scores are the mean matched-edge count over the ten corner-pinned variants, single core, sixty seconds. Iteration rate is never compared across families. ## The starting board: the lever the loop cannot replace Change only the board the loop begins from, and everything else about the run is downstream of it. A greedy construction begins around 348 and the loop lifts it to a mean of 366. A random board begins near 18 and the loop lifts it an enormous 308 points, to a mean of 326. That larger lift is not the loop doing better; it is the loop doing the construction's job badly. The random start, after millions of iterations, still finishes below where the greedy start *began*. This is the study's first and firmest result: **construction is the lever, repair is the polish.** A rarest-colour-first greedy construction (the Selby and Riordan heuristic that a scarce colour should be spent where it is forced) starts a little higher still and finishes at a mean of 373, the best of the *greedy* starts. The clearest proof of the point is to start from a genuinely strong board rather than a greedy one. The final starting-board variant hands the loop a board built by the [DFS study's](/research/lab/experiments/raphael-anjou/dfs-study) break-DFS: the run spends its first twenty seconds backtracking to a board in the low 440s, then repairs it for the remaining forty. That start is a hundred points above a greedy construction, and it carries straight through to the finish. It is the highest-scoring variant in the whole study, at a mean of 446 (best 449), far above the random-destroy loop's 402, and it settles the construct-then-refine question the rest of the study circles: repair *does* add a few edges on top of a strong backtracked board, but only a few, and the board it starts from decides almost everything. This is exactly the division of labour the records use, and this study reproduces it end to end on one core in one minute: a backtracker to build a good board, then a repair loop to squeeze the last edges out of it. ## The destroy operator: attacking the breaks can backfire Now fix the greedy start and change only which cells each iteration lifts. This is the axis with the study's most surprising result. > **[Figure]** The four destroy operators, on one board of broken seams — interactive: DestroyOperatorDiagram. Rendered on the canonical page (link above); not shown in this markdown export. - **A geometry-blind random destroy wins the destroy comparison, at a mean of 402 (best 409).** Lifting twelve *random* cells instead of the broken ones, it keeps sampling fresh regions of the board, accepts nearly three quarters of its moves, and its best score keeps improving deep into the run: its last improvement lands past three million iterations, where every conflict-driven variant has long since frozen. It is the best of every variant that starts from a greedy board (only the DFS-seeded start, a different lever entirely, finishes higher). - **Every conflict-driven operator finishes below it, and the more it fixates on the breaks, the worse it does.** The mismatched-cells anchor, which lifts up to a dozen of the broken cells, averages 366 and stalls early: it rips out the same clustered tangle, greedily rebuilds it to almost the same placement, and its best score stops moving within a few thousand iterations. The component-plus-halo operator, which lifts one whole connected tangle (a much larger hole), does worse still, at 350, and its best last improves at iteration 211: a hole that size hands the greedy refill a subproblem it cannot improve, so almost nothing is ever kept. - **A whole-band destroy is inert.** Lifting the two rows with the most breaks leaves the greedy refill a subproblem nearly as hard as the puzzle itself; on nine of the ten instances it makes *zero* improvements over the whole minute, so its reported score is simply its starting board. The pattern is clean and worth stating plainly: on this mediocre greedy start, the more precisely an operator targets the existing breaks, the worse it does, and blind random destroy wins. This is the opposite of the natural intuition, and of what works on a *near-record* board, where the whole board is close to optimal and the community's tuning found conflict-driven and component operators most valuable precisely because the few remaining mismatches are the only thing left to fix. This study never reaches that regime. Sixty seconds on a mediocre board leaves broad improvement available everywhere, and there an operator that keeps re-attacking the same broken cluster, or that tears out a hole too large to rebuild well, both lose to one that simply keeps trying fresh small regions. The finding is not "conflict-driven destroy is bad" but "which operator wins depends on how good the board already is, and on a mediocre board, exploring beats both fixating and over-destroying." ## Repair: how the hole is rebuilt Fix the destroy and change only the refill. Breaking the greedy refill's exact score ties with a seeded coin, rather than deterministically, adds a little exploration and helps slightly, to a mean of 365. The sharper comparison is greedy against *exact* refill, and it has to be set up carefully to be a clean one-axis test: the exact refill only pays off when the hole is small enough to search, so the study pairs it with a small destroy (at most six mismatched cells) and compares it against the *same* small destroy refilled greedily, so the only thing that changes between the two is the refill. Set up this way, the exact refill runs on every iteration rather than falling back to greedy, rebuilding each small hole to its true optimum. The result is a clean negative one. The exact refill (mean 360) does **not** beat the greedy refill of the same small hole (mean 363); if anything it is a shade behind. Two things explain it. The exact refill accepts nearly every iteration, because a locally-optimal rebuild of a six-cell hole almost never lowers the score, so the loop drifts sideways rather than climbing. And it buys that local optimality at roughly a third of the iteration count, so over a fixed minute it explores less of the board. On this puzzle, at this budget, a locally-perfect rebuild of a tiny region is not worth what it costs: the greedy refill's cheaper, slightly worse rebuilds, run more often, reach just as far. This is the same node-rate-is-not-score question the DFS study's heuristic engines raise, and here the answer comes out on the side of more, cheaper iterations, which is worth recording precisely because the opposite is so often assumed. ## Acceptance: how much a non-improving move is allowed matters Fix the loop and change only when a non-improving candidate is kept. Of the five axes, this one moves the score the most after the destroy operator. - **A strict hill-climb, which keeps only strict improvements, is the weakest, at a mean of 361.** Refusing every sideways move locks it into the first basin it finds; its accept rate is essentially zero. - **Allowing equal-or-better moves (the anchor) does better, at 366.** The sideways moves let it drift across the equal-score plateaus that dominate this landscape. - **A cooling simulated-annealing rule is the strongest acceptance by a clear margin, at 377 (best 394), among the best of the greedy-start variants.** Allowing occasional *worsening* moves early, then cooling, lets it leave a plateau that pure sideways drift is trapped on, and its best score keeps improving to around iteration twenty thousand rather than freezing in the first few thousand. A late-acceptance rule, which compares against the score some tens of iterations ago, lands between the two at 369. So the acceptance rule is a real lever here, not a detail: strict to annealing is a sixteen-point swing on the same loop (361 to 377). That is worth stating against a known observation from the community's own ALNS tuning, that across a wide range of annealing temperatures the final scores were essentially identical. The two are not in conflict. That tuning was done on near-record boards, where the landscape is a sea of equal-score plateaus and any temperature accepts almost everything; this study's mediocre starting board still has real downhill structure to exploit, so whether the rule will step downhill to escape a plateau genuinely matters. Which acceptance rule wins, like which destroy operator wins, depends on how good the board already is. ## Restart: neither perturbation moves the needle Fix the loop and change only what happens once it stalls. Doing nothing lets the run grind the same basin for the rest of the minute. A random *kick*, which unplaces and randomly refills a couple of dozen cells when the best has not moved for a while, and a *revert to the best board so far*, which re-attacks the incumbent, are the two perturbations tested. Both land within a point of the no-restart anchor (365 and 365, against the anchor's 366). This is a clean null result: bolting a stall-detector and a perturbation onto the greedy-mismatch loop does not help it, because the perturbation either throws away the structure that made the board good (the kick) or returns to a board the same operator has already stalled on (the revert). Neither turns the loop into a basin-escaper; on this puzzle, escaping a basin needs a different move than perturb-and-repair, which is exactly what the [rigidity wall](/research/why/rigidity-wall) and the [σ-cycle structure](/research/why/sigma-cycles) explain. ## The through-line Two themes run through the five comparisons. The first is that **the two decisions that move the score are the destroy operator and the acceptance rule**, and both move it in the same counterintuitive direction: the winning choices are the ones that keep the loop *exploring* rather than *exploiting*. Random destroy beats every operator that targets the breaks; annealing, which steps downhill to leave a plateau, beats every rule that only moves sideways or uphill. Refining the refill and bolting on a restart, the two decisions that try to be cleverer about a region the loop is already stuck on, buy nothing. The second is why exploring wins here and fixating wins on a near-record board: **the repair loop is a basin explorer, not a basin escaper.** On a mediocre board there is broad downhill structure everywhere, so the moves that cover more of it win; on a near-record board there is none left but a single interlocking cycle, so the moves that target it precisely win. Neither regime lets perturb-and-repair escape a basin once it is in one. That is why the construct-then-refine pipelines that reach this project's best boards divide the labour the way they do: a strong constructive producer to choose a good basin, and repair as the last mile inside it, never asked to climb out. ## Related - [The repair study](https://eternity2.dev/research/lab/experiments/raphael-anjou/repair-study) — The sibling of the DFS study, for the other way people attack Eternity II: destroy part of a board, rebuild it, keep the change if it helps. One question, asked carefully. What does each decision in that loop buy: which region to destroy, how to rebuild it, when to keep a move, when to restart, and what board to start from? - [How the study is built](https://eternity2.dev/research/lab/experiments/raphael-anjou/repair-study/method) — The engine behind the repair study: one composable destroy-and-repair loop where a variant is a declared change over a parent, the shared IO and scorer it sits on with the DFS study, an incrementally-maintained mismatch map, and the definitions of every statistic the study raises. - [Local search and ALNS](https://eternity2.dev/research/build/local-search/local-search-alns) — Destroy part of a board, rebuild it better, and let the algorithm learn which demolitions pay. Adaptive large-neighborhood search is the most reliable polisher this project has, and the cleanest demonstration of the wall where polishing ends. --- # How the study is built > The engine behind the repair study: one composable destroy-and-repair loop where a variant is a declared change over a parent, the shared IO and scorer it sits on with the DFS study, an incrementally-maintained mismatch map, and the definitions of every statistic the study raises. - Canonical page (with interactive figures/demos): https://eternity2.dev/research/lab/experiments/raphael-anjou/repair-study/method/ - Updated: 2026-07-16 - Topics: local-search, speed - Source: The engine workspace (repair-engine, repair-run) on the shared e2-core / e2-io library — https://github.com/raphael-anjou/eternity2/tree/main/research/experiments/repair-study/engine --- This page is the apparatus behind the [repair study](/research/lab/experiments/raphael-anjou/repair-study): how the engine is built, why a new variant is cheap to add, and what every number on the results means. It is the deliberate twin of the [DFS study's method page](/research/lab/experiments/raphael-anjou/dfs-study/method), and it sits on the *same* shared library: the board, the piece set, the one canonical scorer and the IO contract all come from a common `e2-core` / `e2-io` crate that the backtracking study uses too. A repaired board and a backtracked board are therefore scored by the identical code, which is what lets numbers from the two studies sit on one axis. ## A variant is a declared change over a parent Every algorithm in the study is the *same* destroy-and-repair loop, parameterised by five independent choices: - **starting board**: the board the loop begins from (random, greedy construction, or a rarest-colour-first greedy construction); - **destroy operator**: which cells each iteration lifts (random, the mismatched cells, the worst row band, or one connected mismatch component plus a halo); - **repair**: how the hole is refilled (greedy most-constrained-first, the same with jittered tie-breaks, or a bounded exact refill for small holes); - **acceptance**: whether a candidate replaces the working board (keep if not worse, strict improvements only, simulated annealing, or late-acceptance); - **restart**: what happens on a stall (nothing, a random kick, or a revert to the best board so far). A variant is a small record naming those five choices, together with **the parent it derives from and a one-line description of the single change it adds**. Adding a variant means adding one record to the registry, with no new loop code unless the idea is a genuinely new strategy. The "what stacks on what" matrix on the results page is generated from those descriptions, so it cannot drift from the code that ran. ## The mismatch map, maintained incrementally A backtracker builds a board up from nothing; a repair loop always holds a *complete* board and edits it. The cells worth attacking are the ones touching a broken edge, so the engine keeps a live count, per cell, of the broken interior edges incident to it. Placing or lifting a piece updates only the edges around that one cell, never the whole board, so a conflict-driven destroy operator can ask "which cells touch a mismatch?" without rescanning. The running score is kept the same way: each placement adjusts it by the handful of seams that changed. A full rescan happens exactly once, when the starting board is built; from then on the loop is incremental. This is what makes hundreds of thousands of iterations in sixty seconds possible, and it is the same discipline the [ALNS theory page](/research/build/local-search/local-search-alns) describes as keeping destroy at cost proportional to the hole, not the board. ## The scorer is the single source of truth No engine's self-reported score is trusted. The loop's incremental score is a performance device; the *published* number is always a fresh canonical re-score of the output board, through the same scorer the site and the DFS study use (matched, non-border, interior adjacencies, counted right and down per cell). A test asserts the incremental score and the canonical score agree after thousands of random place-and-lift edits, so the fast path can be trusted to track the truth rather than drift from it. ## The statistics the study raises For every run the engine records, and the results carry all the way to the page: - **final score**: the canonical matched edges (of 480) of the best board found. - **lift**: final score minus the starting board's score. This isolates the repair loop's own contribution from the construction it began with: a variant that starts high can add little and still finish high, and the lift is what separates the two. - **the stall (last-best iteration vs total iterations)**: the iteration at which the global best last improved, against how many iterations the budget bought. This is the study's headline axis: when the first is far below the second, the run found its answer early and then moved nothing. - **accept rate**: the fraction of iterations the acceptance rule kept. A rate near zero means the loop is proposing changes it almost always rejects, often a sign it is re-attacking the same region. - **mean destroy size**: cells lifted per iteration, so a large-hole operator is not silently compared to a small-hole one. - **iterations per second**: reported per variant and **never compared across families**, because an iteration running an exact refill is not the same unit of work as one running a greedy fill. - **restarts**: perturbations fired, zero for a variant with no restart policy. The page also draws a **convergence curve** for a few representative variants: the best score so far, sampled every two hundred iterations, as a typical run progresses. It is the clearest picture of the stall: the curve rises steeply, then goes flat while the iteration count keeps climbing. ## Honesty about the greedy engine's speed Like the DFS study's MRV engine, the repair loop here is written for clarity first. The greedy refill rescans the remaining piece pool for every cell it fills, rather than maintaining candidate lists incrementally, so its iterations-per-second is this clean engine's rather than the best a tuned repair kernel could reach. The ranking by score does not depend on it, since throughput is a separate axis never mixed into the score comparison, but the iteration rates should be read as this engine's, not as the ceiling for destroy-and-repair. ## What this study deliberately does not claim This is a study of the *plain* repair loop, one decision at a time, at a small fixed budget. It is not the record pipeline: the boards that reach the mid-450s and beyond combine a strong constructive producer, longer runs, and repair as a final polish, and several of the operator findings here would read differently on a near-record board than they do on the mediocre greedy start the loop begins from. Where a result depends on the starting board's quality, the findings page says so. The community's own tuning found, for instance, that conflict-driven and component operators are valuable precisely on near-optimal boards where the few remaining mismatches are the only thing left to fix, the regime this study's short runs never reach. ## Reproducibility The engine, the ten variants, the committed per-run results and the grid scripts all live under the study's [backing directory](https://github.com/raphael-anjou/eternity2/tree/main/research/experiments/repair-study). `just experiments repair-study` rebuilds the engine and reruns the whole grid; the run is deterministic at a fixed seed, and the corner arrangement is the only diversity axis. ## Related - [The repair study](https://eternity2.dev/research/lab/experiments/raphael-anjou/repair-study) — The sibling of the DFS study, for the other way people attack Eternity II: destroy part of a board, rebuild it, keep the change if it helps. One question, asked carefully. What does each decision in that loop buy: which region to destroy, how to rebuild it, when to keep a move, when to restart, and what board to start from? - [What each decision buys](https://eternity2.dev/research/lab/experiments/raphael-anjou/repair-study/findings) — The five comparisons at the heart of the repair study, worked through: blind random destroy wins while every conflict-targeting operator loses; construction sets the floor; simulated annealing is the strongest acceptance rule; and the clever refinements (exact refill, restarts) buy nothing at this budget. - [Local search and ALNS](https://eternity2.dev/research/build/local-search/local-search-alns) — Destroy part of a board, rebuild it better, and let the algorithm learn which demolitions pay. Adaptive large-neighborhood search is the most reliable polisher this project has, and the cleanest demonstration of the wall where polishing ends. --- # Single-core benchmark > Fifteen solvers, ours and our implementations of the community's two record backtrackers, each run once on ten corner-pinned variants of the official puzzle, single core, 60 seconds per run. The finding: node count is not score. - Canonical page (with interactive figures/demos): https://eternity2.dev/research/lab/experiments/single-core-benchmark/ - Updated: 2026-07-13 - Topics: speed, construction, backtracking - Reproduce: `just experiments single-core-benchmark` - Source: Runnable engine + committed results + scripts (this experiment's backing directory) — https://github.com/raphael-anjou/eternity2/tree/main/research/experiments/single-core-benchmark --- Give every solver the same budget, one core and one minute, and which one wins? The answer overturns the obvious intuition. Several solvers, ours and our implementations of the community's two record backtrackers, each ran once on ten corner-pinned variants of the official puzzle, single-threaded, 60 seconds a run. Every board was re-scored by one canonical scorer; no engine's self-reported score is trusted. The maximum possible score is 480. > **Every engine here is our code** > > `blackwood_style` and `verhaard_style` are **our from-scratch implementations** of Joshua Blackwood's and Louis Verhaard's published algorithms, not the authors' own programs. Verhaard's `eii` only ever shipped as a Win32 binary, so a re-implementation (its constants recovered from `eii.exe`) is the only way to run it at all. Blackwood's real C# *is* [public](https://github.com/jblackwood345/EternityII_Solver), but it hardcodes its 256 pieces and its thread count, so it cannot read this grid's variants or be pinned to one core without editing it. Scores here measure our reading of each algorithm, not the authors' engineering, and should not be quoted as "Blackwood scores N". The leaderboard below shows the methods that compete on score. A second family, the CSP presets (one arc-consistency engine run under a dozen ordering knobs), is a different category: its best preset reaches about 183, less than half a contender's score, so it earns no leaderboard row. That preset sweep is a study in its own right, on its [own page](/research/lab/experiments/single-core-benchmark/csp-presets). ## What a minute of one core buys The two record backtrackers dominate this budget. Our Verhaard-style engine reaches a mean of **440.8** (best 451) and our Blackwood-style engine **436.4** (best 440), both exploring 20 to 40 million search-nodes per second. Nothing else comes close: naive DFS lands at **365.6**, and the best CSP preset at about **183**. The gap between those two groups is the finding. All four families see the same puzzle and the same 60 seconds, and they finish 250 points apart. What separates them is not speed: the CSP engines are three orders of magnitude slower per node than the backtrackers and still beat naive DFS on friendly variants, because each node is pruned rather than merely visited. Node count and score are not the same axis. What this grid cannot tell you is where the ceiling is. The best board here (451) is still 13 points short of the community's 5-clue record of 464, and the top engine's mean sits about 24 short; the records were not set in a minute, they came from farms and months. This measures per-core efficiency at a fixed small budget, nothing more. > **[Figure]** The leaderboard: mean score over ten corner variants, single core, 60 s — interactive: BenchmarkLeaderboard. Rendered on the canonical page (link above); not shown in this markdown export. ## Reading the table The two backtrackers are the top of this board and they are stable there: the Verhaard-style engine spans 437 to 451 across the ten variants, the Blackwood-style engine 431 to 440. The naive baseline is the floor: a fast, junk-filled 365 that shows what raw matched-edge count looks like without any board quality. Throughput units differ by family and are never cross-compared. The backtrackers count search-nodes per second, the CSP engines the same but at 5 to 10 thousand, because each of their nodes runs full arc-consistency. The CSP family trades throughput for pruning, which is why it explores far fewer nodes yet still beats naive DFS on good variants. ## What each contender is doing - **Verhaard and Blackwood (backtrackers, ranks 1 to 2).** Depth-gated-break DFS at 20 to 40 million nodes per second. They punch to 437 to 451 but hit a wall: the endgame needs far more compute than 60 seconds allows. Blackwood found his 470 after about a month on a single PC, and called it "a stroke of luck" ([message 10194](https://groups.io/g/eternity2/message/10194)). - **Naive DFS (the baseline).** Fills the whole board allowing every break. In row-major order (`anjou-naive_rowmajor`) it reaches a high matched-edge count (365) but a low-quality board full of breaks. Fast, and junk. It sits on the board as a floor: the number a method has to clear to be worth anything. (The visit-order sensitivity of naive DFS, and why the spiral variant collapses to 78, is on the [CSP presets page](/research/lab/experiments/single-core-benchmark/csp-presets) alongside the other same-engine ablations.) ## Where these numbers sit This grid caps every engine at one core for 60 seconds, far below the compute that produced the records below. It measures per-core efficiency and heuristic quality, not peak reachable score. An engine that ranks high here reaches good boards cheaply; the record numbers need many cores times hours. Every variant here pins all 5 official clues (plus 3 corners, so 8 hints in total), so the relevant ceiling is the **5-clue community record of 464**, not the all-hints 470 (which uses more than the 5 clues). That 464 is what the leaderboard's dashed line marks. | reference | score | conditions | |:--|--:|:--| | Community 5-clue record | 464 | Benjamin Riotte, July 2026 (same 5 clues these variants pin) | | This grid's best (Verhaard-style) | 451 | one core, 60 s (mean 440.8 over 10 variants) | | Blackwood-style in this grid | 440 | one core, 60 s (mean 436.4 over 10 variants) | | Community all-hints ceiling | 470 | Blackwood, ~1 month on a single PC, uses more than 5 clues | ## Method and reproducibility Each of the ten variants is the official puzzle plus three pinned corner cells (distinct corner-piece arrangements), so all ten share the 256-piece set and 5 clue hints but differ in three corner constraints. They are emitted as both site-schema JSON (for the native engines) and CSV (for the standalone engines) from one generator, so every algorithm sees identical instances. One run per puzzle, fixed seed; the corner arrangement is the only diversity axis. Every run emits a bucas `.url`, and the score is the canonical matched-edge count from the same scorer, never the engine's self-report. There were zero failures across all 150 runs. Every engine in the grid is our own open-source code and runs from this repository, including the two written from the community's published algorithms; no third-party solver is vendored here. The grid measures all of them; the leaderboard above shows only the five that compete on score, and the [CSP presets page](/research/lab/experiments/single-core-benchmark/csp-presets) shows the rest. The crate workspace, the ten variants, the committed per-run results and the grid scripts all live under the experiment's [backing directory](https://github.com/raphael-anjou/eternity2/tree/main/research/experiments/single-core-benchmark), and `just experiments single-core-benchmark` builds the engines and reruns the whole grid. The native family (the naive and CSP presets) is one binary selected by preset; the two backtrackers are a binary each, driven by a small wrapper. Both speak the same puzzle-in, bucas-url-out contract, and every board is re-scored by the one canonical scorer. ## Companion findings Profiling put 96.6 percent of the CSP family's time in one heavily pre-optimised AC-3 loop. That engine is already at its performance ceiling; the benchmark speeds are its real speeds, not an implementation gap. Separately, the community's Blackwood constants do not transfer across colour labelings: its published privileged colours scored 387 in our labeling versus 435 for a re-fit, a 48-point gap that our Blackwood closes by re-fitting only the labeling-relative colour IDs while matching every structural element of the published spec. ## Open work The grid runs our implementations. Two of the community's three record engines can in principle be run directly, and that is the obvious next measurement: - **Peter McGavin's C generator.** He posted the source to the list in January 2026 as `genbody71.zip` ([message 11749](https://groups.io/g/eternity2/message/11749)). It builds on Apple silicon with `clang` and its generate pass emits a 10,363-line `body.c` specialised to one puzzle. It is the fastest engine the community has measured, at 295M placements/s on Joe's CPU ([message 11750](https://groups.io/g/eternity2/message/11750)), and it is absent from this grid. - **Joshua Blackwood's C#.** [Public and GPL-3.0](https://github.com/jblackwood345/EternityII_Solver); it builds unmodified on .NET 8. But it hardcodes all 256 pieces in `Util.cs`, fixes `number_virtual_cores = 64`, and takes no arguments, so pinning it to one core or feeding it this grid's variants means editing his source, at which point the artifact is no longer purely his. Running it as published, on the plain puzzle, is the faithful form of that measurement. - **Louis Verhaard's `eii`** cannot be run at all: the download from his own site ships `eii.exe` and no source, which is why our engine reconstructs it from the binary. Neither engine is vendored into this repository; both are fetched and run locally when measured. ## Pages in this section - [CSP presets, measured](https://eternity2.dev/research/lab/experiments/single-core-benchmark/csp-presets) — One constraint-propagation engine, run under a dozen ordering and propagator presets, on the same ten corner-pinned variants as the leaderboard. A study of what each knob buys, kept off the headline board because the best preset reaches less than half a contender's score. ## Related - [PRIOR](https://eternity2.dev/research/lab/experiments/raphael-anjou/learning/prior) — Build a board from nothing, breaking ties by where pieces tend to sit in the strong boards we already have. It reaches a high score with no starting board to copy. - [Beam search](https://eternity2.dev/research/build/construct/beam-search) — Keep the K most promising partial boards alive at once and grow them cell by cell. Beam search is the workhorse behind this project's from-scratch builders, and a clean illustration of why breadth alone stalls in the deep interior. --- # CSP presets, measured > One constraint-propagation engine, run under a dozen ordering and propagator presets, on the same ten corner-pinned variants as the leaderboard. A study of what each knob buys, kept off the headline board because the best preset reaches less than half a contender's score. - Canonical page (with interactive figures/demos): https://eternity2.dev/research/lab/experiments/single-core-benchmark/csp-presets/ - Updated: 2026-07-15 - Topics: backtracking, search-space - Reproduce: `just experiments single-core-benchmark` - Source: Runnable engine + committed results + scripts (this experiment's backing directory) — https://github.com/raphael-anjou/eternity2/tree/main/research/experiments/single-core-benchmark --- The [single-core benchmark](/research/lab/experiments/single-core-benchmark) leaderboard shows the methods that compete on score. This page shows the rest: a dozen presets of one constraint-satisfaction engine, plus the naive DFS in its weaker visit order. They are not a dozen solvers. They are one arc-consistency core wearing different heads, kept so the exact cost of each classic technique can be read off a number instead of argued about. > **[Figure]** CSP presets: mean score over ten corner variants, single core, 60 s — interactive: BenchmarkLeaderboard. Rendered on the canonical page (link above); not shown in this markdown export. ## What each knob buys The presets vary two things: the order the engine assigns cells, and how hard it propagates before committing. Holding the puzzle and the budget fixed, the score gap between two presets is the value of that one knob. - **Least-constraining-value ordering helps.** `anjou-gacolor_ac3_lcv` reaches a mean of 114 against the plain `anjou-gacolor_ac3` at 76: choosing the value that rules out the fewest neighbours is worth about 38 points here. - **Some knobs are inert at this depth.** Three presets (`anjou-gacolor_ac3`, `anjou-gacolor_ac3_ns1`, `anjou-verhaard_preferred`) produced byte-identical boards on this puzzle. NS-1 and preferred ordering add nothing at 60 seconds: the engine never searches deep enough for them to bite. - **Border-first ordering is the strongest preset.** `anjou-border_first_lcv` and `anjou-rare_color_first` top the sweep at about 183, by committing the over-constrained frame before the free interior. It is still less than half a contender's score. ## Why none of them competes Every preset is bimodal. On a friendly corner arrangement the arc-consistency search reaches 340 to 349; on a hostile one it collapses to about 55, pinned in a bad basin it cannot escape inside 60 seconds. The mean sits low because the bad corners drag it down, and no ordering knob fixes the basin problem. That is the real story of this family: propagation makes each node well-pruned but expensive, so the search is strong where the instance is forgiving and helpless where it is not. The constructive engines on the leaderboard never enter that trap, which is why a preset at 183 sits on a different page from the leaderboard's contenders, which top out at 451. ## The naive DFS is here too, for one reason Naive depth-first search with every break allowed is not a CSP preset, but its visit order belongs to the same lesson. In row-major order (`anjou-naive_rowmajor`, on the leaderboard as the baseline) it reaches 365; the same DFS in spiral visit order (`anjou-naive_spiral`) collapses to a mean of 78. The visit-order choice alone costs the naive search nearly 290 points, the same kind of ordering sensitivity the CSP presets show, at a larger scale. ## Method and reproducibility These presets ran in the same grid as the leaderboard: ten official-puzzle variants, each with three pinned corner cells, single core, 60 seconds, fixed seed, one run per variant. Every board is re-scored by the one canonical matched-edge scorer, never the engine's self-report. The engine, the ten variants, the committed per-run results and the scripts live under the experiment's [backing directory](https://github.com/raphael-anjou/eternity2/tree/main/research/experiments/single-core-benchmark), and `just experiments single-core-benchmark` reruns the whole grid, contenders and presets together. ## Related - [Single-core benchmark](https://eternity2.dev/research/lab/experiments/single-core-benchmark) — Fifteen solvers, ours and our implementations of the community's two record backtrackers, each run once on ten corner-pinned variants of the official puzzle, single core, 60 seconds per run. The finding: node count is not score. - [Arc consistency, from AC-3 up](https://eternity2.dev/research/build/reduce/arc-consistency) — Forward checking looks one move ahead; arc consistency makes every cell's candidate list defend itself against every neighbour's, to a fixed point. Mackworth's AC-3, the optimal refinements that followed, and what the whole family actually measured on this puzzle, including where it is unsound. - [Fill orders](https://eternity2.dev/research/build/backtracking/fill-order) — The order in which a backtracker visits the 256 cells is its one free choice: it costs nothing at runtime and moves the size of the search tree by orders of magnitude. Twenty years of community science, from the fixed-vs-dynamic wars and the strategy races to the magic 10×16 square and Verhaard's comb search, all answer the same question: which path through the board is cheapest? --- # Papers > The academic literature on Eternity II and edge-matching puzzles, drawn from the project's research notes and the community reading list, and ranked by how useful each paper actually is if your goal is to write a solver. - Canonical page (with interactive figures/demos): https://eternity2.dev/research/papers/ - Updated: 2026-07-15 - Topics: exact-methods, search-space --- The short version: the complexity results tell you why it's hard, the SAT/CSP papers explain why off-the-shelf solvers hit a wall, and the constraint-propagation and large-neighborhood papers are the ones whose ideas show up in the strongest solvers. > **[Interactive: PapersView]** Rendered on the canonical page (link above); not shown in this markdown export. --- # Who's who of E2 research > Two decades of Eternity II research were done by named people on a mailing list. This page is the gallery: who they are, what each of them contributed, and where to read it in their own words. A thank-you as much as an index. - Canonical page (with interactive figures/demos): https://eternity2.dev/research/people/ - Updated: 2026-07-02 - Source: Brendan Owen derives the 17+5 design as the hardest possible puzzle (groups.io message 1947) — https://groups.io/g/eternity2/message/1947 - Source: Louis Verhaard's first-person account of the 467: “it was my program that did the job” (groups.io message 6891) — https://groups.io/g/eternity2/message/6891 - Source: Peter McGavin solves Brendan Owen's 10×10 benchmark (groups.io message 9686) — https://groups.io/g/eternity2/message/9686 - Source: Joshua Blackwood's 470, the standing record (groups.io message 10117) — https://groups.io/g/eternity2/message/10117 - Source: Al Hopfer states the NS-1 border balance (groups.io message 10754) — https://groups.io/g/eternity2/message/10754 - Source: Brendan Owen returns to the list after fourteen years (groups.io message 11500) — https://groups.io/g/eternity2/message/11500 --- The [history pages](/research/community/hunt) tell the community's story in order; this page tells it by person. Nearly everything this wiki knows (every record, theory, tool and [documented dead end](/research/build/dead-ends)) traces back to someone who posted it on the [eternity2 mailing list](https://groups.io/g/eternity2), usually for free, often for years. Consider this gallery an index and a thank-you at the same time. Names appear as people signed their public posts; every claim links to a message. Many of the people below have their own contributor page: a name in **bold with a link** opens it, gathering their profile, their sourced posts, and any pages they have written here. [Raphaël Anjou](/research/people/raphael-anjou), who maintains the wiki and runs the lab experiments, has one too, one researcher among the others. The names without a link are documented right here, on this page. ## The founders and launch analysts (2000–2007) ### [Brendan Owen](/research/people/brendan-owen) The founder. Owen created the eternity_two group in October 2000, six and a half years before the puzzle existed ([msg 384](https://groups.io/g/eternity2/message/384)), and set its scientific tone: within two days of the January 2007 announcement he had derived the expected-solutions formula that makes difficulty a design parameter ([msg 38](https://groups.io/g/eternity2/message/38)), and on launch weekend he digitized the real pieces and published the first solution-count estimate ([msg 987](https://groups.io/g/eternity2/message/987)). His signature results: the proof that a 17+5 colour split is the hardest possible 16×16 ([msg 1947](https://groups.io/g/eternity2/message/1947)), the exact search-tree model now called [complex theory](/research/why/complex-theory) ([msg 5197](https://groups.io/g/eternity2/message/5197), [msg 5209](https://groups.io/g/eternity2/message/5209)), the 9×9/10×10 [benchmark puzzles](/research/build/benchmarks) the community still races on, and the closed-form peak-depth proof 256 × (1 − 1/e) ([msg 8125](https://groups.io/g/eternity2/message/8125)). After a farewell at the contest's close ([msg 8429](https://groups.io/g/eternity2/message/8429)) he returned in 2025, refining his own model ([msg 11500](https://groups.io/g/eternity2/message/11500), [msg 11546](https://groups.io/g/eternity2/message/11546)). ### [Günter Stertenbrink](/research/people/gunter-stertenbrink) An Eternity I veteran and the group's earliest provocateur of estimates: in 2001 he asked, years ahead of the fact, how one would design a puzzle with a huge prize and only a ~1% chance of being solved in ten years ([msg 15](https://groups.io/g/eternity2/message/15)), and he greeted the 2005 press claims with "So we can conclude, the end of the universe is in several years." ([msg 34](https://groups.io/g/eternity2/message/34)). For two decades he checked the list's numbers, from exact-cover conversions in 2007 to the nodes-per-watt hardware ledger of the 2010s. ### [Dave Clark](/research/people/dave-clark) Author of the distributed Eternity I solver ESolve, he rejoined in 2001 ([msg 21](https://groups.io/g/eternity2/message/21)) and built eternity2.net, the BOINC project that was the community's public face in 2007 ([msg 756](https://groups.io/g/eternity2/message/756)). He shut it down with full accounting: 1.6 TFlops, over 10^19 operations, no solution ([msg 3511](https://groups.io/g/eternity2/message/3511)). He open-sourced his solver ([msg 3716](https://groups.io/g/eternity2/message/3716)) and left the archive its best primary source on the puzzle's creation: his phone call with Monckton describing how the solution was generated and vaulted ([msg 4177](https://groups.io/g/eternity2/message/4177)). ### Txibilis Angel de Vicente, who signed Txibilis, built the standard suite of E2-like benchmark boards ([msg 1886](https://groups.io/g/eternity2/message/1886)) and was the community's best hand-designer of [fill orders](/research/build/backtracking/fill-order). His duel with doc_s_smith's automated optimizer drove full-search node counts down by orders of magnitude ([msg 2928](https://groups.io/g/eternity2/message/2928)). The benchmark culture that later validated complex theory starts with him. ### doc_s_smith Mid-duel, the list discovered who doc_s_smith was: Dietmar Wolz, finder of most of the known Eternity I solutions ([msg 2972](https://groups.io/g/eternity2/message/2972)). His automated strategy optimizer set benchmark records in 2007 ([msg 2896](https://groups.io/g/eternity2/message/2896)); returning in 2010 he published a Java toolbox that turned the list into an algorithms workshop ([msg 7755](https://groups.io/g/eternity2/message/7755)) and gave the post-contest era its working goal: "beat 468 matching edges" ([msg 7803](https://groups.io/g/eternity2/message/7803)). ### kubzpa Author of the first serious solution-count paper, putting E2 near 15 million solutions ([msg 3497](https://groups.io/g/eternity2/message/3497)), and of the era's cleanest impossibility result: the parity argument that no board can score exactly 479 by its interior seams ([msg 1640](https://groups.io/g/eternity2/message/1640)). It held for seventeen months, until Verhaard pointed out the one loophole ([msg 6317](https://groups.io/g/eternity2/message/6317)): flip a border piece whose two outward border edges share a colour, and the board reads as 479 while those unscored rim edges go untouched. That is a technicality of the unscored border, not a break in the interior-parity math, which still holds, as Verhaard himself noted that 479 "cannot be achieved in another way" ([msg 6319](https://groups.io/g/eternity2/message/6319)). ### mjqxxxx Michael Quist was the list's mathematical referee. He posted the first fully rigorous counting framework for E2-like puzzles ([msg 1221](https://groups.io/g/eternity2/message/1221)), sharpened the border-balance theory ([msg 2098](https://groups.io/g/eternity2/message/2098)), and his reviews caught the flaws that made others' results solid. Kubzpa amended his solution-count paper after his pass caught a flawed Monte Carlo run ([msg 3589](https://groups.io/g/eternity2/message/3589)). ## The prize years (2007–2010) ### [Louis Verhaard](/research/people/louis-verhaard) The only person the puzzle ever paid. His eii solver, released publicly "because I am stuck" ([msg 5940](https://groups.io/g/eternity2/message/5940)), found the 467 that won the $10,000 scrutiny prize, entered under the name of his wife, Anna Karlsson, as he confirmed himself: "Anna is my wife… it was my program that did the job" ([msg 6349](https://groups.io/g/eternity2/message/6349), [msg 6891](https://groups.io/g/eternity2/message/6891), [msg 7451](https://groups.io/g/eternity2/message/7451)). His methods became canon: comb-search fill orders ([msg 6112](https://groups.io/g/eternity2/message/6112)) and depth-gated edge slipping ([msg 7321](https://groups.io/g/eternity2/message/7321)). He was also complex theory's staunchest defender: "the finest work that has ever been published about E2" ([msg 7810](https://groups.io/g/eternity2/message/7810)), and his 467 stood for twelve years. ### Yannick Kirschhoffer Author of the Eternity II Editor, the cross-platform Java editor and solver GUI released in February 2008 ([msg 4544](https://groups.io/g/eternity2/message/4544)) that became the community's standard board tool for years. He was still offering help with its code when it resurfaced in 2012 ([msg 9064](https://groups.io/g/eternity2/message/9064)). ### Fred Posting as Eternity Blogger, Fred built E2Lab in a burst of near-daily releases in autumn 2009 ([msg 7148](https://groups.io/g/eternity2/message/7148)), an editor/solver whose deliberate removal of its own "magic button", "to respect the game rules", says a lot about the list's ethics ([msg 7150](https://groups.io/g/eternity2/message/7150)). His blog hosted the community's tables through the post-contest years. ### [Al Hopfer](/research/people/al-hopfer) A regular since 2008 and the community's border theorist. His "balance doctrine" for puzzle generation appears in 2009 ([msg 6842](https://groups.io/g/eternity2/message/6842), [msg 6844](https://groups.io/g/eternity2/message/6844)); in 2022 he stated the exact condition this wiki calls the [NS-1 border balance](/research/why/border-balance) ([msg 10754](https://groups.io/g/eternity2/message/10754), [msg 10757](https://groups.io/g/eternity2/message/10757)), and backed it with a fully documented 222-piece partial with completed border ([msg 10862](https://groups.io/g/eternity2/message/10862)). ## The long decade (2010–2019) ### [Peter McGavin](/research/people/peter-mcgavin) The era's anchor, and arguably the puzzle's most consequential researcher after Owen. His work has [its own page](/research/lab/experiments/peter-mcgavin/backtracker). He computed the canonical ~14,702 expected solutions ([msg 8924](https://groups.io/g/eternity2/message/8924)), transcribed complex theory into LaTeX ([msg 9188](https://groups.io/g/eternity2/message/9188)) and later into exact C code ([msg 11197](https://groups.io/g/eternity2/message/11197)), which this site ports. In 2017 he solved Owen's hint-free 10×10 in ~180 core-years, inside the theory's error bars, its strongest validation ever ([msg 9686](https://groups.io/g/eternity2/message/9686), [msg 9688](https://groups.io/g/eternity2/message/9688)), and in 2020 he held the record himself: "New record score of 469! Only 11 breaks!" ([msg 10045](https://groups.io/g/eternity2/message/10045)). ### Tony Wauters Academia in person. He posted his group's peer-reviewed hyper-heuristic paper (461/480 in an hour) and stayed to answer questions ([msg 9017](https://groups.io/g/eternity2/message/9017), [msg 9023](https://groups.io/g/eternity2/message/9023)), and his group followed with the 2017 MILP and Max-Clique work ([msg 9683](https://groups.io/g/eternity2/message/9683)). ### Michael Field A fastest-solver veteran of the early years who became the group's hardware realist: his FPGA backtracker design projected ~5G placements per second per chip ([msg 9226](https://groups.io/g/eternity2/message/9226)), and his capacity analyses of GPU and FPGA routes told the list what silicon could and could not buy ([msg 9003](https://groups.io/g/eternity2/message/9003)). ### Arnaud Carré Arrived in 2009 and reset the speed standard in 2014 with a 114.5 million recursions per second single-core solver offered as a comparison baseline ([msg 9233](https://groups.io/g/eternity2/message/9233)), returning in 2018 for the benchmark races. ### Adam Miles The GPU flank. Arriving in 2017, he moved from CPU bit-tricks to a DirectX 12 compute solver running on an Xbox One X ([msg 9811](https://groups.io/g/eternity2/message/9811)) and re-verified Owen's 9×9 set 1 exhaustively on GPU: the same 2 solutions as the 2014 CPU census, in 25.4 hours ([msg 9822](https://groups.io/g/eternity2/message/9822)). ### JSA The community's verifier and, later, its rescuer. In 2009 he reproduced the 467 with Verhaard's public solver, ~82 days on one PC, logging exactly how thin the air gets above 466 ([msg 6687](https://groups.io/g/eternity2/message/6687)). When Yahoo announced it would erase the archive in 2019, JSA paid the groups.io transfer fee, offering "I can pay for the first 5 years" ([msg 2](https://groups.io/g/eternity2/message/2)), and he still writes the group's welcome notes ([msg 11771](https://groups.io/g/eternity2/message/11771)). ### Ole Knudsen Kronjuvel (Kron) was there from the earliest years, retro-claimed a 231-piece partial from October 2007 ([msg 7563](https://groups.io/g/eternity2/message/7563)), and as group owner created the new groups.io home during the 2019 migration. The 2026 welcome note opens with a tribute to him; he has been missing from the list since 2023 ([msg 11771](https://groups.io/g/eternity2/message/11771)). ## The record wave and the modern era (2019–2026) ### [Joshua Blackwood](/research/people/joshua-blackwood) The outsider who ended the twelve-year freeze. Unknown to the list, he announced a 468 on Reddit in August 2020 ([msg 10032](https://groups.io/g/eternity2/message/10032)), open-sourced his solver days later ([msg 10037](https://groups.io/g/eternity2/message/10037)) along with rare negative results (SAT, GPU and 2×2 caches all measured and discarded, [msg 10056](https://groups.io/g/eternity2/message/10056)), and in March 2021 posted the 470 that still stands ([msg 10117](https://groups.io/g/eternity2/message/10117)), found with the exact public code ([msg 10161](https://groups.io/g/eternity2/message/10161)). His algorithm is [decoded on this wiki](/research/lab/experiments/joshua-blackwood/solver). ### [Jef Bucas](/research/people/jef-bucas) The modern era's infrastructure. He raised the alarm that triggered the archive migration ([msg 9920](https://groups.io/g/eternity2/message/9920)), built the [e2.bucas.name](https://e2.bucas.name) board viewer that became the community's record book ([msg 9955](https://groups.io/g/eternity2/message/9955)), rewrote Blackwood's solver in C as libblackwood, roughly doubling its speed and powering the November 2020 wave of 469s ([msg 10065](https://groups.io/g/eternity2/message/10065), [msg 10078](https://groups.io/g/eternity2/message/10078), [msg 10067](https://groups.io/g/eternity2/message/10067)), and tied the 470 in 2024 ([msg 11401](https://groups.io/g/eternity2/message/11401)), always crediting Blackwood. His wrapper_blackwood parameter study is republished [on this wiki](/research/lab/experiments/joshua-blackwood/solver) with his permission ([msg 11905](https://groups.io/g/eternity2/message/11905)). ### Carlos Fernandez The board surgeon. He produced a 469 by a single-piece swap of McGavin's record board ([msg 10074](https://groups.io/g/eternity2/message/10074)), a border-rearranged 470 variant ([msg 11403](https://groups.io/g/eternity2/message/11403)), four-minute 14×14 quadrant solves ([msg 10802](https://groups.io/g/eternity2/message/10802)), and high rungs of the five-clue ladder ([msg 11068](https://groups.io/g/eternity2/message/11068)). ### Bruno Gauthier A speed veteran of the 2014 era whose Forth solver ran at 80–90 million nodes per second ([msg 9265](https://groups.io/g/eternity2/message/9265)), he held the strictest record on the books for over three years: 460/480 with all five clue pieces at their official positions, from 2023 ([msg 11074](https://groups.io/g/eternity2/message/11074)) until Benjamin Riotte's 464 in July 2026. ### Benjamin Riotte Holder of the strict five-clue record. In July 2026 he pushed the best board respecting all five clue placements from Gauthier's long-standing 460 to **464/480** (16 broken edges), with his own modified-Blackwood DFS ([groups.io](https://groups.io/g/eternity2/message/11919)). Igor Pejic reached the same 463–464 range independently in the same thread. It was the first movement on the strict-canonical line in over three years. ### [Marijn Heule](/research/people/marijn-heule) The SAT world's contact point. In the long-running SAT thread, a collaborator of Marijn Heule reported that Heule's group had re-implemented and improved the encoding behind the 2008 SAT benchmark results ([msg 10969](https://groups.io/g/eternity2/message/10969)), the state of the art of the exact-methods flank, which was still debating 4 GB CNF encodings on the archive's very last day ([msg 11822](https://groups.io/g/eternity2/message/11822)). ### [Raphaël Anjou](/research/people/raphael-anjou) Maintains this wiki and runs the experiments catalogued in [the lab](/research/lab); his write-ups gather on his [contributor page](/research/people/raphael-anjou), one researcher among the others. ### [William Millilaw](/research/people/william-millilaw) Ran a dense two-week solver campaign in 2026, most of it recorded as refutations of methods that do not crack the puzzle. Two of his findings sharpen the ceiling: a replica freeze test, and a halo SAT-residual test showing the record boards are strict local optima. We reproduced the second on the public boards, and it lands on the [rigidity wall](/research/why/rigidity-wall) alongside the integer-programming proofs ([reproduction](https://github.com/raphael-anjou/eternity2/tree/main/research/topics/rigidity-sat-halo)). ### onesmallstep Founded the community's Discord server in November 2021 and kept it alive through the quiet years (reported on the community Discord, November 2021; no public message link). A dedicated solver in his own right (self-reported best around 466–467), he is also the reason the wiki once mis-carried a "2025 470": a record *relay* misread as a record *claim*, corrected here from the Discord archive itself. ### Reinout Annaert The Discord era's methodical hunter: a self-reported best of 469, the linear-run subculture (229- and 230-piece consecutive partials), and the man who settled where the hint placements come from: "They directly come from Tomy's Hint Puzzles" (reported on the community Discord, December 2024; no public message link). On the mailing list he confirms storing solution figures scoring above 467/480 ([msg 11549](https://groups.io/g/eternity2/message/11549)). His suggestions also shaped this site's playground roadmap. ## And many more No gallery this size is complete. Among the many who belong here: Alan O'Donnell, who had the first working solver weeks after the announcement ([msg 64](https://groups.io/g/eternity2/message/64)); Max, Verhaard's sparring partner in the run to 467, whose own best was 465 ([msg 6348](https://groups.io/g/eternity2/message/6348)); istarinz, who broke 558 million placements per second in 2008 and became the group's exhaustive-search verification authority ([msg 6212](https://groups.io/g/eternity2/message/6212)); antminder, whose assignment-repair hybrid averaged a 462 per day in 2008 ([msg 5589](https://groups.io/g/eternity2/message/5589)); Pierre Schaus, whose constraint-programming paper supplied that repair operator ([msg 5601](https://groups.io/g/eternity2/message/5601)); capiman26061973, founder of the five-clue ladder ([msg 11037](https://groups.io/g/eternity2/message/11037)) and the invalid-combination mining programme ([msg 7768](https://groups.io/g/eternity2/message/7768)); David Barr, open-source GPU and browser solvers across a decade ([msg 9367](https://groups.io/g/eternity2/message/9367), [msg 11121](https://groups.io/g/eternity2/message/11121)); Henk van der Griendt, who found the prize announcement everyone else had missed ([msg 6337](https://groups.io/g/eternity2/message/6337)); and juraj.pivovarov, the community's rapid-prototyping conscience ([msg 9411](https://groups.io/g/eternity2/message/9411)). ## Corrections welcome This page will always be incomplete, and it may be wrong in places: a misattributed result, a missing name, a preferred spelling. If any of it concerns you or your work, please say so on the [mailing list](https://groups.io/g/eternity2) or through the [contribute page](/research/contribute): corrections land with the same sourcing rules as everything else here, and credit is the whole point of this page. ## Related - [The hunt, a history (part I: 2000–2009)](https://eternity2.dev/research/community/hunt) — The community's story, from a mailing list founded seven years before the puzzle existed to the $10,000 scrutiny prize won under a borrowed name, with every event sourced to its original message. Part I of a growing chronicle. - [The hunt, a history, part II: 2009–2026](https://eternity2.dev/research/community/hunt-part-2) — Seventeen years after the prize: the contest dies with its solution locked in a safe, 467 stands for a decade, the archive survives Yahoo's shutdown by days, and then an outsider from Reddit rewrites the record book. Every event sourced to its original message. - [Records & solvers](https://eternity2.dev/research/records) — Eternity II has never been solved, but fifteen years of community effort have pushed the best board to 470/480. Who holds what, how they did it, and why some headline "480" boards are not actually the real puzzle. --- # Records & solvers > Eternity II has never been solved, but fifteen years of community effort have pushed the best board to 470/480. Who holds what, how they did it, and why some headline "480" boards are not actually the real puzzle. - Canonical page (with interactive figures/demos): https://eternity2.dev/research/records/ - Updated: 2026-07-16 - Source: eternity2 mailing-list archive (groups.io): the record announcements; free account required to read — https://groups.io/g/eternity2 - Source: Wikipedia: Eternity II puzzle (the $2M prize, the 2010 deadline and Verhaard's 467) — https://en.wikipedia.org/wiki/Eternity_II_puzzle - Source: Louis Verhaard's own account of his 467 solver — https://www.shortestpath.se/eii/eii_details.html - Source: e2.bucas.name (Jef Bucas): the community board viewer; every linked board can be re-scored there — https://e2.bucas.name --- This page tracks the score: who held the best board at each point, and how they did it. For the story around the numbers, the turning points that moved the puzzle, see the [history at a glance](/research/history); the strongest methods live in the mailing list and Discord, not in journals. > **[Interactive: RecordsView]** Rendered on the canonical page (link above); not shown in this markdown export. ## Related - [History: the big steps](https://eternity2.dev/research/history) — The Eternity II story at a glance, from the mailing list founded in 2000 to the 470 record that still stands. A scannable timeline of the turning points, each linking into the full two-part history and the message where it happened. - [Experiments](https://eternity2.dev/research/lab/experiments) — The lab's named search experiments, one section per researcher. Each is a real run against Eternity II with its idea, its best board, and the questions it left open. Raphaël Anjou's notebook is here in full; the notebook is open to anyone else's. - [The rigidity wall](https://eternity2.dev/research/why/rigidity-wall) — Every record board we have is frozen in place. You cannot nudge your way from a great board to a perfect one, and we can prove it. --- # Reference numbers > Exact counts of how many valid ways a small block can be filled at a given position of the official Eternity II board, under increasingly constrained rules: known-good numbers to check your solver's edge-matching and constraint code against. - Canonical page (with interactive figures/demos): https://eternity2.dev/research/reference/ - Updated: 2026-07-11 - Topics: backtracking - Reproduce: `just research-subgrid` - Source: sylvogel's published subgrid counts (groups.io message 11879) — https://groups.io/g/eternity2/message/11879 - Source: This project's reproducible Rust generator + committed results (GitHub) — https://github.com/raphael-anjou/eternity2/tree/main/research/topics/subgrid-placement-counts --- How many distinct, edge-matching ways can you fill a small block of the official board? These counts are the ground truth to test a solver against: if your edge-matching and constraint code disagrees with the numbers below on a 2×2 corner, the bug is in your code, not the table. The upright figures here are computed from the official piece set by this project's reproducible Rust generator (linked below), so anyone can rerun them. The handful of italic figures are counts too large to enumerate exactly in seconds (tens of billions to tens of trillions of fillings); those are **sylvogel's published values**, reproduced here for completeness and credited in the sources. Everything else is recomputed here from scratch. > **[Interactive: ReferenceTableView]** Rendered on the canonical page (link above); not shown in this markdown export. ## Related - [Known facts & numbers](https://eternity2.dev/research/build/known-facts) — The numbers every Eternity II researcher ends up re-deriving, collected in one place with their provenance: the puzzle definition, the clue placements, scoring conventions, the record table, search-space sizes and the structural counts. - [The community's benchmarks](https://eternity2.dev/research/build/benchmarks) — How a community forbidden from sharing the pieces built a shared test culture anyway: derived-count verification protocols, the Txibilis and beginner suites, node-count duels, full enumerations, and the one benchmark that is still standing open today. --- # Why it's hard > Eternity II is not accidentally difficult. It was designed to resist cleverness, and the measurable structural walls (rigidity, entropy, forbidden patterns) explain why no search, however clever, has reached the end. - Canonical page (with interactive figures/demos): https://eternity2.dev/research/why/ - Updated: 2026-07-01 --- Eternity II is not accidentally difficult. This is the science of why no search, however clever, has reached the end: the puzzle's design, and the structural walls that show up once you start measuring. > **[Interactive: ScoringPrimer]** Rendered on the canonical page (link above); not shown in this markdown export. ## Engineered to resist cleverness Eternity I fell in 2000 because Alex Selby and Oliver Riordan discovered the puzzle had vastly more solutions than its designer believed, and aimed their search at the most "solution-dense" regions. For Eternity II, the publisher hired the winners: Selby and Riordan helped design and stress-test the new puzzle so that no such statistical shortcut survives. The visible fingerprints of that vetting: a single designed solution baked into balanced color counts, no rotationally-symmetric pieces, no duplicate pieces, and piece-count/color-count parameters sitting at the empirical hardness peak (later confirmed by Ansótegui et al.). The puzzle isn't accidentally hard. It was tuned to be. One thing that looks like a design choice but isn't: the border uses its own set of five motifs, separate from the interior's. That separation is automatic, not engineered. Because the outer rim is solid grey, every border piece has its grey edge fixed outward, so its coloured edges only ever meet other border edges (sideways) or the interior (inward), and the two pools never touch. The border motifs could be any five colours, even a relabelling of interior ones, without changing the puzzle at all. They read as "rare" only because there are fewer border edges to colour, not because the designers confined a scarce resource to the frame to thwart solvers. (Thanks to Vasily V. on the groups.io list for the correction.) ## The structural walls Beyond the design story, the puzzle has measurable structure that explains the gap between the best known board (470/480) and a full solution. Each of these is published with the exact computation behind it. ## Pages in this section - [Why a faster computer doesn't help](https://eternity2.dev/research/why/prune-vs-speed) — The single most important idea in hard combinatorial search: shrinking the space you search beats searching it faster, by an exponential margin. Eternity II is engineered so you can barely shrink it at all. - [Which wall stops which method](https://eternity2.dev/research/why/walls-and-methods) — The research section has two halves: the structural walls that make Eternity II hard, and the algorithms built to climb them. This page is the bridge: each method lined up against the wall it actually attacks, and the score where that wall stopped it. - [Is this instance NP-complete, and how do I encode it?](https://eternity2.dev/research/why/how-hard-is-this-instance) — Edge matching is NP-complete as a family, but that says nothing about one fixed 16×16 board: a single instance is a constant, not a problem. What is true is the family's worst-case hardness and this instance's empirical hardness, and how to write the puzzle for a SAT, exact-cover, or ILP solver with small worked sketches. - [Complex theory: counting the search before you run it](https://eternity2.dev/research/why/complex-theory) — Brendan Owen's complex theory estimates how wide the search tree is at every depth, and even how many solutions exist at all. Many in the community consider it the single most important thing to understand about Eternity II. - [Tuned to the hardness peak](https://eternity2.dev/research/why/phase-transition) — Eternity II uses 22 colors. They split 17 interior to 5 frame-only, and that 17 is exactly where this kind of puzzle is hardest to solve. - [Designed to be unsolvable: the recipe](https://eternity2.dev/research/why/design-recipe) — Eternity II follows a recipe for the hardest possible edge-matching puzzle: compact shape, no symmetric or duplicate pieces, split palettes, flat frequencies, one expected solution. The community reverse-engineered every ingredient in the launch year. - [The rigidity wall](https://eternity2.dev/research/why/rigidity-wall) — Every record board we have is frozen in place. You cannot nudge your way from a great board to a perfect one, and we can prove it. - [Why basin-hopping looks impossible](https://eternity2.dev/research/why/sigma-cycles) — If you can't improve a great board by polishing it, maybe you can jump to a different great board. On every record pair tested, you can't, and the structural reason why is worth seeing. - [Where the mismatches live](https://eternity2.dev/research/why/mismatch-geometry) — A near-perfect board doesn't scatter its few errors evenly. It packs them into one band of five rows and leaves all the rest flawless. Which band is decided by the direction the search filled the board, and you can see the mirror on the real record boards. - [Forbidden patterns](https://eternity2.dev/research/why/forbidden-patterns) — Almost every small patch of pieces you could build is impossible. For a 2×2 square, 99.72% of the ways to place four pieces can never be made to match. - [No forced moves](https://eternity2.dev/research/why/no-forced-moves) — The usual way to crack a logic puzzle is to find a spot where only one piece fits, place it, and repeat. That lever doesn't exist here: every interior piece has between 73 and 137 possible neighbours, and not one is ever pinned to a single option. - [Where you place the hints beats how many](https://eternity2.dev/research/why/hint-geometry) — On a 16×16 puzzle built like Eternity II, eighteen hints scattered across the board solve it in minutes, while the same puzzle needs eighty or more hints piled into contiguous rows to be as easy. Position, not count, is the lever, and it points straight at the endgame. - [Piece theft, where solvers die](https://eternity2.dev/research/why/piece-theft) — A solver fills a few rows for free, then hits a wall in the middle of the board. Here's the mechanism: a scarce piece spent in the wrong place, rows ago. - [The rare colors live on the frame](https://eternity2.dev/research/why/rare-color-geography) — Five of Eternity II's 22 colors appear only along the border ring, each on exactly 24 edges, never once in the interior. A structural split that shapes how every solver treats the frame. - [The border balance](https://eternity2.dev/research/why/border-balance) — A solved board hides a simple bookkeeping law: every colour the border hands to the interior, the interior hands straight back. Break it and you know instantly the board is wrong; obeying it, though, guarantees nothing. - [Entropy and the area law](https://eternity2.dev/research/why/entropy-area-law) — Eternity II has two rules: edges must match, and each piece is used once. The first is generous. All the hardness lives in the second. --- # The border balance > A solved board hides a simple bookkeeping law: every colour the border hands to the interior, the interior hands straight back. Break it and you know instantly the board is wrong; obeying it, though, guarantees nothing. - Canonical page (with interactive figures/demos): https://eternity2.dev/research/why/border-balance/ - Updated: 2026-07-02 - Topics: search-space, structure - Source: Border edge-type balance observed in the launch summer (angwin_uk, August 2007) — https://groups.io/g/eternity2/message/2073 - Source: mjqxxxx's stronger border condition: even counts, split equally into left and right edges (August 2007) — https://groups.io/g/eternity2/message/2098 - Source: Brendan Owen's paired edge-count observation on planted sets (June 2007) — https://groups.io/g/eternity2/message/422 - Source: Hopfer's 2022 statement of the multiset-equality condition (groups.io msg 10754) — https://groups.io/g/eternity2/message/10754 - Source: Hopfer's crisp restatement: same mixture of internal images on all 56 border pieces (msg 10757) — https://groups.io/g/eternity2/message/10757 --- Look only at the seam between the outer ring of border pieces and the first ring of interior pieces. Each edge across that seam shows one colour, counted once from the border side and once from the interior side. In any complete solution the two tallies are identical: the multiset of colours the border presents inward exactly equals the multiset the interior presents outward. Call the imbalance the **deficit**, $\Delta$: half the total mismatch between the two tallies. A finished, correct board has $\Delta = 0$. The four known full solutions, across four different piece sets, all satisfy it exactly. So $\Delta > 0$ is a certificate that a board can never be completed: a real, cheap necessary condition. ## The law, in one line Across the border↔interior seam, the colours the border shows inward and the colours the interior shows outward are the same multiset. Writing $A[c]$ and $B[c]$ for the two per-colour tallies: $$ \Delta \;=\; \tfrac{1}{2} \sum_{c} \bigl|\, A[c] - B[c] \,\bigr| \;=\; 0 . $$ ## See it on a real board A solved 8×8 starts in balance ($\Delta = 0$). Lift a border piece and watch which colours fall out of balance, and the deficit climb. Then try the swap button, and watch the catch. > **[Figure]** Interactive: the NS-1 border-balance deficit — interactive: Ns1Lab. Rendered on the canonical page (link above); not shown in this markdown export. ## The catch, and why it matters Swapping two border pieces leaves $\Delta$ at 0. The swap moves colours around the seam without changing either tally, so the invariant is blind to it. Worse, on a near-solution most of the remaining errors aren't on the border seam at all. They sit interior-to-interior, where NS-1 never looks: on 469-class boards over 85% of the unmatched edges are invisible to it. That is the whole texture of Eternity II in miniature. A check this clean still only ever says "definitely broken", never "definitely fine". The puzzle resists every cheap certificate of progress. ## Is it useful, then? Yes, as a late-search pruner. Once a solver has closed the border ring, enforcing $\Delta = 0$ rejects 10–28% of deep dead-ends for the price of one pass over the 56 seam edges. It is necessary-but-loose: it throws away bad states cheaply and leaves the hard part, the interior, untouched. ## Related - [The rare colors live on the frame](https://eternity2.dev/research/why/rare-color-geography) — Five of Eternity II's 22 colors appear only along the border ring, each on exactly 24 edges, never once in the interior. A structural split that shapes how every solver treats the frame. - [Forbidden patterns](https://eternity2.dev/research/why/forbidden-patterns) — Almost every small patch of pieces you could build is impossible. For a 2×2 square, 99.72% of the ways to place four pieces can never be made to match. - [No forced moves](https://eternity2.dev/research/why/no-forced-moves) — The usual way to crack a logic puzzle is to find a spot where only one piece fits, place it, and repeat. That lever doesn't exist here: every interior piece has between 73 and 137 possible neighbours, and not one is ever pinned to a single option. --- # Complex theory: counting the search before you run it > Brendan Owen's complex theory estimates how wide the search tree is at every depth, and even how many solutions exist at all. Many in the community consider it the single most important thing to understand about Eternity II. - Canonical page (with interactive figures/demos): https://eternity2.dev/research/why/complex-theory/ - Updated: 2026-07-02 - Topics: structure, backtracking - Source: Brendan Owen's peak-depth closed form, 256·(1−1/e) (groups.io msg 8125, 2010) — https://groups.io/g/eternity2/message/8125 - Source: Peter McGavin's 10×10 solve validating complex theory (groups.io msg 9686, 2017) — https://groups.io/g/eternity2/message/9686 - Source: Brendan Owen's solution-count estimates (groups.io message 5209) — https://groups.io/g/eternity2/message/5209 - Source: Peter McGavin's reference implementation and depth table (groups.io message 11197) — https://groups.io/g/eternity2/message/11197 - Source: Brendan Owen's "Backtracker estimates" tabulation for the clue puzzles and E2 (groups.io Databases) — https://groups.io/g/eternity2/databases - Source: Brendan Owen's estimated-vs-actual validation, "NxM puzzles using Eternity II subset pieces" (groups.io Files, Brendan folder) — https://groups.io/g/eternity2/files/Brendan/NxM_actual_theory.pdf - Source: Brendan Owen's heuristic-vs-node-count study, "Heuristics: 20×2 rectangle" (groups.io Files, Brendan folder) — https://groups.io/g/eternity2/files/Brendan/heuristics.pdf --- > **Whose idea this is** > > Complex theory is due to Brendan Owen, one of the puzzle's vetters; Peter McGavin [implemented it in C](https://groups.io/g/eternity2/message/11197) with arbitrary-precision arithmetic and posted the numbers. We're writing it up here because a community member (Dan Karlsson) rightly pointed out it was missing, and because it underpins almost every good decision you can make about a solver, above all the choice of search order. ## The idea Take a scan order and walk it one cell at a time. At each new cell, a random unused piece matches its already-placed neighbours with some probability: a product of per-edge colour-match chances. Multiply that by how many pieces are left and you get the expected number of ways to extend the board one cell further. Chain this down all 256 cells and you have a closed-form estimate of how wide the search tree is at every depth and, at the last cell, how many full solutions the puzzle has. It is an average, not a true count: it assumes the 22 edge colours are drawn independently, which they aren't (four edges are bolted to one rigid piece). But calibrated against small puzzles where the real count is known, it lands within about a factor of two. That is more than enough to see the shape. ## The headline numbers | Clues placed | Expected solutions | | ---------------------------------- | ------------------ | | One clue (the centre piece only) | ≈ 14,702 | | All five official clues | ≈ 1 | With only the mandatory centre piece the puzzle has on the order of fifteen thousand solutions; add the four other clues and the expected count drops to about $4\times10^{-8}$: overwhelmingly, exactly one. This is the formal reason the 5-clue puzzle has a single designed solution. ## The same numbers, checked against reality Brendan tabulated the estimate not just for E2 but for the four smaller *clue puzzles*, and this is where it earns trust. The clue puzzles are small enough that their trees were searched exhaustively, so the estimate sits right next to the true count. It lands within a factor of two, the calibration this page keeps promising. The table also records the best-known fill order for each puzzle, and they are not all the same: the order is a choice the search-space shape rewards or punishes, not a property of the puzzle. > **[Interactive: ClueEstimatesTable]** Rendered on the canonical page (link above); not shown in this markdown export. The clue puzzles are four data points; Brendan checked the model far more widely. His **"NxM puzzles using Eternity II subset pieces"** study plots the estimated nodes-per-solution against the *actual* count for on the order of a hundred smaller boards built from E2's own pieces, and on a log-log axis the cloud hugs the diagonal across eleven orders of magnitude, from ten nodes to $10^{11}$. That is the real basis for trusting the estimate on a board too large to ever search: it has been right everywhere it *could* be checked. A companion study even shows a dead-simple static score (the sum of per-cell edge-match counts, squared) predicts a rectangle's total node count with an $R^2$ of about 0.84, more evidence that the search cost is baked into the board's structure before you place a piece. ## The funnel Plot the expected width at each depth and three regimes appear. Their shape is what the community calls the E2 funnel. Play the sweep below and watch the counter: it climbs into the billions, then barely moves for a hundred cells across the plateau, that flat crawl through an astronomically wide band is the wall, before the last sixty pieces funnel it back down. > **[Figure]** interactive: ComplexFunnelAnimated. Rendered on the canonical page (link above); not shown in this markdown export. ## Try it: the order decides the funnel The same estimate, run live for different scan orders. The plateau peak (the widest point the search must cross) is decided by the order alone, before a single node is placed. > **[Figure]** Interactive: the search-space funnel — interactive: ComplexFunnelLab. Rendered on the canonical page (link above); not shown in this markdown export. ## Three regimes - **Growth (depth 1–50).** Solutions multiply geometrically from one to about $10^{27}$. Every placement is essentially free; nothing constrains you yet. - **Plateau (depth 50–200).** The tree is at its widest, about $10^{45}$ ways to extend, while the solution count barely moves. This is where backtrackers spend roughly 99% of their time, matching Joe's empirical finding that most time is spent below depth 150. - **Collapse (depth 200–256).** The width falls from $10^{45}$ back to about $10^{4}$. The last ~60 pieces are tightly constrained: each one placed eliminates orders of magnitude of branches. The endgame is locally easy; the hard part is reaching it. ## Why it changes how you search If almost all the work is in the plateau, the goal isn't raw speed. It is getting across the plateau to the funnel entrance (around depth 200), after which the search chains down deterministically. And because complex theory scores a scan order before you run it, you can compare orders by the height of their plateau peak rather than by trial and error. That is the rigorous version of a rule this site states everywhere: the fill order is a first-class choice, and McGavin's bottom-left, left-to-right scan was picked because complex theory said it was good. ## Bigger tiles The same idea works if you place 2×2 or 3×3 tiles instead of single pieces: a whole block of cells is committed at once, with its internal edges already matched. The [search-path playground](/playground/paths) lets you do this for real: pick a block shape (1×1, 2×1, 2×2, 3×3, …) and stamp blocks onto the grid to build a block path. Race it and a dedicated macro-piece solver commits one whole valid sub-assembly per block instead of one piece at a time, so the search advances region by region. The plateau-peak estimate alongside still scores the cell order your blocks imply, predicting the cost before you run a single node. ## What it can't see Complex theory is a first-moment estimate, so it is blind to one thing: whether the many counted partial boards are genuinely distinct. The [entropy and area-law results](/research/why/entropy-area-law) show that distinctness collapses past ~80 cells, a second-order effect the independent-edge model cannot capture. So use complex theory to choose orders and read the tree's shape, never as a true count or a bound. ## Provenance and validation The theory's paper trail runs through the mailing list. Brendan Owen posted the completed model in April 2008 ([msg 5197](https://groups.io/g/eternity2/message/5197), [5209](https://groups.io/g/eternity2/message/5209)), and later proved a neat closed form: for a scan order the node-count peak sits at depth $256\,(1 - 1/e) \approx 161.8$ ([msg 8125](https://groups.io/g/eternity2/message/8125)); the funnel above peaks there empirically. Peter McGavin typeset the theory ([msg 9188](https://groups.io/g/eternity2/message/9188)), published the 14,702 expected-solutions figure as early as 2011 ([msg 8924](https://groups.io/g/eternity2/message/8924)), and in 2017 delivered its strongest validation: solving Brendan's hint-free 10×10 benchmark by searching complex-theory-ranked first rows: roughly 180 core-years, landing inside the theory's predictions ([msg 9686](https://groups.io/g/eternity2/message/9686), [9688](https://groups.io/g/eternity2/message/9688)). His 2024 reference C implementation ([msg 11197](https://groups.io/g/eternity2/message/11197)) is what this page's live estimator ports, line for line. ## Related - [Why a faster computer doesn't help](https://eternity2.dev/research/why/prune-vs-speed) — The single most important idea in hard combinatorial search: shrinking the space you search beats searching it faster, by an exponential margin. Eternity II is engineered so you can barely shrink it at all. - [Tuned to the hardness peak](https://eternity2.dev/research/why/phase-transition) — Eternity II uses 22 colors. They split 17 interior to 5 frame-only, and that 17 is exactly where this kind of puzzle is hardest to solve. - [Entropy and the area law](https://eternity2.dev/research/why/entropy-area-law) — Eternity II has two rules: edges must match, and each piece is used once. The first is generous. All the hardness lives in the second. --- # Designed to be unsolvable: the recipe > Eternity II follows a recipe for the hardest possible edge-matching puzzle: compact shape, no symmetric or duplicate pieces, split palettes, flat frequencies, one expected solution. The community reverse-engineered every ingredient in the launch year. - Canonical page (with interactive figures/demos): https://eternity2.dev/research/why/design-recipe/ - Updated: 2026-07-02 - Topics: structure - Source: guenter stertenbrink poses the design problem: a puzzle with ~1% chance of falling in ten years (msg 15, February 2001) — https://groups.io/g/eternity2/message/15 - Source: Brendan Owen, Design the hardest puzzle: the full recipe and the 17.14 derivation (msg 1947, August 2007) — https://groups.io/g/eternity2/message/1947 - Source: Brendan Owen, Hardest Puzzle Estimates: the hardest-parameter table for every board size (msg 2164) — https://groups.io/g/eternity2/message/2164 - Source: Brendan Owen, Piece Frequencies: the flat distribution that killed the Eternity I method (msg 1667) — https://groups.io/g/eternity2/message/1667 - Source: Brendan Owen citing The Times: Selby and Riordan wrote the generator for Monckton (msg 3373) — https://groups.io/g/eternity2/message/3373 - Source: Dave Clark's account of a phone call with Christopher Monckton on how the puzzle was generated (msg 4177) — https://groups.io/g/eternity2/message/4177 - Source: The piece design-space census: 256 pieces from roughly 21,000 possible, symmetric forms avoided (msgs 8014–8034; census in msg 8025) — https://groups.io/g/eternity2/message/8025 - Source: Brendan Owen on the designers' solution locked in a safe (msg 8823) — https://groups.io/g/eternity2/message/8823 --- Eternity II is not a puzzle that happens to be hard. It is the output of a recipe: a short list of design rules that, followed together, produce the hardest edge-matching puzzle a given number of pieces can make, while still guaranteeing that a solution exists. The remarkable part is that the recipe was not leaked or published by the designers. The community reconstructed it, ingredient by ingredient, within weeks of launch, mostly in one August 2007 post by Brendan Owen titled, fittingly, "Design the hardest puzzle" ([msg 1947](https://groups.io/g/eternity2/message/1947)). This page walks through that recipe: what each rule is, what it costs anyone trying to solve the puzzle, and where each claim comes from. The measurement of the sharpest single ingredient (the colour count sitting exactly on the hardness peak) has [its own page](/research/why/phase-transition); here it takes its place among the others. ## The problem came before the puzzle The design problem was stated on the mailing list six years before anyone had to solve it. In February 2001, with Eternity I barely cold and Eternity II still a rumour, guenter stertenbrink asked the group how one would design a puzzle carrying a £5M prize so that it had only about a 1% probability of being solved within ten years ([msg 15](https://groups.io/g/eternity2/message/15)). Replies discussed scaling Eternity-I-style difficulty and even hiding cryptographic problems in the edges. That is exactly the tightrope a prize puzzle must walk. Make it too easy and the prize is lost; that is what happened to Eternity I, which fell in 2000 because it had vastly more solutions than its designer believed. Make it literally impossible and the contest is fraud. The target is a puzzle that provably has a solution, positioned so that no realistic amount of computing finds it within the contest window. Eternity II's designers had watched Eternity I die, and the recipe below reads like a point-by-point response. ## The recipe, ingredient by ingredient ### Keep the shape compact The first rule in Owen's derivation: use a compact board, the 16×16 square, rather than anything elongated or irregular ([msg 1947](https://groups.io/g/eternity2/message/1947)). A compact shape maximises the share of interior joins, where uncertainty is highest, and leaves no thin arms or corridors that a solver could exhaust cheaply and use as an anchor. Owen later verified the consequence experimentally: on comparable 16×16 designs with unbalanced palettes there is always some region that is cheaper to tile first (for a 2/19 split, starting in the middle is over a hundred times cheaper than a row scan), but on E2's actual parameters no such region exists. The design has, in his words, "no weak areas to start tiling from" ([msg 5263](https://groups.io/g/eternity2/message/5263), design comparison [msg 5243](https://groups.io/g/eternity2/message/5243)). ### No symmetric pieces, no duplicates Every one of the 256 pieces is unique, and none is symmetric under rotation ([msg 1947](https://groups.io/g/eternity2/message/1947)). In 2010 the community counted the design space to see how deliberate this is: with 5 frame and 17 interior patterns there are roughly 21,000 possible piece designs, including forms like *aaaa*, *abab* and *aabb* that repeat under rotation. The real set pointedly avoids all of them ([msgs 8014–8034](https://groups.io/g/eternity2/message/8014)). The consequence is the absence of freebies. A duplicate pair would let any solution be rewritten by swapping the two pieces, doubling the solution count for free; a rotationally symmetric piece would collapse orientations and shrink the decision space. Denying both keeps the expected solution count pinned where the designers wanted it and hands the solver exactly zero symmetry to exploit: every placement is a full, independent decision among 4 orientations of distinct pieces. There is a second, quieter reason to bar symmetric pieces, and Owen measured it. A symmetric piece is not just structurally redundant, it is easier to *place*, because it fits more contexts. He built a set of 289 pieces (all 17 of the 90-degree-symmetric forms, all 136 of the 180-degree-symmetric ones, and 136 random asymmetric pieces), tiled a small rectangle every possible way, and counted how often each piece appeared across all 759 million solutions. The asymmetric pieces showed up **2.08 times** as often as the 180-degree-symmetric ones and **4.14 times** as often as the 90-degree-symmetric ones ([msg 2076](https://groups.io/g/eternity2/message/2076)). So symmetric pieces are the *hard-to-tile* ones, and a puzzle that included them would hand a solver exactly the uneven-tileability handhold that [flat colour frequencies](#make-every-frequency-flat) are meant to remove. Banning them keeps every piece about equally hard to place, with no easy ones to save for last. ### Two palettes, strictly separated The 22 colours split into 17 interior colours and 5 that appear only on the joins between border pieces, never inside ([msg 1947](https://groups.io/g/eternity2/message/1947)). This turns the frame into its own sub-puzzle whose difficulty can be tuned independently of the interior, so that neither part is a soft entry point: the same balancing act as the compact shape, applied to the palette. The five frame-only colours are also the rare ones, quarantined at the rim where their scarcity cannot create over-constrained interior cells that propagation would feast on. That visible signature has [its own page](/research/why/rare-color-geography). ### Make every frequency flat When Owen digitised his set on launch day he found the edge-colour distribution "as flat as could be": 24 edges of each of the 5 border-join colours, 48–50 of each of the 17 interior colours ([msg 1054](https://groups.io/g/eternity2/message/1054)). This single ingredient is the one that killed the Eternity I playbook. Eternity I was cracked largely through piece-difficulty ordering: its piece tileabilities varied enormously, so solvers could save the easiest pieces for last and let the statistics carry them home. Two weeks after launch Owen showed E2's flat distribution makes that approach worthless: when every colour is equally common, every piece is about equally tileable, and no ordering heuristic gets traction ([msg 1667](https://groups.io/g/eternity2/message/1667)). As doc_s_smith, one of the people who actually solved Eternity I, put it in reply, most-constrained-position selection became "our only other hope" ([msg 1722](https://groups.io/g/eternity2/message/1722)). ### Aim for exactly one solution The last ingredient sets the colour counts themselves. Owen worked backwards from the requirement "about one expected solution": setting the expected number of interior tilings to 1 and solving for the interior colour count gives $$I = (196! \cdot 4^{196})^{1/392} \approx 17.14$$ Round to 17, add the separately-tuned 5 border colours, and you have Eternity II's exact palette ([msg 1947](https://groups.io/g/eternity2/message/1947)). Owen backed the derivation with simulations, defended 17+5 against the neighbouring 16+8 design from the same one-expected-solution family, since it better balances the tileability of border and interior pieces and leaves no cheap way in through the frame ([msg 2426](https://groups.io/g/eternity2/message/2426)), and followed up with a table of hardest parameters for every board size, a general recipe of which E2 is the 16×16 row ([msg 2164](https://groups.io/g/eternity2/message/2164)). One expected solution is not an arbitrary aesthetic. It is the setting where solutions are as scarce as they can be while still existing: the peak of the phase transition, the point where search is provably at its worst. That measurement, and the published analyses that later confirmed Owen's number, live on the [hardness-peak page](/research/why/phase-transition). The flip side proves the knob is real: a deliberately *loosened* 16×16 design discussed on the list has around 10^42 expected solutions, though Owen warned that even that one is no pushover ([msg 4968](https://groups.io/g/eternity2/message/4968)). ## Who actually designed it Christopher Monckton invented the Eternity franchise and put up the prize, but his original idea for the sequel was a 1001-piece three-dimensional puzzle. Owen relayed this while noting that "the actual design is from Alex and Oliver" ([msg 2697](https://groups.io/g/eternity2/message/2697)). Alex Selby and Oliver Riordan are the two mathematicians who won Eternity I by discovering it had far more solutions than intended; Monckton hired the people who beat him. The group suspected this weeks before launch ([msg 716](https://groups.io/g/eternity2/message/716)), saw it confirmed in an official Tomy leaflet (the inventor met the E1 winners on breakfast television and asked them to work on E2's development; [msg 901](https://groups.io/g/eternity2/message/901)), and finally sourced it to a Times article: Selby and Riordan designed the puzzle-generating program ([msg 3373](https://groups.io/g/eternity2/message/3373)). That provenance explains the recipe's precision. The one team on earth with first-hand experience of how a prize puzzle fails statistically was paid to make sure the failure mode was gone. Every ingredient above (flatness, no duplicates, balanced palettes, one expected solution) closes a door that Selby and Riordan themselves had walked through in 2000. ## How the pieces were generated: a second-hand account The only detailed account of the generation process in the archive is second-hand and should be read as such. Dave Clark, founder of the eternity2.net distributed project, recounted a long phone conversation he had with Monckton on 26 July 2007: the puzzle was generated from entropy typed at a keyboard by the contest judges (some 200 inputs), regenerated until the judges were satisfied, then printed exactly once and vaulted. Monckton described the random-number generator to him as using "gaussian residues of powers of appropriately chosen primes", which Clark took to be Selby and Riordan's own implementation ([msg 4177](https://groups.io/g/eternity2/message/4177)). The thread briefly entertained the idea of attacking a cryptographically weak generator; a reply pointed out that if the construction was Blum–Blum–Shub-like it would be provably hard ([msg 4180](https://groups.io/g/eternity2/message/4180)). Nothing came of the angle, but the account stands as the archive's best primary-adjacent source on where the 256 pieces actually came from. ## The insurance policy A puzzle designed never to be solved still has to prove it *can* be. The Tomy launch material stated that nobody, not the inventor and not the designers, knows the solution: the generator printed it "between pages of random text whilst all parties were out of the room", and the output was sealed in front of witnesses ([msg 901](https://groups.io/g/eternity2/message/901)). After the contest ended unclaimed, Owen gave the statement still quoted today: "I am sure Alex and Oliver created a solution when Chris paid them to generate a practically impossible puzzle", and that it lies hidden amongst reams of printed text locked in a safe, as insurance against any legal challenge to the contest's good faith ([msg 8823](https://groups.io/g/eternity2/message/8823)). That safe is the recipe's final ingredient. The designed solution is what lets the puzzle sit at one-expected-solution instead of zero: existence guaranteed by construction, discovery priced beyond any contestant's reach. ## What the recipe means if you attack the puzzle today Every generic shortcut you might reach for was anticipated and priced in nearly two decades ago. Piece-frequency ordering died with the flat distribution. Symmetry and duplicate tricks have nothing to grab. There is no soft region to tile first, no palette imbalance to lever, and the colour count sits at the exact setting where search is worst. The community's twenty years of records (467 in 2008, 470 in 2021, none since) are the empirical readout of a design that worked precisely as intended. That does not make the puzzle impossible: one solution certifiably exists, printed and locked away. It means the remaining gap is not a tuning problem. Anything that closes it will have to be an idea the designers could not anticipate. That is, in the end, what this wiki is for. ## Related - [Tuned to the hardness peak](https://eternity2.dev/research/why/phase-transition) — Eternity II uses 22 colors. They split 17 interior to 5 frame-only, and that 17 is exactly where this kind of puzzle is hardest to solve. - [The rare colors live on the frame](https://eternity2.dev/research/why/rare-color-geography) — Five of Eternity II's 22 colors appear only along the border ring, each on exactly 24 edges, never once in the interior. A structural split that shapes how every solver treats the frame. - [The hunt, a history (part I: 2000–2009)](https://eternity2.dev/research/community/hunt) — The community's story, from a mailing list founded seven years before the puzzle existed to the $10,000 scrutiny prize won under a borrowed name, with every event sourced to its original message. Part I of a growing chronicle. --- # Entropy and the area law > Eternity II has two rules: edges must match, and each piece is used once. The first is generous. All the hardness lives in the second. - Canonical page (with interactive figures/demos): https://eternity2.dev/research/why/entropy-area-law/ - Updated: 2026-07-01 - Topics: structure - Reproduce: `just research-entropy-area-law` - Source: Fekete's subadditivity lemma, the theorem behind the entropy limit h∞ existing at all — https://en.wikipedia.org/wiki/Subadditivity#Subadditive_sequences - Source: Shannon entropy of a source, the h(n) quantities measured here — https://doi.org/10.1002/j.1538-7305.1948.tb01338.x --- CartesianGrid, Line, LineChart, ResponsiveContainer, Tooltip, XAxis, YAxis, } from "recharts"; Forget the use-each-piece-once rule for a moment and treat the 196 interior pieces as reusable tiles. Count the valid all-matched patches and they grow exponentially with size: there's no shortage of locally-valid ways to tile. The matching grammar is rich, not restrictive. We can measure that richness exactly. For a strip of width $n$, the growth rate per cell is an entropy density $h(n)$, and the sequence decreases toward the true two-dimensional value as the strip widens. ## The grammar's entropy, width by width > **[Figure]** interactive: EntropyChart. Rendered on the canonical page (link above); not shown in this markdown export. ## Then the area law bites Now put the use-each-piece-once rule back, and ask how often a random color-valid $n \times n$ patch actually uses distinct pieces. Call it $\rho(n)$. It collapses, and it collapses in the area, not the perimeter: $$ \rho(n) \;\approx\; \exp(-\alpha\, n^2), \qquad \alpha \approx 0.085. $$ An area-law decay is brutal because area grows quadratically. The fraction of realizable patches drops below one in a thousand at around eighty cells. > **[Figure]** interactive: RhoChart. Rendered on the canonical page (link above); not shown in this markdown export. ## See the gap open The same idea on the real pieces, exactly counted. Step the block size and watch how many colour-valid blocks survive the use-each-piece-once rule. > **[Figure]** Interactive: distinctness collapse and rho decay — interactive: EntropyScarcityLab. Rendered on the canonical page (link above); not shown in this markdown export. ## Why it matters Eighty cells is not arbitrary. It's the size of the smallest moves that separate the best known boards. The matching grammar stays rich up to about that scale, then the distinctness rule collapses it. So the wall isn't in the part that looks hard, matching colors; it's in the quiet rule that each piece is used once, whose cost grows with area, on a board just large enough for it to bite. See [why basin-hopping is impossible](/research/why/sigma-cycles). ## The theorem, briefly The per-width entropy has a well-defined limit. Joining an $n_1$-wide and an $n_2$-wide strip side by side only adds a seam constraint, so the eigenvalues satisfy $$ \lambda_{n_1+n_2} \;\le\; \lambda_{n_1}\,\lambda_{n_2}. $$ Taking logs makes $\log \lambda_n$ subadditive, and Fekete's lemma gives the limit as an infimum, which is exactly why the curve above decreases: $$ h_\infty \;=\; \lim_{n\to\infty}\frac{\log_{10}\lambda_n}{n} \;=\; \inf_n \frac{\log_{10}\lambda_n}{n}. $$ The upper bound is the purely horizontal rate: ignoring vertical constraints only adds patches, so $$ 0 \;<\; h_\infty \;\le\; \log_{10}\lambda_H \;=\; 1.6645, $$ with $\lambda_H = 46.18$ the spectral radius of the horizontal color-compatibility matrix. Positivity holds because the grammar supports exponentially many chains, so the density is strictly between zero and 1.6645, measured near 0.67. ## Related - [Tuned to the hardness peak](https://eternity2.dev/research/why/phase-transition) — Eternity II uses 22 colors. They split 17 interior to 5 frame-only, and that 17 is exactly where this kind of puzzle is hardest to solve. - [Why a faster computer doesn't help](https://eternity2.dev/research/why/prune-vs-speed) — The single most important idea in hard combinatorial search: shrinking the space you search beats searching it faster, by an exponential margin. Eternity II is engineered so you can barely shrink it at all. - [Forbidden patterns](https://eternity2.dev/research/why/forbidden-patterns) — Almost every small patch of pieces you could build is impossible. For a 2×2 square, 99.72% of the ways to place four pieces can never be made to match. - [Solution counting: measuring what you cannot find](https://eternity2.dev/research/build/analysis/solution-counting) — Nobody has ever seen a full Eternity II solution, yet the community knows, to within a factor of two, how many exist. This page is the story and the craft of that number: exact censuses on small boards, the expectation formula and its twenty-year convergence on 14,702, and the culled-search estimates that were trusted only when four independent runs agreed. --- # Forbidden patterns > Almost every small patch of pieces you could build is impossible. For a 2×2 square, 99.72% of the ways to place four pieces can never be made to match. - Canonical page (with interactive figures/demos): https://eternity2.dev/research/why/forbidden-patterns/ - Updated: 2026-07-01 - Topics: structure, search-space - Reproduce: `just research-forbidden-patterns` - Source: Forbidden patterns: article, source and results (GitHub) — https://github.com/raphael-anjou/eternity2/tree/main/research/topics/forbidden-patterns --- Eternity II has 256 square tiles, each with a color on all four sides. 196 of them are interior pieces, the ones with no grey border edge, so the only ones that ever sit inside the board. Take a few of those, drop them into a small shape, and rotate them however you like. Most of the time the colors simply won't line up, no matter what you try. The bigger the shape, the worse it gets. Two pieces side by side fail to fit about 39% of the time. Add a third in an L and you're stuck 83% of the time. Close up a 2×2 square and 99.72% of all placements are dead on arrival: only about 1 in 358 works. ## One that fits, one that can't
> **[Figure]** interactive: BoardSvg. Rendered on the canonical page (link above); not shown in this markdown export. > **[Figure]** interactive: BoardSvg. Rendered on the canonical page (link above); not shown in this markdown export.
## Try it: draw four pieces > **[Figure]** Interactive: paint a patch and watch it forbid itself — interactive: ForbiddenPatchLab. Rendered on the canonical page (link above); not shown in this markdown export. ## Where 99.72% comes from A rough estimate explains why the number is so high. Two adjacent pieces share one edge. Each interior piece carries colors from the 17-color interior palette, so a random pair of half-edges matches with probability roughly $$ \Pr[\text{one edge matches}] \;\approx\; \frac{1}{17} \;\approx\; 6\%. $$ A 2×2 square has four internal edges to satisfy at once. Rotations give each piece four chances, but the four edges are coupled, so a back-of-the-envelope independence estimate puts the chance all four match at very roughly $$ \Pr[\text{2}\times\text{2 feasible}] \;\sim\; 1 - \left(1 - \tfrac{1}{17}\right)^{\!c} \ \text{per rotation budget} \;\Rightarrow\; \lesssim 1\%, $$ which is already under one percent. The exact exhaustive count lands at 0.28% feasible, that is 99.72% forbidden $(\,0.28\% = \tfrac{3{,}993{,}696}{1{,}431{,}033{,}240}\,)$. The estimate is crude because the edges aren't independent and the colors aren't uniform, but it gets the order of magnitude right and shows why closing a square is so much harder than placing a single pair. ## The exact counts Every distinct-piece placement of each shape, checked exhaustively, with no sampling. | Shape | Placements | Forbidden | Forbidden % | | ---------------- | -------------: | ------------: | ----------: | | Two side by side | 38,220 | 14,890 | 38.96% | | Two stacked | 38,220 | 14,890 | 38.96% | | L of three | 7,414,680 | 6,173,828 | 83.26% | | 2×2 square | 1,431,033,240 | 1,427,039,544 | 99.72% | Computed exactly from the official set; the run reproduces identically every time (about twenty seconds). The [article, source and results are on GitHub](https://github.com/raphael-anjou/eternity2/tree/main/research/topics/forbidden-patterns). ## Forbidden before you even pick a piece The scarcity starts one level below whole pieces, at the colors. An interior cell shows two of the 17 interior colors on any given corner, the two edges that meet there, which is $17 \times 17 = 289$ possible ordered color pairs. Not all of them exist. Back in 2008 the community noticed that **20 of those 289 pairs are voids**: no interior piece, in any rotation, presents that particular pair of colors on adjacent edges ([msg 5027](https://groups.io/g/eternity2/message/5027)). So a partial board that forces a cell to answer with one of those 20 corner-pairs is dead on the spot, before a single piece is tried, and a fast solver can reject it with one table lookup. It is the same lesson as the 2×2 count, pushed down to the smallest unit that can be impossible: the constraints bite so early that whole categories of local demand have no legal answer at all. ## Why it matters A finished, correct board has zero forbidden patches: by definition, everything matches. So counting the forbidden patches in a board tells you roughly how far it is from a real solution, even when two boards have the same number of matched edges. Weak boards are full of forbidden squares; the best boards ever found have only a couple of dozen left. It also shows, from another angle, why the puzzle shrugs off clever local fixes. When 99.72% of small squares are impossible, the pieces that do fit together are rare and specific. There's almost no room to shuffle things around without breaking something. The good arrangements are scarce and rigid. ## A second axis of progress Counting forbidden squares turns the idea into a usable signal. Pick a real record board: the number of forbidden 2×2 windows falls as the matched-edge score rises. Two boards with the same edge-score can still differ here: the one with fewer forbidden squares is structurally closer to a solution, which is why some solvers track forbidden-patch count as a tiebreak. > **[Figure]** Interactive: count feasible vs forbidden placements — interactive: ForbiddenCountLab. Rendered on the canonical page (link above); not shown in this markdown export. ## Related - [Entropy and the area law](https://eternity2.dev/research/why/entropy-area-law) — Eternity II has two rules: edges must match, and each piece is used once. The first is generous. All the hardness lives in the second. - [KEYRING](https://eternity2.dev/research/lab/experiments/raphael-anjou/learning/keyring) — Build a board from scratch, ranking each next piece by three signals learned from past strong boards. Reached 460 in a board family no earlier search had cracked. - [Arc consistency, from AC-3 up](https://eternity2.dev/research/build/reduce/arc-consistency) — Forward checking looks one move ahead; arc consistency makes every cell's candidate list defend itself against every neighbour's, to a fixed point. Mackworth's AC-3, the optimal refinements that followed, and what the whole family actually measured on this puzzle, including where it is unsound. --- # Where you place the hints beats how many > On a 16×16 puzzle built like Eternity II, eighteen hints scattered across the board solve it in minutes, while the same puzzle needs eighty or more hints piled into contiguous rows to be as easy. Position, not count, is the lever, and it points straight at the endgame. - Canonical page (with interactive figures/demos): https://eternity2.dev/research/why/hint-geometry/ - Updated: 2026-07-10 - Topics: structure, search-space, backtracking - Source: Joe's hint-density study and Peter McGavin's 18-hint solve (groups.io thread 'A method to prune E2 search space by 17-30%+', msg 11725) — https://groups.io/g/eternity2/message/11725 - Source: Peter McGavin: 18 scattered hints solve the 16×16 E2-like puzzle in under 15 minutes (groups.io msg 11746) — https://groups.io/g/eternity2/message/11746 - Source: Peter McGavin: the optimised backtracker traces to Mike's 2007 post (groups.io msg 3098) — https://groups.io/g/eternity2/message/3098 --- Give a solver some correct pieces for free and the puzzle gets easier. The obvious question is how many you need. The better question, it turns out, is *where* they go. On a 16×16 puzzle built with Eternity II's exact colour recipe, eighteen hints placed in the right spots solve it in minutes; the same puzzle wants eighty or more hints, if you pile them into contiguous rows, to be that easy. A fourfold difference in count, decided entirely by geometry. ## Two ways to spend the same eighteen hints > **[Interactive: HintGeometryDiagram]** Rendered on the canonical page (link above); not shown in this markdown export. The left board is the real layout Peter McGavin used: eighteen hints on a regular lattice, every third column on a few odd rows. His plain scan-row backtracker solved Joe's 16×16 E2-like puzzle (five border colours, seventeen interior colours, the same distribution as the official puzzle) in under fifteen minutes on a single core, walking a search tree of 41,160,067,167 placements. Dropping to fifteen hints still worked; the search just grew to several hours. Pile eighteen hints into the first rows instead, the way a top-down scan naturally accumulates them, and they buy almost nothing: the hard part of the board is still completely open. Joe had come at it from the other side, seeding whole contiguous rows from a known solution, and needed far more before the puzzle fell:
18
scattered hints, solved in minutes
88+
contiguous-row hints for comparable ease
99%
of search time spent below depth 132
70%
of search time spent below depth 150
## Why position wins: the hints have to reach the endgame The two right-hand numbers explain the left-hand ones. Joe instrumented his backtracker over a billion iterations and found the work is not spread across the board at all: 99% of it happens after depth 132 of 256, and 70% after depth 150. Nearly all the pain is in the back half of the fill, and most of it past the three-fifths mark. A block of contiguous hints at the top is spent exactly where the search was never going to struggle. It shortens an easy beginning and leaves the expensive tail untouched. Scattered hints do the opposite: dotted through the board, including down into the region the search reaches last, they pre-empt the choices that would otherwise blow up deep in the tree. This is the same fact the record boards wear on their surface. A near-perfect board packs all its damage into the band of rows the search finished on, because [whichever rows you fill last are where the puzzle makes you pay](/research/why/mismatch-geometry). Hints only help to the extent they reach that band before the search does. It also fits [why the interior gives no forced moves](/research/why/no-forced-moves): with every interior cell still accepting scores of neighbours, a hint's value is not local propagation but global constraint, cutting off whole subtrees the search would otherwise have to walk. A hint far from the hard region cuts off subtrees that were cheap anyway. ## What it does and doesn't say This is a result about a 16×16 puzzle built to Eternity II's colour recipe, not about the official puzzle, whose five fixed clues are a different, much smaller gift in different places. What transfers is the shape of the lesson, and it is the same one the [prune-versus-speed](/research/why/prune-vs-speed) argument makes from the other direction: what matters is changing where the search spends its effort, and the effort lives in the endgame. A handful of hints aimed at that endgame is worth a great many aimed anywhere else. > **Note** > > The counts, the 41-billion-node tree, and the depth statistics are Joe's and Peter McGavin's measurements, reported on the eternity2 groups.io list in January 2026; the scattered layout shown is decoded from Peter's posted board (msg 11746). The optimised backtracker Peter used traces back to Mike's 2007 post (msg 3098). These are community results on a specific E2-like puzzle, recorded here with attribution rather than re-derived. ## Related - [Where the mismatches live](https://eternity2.dev/research/why/mismatch-geometry) — A near-perfect board doesn't scatter its few errors evenly. It packs them into one band of five rows and leaves all the rest flawless. Which band is decided by the direction the search filled the board, and you can see the mirror on the real record boards. - [No forced moves](https://eternity2.dev/research/why/no-forced-moves) — The usual way to crack a logic puzzle is to find a spot where only one piece fits, place it, and repeat. That lever doesn't exist here: every interior piece has between 73 and 137 possible neighbours, and not one is ever pinned to a single option. - [Why a faster computer doesn't help](https://eternity2.dev/research/why/prune-vs-speed) — The single most important idea in hard combinatorial search: shrinking the space you search beats searching it faster, by an exponential margin. Eternity II is engineered so you can barely shrink it at all. --- # Is this instance NP-complete, and how do I encode it? > Edge matching is NP-complete as a family, but that says nothing about one fixed 16×16 board: a single instance is a constant, not a problem. What is true is the family's worst-case hardness and this instance's empirical hardness, and how to write the puzzle for a SAT, exact-cover, or ILP solver with small worked sketches. - Canonical page (with interactive figures/demos): https://eternity2.dev/research/why/how-hard-is-this-instance/ - Updated: 2026-07-08 - Topics: exact-methods - Source: Demaine & Demaine 2007, "Jigsaw Puzzles, Edge Matching, and Polyomino Packing: Connections and Complexity" (Graphs and Combinatorics 23): edge matching is NP-complete — https://doi.org/10.1007/s00373-007-0713-4 - Source: Ansótegui, Béjar, Fernàndez & Mateu, How Hard is a Commercial Puzzle: the Eternity II Challenge (CCIA 2008) — https://repositori.udl.cat/bitstreams/0b6533fe-54e5-4070-85fe-80f7d35837d8/download - Source: Knuth, The Art of Computer Programming, Volume 4B: Algorithm X and Algorithm C (exact covering with colours) — https://www-cs-faculty.stanford.edu/~knuth/taocp.html - Source: Eternity II puzzle (Wikipedia) — https://en.wikipedia.org/wiki/Eternity_II_puzzle --- This page answers a question that keeps surfacing on Math and CS Stack Exchange and tops the dispute list on Wikipedia's Talk page for the puzzle: edge matching is NP-complete in general, so does that tell us anything about *this* fixed 16×16 board, and concretely, how would you hand Eternity II to a solver? The short answers are: no, not directly, and here are three encodings. ## First, the category error NP-completeness is a property of a *problem*, which in complexity theory means an infinite family of instances indexed by a size parameter $n$. "Edge-matching puzzles" is such a family: given $n$, a set of square tiles, and a colour alphabet, decide whether the tiles tile an $n \times n$ frame with all abutting edges agreeing. That decision problem is NP-complete ([Demaine & Demaine 2007](https://doi.org/10.1007/s00373-007-0713-4)), which means both that a proposed solution is checkable in polynomial time and that every problem in NP reduces to it. A single fixed board is not a family. The Eternity II instance has a definite answer, "yes, it is solvable" (the designers built it from a solution) or in the 5-clue competition form "yes, with exactly this arrangement". That answer is a single bit. A single bit is a constant, and "is this constant NP-complete?" is not a well-formed question: there is a constant-time algorithm that prints the answer (`return true`), it just has the answer baked in. Asking whether one instance is NP-complete is the same category error as asking whether the number 17 is polynomial-time. So the family is hard and the instance is a constant. What, then, is actually true and useful about the difficulty of the board on your desk? ## What is actually true Two separate statements, kept apart: - **Worst-case hardness of the family.** Because the general problem is NP-complete, no algorithm is known that beats exponential time in the worst case as $n$ grows, and finding one would prove $\mathrm{P}=\mathrm{NP}$. This bounds what any general edge-matching solver can promise. It says nothing about how a *specific* input behaves. - **Empirical hardness of this instance.** Hardness you can measure. The 16×16 board has on the order of $1.115\times10^{557}$ distinct piece-and-rotation arrangements, and the puzzle appears to admit very few solutions (the 5-clue form is designed for essentially one; see [complex theory](/research/why/complex-theory) for the expected-count estimate). A backtracking search therefore threads an astronomically wide space toward a near-empty solution set, so it spends almost all of its time exploring dead ends. That is why the puzzle is hard *in practice*, and it is a claim about this board, not about the family. The worst-case theorem and the empirical difficulty point the same way here, but they are different kinds of statement and only one of them is a theorem. A family can be NP-complete while a given instance is trivial (many are), and an instance can be brutally hard to solve in practice even inside a family that is polynomial. Ansótegui et al. made exactly the empirical case for Eternity II, building solver benchmarks from it and measuring the difficulty directly rather than appealing to the general theorem ([CCIA 2008](https://repositori.udl.cat/bitstreams/0b6533fe-54e5-4070-85fe-80f7d35837d8/download)). > **The one-line version** > > "Is Eternity II NP-complete?" No: an instance has no complexity class. "Is the edge-matching problem NP-complete?" Yes. "Is this instance hard to solve?" Empirically yes, because the search space is ~$10^{557}$ wide and the solution set is nearly empty, so search drowns in dead ends. ## Encoding it: the setup The rest is practical: how do you write the board so a solver can chew on it? All three encodings below share the same skeleton. Number the cells $c = 1 \dots 256$, the pieces $p = 1 \dots 256$, and the rotations $r \in \{0, 1, 2, 3\}$. A *placement* is a triple $(c, p, r)$: piece $p$ dropped into cell $c$ turned by $r$ quarter-turns. Every encoding has to say three things: 1. each cell gets exactly one placement, 2. each piece is used exactly once, 3. wherever two cells touch, the colours on the shared edge agree. The encodings differ only in how they express constraint 3, the colour match, and that difference is the whole story. The sketches below use a 2×2 or 3×3 board so you can see all the clauses; the 16×16 is the same shape at scale. ## SAT / CNF Introduce a Boolean variable $x_{c,p,r}$, true when piece $p$ sits at cell $c$ in rotation $r$. On the full board that is $256 \times 256 \times 4 \approx 262{,}000$ variables before any constraint. Then: - **Exactly one placement per cell.** For each cell $c$, an at-least-one clause over all its placements, $\bigvee_{p,r} x_{c,p,r}$, plus at-most-one clauses forbidding any two, $\lnot x_{c,p,r} \lor \lnot x_{c,p',r'}$ for distinct placements. - **Exactly one cell per piece.** The mirror image: for each piece $p$, one at-least-one clause over the cells it could occupy, plus at-most-one clauses so it is placed only once. - **Edge match.** For every interior adjacency and every placement whose exposed edge shows colour $k$, forbid every placement in the neighbouring cell whose facing edge is not $k$: a binary clause $\lnot x_{c,p,r} \lor \lnot x_{c',p',r'}$ for each conflicting pair. A 2×2 sketch makes the third family concrete. Cells $A$ (top-left) and $B$ (top-right) share a vertical edge; $A$'s east edge must equal $B$'s west edge. For each placement $(A,p,r)$ showing east colour $k$, and each placement $(B,p',r')$ whose west colour is not $k$, add $\lnot x_{A,p,r} \lor \lnot x_{B,p',r'}$. Do the same for $A$/$C$ vertically and the other two interior adjacencies. That is all constraint 3 is: a large pile of "these two placements cannot both be true" binary clauses. The catch is that the pile is enormous. The conflict clauses dominate, the at-most-one encodings add their own blowup (naive pairwise is quadratic; ladder or commander encodings trade it for auxiliary variables), and the result is a formula with millions of clauses whose structure gives conflict-driven search almost nothing to learn from. This has been tried since 2008 and complete SAT solvers stall on the full board; Blackwood, among others, reported that SAT did not help. The encoding is clean, the solver is not the bottleneck, the *instance* is. See [SAT and CSP encodings](/research/build/exact/sat-csp-encodings) for the benchmark history and where SAT verdicts still earn their keep as small-region impossibility proofs. ## Exact cover and dancing links The exact-cover view is tidier, and it hides a trap that trips up almost everyone who reaches for Knuth's dancing links. Set up 512 *items*: one per cell ("cell $c$ is filled") and one per piece ("piece $p$ is used"). Each *option* is a placement $(c,p,r)$, and it covers exactly two items: cell $c$ and piece $p$. A set of options covering every item exactly once is a board with every cell filled and every piece used once. That is a clean exact-cover instance, and Knuth's **Algorithm X** with dancing links solves exact cover beautifully. Here is the trap. Constraints 1 and 2 are cover-once conditions, which is exactly what exact cover expresses. But constraint 3, the colour match, is not a cover-once condition at all: a shared edge is not "used once", it is "assigned a colour that both neighbours agree on". Plain Algorithm X has no way to say this. People encode it, run it, and get boards with mismatched edges, or they try to bolt on extra items and find the cover-once semantics fight them. This exact confusion has its own question on the CS Stack Exchange. The fix is Knuth's own extension, **Algorithm C**, for XCC, exact covering with colours (TAOCP Volume 4B). Alongside the *primary* items (covered exactly once) you add *secondary* items that may be covered any number of times, *provided all options covering a given secondary item assign it the same colour*. Give each interior edge of the grid one secondary item. A placement that exposes colour $k$ on a shared edge assigns colour $k$ to that edge's secondary item. Two placements can then coexist across the edge only if they colour it identically, which is precisely the edge-match constraint, now expressed natively. A 3×3 sketch: 9 cell items and 9 piece items (primary), plus 12 interior-edge items (secondary, one per horizontal or vertical join). The centre cell's placements each touch four secondary edge items and must colour-agree with all four neighbours; a corner cell's placements touch two. Algorithm C threads this without ever emitting a mismatched board. The takeaway students miss: **exact-cover-DLX for Eternity II needs Algorithm C, not Algorithm X.** The [exact cover and dancing links](/research/build/exact/exact-cover-dlx) page walks the full XCC construction and where DLX genuinely shines (small boards, exhaustive solution counting) versus where it stalls on the 16×16. ## ILP and max-clique, briefly Two more framings, useful mainly as pointers: - **Integer linear programming.** Reuse the SAT variables as 0/1 integers $x_{c,p,r}$. Constraints 1 and 2 become equalities $\sum_{p,r} x_{c,p,r} = 1$ per cell and $\sum_{c,r} x_{c,p,r} = 1$ per piece. The edge match becomes, for each interior edge and each colour $k$, a linking condition tying the two neighbours' colour-$k$ placements together (one clean form: a fresh binary edge-colour variable $y_{e,k}$ with $\sum_k y_{e,k} = 1$ and each side's placements implying the matching $y$). It is a feasibility ILP, no objective, and the LP relaxation is weak, so branch-and-bound behaves much like the SAT search. See [LP relaxations](/research/build/exact/lp-relaxations). - **Max clique.** Build a graph whose vertices are legal placements and whose edges join any two placements that are mutually compatible (different cells, different pieces, and agreeing on any shared edge). A full board is a clique of size 256. This is elegant on paper but the graph is huge and clique solvers fare no better; it is worth knowing as a reduction, not as a practical attack. ## Where this leaves you If you came asking whether the theory of NP-completeness makes this instance provably hard, the answer is that it does not, and cannot: complexity classes describe families, and this board is a fixed input with a fixed answer. The general edge-matching problem is NP-complete, which caps what any solver can promise as $n$ grows, but the difficulty you actually feel is empirical, a $10^{557}$-wide space over a nearly empty solution set. Every encoding above faithfully captures the puzzle; none of them makes it easy, because the hardness lives in the instance, not in the choice of formalism. Once the board is encoded, the leverage that remains is [arc consistency](/research/build/reduce/arc-consistency) and smart search order, which is where the rest of this section picks up. ## Related - [Complex theory: counting the search before you run it](https://eternity2.dev/research/why/complex-theory) — Brendan Owen's complex theory estimates how wide the search tree is at every depth, and even how many solutions exist at all. Many in the community consider it the single most important thing to understand about Eternity II. - [SAT and CSP encodings](https://eternity2.dev/research/build/exact/sat-csp-encodings) — Write the puzzle as clauses and hand it to an industrial solver: the obvious move, tried since 2008. Why complete solvers stall on the full board, and where their verdicts still earn their keep as impossibility proofs. - [Exact cover and dancing links](https://eternity2.dev/research/build/exact/exact-cover-dlx) — Eternity II states cleanly as an exact-cover problem, and Knuth's Algorithm X with dancing links is the classic machine for those. Where it genuinely shines (small boards, exhaustive counting) and the two reasons it does not crack the 16×16: an unshrunk search tree, and no partial credit. - [Arc consistency, from AC-3 up](https://eternity2.dev/research/build/reduce/arc-consistency) — Forward checking looks one move ahead; arc consistency makes every cell's candidate list defend itself against every neighbour's, to a fixed point. Mackworth's AC-3, the optimal refinements that followed, and what the whole family actually measured on this puzzle, including where it is unsound. --- # Where the mismatches live > A near-perfect board doesn't scatter its few errors evenly. It packs them into one band of five rows and leaves all the rest flawless. Which band is decided by the direction the search filled the board, and you can see the mirror on the real record boards. - Canonical page (with interactive figures/demos): https://eternity2.dev/research/why/mismatch-geometry/ - Updated: 2026-07-02 - Topics: structure - Source: Peter McGavin's 469-record announcement: the board whose eleven unmatched edges this page analyses (groups.io msg 10045, September 2020) — https://groups.io/g/eternity2/message/10045 --- Score a record board edge by edge and a striking thing shows up: the mismatches are not spread around. McGavin's 469 has all eleven of its unmatched edges in the top five rows (rows 0 to 4); rows 5 through 15 are locally perfect. The board is, in effect, a flawless 11-row slab with all the damage swept up against one edge. Now score this project's best from-scratch boards the same way. The damage is again in a five-row band, but at the bottom. KEYRING's and GAUNTLET's mismatches sit in rows 11 to 15, with rows 0 through 10 perfect. It is the same picture flipped top to bottom. ## See it on the real boards Pick a board. The shaded band is where its mismatches actually fall, computed live with the engine's own scoring rule: community boards at the top, this project's at the bottom. > **[Figure]** Interactive: where mismatches are forced to live — interactive: MismatchGeometryLab. Rendered on the canonical page (link above); not shown in this markdown export. ## Why it flips: scan order The flip is not a coincidence; it is the fingerprint of how each board was built. A search that fills the board from the bottom up spends its perfect placements early, low down, and is forced to absorb every accumulated conflict in the last rows it reaches: the top. A search that fills top-down does the exact opposite and piles the damage at the bottom. The mismatches always end up crammed against the edge the solver finished at. Same puzzle, same kind of board, opposite construction order. ## The same band, under a different objective The pattern is not an artefact of how we score. Some solvers optimise a different thing entirely: not matched edges on a full board, but the most pieces you can place with zero conflicts, leaving holes instead of mismatches. Run that objective and the holes land in the same place. Louis Verhaard's "Only seven holes" board places 249 of 256 pieces conflict-free, and all seven holes sit in rows 1 to 4, the top band again. Laurent Zamofing, reaching a similar ceiling in 2026 by recombining the community's record boards, noted the same thing: "the unsolved residual always lands in that top band" ([msg 11901](https://groups.io/g/eternity2/message/11901)). Two objectives that share nothing but the puzzle, and the leftover damage collects against the same edge. It is the construction order, not the scoring rule, that decides where the difficulty ends up. (More on this variant on the [variants page](/research/build/variants).) ## What it tells us This is the visible form of two deeper facts. First, the great boards really are almost-complete: the gap to 480 is concentrated, not diffuse, which is why integer programming finds them locally frozen everywhere except that one band (the rigidity wall). Second, it says the endgame is the whole game: whichever rows you fill last are where the puzzle makes you pay, so the order you search in decides where the difficulty lands. That is the same lesson the playground's path-racing makes you feel, here written into the structure of every record board. > **Note** > > The per-row counts and the highlighted band are computed in your browser from the real board edges (the same scoring rule the engine uses), not hand-placed. The underlying finding and the scan-order explanation are recorded in the project lab notebook. ## Related - [The rigidity wall](https://eternity2.dev/research/why/rigidity-wall) — Every record board we have is frozen in place. You cannot nudge your way from a great board to a perfect one, and we can prove it. - [STAGED](https://eternity2.dev/research/lab/experiments/raphael-anjou/pipelines/staged) — Build the whole board from scratch with no pre-set frame, in stages, letting the border emerge last from whatever pieces are left. - [Which wall stops which method](https://eternity2.dev/research/why/walls-and-methods) — The research section has two halves: the structural walls that make Eternity II hard, and the algorithms built to climb them. This page is the bridge: each method lined up against the wall it actually attacks, and the score where that wall stopped it. - [Why basin-hopping looks impossible](https://eternity2.dev/research/why/sigma-cycles) — If you can't improve a great board by polishing it, maybe you can jump to a different great board. On every record pair tested, you can't, and the structural reason why is worth seeing. --- # No forced moves > The usual way to crack a logic puzzle is to find a spot where only one piece fits, place it, and repeat. That lever doesn't exist here: every interior piece has between 73 and 137 possible neighbours, and not one is ever pinned to a single option. - Canonical page (with interactive figures/demos): https://eternity2.dev/research/why/no-forced-moves/ - Updated: 2026-07-01 - Topics: structure, search-space - Reproduce: `just research-no-forced-moves` - Source: No forced moves: article, source and results (GitHub) — https://github.com/raphael-anjou/eternity2/tree/main/research/topics/no-forced-moves --- Bar, BarChart, CartesianGrid, ResponsiveContainer, Tooltip, XAxis, YAxis, } from "recharts"; Every one of the 196 interior pieces has between 73 and 137 other pieces that can legally sit to its right (counting right-hand partners, as the chart above does). The typical piece has over a hundred options. Not a single piece is ever pinned to one choice. This is the flip side of forbidden patterns. There, almost every combination of pieces is impossible. You'd think all those rules would corner pieces into place. They don't: the constraints rule out combinations without ever cornering an individual piece, so a solver never gets a free, forced move to build on.
{data.forcedPieces}
pieces forced to a single option
{data.minPartners}–{data.maxPartners}
partners per piece (min to max)
{data.meanPartners}
average partners
## How many neighbours each piece allows The 196 interior pieces, bucketed by how many right-hand neighbours each one accepts. The whole distribution sits far from one. > **[Interactive: PartnerHistogram]** Rendered on the canonical page (link above); not shown in this markdown export. ## See it on a real puzzle The engine fills a few cells; then we count, live, how many pieces legally fit the next one. It almost never drops to one. > **[Figure]** Interactive: candidate counts, cell by cell — interactive: ForcedMovesLab. Rendered on the canonical page (link above); not shown in this markdown export. ## Why it matters Put this beside forbidden patterns and the real shape of the difficulty appears. Locally the puzzle looks loose: any piece fits next to plenty of others, so there's nothing to propagate and no chain of forced moves to ride. Globally almost every combination is illegal. The hardness lives in that gap: lots of local freedom, almost no global consistency. A solver has to make a long run of free-looking choices that only turn out wrong much later. ## Related - [Why a faster computer doesn't help](https://eternity2.dev/research/why/prune-vs-speed) — The single most important idea in hard combinatorial search: shrinking the space you search beats searching it faster, by an exponential margin. Eternity II is engineered so you can barely shrink it at all. - [Piece theft, where solvers die](https://eternity2.dev/research/why/piece-theft) — A solver fills a few rows for free, then hits a wall in the middle of the board. Here's the mechanism: a scarce piece spent in the wrong place, rows ago. - [Tuned to the hardness peak](https://eternity2.dev/research/why/phase-transition) — Eternity II uses 22 colors. They split 17 interior to 5 frame-only, and that 17 is exactly where this kind of puzzle is hardest to solve. - [Arc consistency, from AC-3 up](https://eternity2.dev/research/build/reduce/arc-consistency) — Forward checking looks one move ahead; arc consistency makes every cell's candidate list defend itself against every neighbour's, to a fixed point. Mackworth's AC-3, the optimal refinements that followed, and what the whole family actually measured on this puzzle, including where it is unsound. --- # Tuned to the hardness peak > Eternity II uses 22 colors. They split 17 interior to 5 frame-only, and that 17 is exactly where this kind of puzzle is hardest to solve. - Canonical page (with interactive figures/demos): https://eternity2.dev/research/why/phase-transition/ - Updated: 2026-07-02 - Topics: structure - Reproduce: `just research-phase-transition` - Source: Brendan Owen, Design the hardest puzzle: the 17+5 derivation (eternity2 mailing list, August 2007) — https://groups.io/g/eternity2/message/1947 - Source: Ansótegui, Béjar, Fernández & Mateu, On the hardness of solving edge matching puzzles as SAT or CSP problems (Constraints, Springer 2013) — https://link.springer.com/article/10.1007/s10601-012-9128-9 - Source: Ansótegui, Béjar, Fernández & Mateu, How Hard is a Commercial Puzzle: the Eternity II Challenge — https://repositori.udl.cat/server/api/core/bitstreams/0b6533fe-54e5-4070-85fe-80f7d35837d8/content --- Hard search problems have a difficulty knob. Loosen it and there are many solutions, so a search trips over one fast. Tighten it and there are none, which is often easy to prove. In between sits a narrow band where solutions are scarce but real, and that's where search blows up. People call it a phase transition, like water freezing. For edge-matching puzzles the knob is the number of colors. Too few and pieces fit together countless ways; too many and they barely fit at all. The [published analysis](https://link.springer.com/article/10.1007/s10601-012-9128-9) puts the peak at around 17 interior colors, the setting where a puzzle this size has about one solution. Eternity II uses 17. The community had that number within weeks of launch: in August 2007, Brendan Owen derived $I = (196! \cdot 4^{196})^{1/392} \approx 17.14$ interior colours from the "about one expected solution" criterion, exactly the published parameters, years before the academic analyses ([Design the hardest puzzle, msg 1947](https://groups.io/g/eternity2/message/1947)). ## The difficulty wall > **[Figure]** Interactive: the colour-count difficulty peak — interactive: PhaseTransitionLab. Rendered on the canonical page (link above); not shown in this markdown export. ## Or measure it yourself The chart above is precomputed. This one isn't: the engine solves fresh puzzles live, one per colour count, and draws the peak from real runs in your browser. > **[Figure]** Interactive: solve across the difficulty peak live — interactive: PhaseTransitionLiveLab. Rendered on the canonical page (link above); not shown in this markdown export. ## The transition, measured on real pieces The colour-count argument says *where* the peak is. In March 2008 Brendan Owen went and watched a phase transition happen, directly, on the actual pieces. He took a thin 2-by-L interior rectangle and tiled it with random sets of E2's interior pieces, four hundred random sets at each length, and recorded how many could be completed with no mismatch ([msg 4909](https://groups.io/g/eternity2/message/4909)). > **[Interactive: RectangleTransitionChart]** Rendered on the canonical page (link above); not shown in this markdown export. The shape is the phase transition in miniature. A 2-by-1 or 2-by-2 strip is so short that random pieces often just fit: 58% solvable at length 1. Then it dies completely. From length 4 through 15, not one random set out of four hundred tiles the rectangle at any length: solutions are so scarce they effectively do not exist. And then they come back. At length 16 one set in four hundred works, by 19 it is 8.5%, by 21 it is 57%, and by 22 nearly nine in ten. The region where solutions are vanishingly rare but not yet impossible is exactly the hard band, and it is not a story or a model here, it is a count. It is also why a 14-cell-wide interior is so punishing: it sits in the steep part of that climb, where a solution exists but almost no random arrangement is one. ## The split, straight from the pieces Sorting the official set's colors by where they appear shows the design plainly.
5 frame-only colors
{data.frameOnlyColors.map((c) => (
> **[Interactive: MotifSwatch]** Rendered on the canonical page (link above); not shown in this markdown export. '{colorToLetter(c)}'
))}
These appear only on border and corner pieces, never in the interior. They are the rare colors, kept to the edge.
17 interior colors
{data.interiorColors.map((c) => (
> **[Interactive: MotifSwatch]** Rendered on the canonical page (link above); not shown in this markdown export. '{colorToLetter(c)}'
))}
The palette of the inside of the board, where almost all the matching happens.
## The set in numbers | | Count | | ----------------- | ----: | | Corner pieces | 4 | | Edge pieces | 56 | | Interior pieces | 196 | | Interior colors | 17 | | Frame-only colors | 5 | ## Why it matters This is the clearest single sign that Eternity II was made hard on purpose. Board size, piece count and color split all aim at the same target: a puzzle with about one solution, placed at the worst possible spot for any search to find it. The difficulty was chosen, the way a good exam is neither trivial nor impossible. How do we know the peak is real and not just a story? Two ways meet here. The published analysis [derives it](https://repositori.udl.cat/server/api/core/bitstreams/0b6533fe-54e5-4070-85fe-80f7d35837d8/content): for framed edge-matching puzzles, the color count where you'd expect about one solution falls near 17, and that is the hardest setting to search. And you can watch a piece of it yourself in the demo above: build real puzzles, count the work, and see it explode when colors are scarce. The impact is concrete. It means the gap to a solution isn't a tuning problem you can grind away with a faster machine; the puzzle was placed where search is worst on purpose, so beating it needs a genuinely better idea, not just more effort. See the difficulty measured live on the [Algorithms page](/algorithms). ## Related - [Designed to be unsolvable: the recipe](https://eternity2.dev/research/why/design-recipe) — Eternity II follows a recipe for the hardest possible edge-matching puzzle: compact shape, no symmetric or duplicate pieces, split palettes, flat frequencies, one expected solution. The community reverse-engineered every ingredient in the launch year. - [Why a faster computer doesn't help](https://eternity2.dev/research/why/prune-vs-speed) — The single most important idea in hard combinatorial search: shrinking the space you search beats searching it faster, by an exponential margin. Eternity II is engineered so you can barely shrink it at all. - [Entropy and the area law](https://eternity2.dev/research/why/entropy-area-law) — Eternity II has two rules: edges must match, and each piece is used once. The first is generous. All the hardness lives in the second. - [No forced moves](https://eternity2.dev/research/why/no-forced-moves) — The usual way to crack a logic puzzle is to find a spot where only one piece fits, place it, and repeat. That lever doesn't exist here: every interior piece has between 73 and 137 possible neighbours, and not one is ever pinned to a single option. --- # Piece theft, where solvers die > A solver fills a few rows for free, then hits a wall in the middle of the board. Here's the mechanism: a scarce piece spent in the wrong place, rows ago. - Canonical page (with interactive figures/demos): https://eternity2.dev/research/why/piece-theft/ - Updated: 2026-07-01 - Topics: structure, search-space - Reproduce: `just research-piece-theft` - Source: Régin 1994, “A Filtering Algorithm for Constraints of Difference in CSPs” (AAAI-94), the all-different reasoning that predicts starvation — https://cdn.aaai.org/AAAI/1994/AAAI94-055.pdf --- Bar, BarChart, CartesianGrid, ResponsiveContainer, Tooltip, XAxis, YAxis, } from "recharts"; Fill the board top-left to bottom-right and every new cell already knows two of its colors: the north color from the piece above, the west color from the piece to the left. The cell needs an unused piece that can show that exact pair. Those demands are scarce, with only about three possible pieces on average, and 47 of them have just one. So a board that looks healthy, most pieces still in the box, can already be doomed. Somewhere back up the board, the single piece that could ever serve an upcoming cell was used for something else. When the solver finally reaches that cell, there's nothing to place. ## How a cell dies > **[Interactive: PieceTheftDiagram]** Rendered on the canonical page (link above); not shown in this markdown export. ## How many pieces can serve a demand
{data.uniqueServerDemands}
demands served by a single piece
{data.meanServers}
pieces per demand, on average
{data.occurringDemands}
distinct demands that occur
> **[Figure]** interactive: ServersChart. Rendered on the canonical page (link above); not shown in this markdown export. ## Starve a cell yourself The engine fills a board to a cell with a single legal supplier; steal that piece and watch the cell die with the box still full. > **[Figure]** Interactive: where solvers die to piece theft — interactive: PieceTheftLab. Rendered on the canonical page (link above); not shown in this markdown export. ## Why it matters A tempting fix is a global check: do the remaining pieces still cover the remaining cells? It doesn't help. Globally the supply is fine; the failure is one scarce piece misallocated, not a shortage. So a global lookahead sees nothing wrong right up until the cell turns out to have no server, which is why this wall resisted so many attempts to prune it early. Set this beside [no forced moves](/research/why/no-forced-moves) and the trap is complete. Every piece has dozens of places it could go, so the solver is never told where a scarce piece must be saved, yet each scarce piece has exactly one demand it must be saved for. Freedom to place, no guidance on where to save. ## Related - [No forced moves](https://eternity2.dev/research/why/no-forced-moves) — The usual way to crack a logic puzzle is to find a spot where only one piece fits, place it, and repeat. That lever doesn't exist here: every interior piece has between 73 and 137 possible neighbours, and not one is ever pinned to a single option. - [PRIOR](https://eternity2.dev/research/lab/experiments/raphael-anjou/learning/prior) — Build a board from nothing, breaking ties by where pieces tend to sit in the strong boards we already have. It reaches a high score with no starting board to copy. --- # Why a faster computer doesn't help > The single most important idea in hard combinatorial search: shrinking the space you search beats searching it faster, by an exponential margin. Eternity II is engineered so you can barely shrink it at all. - Canonical page (with interactive figures/demos): https://eternity2.dev/research/why/prune-vs-speed/ - Updated: 2026-07-01 - Topics: speed, search-space, backtracking - Reproduce: `just research-prune-vs-speed` - Source: Article, source and results on GitHub (research/topics/prune-vs-speed) — https://github.com/raphael-anjou/eternity2/tree/main/research/topics/prune-vs-speed - Source: Peter McGavin: early doom-detection pruning is generally too expensive to be worthwhile (groups.io msg 11848) — https://groups.io/g/eternity2/message/11848 - Source: @95A31: a full battery of feasibility checks turned out to be useless on an 8×8 search (groups.io msg 11856) — https://groups.io/g/eternity2/message/11856 --- Picture the search as a tree. From the empty board you choose a piece for the first cell; from there a piece for the second; and so on, 256 cells deep. The number of leaves at the bottom is the branching factor raised to the depth, an astronomically large number. To prove a region has no solution, a search has to walk that tree. Now there are two ways to do less work. You can go **faster**: a better engine, more cores, hand-tuned inner loops. Or you can make the tree **smaller**, pruning branches that can't lead to a solution, so the effective branching factor drops. These sound similar. They are not even close. ## Constant versus exponential A speedup is a constant divisor. Make the machine 1000× faster and you do 1000× less waiting, the same whether the tree is ten levels deep or ten thousand. It buys you a fixed multiple, full stop. A prune compounds. Shave even a few percent off the branching factor and you save that fraction at every single level. Over 256 levels the savings multiply into each other: cutting the branching factor from $b$ to $b'$ divides the work by $(b/b')^{256}$. A 5% cut, applied all the way down, is worth $(1/0.95)^{256} \approx 5\times10^{5}$, a five-hundred-thousand-fold speedup's worth of work, from one cheap structural idea. That beats almost any speedup a real machine can offer. ## Feel the gap Trade a raw speedup against a small per-level prune and watch the prune win by orders of magnitude. > **[Figure]** Interactive: pruning power vs raw speed — interactive: PruneVsSpeedLab. Rendered on the canonical page (link above); not shown in this markdown export. ## Why this is exactly E2's curse If pruning is the lever that matters, the hard puzzles are the ones you can't prune. Eternity II was tuned to be precisely that. Four of its walls are, underneath, all the same statement: there is nothing local to prune on. - **[No forced moves](/research/why/no-forced-moves)**: every interior cell still has 73 to 137 legal neighbours, so propagation almost never collapses a cell to one choice. The branching factor stays stubbornly high. - **[On the hardness peak](/research/why/phase-transition)**: the piece and colour counts sit where there is about one expected solution, leaving no solution-dense region to aim a statistical shortcut at, the trick that cracked Eternity I. - **[The area law](/research/why/entropy-area-law)**: the count of genuinely-distinct partial boards collapses past ~80 cells, but no local scoring signal can see that global collapse, so you can't prune toward it cheaply. - **[Rigidity](/research/why/rigidity-wall)**: even at a record board, the move to a better one is huge and indivisible, with no gradient to follow and nothing nearby to prune away. ## What it means for everything else here This is the lens for the whole research section. A far faster engine makes the same search cheaper, not smaller, and does not move the record. Every experiment that did move the needle changed the shape of the search instead: a different scan order, a learned prior over where pieces sit, a confined region for the mismatches. And every dead end is, at heart, a prune that the puzzle's global structure refuses to honour. Speed first feels productive; it is almost never where the gap to 480 is hiding. ## The community landed here too, the hard way The counterintuitive half of this is that even *legal* pruning often loses. A check that detects a doomed partial board and backtracks early sounds like a free win, but if the check costs more than the subtree it saves, a plain backtracker that just barrels ahead is faster. Peter McGavin put the settled view plainly on the groups.io list: methods that try to detect a doomed partial placement and backtrack early "are generally considered too expensive to be worthwhile". A newcomer running a decision-diagram solver, @95A31, then confirmed it from scratch: after building a full battery of feasibility checks he reported that "all the feasibility checks I implemented turned out to be useless", with a complete 8×8 search still grinding through 953 billion nodes over 17 hours. The lesson is not that pruning is bad, it is that a prune only pays if it is *cheaper than the search it removes*, and on this puzzle almost nothing local clears that bar. > **Note** > > The tree numbers in the demo are illustrative: a branching factor and depth chosen to be E2-like and legible, not a measurement of a specific solver. The hardness curve and node counts, however, are real engine measurements on small puzzles, deterministic and reproducible with `just research-prune-vs-speed`. The principle itself, constant divisor versus exponential divisor, is exact. ## Related - [Which wall stops which method](https://eternity2.dev/research/why/walls-and-methods) — The research section has two halves: the structural walls that make Eternity II hard, and the algorithms built to climb them. This page is the bridge: each method lined up against the wall it actually attacks, and the score where that wall stopped it. - [Complex theory: counting the search before you run it](https://eternity2.dev/research/why/complex-theory) — Brendan Owen's complex theory estimates how wide the search tree is at every depth, and even how many solutions exist at all. Many in the community consider it the single most important thing to understand about Eternity II. - [No forced moves](https://eternity2.dev/research/why/no-forced-moves) — The usual way to crack a logic puzzle is to find a spot where only one piece fits, place it, and repeat. That lever doesn't exist here: every interior piece has between 73 and 137 possible neighbours, and not one is ever pinned to a single option. - [Tuned to the hardness peak](https://eternity2.dev/research/why/phase-transition) — Eternity II uses 22 colors. They split 17 interior to 5 frame-only, and that 17 is exactly where this kind of puzzle is hardest to solve. - [The rigidity wall](https://eternity2.dev/research/why/rigidity-wall) — Every record board we have is frozen in place. You cannot nudge your way from a great board to a perfect one, and we can prove it. - [Arc consistency, from AC-3 up](https://eternity2.dev/research/build/reduce/arc-consistency) — Forward checking looks one move ahead; arc consistency makes every cell's candidate list defend itself against every neighbour's, to a fixed point. Mackworth's AC-3, the optimal refinements that followed, and what the whole family actually measured on this puzzle, including where it is unsound. --- # The rare colors live on the frame > Five of Eternity II's 22 colors appear only along the border ring, each on exactly 24 edges, never once in the interior. A structural split that shapes how every solver treats the frame. - Canonical page (with interactive figures/demos): https://eternity2.dev/research/why/rare-color-geography/ - Updated: 2026-07-01 - Topics: structure - Reproduce: `just research-rare-color-geography` - Source: Brendan Owen derives the 17+5 colour design as the hardest possible puzzle (groups.io message 1947) — https://groups.io/g/eternity2/message/1947 --- Bar, BarChart, CartesianGrid, Legend, ResponsiveContainer, Tooltip, XAxis, YAxis, } from "recharts"; The 22 colors don't play equal roles. Sort them by where their edges sit and they split into two clean classes: five rare colors fenced off to the border, and seventeen common colors that do almost all their work inside the board. ## Where the rare colors are allowed Pick one of the five rare colors and watch the board: all 24 of its edges light up around the frame ring, and the 14×14 interior stays completely blank. Switch to a common color and the interior fills instead. That empty middle, for every rare color, is the whole finding. > **[Figure]** interactive: RareColorRing. Rendered on the canonical page (link above); not shown in this markdown export. ## The five rare colors > **[Interactive: RareSwatches]** Rendered on the canonical page (link above); not shown in this markdown export.
{data.edgesPerRareColor}
edges each
{data.rareEdgesTotal}
rare edges, all on the frame
0
rare edges in the interior
## Frame vs interior, color by color > **[Figure]** interactive: FrameInteriorChart. Rendered on the canonical page (link above); not shown in this markdown export. > **[Figure]** Interactive: the rare-colour border geography — interactive: RareColorLab. Rendered on the canonical page (link above); not shown in this markdown export. ## Why it matters The split itself is structural, not a defensive trick. Because the outer rim is solid grey, every border piece keeps its grey edge facing out, so its coloured edges only ever meet other border edges or the interior: the border and interior colours live in separate pools no matter what. The five border colours read as "rare" simply because there are far fewer border edges to colour, and they could be relabelled to any five values (even reusing interior ones) without changing the puzzle at all. (See the [design note on why](/research/why#engineered-to-resist-cleverness), with thanks to Vasily V. on the groups.io list for the correction.) What is real, and what matters for solving, is the consequence: the 14×14 interior is left to seventeen common colours with no rare, highly-constraining signal anywhere in it, which is a large part of why interior search has so little to grip. The border, where the colour pool is small and matches are tight, is correspondingly the part every strong board gets essentially perfect. Eternity II's colour counts were balanced to remove the statistical handholds that sank Eternity I; this geography is where you feel the result. See [why the interior gives no forced moves](/research/why/no-forced-moves). ## Related - [Designed to be unsolvable: the recipe](https://eternity2.dev/research/why/design-recipe) — Eternity II follows a recipe for the hardest possible edge-matching puzzle: compact shape, no symmetric or duplicate pieces, split palettes, flat frequencies, one expected solution. The community reverse-engineered every ingredient in the launch year. - [Forbidden patterns](https://eternity2.dev/research/why/forbidden-patterns) — Almost every small patch of pieces you could build is impossible. For a 2×2 square, 99.72% of the ways to place four pieces can never be made to match. - [The border balance](https://eternity2.dev/research/why/border-balance) — A solved board hides a simple bookkeeping law: every colour the border hands to the interior, the interior hands straight back. Break it and you know instantly the board is wrong; obeying it, though, guarantees nothing. - [CLOISTER](https://eternity2.dev/research/lab/experiments/raphael-anjou/pipelines/cloister) — Fix a perfect border, then search the interior with the border's edges treated as hard constraints from the very first cell. --- # The rigidity wall > Every record board we have is frozen in place. You cannot nudge your way from a great board to a perfect one, and we can prove it. - Canonical page (with interactive figures/demos): https://eternity2.dev/research/why/rigidity-wall/ - Updated: 2026-07-10 - Topics: structure, local-search, exact-methods - Source: Local rigidity theorem (project paper, 2026-05-16): ≥13 MIP proofs of halo-optimality across 3–4 basins, out to halo-4 — https://github.com/raphael-anjou/eternity2/tree/main/research - Source: Land & Doig 1960, branch and bound, the exact method behind every region solve — https://doi.org/10.2307/1910129 - Source: benj39100: GPU annealing on the strict-5-clue board hits the same frozen core; best score grows with distance from the incumbent (groups.io msg 11902) — https://groups.io/g/eternity2/message/11902 - Source: William Millilaw's independent halo SAT-residual and replica freeze tests, reproduced here on the public record boards (all UNSAT out to a two-cell halo) — https://github.com/raphael-anjou/eternity2/tree/main/research/topics/rigidity-sat-halo --- Here is the intuition almost everyone starts with: get close, then tidy up the last few mismatches. Swap a couple of pieces, rotate a few, and surely the score creeps up to 480. It doesn't. On every top board we have tested, the last mismatches are locked. Move anything nearby and the score stays the same or drops. The good boards aren't almost-solutions waiting for a polish; they're isolated points with nowhere better to go next door. ## Watch the region grow > **[Interactive: RigidityHalo]** Rendered on the canonical page (link above); not shown in this markdown export. ## Try to beat it yourself A real perfect small board. Swap any two pieces, or let the engine try every swap. Nothing beats it; that's rigidity, live. > **[Figure]** Interactive: swap pieces and watch the score refuse to rise — interactive: RigidityLab. Rendered on the canonical page (link above); not shown in this markdown export. ## How this is known The result does not rest on trying a lot of swaps and giving up. It comes from an exact question put to an integer-programming solver: take a region of the board, free every piece inside it, and find the single best way to fill it back in. The solver searches that whole local space exactly, not by sampling. The answer keeps coming back the same: the best arrangement is the one already there. We proved it for region after region, across three different record boards, and out to a radius of four cells, which is a block of dozens of cells at once. Every time, no improvement exists. ## Method: the MIP proof The exact question, stated precisely. Around each defect cell take the *halo-$r$* region: every cell within $r$ steps. Free all pieces inside it, keep the rest of the board fixed as a boundary, and solve an integer program for the best legal refill. Binary variables $x_{c,p,\theta} \in \{0,1\}$ place piece $p$ at rotation $\theta$ in cell $c$; one-piece-per-cell and one-cell-per-piece constraints make it an assignment problem; the objective maximizes matched edges, counting the fixed boundary. A 64-cell region is about 18,700 binary variables. Branch and bound then either finds a strictly better refill or proves, with a dual bound, that none exists. It never finds one. The proofs, region by region: | Region | Board | Cells | Solver time | Result | |---|---|---:|---:|---| | halo-2, per-component (×8) | 3 basins (469, 459, 458) | 2–32 | seconds each | all Δ = +0, **proven** | | halo-1 joint | McGavin 469 | 37 | 895 s | Δ = +0, **proven** | | halo-1 joint | Local 459 | 59 | 1800 s | Δ = +0, **proven** | | halo-3, per-component | McGavin 469 | 42 + 47 | 929 s | Δ = +0, **proven** | | halo-4, component 0 | McGavin 469 | 57 | 1200 s | Δ = +0, **proven** | Across four basins and ≥13 regions the answer is invariant: the incumbent board is locally MIP-optimal, out to halo-4 for McGavin's 469. The one region left with a gap, the top-four rows, 64 cells, still gives a *sound* result: a dual bound of 123 against the incumbent's 116, so even the unclosed case cannot exceed the wall by much (it implies a board-wide bound of ≤ 476). The badge says *proven* rather than *conjectured* for the regions actually closed; the general statement over *all* boards remains a conjecture, supported by every region tested to date. ## Why it matters This reframes the whole gap to 480. The distance from the best known board to a solution is not a pile of small fixes waiting to be found. If it were, this kind of local search would have found them. The barrier is that the good boards sit at the bottom of their own little valleys, and the valley walls are exact, not approximate. It also tells you what won't work. Polishing, hill-climbing, and most local-repair heuristics are trying to walk uphill from a frozen point. There is no uphill. Reaching a solution needs a move that rearranges a large region all at once, or a different starting point entirely, not a better polish. ## Someone hit the same wall from the annealing side The MIP proof approaches the wall analytically. In June 2026 another researcher ran headlong into it empirically. Working the strict five-clue board with a GPU simulated-annealing solver (4096 parallel replicas), benj39100 reported two things that read like a restatement of this page. First, the best score a run could reach *increased with distance from the current best board*: to climb from 429 toward 432 the winning perturbations had to migrate steadily further out, because near the incumbent there was no improving move to find. Second, across all their best boards the same roughly forty-two broken edges formed a frozen "hard core" that local search never touched, so they had to add an explicit term that *rewarded* prying that core open. A locally frozen incumbent with no nearby gradient, and a small locked set of defects nothing local will move: that is the rigidity wall, seen from a completely different method. ## And again, from a SAT solver A third researcher reached the same conclusion with a third tool. William Millilaw, working the ceiling independently, ran two tests. The first was a freeze test: perturb the root of a top board, re-optimize, and see which cells come back. On his best boards 93 to 100 percent of the cells returned to exactly where they were, a frozen core the search could not move. The second was a decision question for a SAT solver. Free the cells around the mismatches, demand that every freed edge match, and ask whether any arrangement of those pieces satisfies it. His solver answered UNSAT. We [reproduced that SAT test](https://github.com/raphael-anjou/eternity2/tree/main/research/topics/rigidity-sat-halo) on the public record boards, with our own encoder and a positive control to make sure a matched region comes back satisfiable. Every record board we tried, from Verhaard's 467 up to Blackwood's 470, is UNSAT out to a two-cell halo: no local rearrangement of a record board's own pieces closes a single mismatch. Integer programming optimizes and bounds; annealing runs into the wall by hand; SAT decides and returns a refutation. Three methods, one answer. His earlier snake-and-local-search work put a number on why. The largest patch any of his repair operators could rewrite in one move was about 48 cells, while two of the known good boards, both near the ceiling, differ across roughly 225 cells. A move that can only touch 48 cells cannot cross a 225-cell gap, so no sequence of them reaches a different basin. He looked for a chain of small improving moves that would tunnel out and found none: zero improvements across twenty-eight million four- and five-move combinations at the plateau. That is the same wall stated as a budget. Local repair rewrites too little at once to leave the valley, which is why escaping needs a move that rearranges a large region all at once, exactly as the proof section above concludes. > **The next piece of the picture** > > If you can't improve a board locally, maybe you can hop from one good board to another. That fails too, for a related reason: [see why basin-hopping is impossible](/research/why/sigma-cycles). *The proofs use integer programming on regions of each board; they run for minutes per region on a solver, so they aren't reproduced live here. The boards themselves are bundled and checkable in the viewer.* ## Related - [Why basin-hopping looks impossible](https://eternity2.dev/research/why/sigma-cycles) — If you can't improve a great board by polishing it, maybe you can jump to a different great board. On every record pair tested, you can't, and the structural reason why is worth seeing. - [Which wall stops which method](https://eternity2.dev/research/why/walls-and-methods) — The research section has two halves: the structural walls that make Eternity II hard, and the algorithms built to climb them. This page is the bridge: each method lined up against the wall it actually attacks, and the score where that wall stopped it. - [Why a faster computer doesn't help](https://eternity2.dev/research/why/prune-vs-speed) — The single most important idea in hard combinatorial search: shrinking the space you search beats searching it faster, by an exponential margin. Eternity II is engineered so you can barely shrink it at all. - [PALIMPSEST](https://eternity2.dev/research/lab/experiments/raphael-anjou/learning/palimpsest) — Read every strong board to find the habits that quietly hold a board back, then break them. This experiment produced the project's best board: 463 of 480. - [MIDDEN](https://eternity2.dev/research/lab/experiments/raphael-anjou/pipelines/midden) — Decide in advance not when a board may break, but where: confine every mismatch to a chosen shape of cells, and search for the best shape. - [LP and ILP relaxations: half a piece everywhere](https://eternity2.dev/research/build/exact/lp-relaxations) — Write Eternity II as an integer program, drop the integrality, and a linear solver reaches zero error in seconds, with 30% of one piece and 20% of another sharing a corner. Eighteen years of community campaigns measured where the fractional comfort ends: a plateau at 420–440 edges the moment the pieces must be whole, an ILP wall at 8×8, and an academic best of 461-in-an-hour. What the optimizer's road teaches, and where LP still earns its keep. --- # Why basin-hopping looks impossible > If you can't improve a great board by polishing it, maybe you can jump to a different great board. On every record pair tested, you can't, and the structural reason why is worth seeing. - Canonical page (with interactive figures/demos): https://eternity2.dev/research/why/sigma-cycles/ - Updated: 2026-07-02 - Topics: structure, local-search - Source: Peter McGavin's 469-record announcement: the board the cycles are computed against (groups.io msg 10045, September 2020) — https://groups.io/g/eternity2/message/10045 --- Two top boards look totally different, but they're related: you can turn one into the other by picking up a set of pieces and shifting each one into the spot the next was using, all the way around a loop. Mathematicians call that loop a cycle. Do the whole loop and you arrive at the other board. Here's the catch. Between the best boards, that loop is enormous and there's only one of it. Going from a 459 board to McGavin's 469 means one single interlocking cycle of 154 cells, spanning the entire interior of the board. ## One loop, all or nothing > **[Interactive: SigmaCycleDiagram]** Rendered on the canonical page (link above); not shown in this markdown export. ## Try it on a real small puzzle This is no diagram: the live engine finds two real solutions, computes the actual cycles between them, and scores every step you take. > **[Figure]** Interactive: apply part of the swap cycle — interactive: SigmaCycleLab. Rendered on the canonical page (link above); not shown in this markdown export. ## How we know We computed the exact cycles between three different record boards and then tried every partial move: apply just some of the loop and see what the score does. The result is blunt. Every partial application makes the score worse, with drops ranging from a few points to over a hundred. There is no subset of the loop that helps, not one. That's what makes it a wall. To move from one good board toward a better one you'd have to commit to shifting up to 154 cells at once, with no improving step along the way to guide you there. Every search that works in steps is blind to a move like that. ## The cycles, measured - 459 to 458: 14 cycles, largest 85 cells. - 458 to McGavin 469: one giant cycle of 80 cells, spanning rows 1 to 14. - 459 to McGavin 469: one giant cycle of 154 cells. - **In every case, every smaller piece of the cycle scores worse: the property held in all three basin pairs tested, though three pairs is a small sample and it is not proven to hold in general.** ## Why it matters Together with [the rigidity wall](/research/why/rigidity-wall), this closes off the two obvious escape routes at once. You can't climb out of a good board locally, and (on every record pair measured here) you can't hop to a neighbour either, because the nearest better board is one indivisible move of 80 to 154 cells away. This is a plausible part of why the 470 record has stood since 2021: the moves that would beat it appear too large for any step-by-step search to find. *Cycles are computed exactly from pairs of record boards by composing their piece permutations; the subset tests enumerate sub-cycles and rescore. The animation above is a schematic of the mechanism, not the 154-cell cycle itself.* ## Related - [The rigidity wall](https://eternity2.dev/research/why/rigidity-wall) — Every record board we have is frozen in place. You cannot nudge your way from a great board to a perfect one, and we can prove it. - [Where the mismatches live](https://eternity2.dev/research/why/mismatch-geometry) — A near-perfect board doesn't scatter its few errors evenly. It packs them into one band of five rows and leaves all the rest flawless. Which band is decided by the direction the search filled the board, and you can see the mirror on the real record boards. - [KEYRING](https://eternity2.dev/research/lab/experiments/raphael-anjou/learning/keyring) — Build a board from scratch, ranking each next piece by three signals learned from past strong boards. Reached 460 in a board family no earlier search had cracked. --- # Which wall stops which method > The research section has two halves: the structural walls that make Eternity II hard, and the algorithms built to climb them. This page is the bridge: each method lined up against the wall it actually attacks, and the score where that wall stopped it. - Canonical page (with interactive figures/demos): https://eternity2.dev/research/why/walls-and-methods/ - Updated: 2026-07-02 - Topics: structure - Source: Ansótegui, Béjar, Fernández & Mateu, How Hard is a Commercial Puzzle: the Eternity II Challenge — https://repositori.udl.cat/server/api/core/bitstreams/0b6533fe-54e5-4070-85fe-80f7d35837d8/content --- Every cell of the map below is grounded in this project's published work. The four walls themselves are corroborated by the published literature; the experiment results are this project's own work, each written up on its own page; they are not claimed to be externally verified. ## The four walls, in one line each Every one of them is a version of the same statement: there is nothing local to prune on. - **[No forced moves](/research/why/no-forced-moves)**. Every interior cell keeps 73–137 legal pieces, so the branching factor never collapses. - **[The hardness peak](/research/why/phase-transition)**. With ≈17 interior colours the puzzle sits at the phase transition: about one expected solution, the worst place to search. - **[The area law](/research/why/entropy-area-law)**. Genuinely-distinct partial boards collapse past ~80 cells, but no local score can see that global fact. - **[Rigidity](/research/why/rigidity-wall)**. Records are locally frozen; the step to a better board is one giant, indivisible swap with no gradient to follow. ## The map Columns are the walls; rows are the methods, best score first. A filled mark (●) means the method is fundamentally working against that wall. The community ceiling on this puzzle is 470; the full solution is 480. | Method | Best | [Forced moves](/research/why/no-forced-moves) | [Hardness peak](/research/why/phase-transition) | [Area law](/research/why/entropy-area-law) | [Rigidity](/research/why/rigidity-wall) | New basin | | --- | --- | :-: | :-: | :-: | :-: | --- | | [PALIMPSEST](/research/lab/experiments/raphael-anjou/learning/palimpsest) · from the corpus | 463/480 | | | | ● | no | | [PRIOR](/research/lab/experiments/raphael-anjou/learning/prior) · from scratch | 460/480 | | ● | | ● | no | | [KEYRING](/research/lab/experiments/raphael-anjou/learning/keyring) · from scratch | 460/480 | | | | ● | new family | | [REPLAY](/research/lab/experiments/raphael-anjou/learning/replay) · decode & replay | 460/480 | | | | ● | no | | [GAUNTLET](/research/lab/experiments/raphael-anjou/pipelines/gauntlet) · from scratch | 458/480 | | | | ● | new family | | [CLOISTER](/research/lab/experiments/raphael-anjou/pipelines/cloister) · anchor & constrain | 453/480 | | | ● | ● | no | | [MIDDEN](/research/lab/experiments/raphael-anjou/pipelines/midden) · anchor & constrain | 452/480 | | | ● | ● | no | | [LADDER](/research/lab/experiments/raphael-anjou/pipelines/ladder) · concentrate effort | 451/480 | ● | ● | | | new family | | [LODESTONE](/research/lab/experiments/raphael-anjou/learning/lodestone) · from scratch | 451/480 | ● | | | | no | | [MOSAIC](/research/lab/experiments/raphael-anjou/pipelines/mosaic) · solve a piece exactly | 448/480 | ● | ● | | | no | | [BANDSAW](/research/lab/experiments/raphael-anjou/meet-in-the-middle/bandsaw) · solve a piece exactly | 437/480 | ● | ● | | | no | | [STAGED](/research/lab/experiments/raphael-anjou/pipelines/staged) · from scratch | 436/480 | ● | | ● | | no | ### How to read it Almost every method ends up against rigidity, the wall that says the great boards are isolated islands. The build-from-scratch and corpus methods (PRIOR, KEYRING, PALIMPSEST, GAUNTLET) try to reach a new island by steering construction with learned signal; they top out at 458–463 and a couple of them do reach genuinely new families, but none crosses to the ceiling. The concentrate and exact methods (LADDER, BANDSAW) instead attack the search itself (the high branching factor and the unsearchable peak) and pay for it at the endgame. The anchor methods (CLOISTER, MIDDEN) localise the damage but hit the area-law wall in the interior. No single wall is the whole story, and no method gets through all four. ## Where each one stopped, and why The ceiling is never arbitrary. For each method, its own write-up records the exact reason the score stopped climbing, quoted here in one line. - **[PALIMPSEST](/research/lab/experiments/raphael-anjou/learning/palimpsest)** (463/480). Reached 463, the project best, by reading the corpus to find which shared choices are traps and steering a 15-basin sweep around them. Forcing the search to avoid the traps directly made boards worse: the value was in where to look, not a hard rule. - **[PRIOR](/research/lab/experiments/raphael-anjou/learning/prior)** (460/480). Plateaus at 460: the learned position prior gets a from-scratch build into the 460 class fast, but the corpus signal alone is not enough to leave it. - **[KEYRING](/research/lab/experiments/raphael-anjou/learning/keyring)** (460/480). Three learned signals voting (position, adjacency, 2×2 patch) reached 460 in a corner arrangement no board had cracked before, a new family, but the patch signal is marginal and the polish still caps at 460. - **[REPLAY](/research/lab/experiments/raphael-anjou/learning/replay)** (460/480). Replays the community's strict-460 boards exactly and reveals the move ordinary search misses: 4–5 cells that take two mismatches at once, unreachable for a search that allows at most one. - **[GAUNTLET](/research/lab/experiments/raphael-anjou/pipelines/gauntlet)** (458/480). Running the beam in nine scan directions opened a brand-new 458 family (scan order is a stronger diversity axis than the random seed), but a second round topped out at 457 with no 461: the new family saturates like the others. - **[CLOISTER](/research/lab/experiments/raphael-anjou/pipelines/cloister)** (453/480). As a standalone interior solver it confirms a real rim-compatibility bonus, but that bonus cannot be retrofitted after the fact (the same rigidity as the full board), so it settles in the low 450s. - **[MIDDEN](/research/lab/experiments/raphael-anjou/pipelines/midden)** (452/480). Choosing where (not when) the board may break extends the perfect run from 153 to 167–174 cells, but the dispersed geometry still fails at the endgame: nothing absorbs the last damage. - **[LADDER](/research/lab/experiments/raphael-anjou/pipelines/ladder)** (451/480). Floods cheap probes and promotes the deepest, reaching a 451 strict board with no record to copy, the first escape from the universal 444–450 band, but the supply of perfect openings runs out and the rungs all converge to one ceiling. - **[LODESTONE](/research/lab/experiments/raphael-anjou/learning/lodestone)** (451/480). A scarce-demand prior used only as a tiebreaker lifts the from-scratch median by two (449→451) and tightens the variance, but any larger weight collapses it: scarcity is a real but weak signal, and it never touches the basin ceiling. - **[MOSAIC](/research/lab/experiments/raphael-anjou/pipelines/mosaic)** (448/480). Composes exact 4×4 block solutions with soft seams, reaching 448 from scratch, but the shortfall lands almost entirely in the last three corner blocks, where the piece pool runs thin: the same piece-theft, now a single bright spot. - **[BANDSAW](/research/lab/experiments/raphael-anjou/meet-in-the-middle/bandsaw)** (437/480). Solves an endgame band to proven optimality, and in doing so measures the exactness wall: the search tree grows about twentyfold per extra allowed mismatch, on both sides, so meeting in the middle stops paying at full size. - **[STAGED](/research/lab/experiments/raphael-anjou/pipelines/staged)** (436/480). Builds the whole board with no pre-set frame and an emergent border, reaching 436, well below the records. That gap is the finding: it measures exactly how much the usual frame-first anchor is worth. ## The shape of the gap Read down the table and the lesson of the whole project is visible at a glance: the methods that move the score change the shape of the search, whether a scan order, a learned prior, or a confined region, never its raw speed. And every one of them stops at a wall that is global, not local. The ten edges from 470 to 480 are not a polishing problem; they are on the far side of all four walls at once. A separate 2026 campaign by William Millilaw reached the same conclusion from the diversity side. Sweeping the full method list, he found that almost everything (adaptive local search from scratch, snake placement, the top of a trained generator's distribution) keeps rediscovering the same handful of basins, and only parallel tempering reliably produced genuinely new ones, boards far apart from the known set. Even that plateaus quickly. His reading is the one this table keeps making: the bottleneck is not the score a method reaches but the number of distinct basins it can find, and no method in the standard arsenal finds enough of them. > **Note** > > Each saturation line is distilled from the project's lab notebook (one entry per experiment). The four walls are corroborated by the published literature: the 17-colour phase transition by Ansótegui, Béjar, Fernández & Mateu, "How Hard is a Commercial Puzzle: the Eternity II Challenge"; the missing gradient and deep basins by the Eternity II local-search literature. ## Related - [Why a faster computer doesn't help](https://eternity2.dev/research/why/prune-vs-speed) — The single most important idea in hard combinatorial search: shrinking the space you search beats searching it faster, by an exponential margin. Eternity II is engineered so you can barely shrink it at all. - [The rigidity wall](https://eternity2.dev/research/why/rigidity-wall) — Every record board we have is frozen in place. You cannot nudge your way from a great board to a perfect one, and we can prove it. - [Experiments](https://eternity2.dev/research/lab/experiments) — The lab's named search experiments, one section per researcher. Each is a real run against Eternity II with its idea, its best board, and the questions it left open. Raphaël Anjou's notebook is here in full; the notebook is open to anyone else's. - [No forced moves](https://eternity2.dev/research/why/no-forced-moves) — The usual way to crack a logic puzzle is to find a spot where only one piece fits, place it, and repeat. That lever doesn't exist here: every interior piece has between 73 and 137 possible neighbours, and not one is ever pinned to a single option.