Principal declarations
theorem Rollout.run_length
Module NimRollout
(lean/NimRollout.lean, lines 88–94) · file SHA-256 1a99428d71573d31… Axioms reported by the fresh build: propext, Quot.sound
EXECUTION COUNT: every complete run of `pi_j`, under any tie-breaking rule,
has exactly `sum_h (h / 2^j + h % 2^j)` moves.
Statement as elaborated and printed by Lean 4.26.0
∀ {j : ℕ} {p : List ℕ} {n : ℕ}, NimAudit.Rollout.Run j p n → n = NimAudit.rolloutCount j p
Exact source text, lines 88–94
88/-- EXECUTION COUNT: every complete run of `pi_j`, under any tie-breaking rule,89 has exactly `sum_h (h / 2^j + h % 2^j)` moves. -/90theorem run_length {j : Nat} {p : List Nat} {n : Nat} (hr : Run j p n) :91 n = rolloutCount j p := by92 induction hr with93 | done p hz => exact (rolloutCount_zero hz).symm94 | step p q n hm _ ih => rw [ih, policyMove_count hm]
Project declarations in the statement: Rollout.Run, rolloutCount
Project declarations used by the proof or definition body
Rollout.PolicyMove, Rollout.Run, Rollout.Run.rec, Rollout.policyMove_count, Rollout.rolloutCount_zero, rolloutCount
theorem Rollout.run_parity
Module NimRollout
(lean/NimRollout.lean, lines 96–102) · file SHA-256 1a99428d71573d31… Axioms reported by the fresh build: propext, Quot.sound
PARITY OF EXECUTION: the number of moves of any complete run of `pi_j` has
low bit equal to the channel value of the nim-sum
(bit 0 for j = 0; bit j XOR bit 0 for j ≥ 1).
Statement as elaborated and printed by Lean 4.26.0
∀ {j : ℕ} {p : List ℕ} {n : ℕ},
NimAudit.Rollout.Run j p n → n.testBit 0 = NimAudit.channel j (NimAudit.nimSum p)
Exact source text, lines 96–102
96/-- PARITY OF EXECUTION: the number of moves of any complete run of `pi_j` has97 low bit equal to the channel value of the nim-sum98 (bit 0 for j = 0; bit j XOR bit 0 for j ≥ 1). -/99theorem run_parity {j : Nat} {p : List Nat} {n : Nat} (hr : Run j p n) :100 n.testBit 0 = channel j (nimSum p) := by101 rw [run_length hr]102 exact rollout_count_channel j p
Project declarations in the statement: Rollout.Run, channel, nimSum
Project declarations used by the proof or definition body
Rollout.Run, Rollout.run_length, channel, nimSum, rolloutCount, rollout_count_channel
theorem Game.reconstruct_eq
Module NimGame
(lean/phase2/NimGame.lean, lines 224–240) · file SHA-256 23df6bb87ecfd344… Axioms reported by the fresh build: propext, Quot.sound
RECONSTRUCTION: on a B-bit board (any N, including the empty and terminal
boards), the B rollout outcomes determine the full nim-sum.
Statement as elaborated and printed by Lean 4.26.0
∀ {B : ℕ} {p : List ℕ},
NimAudit.Game.Width B p →
NimAudit.Game.reconstruct B (NimAudit.Game.outcomes p) = NimAudit.nimSum p
Exact source text, lines 224–240
224/-- RECONSTRUCTION: on a B-bit board (any N, including the empty and terminal225 boards), the B rollout outcomes determine the full nim-sum. -/226theorem reconstruct_eq {B : Nat} {p : List Nat} (hw : Width B p) :227 reconstruct B (outcomes p) = nimSum p := by228 apply Nat.eq_of_testBit_eq229 intro i230 rw [reconstruct, testBit_ofBits]231 by_cases hi : i < B232 · simp only [hi, decide_true, Bool.true_and, recoverBit, outcomes, rolloutWinner_channel]233 by_cases h0 : i = 0234 · subst h0; simp [channel]235 · simp only [h0, if_false, channel, if_true]236 cases (nimSum p).testBit i <;> cases (nimSum p).testBit 0 <;> rfl237 · simp only [hi, decide_false, Bool.false_and]238 symm239 apply Nat.testBit_lt_two_pow240 exact Nat.lt_of_lt_of_le (nimSum_lt hw) (Nat.pow_le_pow_right (by decide) (by omega))
Project declarations in the statement: Game.Width, Game.outcomes, Game.reconstruct, nimSum
Project declarations used by the proof or definition body
Game.Width, Game.nimSum_lt, Game.ofBits, Game.outcomes, Game.reconstruct, Game.recoverBit, Game.rolloutWinner, Game.rolloutWinner_channel, Game.testBit_ofBits, channel, nimSum
theorem Rollout.exists_decreasing_heap
Module NimRollout
(lean/NimRollout.lean, lines 281–314) · file SHA-256 1a99428d71573d31… Axioms reported by the fresh build: propext, Quot.sound
LEGAL MOVE TO ZERO: if the nim-sum `s` is nonzero, some heap `x` has
`x ^^^ s < x`; replacing it by `x ^^^ s` is a legal Nim move and, by
`move_to_zero_algebra`, yields nim-sum zero.
Statement as elaborated and printed by Lean 4.26.0
∀ (p : List ℕ),
NimAudit.nimSum p ≠ 0 →
∃ pre x post,
p = pre ++ x :: post ∧
x ^^^ NimAudit.nimSum p < x ∧ NimAudit.nimSum (pre ++ (x ^^^ NimAudit.nimSum p) :: post) = 0
Exact source text, lines 281–314
281/-- LEGAL MOVE TO ZERO: if the nim-sum `s` is nonzero, some heap `x` has282 `x ^^^ s < x`; replacing it by `x ^^^ s` is a legal Nim move and, by283 `move_to_zero_algebra`, yields nim-sum zero. -/284theorem exists_decreasing_heap (p : List Nat) (hs : nimSum p ≠ 0) :285 ∃ pre x post, p = pre ++ x :: post ∧ x ^^^ nimSum p < x ∧286 nimSum (pre ++ (x ^^^ nimSum p) :: post) = 0 := by287 let s := nimSum p288 let k := s.log2289 have htop : s.testBit k = true := by290 cases hb : s.testBit k with291 | true => rfl292 | false =>293 exfalso294 have hlt : s < 2 ^ k := by295 apply Nat.lt_pow_two_of_testBit296 intro i hi297 by_cases hik : i = k298 · subst hik; exact hb299 · apply Nat.testBit_lt_two_pow300 exact Nat.lt_of_lt_of_le Nat.lt_log2_self (Nat.pow_le_pow_right (by decide) (by omega))301 exact absurd (Nat.log2_self_le hs) (Nat.not_le.mpr hlt)302 have habove : ∀ i, k < i → s.testBit i = false := by303 intro i hi304 apply Nat.testBit_lt_two_pow305 exact Nat.lt_of_lt_of_le Nat.lt_log2_self (Nat.pow_le_pow_right (by decide) (by omega))306 obtain ⟨x, hxmem, hxk⟩ := exists_heap_testBit htop307 have hlt : x ^^^ s < x := by308 apply lt_of_top_testBit (k := k)309 · rw [Nat.testBit_xor, hxk, htop]; rfl310 · exact hxk311 · intro i hi312 rw [Nat.testBit_xor, habove i hi, Bool.xor_false]313 obtain ⟨pre, post, rfl⟩ := List.append_of_mem hxmem314 exact ⟨pre, x, post, rfl, hlt, move_to_zero_algebra pre post x⟩
Project declarations in the statement: nimSum
Project declarations used by the proof or definition body
Rollout.exists_heap_testBit, Rollout.lt_of_top_testBit, move_to_zero_algebra, nimSum
theorem Game.agent_wins
Module NimGame
(lean/phase2/NimGame.lean, lines 376–388) · file SHA-256 23df6bb87ecfd344… Axioms reported by the fresh build: propext, Quot.sound
END-TO-END STRATEGY GUARANTEE (Target 1C): on B-bit boards, the agent that
queries the B structured rollouts, reconstructs the nim-sum and plays the
selected move wins from every nonzero-nim-sum position against every legal
opponent.
Statement as elaborated and printed by Lean 4.26.0
∀ {B : ℕ} (p : List ℕ),
NimAudit.Game.Width B p → NimAudit.nimSum p ≠ 0 → NimAudit.Game.Wins (NimAudit.Game.agent B) p
Exact source text, lines 376–388
376/-- END-TO-END STRATEGY GUARANTEE (Target 1C): on B-bit boards, the agent that377 queries the B structured rollouts, reconstructs the nim-sum and plays the378 selected move wins from every nonzero-nim-sum position against every legal379 opponent. -/380theorem agent_wins {B : Nat} (p : List Nat) (hw : Width B p) (h : nimSum p ≠ 0) :381 Wins (agent B) p := by382 obtain ⟨q, hsel, hm, hq⟩ := selectMove_zero h383 refine Wins.intro p q (by rw [agent_eq hw]; exact hsel) hm ?_384 intro r hr385 have h1 := move_sum_lt hm386 have h2 := move_sum_lt hr387 exact agent_wins r (width_move (width_move hw hm) hr) (move_from_zero hr hq)388termination_by p.sum
Project declarations in the statement: Game.Width, Game.Wins, Game.agent, nimSum
Project declarations used by the proof or definition body
Game.Move, Game.Width, Game.Wins, Game.Wins.intro, Game.agent, Game.agent_eq, Game.move_from_zero, Game.move_sum_lt, Game.selectMove, Game.selectMove_zero, Game.width_move, nimSum
theorem Game.totalRolloutMoves_le
Module NimGame
(lean/phase2/NimGame.lean, lines 454–467) · file SHA-256 23df6bb87ecfd344… Axioms reported by the fresh build: propext, Quot.sound
Statement as elaborated and printed by Lean 4.26.0
∀ {B : ℕ} {p : List ℕ},
NimAudit.Game.Width B p → NimAudit.Game.totalRolloutMoves B p ≤ B * (p.length * (2 ^ B - 1))
Exact source text, lines 454–467
454theorem totalRolloutMoves_le {B : Nat} {p : List Nat} (hw : Width B p) :455 totalRolloutMoves B p ≤ B * (p.length * (2 ^ B - 1)) := by456 unfold totalRolloutMoves457 have key : ∀ k, ((List.range k).map (fun j => rolloutMoves j p)).sum ≤458 k * (p.length * (2 ^ B - 1)) := by459 intro k460 induction k with461 | zero => simp462 | succ k ih =>463 rw [List.range_succ, List.map_append, List.sum_append_nat, Nat.succ_mul]464 simp only [List.map_cons, List.map_nil, List.sum_cons, List.sum_nil, Nat.add_zero]465 have := rolloutMoves_le (j := k) hw466 omega467 exact key B
Project declarations in the statement: Game.Width, Game.totalRolloutMoves
Project declarations used by the proof or definition body
Game.Width, Game.rolloutMoves_le, Game.totalRolloutMoves, Rollout.rolloutMoves
Definitions these statements use
inductive Rollout.Run
Module NimRollout
(lean/NimRollout.lean, lines 34–38) · file SHA-256 1a99428d71573d31…
`Run j p n`: following `pi_j` from board `p` reaches the all-zero board after
exactly `n` policy moves.
Statement as elaborated and printed by Lean 4.26.0
ℕ → List ℕ → ℕ → Prop
Exact source text, lines 34–38
34/-- `Run j p n`: following `pi_j` from board `p` reaches the all-zero board after35 exactly `n` policy moves. -/36inductive Run (j : Nat) : List Nat → Nat → Prop37 | done (p : List Nat) : (∀ x ∈ p, x = 0) → Run j p 038 | step (p q : List Nat) (n : Nat) : PolicyMove j p q → Run j q n → Run j p (n + 1)
Project declarations in the statement: none
Project declarations used by the proof or definition body
Rollout.PolicyMove
def rolloutCount
Module NimCore
(lean/NimCore.lean, lines 82–82) · file SHA-256 b07db6c505210d5a…
Statement as elaborated and printed by Lean 4.26.0
ℕ → List ℕ → ℕ
Exact source text, lines 82–82
82def rolloutCount (j : Nat) (rows : List Nat) : Nat := (rows.map (heapCount j)).sum
Project declarations in the statement: none
Project declarations used by the proof or definition body
heapCount
def channel
Module NimCore
(lean/NimCore.lean, lines 77–78) · file SHA-256 b07db6c505210d5a…
Statement as elaborated and printed by Lean 4.26.0
ℕ → ℕ → Bool
Exact source text, lines 77–78
77def channel (j sigma : Nat) : Bool :=78 if j = 0 then sigma.testBit 0 else xor (sigma.testBit j) (sigma.testBit 0)
Project declarations in the statement: none
Project declarations used by the proof or definition body
none
def nimSum
Module NimCore
(lean/NimCore.lean, lines 7–9) · file SHA-256 b07db6c505210d5a…
Statement as elaborated and printed by Lean 4.26.0
List ℕ → ℕ
Exact source text, lines 7–9
7def nimSum : List Nat → Nat8 | [] => 09 | h :: t => h ^^^ nimSum t
Project declarations in the statement: none
Project declarations used by the proof or definition body
none
def Game.Width
Module NimGame
(lean/phase2/NimGame.lean, lines 31–32) · file SHA-256 23df6bb87ecfd344…
B-bit board: every heap is below 2^B.
Statement as elaborated and printed by Lean 4.26.0
ℕ → List ℕ → Prop
Exact source text, lines 31–32
31/-- B-bit board: every heap is below 2^B. -/32def Width (B : Nat) (p : List Nat) : Prop := ∀ x ∈ p, x < 2 ^ B
Project declarations in the statement: none
Project declarations used by the proof or definition body
none
def Game.outcomes
Module NimGame
(lean/phase2/NimGame.lean, lines 214–215) · file SHA-256 23df6bb87ecfd344…
The B actual rollout measurements of board p.
Statement as elaborated and printed by Lean 4.26.0
List ℕ → ℕ → Bool
Exact source text, lines 214–215
214/-- The B actual rollout measurements of board p. -/215def outcomes (p : List Nat) : Nat → Bool := fun j => rolloutWinner j p
Project declarations in the statement: none
Project declarations used by the proof or definition body
Game.rolloutWinner
def Game.reconstruct
Module NimGame
(lean/phase2/NimGame.lean, lines 211–212) · file SHA-256 23df6bb87ecfd344…
The nim-sum reconstructed from the B rollout outcomes o 0, ..., o (B-1).
Statement as elaborated and printed by Lean 4.26.0
ℕ → (ℕ → Bool) → ℕ
Exact source text, lines 211–212
211/-- The nim-sum reconstructed from the B rollout outcomes o 0, ..., o (B-1). -/212def reconstruct (B : Nat) (o : Nat → Bool) : Nat := ofBits B (recoverBit o)
Project declarations in the statement: none
Project declarations used by the proof or definition body
Game.ofBits, Game.recoverBit
inductive Game.Wins
Module NimGame
(lean/phase2/NimGame.lean, lines 125–132) · file SHA-256 23df6bb87ecfd344…
`Wins sel p`: the player to move at `p`, always playing the successor chosen by
`sel`, wins against EVERY legal opponent. The selected move is legal, and after
every legal opponent reply the player is again in a `Wins` position. Because
the predicate is inductive, every such play is finite and ends with the
opponent facing a terminal board (normal play: the opponent loses).
Statement as elaborated and printed by Lean 4.26.0
(List ℕ → Option (List ℕ)) → List ℕ → Prop
Exact source text, lines 125–132
125/-- `Wins sel p`: the player to move at `p`, always playing the successor chosen by126 `sel`, wins against EVERY legal opponent. The selected move is legal, and after127 every legal opponent reply the player is again in a `Wins` position. Because128 the predicate is inductive, every such play is finite and ends with the129 opponent facing a terminal board (normal play: the opponent loses). -/130inductive Wins (sel : List Nat → Option (List Nat)) : List Nat → Prop131 | intro (p q : List Nat) : sel p = some q → Move p q →132 (∀ r, Move q r → Wins sel r) → Wins sel p
Project declarations in the statement: none
Project declarations used by the proof or definition body
Game.Move
def Game.agent
Module NimGame
(lean/phase2/NimGame.lean, lines 257–259) · file SHA-256 23df6bb87ecfd344…
The agent: reconstruct the nim-sum from the B root rollouts, then select.
Statement as elaborated and printed by Lean 4.26.0
ℕ → List ℕ → Option (List ℕ)
Exact source text, lines 257–259
257/-- The agent: reconstruct the nim-sum from the B root rollouts, then select. -/258def agent (B : Nat) (p : List Nat) : Option (List Nat) :=259 selectMove (reconstruct B (outcomes p)) p
Project declarations in the statement: none
Project declarations used by the proof or definition body
Game.outcomes, Game.reconstruct, Game.selectMove
def Game.totalRolloutMoves
Module NimGame
(lean/phase2/NimGame.lean, lines 450–452) · file SHA-256 23df6bb87ecfd344…
Total simulated moves of the B root rollouts.
Statement as elaborated and printed by Lean 4.26.0
ℕ → List ℕ → ℕ
Exact source text, lines 450–452
450/-- Total simulated moves of the B root rollouts. -/451def totalRolloutMoves (B : Nat) (p : List Nat) : Nat :=452 ((List.range B).map (fun j => rolloutMoves j p)).sum
Project declarations in the statement: none
Project declarations used by the proof or definition body
Rollout.rolloutMoves
Full modules
Build evidence: fresh isolated rebuild of all 38 bundled modules with Lean (version 4.26.0, started 2026-10-10T15:21:56Z, finished 2026-10-10T15:27:00Z: 38/38 modules compiled, 1588 axiom reports, no errors. See Build for the commands and the independent audit of 2026-10-10 (dated evidence).