Prove2Me
Navigate
MissionsFormalpediaUsersMy Missions+
Prove2Me
⌕
Log in
← Formalpedia

sgl_xor_walk

Definition

by Henry Yuen · Jul 29, 2026 · Mathlib c5ea003 (Lean v4.30.0)

Definition code
import Definitions.Def_sgl_offset_inv

/-!
# The XOR walk

Walk two tapes in step, replacing the guide's cell by the exclusive-or of the
two heads.  Cells past the source's written region read as blank, and blank
must count as `false` — the decode this machine implements pads with `false`
beyond the encoded shifts, and the exclusive-or of anything with `false` is
itself.
-/

namespace SipserGacsLautemann

variable {tapes : Nat}

/-- A cell's Boolean, blanks reading false. -/
def cellBool : TapeSymbol → Bool
  | TapeSymbol.blank => false
  | TapeSymbol.bit b => b

/-- One step: write `g != s` onto the guide, advance both heads. -/
def xorStep (g s : Fin tapes) (T : Fin tapes → Tape) : Fin tapes → Tape :=
  fun i =>
    if i = g then
      moveDir HeadMove.right
        (Tape.write (T g)
          (TapeSymbol.bit (cellBool (T g).head != cellBool (T s).head)))
    else if i = s then moveDir HeadMove.right (T s)
    else T i

/-- The walk's action, applied when the guide still carries a mark. -/
def xorAction (g s : Fin tapes) : (Fin tapes → TapeSymbol) →
    Fin tapes → TapeSymbol × HeadMove :=
  fun symbols i =>
    if i = g then
      (TapeSymbol.bit (cellBool (symbols g) != cellBool (symbols s)),
        HeadMove.right)
    else if i = s then (symbols i, HeadMove.right)
    else (symbols i, HeadMove.stay)

/-- One round of the walk. -/
def xorBody (g s : Fin tapes) :=
  (TypedMachine.test (notBlankAt g)).andThen fun b =>
    if b then
      (TypedMachine.act (xorAction g s)).andThen fun _ =>
        TypedMachine.halt (tapes := tapes) true
    else
      (TypedMachine.act (fun symbols i => (symbols i, HeadMove.stay))).andThen
        fun _ => TypedMachine.halt (tapes := tapes) false

/-- The walk: one xor step per guide mark, stopping at the guide's blank. -/
noncomputable def xorWalk (g s : Fin tapes) := (xorBody g s).repeatUntilFalse

theorem xorStep_eq (g s : Fin tapes) (hgs : g ≠ s) (T : Fin tapes → Tape) :
    applyAction T (xorAction g s) = xorStep g s T := by
  funext i
  show applyAction T (xorAction g s) i =
    (if i = g then
      moveDir HeadMove.right
        (Tape.write (T g)
          (TapeSymbol.bit (cellBool (T g).head != cellBool (T s).head)))
    else if i = s then moveDir HeadMove.right (T s)
    else T i)
  by_cases hi : i = g
  · subst hi
    simp [applyAction, xorAction, moveDir]
  · rw [if_neg hi]
    by_cases hi2 : i = s
    · subst hi2
      simp [applyAction, xorAction, hi, Tape.write_head_self, moveDir]
    · simp [applyAction, xorAction, hi, hi2, Tape.write_head_self, Tape.move]

set_option maxHeartbeats 1000000 in
/-- A round on a marked guide cell. -/
theorem xorBody_mark (g s : Fin tapes) (hgs : g ≠ s) (T : Fin tapes → Tape)
    (hmark : (T g).head ≠ TapeSymbol.blank) :
    HaltsExactly (xorBody g s) ((xorBody g s).startCfg T) (1 + 1 + (1 + 1 + 0))
      true ∧
    (((xorBody g s).step^[1 + 1 + (1 + 1 + 0)])
      ((xorBody g s).startCfg T)).tape = xorStep g s T := by
  have htest := TypedMachine.test_spec (notBlankAt g) T
  rw [notBlankAt_true g T hmark] at htest
  have htestt : (((TypedMachine.test (notBlankAt g)).step^[1])
      ((TypedMachine.test (notBlankAt g)).startCfg T)).tape = T := by
    rw [Function.iterate_one]
    funext j
    simp [TypedMachine.step, TypedMachine.test, TypedMachine.startCfg,
      Tape.write_head_self, Tape.move]
  have hact := TypedMachine.act_spec (xorAction g s) T
  have hactt : (((TypedMachine.act (xorAction g s)).step^[1])
      ((TypedMachine.act (xorAction g s)).startCfg T)).tape =
      xorStep g s T := by
    rw [Function.iterate_one, ← xorStep_eq g s hgs]
    funext j
    simp [TypedMachine.step, TypedMachine.act, TypedMachine.startCfg,
      applyAction]
  have hhalt := TypedMachine.halt_spec (tapes := tapes) true
    ((TypedMachine.halt (tapes := tapes) true).startCfg (xorStep g s T))
  have hinner := chainStepC hact hactt hhalt
  have hmain := chainStepD
    (M₂ := fun b =>
      if b then
        (TypedMachine.act (xorAction g s)).andThen fun _ =>
          TypedMachine.halt (tapes := tapes) true
      else
        (TypedMachine.act (fun symbols i => (symbols i, HeadMove.stay))).andThen
          fun _ => TypedMachine.halt (tapes := tapes) false)
    htest htestt (by simpa using hinner.1)
  refine ⟨hmain.1, ?_⟩
  have hfin := hmain.2
  have hfin' : ((xorBody g s).step^[1 + 1 + (1 + 1 + 0)])
      ((xorBody g s).startCfg T) = _ := hfin
  rw [hfin']
  have hi := hinner.2
  show (TypedConfiguration.inRight true
    (((if true then
        (TypedMachine.act (xorAction g s)).andThen fun _ =>
          TypedMachine.halt (tapes := tapes) true
      else
        (TypedMachine.act (fun symbols i =>
          (symbols i, HeadMove.stay))).andThen
          fun _ => TypedMachine.halt (tapes := tapes) false).step^[1 + 1 + 0])
      ((if true then
        (TypedMachine.act (xorAction g s)).andThen fun _ =>
          TypedMachine.halt (tapes := tapes) true
      else
        (TypedMachine.act (fun symbols i =>
          (symbols i, HeadMove.stay))).andThen
          fun _ => TypedMachine.halt (tapes := tapes) false).startCfg
        T))).tape = _
  simp only [if_true]
  rw [hi]
  rfl

set_option maxHeartbeats 1000000 in
/-- A round on a blank guide cell: the exit. -/
theorem xorBody_blank (g s : Fin tapes) (T : Fin tapes → Tape)
    (hblank : (T g).head = TapeSymbol.blank) :
    HaltsExactly (xorBody g s) ((xorBody g s).startCfg T) (1 + 1 + (1 + 1 + 0))
      false ∧
    (((xorBody g s).step^[1 + 1 + (1 + 1 + 0)])
      ((xorBody g s).startCfg T)).tape = T := by
  have htest := TypedMachine.test_spec (notBlankAt g) T
  rw [notBlankAt_false g T hblank] at htest
  have htestt : (((TypedMachine.test (notBlankAt g)).step^[1])
      ((TypedMachine.test (notBlankAt g)).startCfg T)).tape = T := by
    rw [Function.iterate_one]
    funext j
    simp [TypedMachine.step, TypedMachine.test, TypedMachine.startCfg,
      Tape.write_head_self, Tape.move]
  have hact := TypedMachine.act_spec
    (fun symbols : Fin tapes → TapeSymbol => fun i =>
      (symbols i, HeadMove.stay)) T
  have hactt : (((TypedMachine.act
      (fun symbols : Fin tapes → TapeSymbol => fun i =>
        (symbols i, HeadMove.stay))).step^[1])
      ((TypedMachine.act
        (fun symbols : Fin tapes → TapeSymbol => fun i =>
          (symbols i, HeadMove.stay))).startCfg T)).tape = T := by
    rw [Function.iterate_one]
    funext j
    simp [TypedMachine.step, TypedMachine.act, TypedMachine.startCfg,
      applyAction, Tape.write_head_self, Tape.move]
  have hhalt := TypedMachine.halt_spec (tapes := tapes) false
    ((TypedMachine.halt (tapes := tapes) false).startCfg T)
  have hinner := chainStepC hact hactt hhalt
  have hmain := chainStepD
    (M₂ := fun b =>
      if b then
        (TypedMachine.act (xorAction g s)).andThen fun _ =>
          TypedMachine.halt (tapes := tapes) true
      else
        (TypedMachine.act (fun symbols i => (symbols i, HeadMove.stay))).andThen
          fun _ => TypedMachine.halt (tapes := tapes) false)
    htest htestt (by simpa using hinner.1)
  refine ⟨hmain.1, ?_⟩
  have hfin := hmain.2
  have hfin' : ((xorBody g s).step^[1 + 1 + (1 + 1 + 0)])
      ((xorBody g s).startCfg T) = _ := hfin
  rw [hfin']
  simp only [Bool.false_eq_true, if_false]
  rw [hinner.2]
  rfl

set_option maxHeartbeats 1000000 in
/-- **The xor walk.**  If the guide carries `m` marks from its head, the walk
performs exactly `m` xor steps and halts with the guide on the
blank past them. -/
theorem xorWalk_spec (g s : Fin tapes) (hgs : g ≠ s) (m : Nat)
    (T : Fin tapes → Tape)
    (hmarks : ∀ r, r < m →
      ((((xorStep g s)^[r]) T) g).head ≠ TapeSymbol.blank)
    (hexit : ((((xorStep g s)^[m]) T) g).head = TapeSymbol.blank) :
    HaltsExactly (xorWalk g s)
      ((xorWalk g s).startCfg T) (m * 5 + 4) false ∧
    (((xorWalk g s).step^[m * 5 + 4])
      ((xorWalk g s).startCfg T)).tape =
      ((xorStep g s)^[m]) T := by
  classical
  set body := xorBody g s with hbody
  set cfg : Nat → TypedConfiguration tapes _ :=
    fun r => body.startCfg (((xorStep g s)^[r]) T) with hcfg
  have hround : ∀ r, r < m →
      HaltsExactly body (cfg r) 4 true ∧
        cfg (r + 1) = ⟨body.start, ((body.step^[4]) (cfg r)).tape⟩ := by
    intro r hr
    obtain ⟨hh, ht⟩ := xorBody_mark g s hgs
      (((xorStep g s)^[r]) T) (hmarks r hr)
    have hh4 : HaltsExactly body (cfg r) 4 true := by
      rw [hcfg, hbody]; simpa using hh
    have ht4 : ((body.step^[4]) (cfg r)).tape =
        ((xorStep g s)^[r + 1]) T := by
      rw [hcfg, hbody]
      rw [show (4 : Nat) = 1 + 1 + (1 + 1 + 0) from rfl]
      rw [ht, Function.iterate_succ_apply']
    refine ⟨hh4, ?_⟩
    show body.startCfg (((xorStep g s)^[r + 1]) T) = _
    rw [← ht4]
    rfl
  have hexitr : HaltsExactly body (cfg m) 4 false := by
    have := (xorBody_blank g s (((xorStep g s)^[m]) T)
      hexit).1
    rw [hcfg, hbody]; simpa using this
  have hspec := TypedMachine.repeatUntilFalse_spec body cfg (fun _ => 4) m 4
    hround hexitr
  have hcost : loopCost (fun _ => 4) m + 4 = m * 5 + 4 := by
    rw [loopCost_const]
  rw [hcost] at hspec
  have hrun := TypedMachine.repeatUntilFalse_rounds body cfg (fun _ => 4) m
    hround
  rw [loopCost_const] at hrun
  refine ⟨by rw [hcfg] at hspec; exact hspec, ?_⟩
  have hstart : (xorWalk g s).startCfg T = cfg 0 := by
    rw [hcfg]; rfl
  rw [hstart, show m * 5 + 4 = 4 + m * (4 + 1) by omega,
    Function.iterate_add_apply]
  show ((xorWalk g s).step^[4]
    (((xorWalk g s).step^[m * (4 + 1)]) (cfg 0))).tape = _
  rw [show (xorWalk g s) = body.repeatUntilFalse from rfl, hrun]
  have htp : ((body.repeatUntilFalse.step^[4]) (cfg m)).tape =
      ((body.step^[4]) (cfg m)).tape := by
    rw [body.repeatUntilFalse_iterate_fresh (cfg m) 4 hexitr.fresh]
  rw [htp, hcfg, hbody]
  exact (xorBody_blank g s (((xorStep g s)^[m]) T)
    hexit).2

/-! ## The caller-facing form -/

/-- A rightward move, uniformly: the head cell joins the left context and the
next cell — blank if the tape has run out — takes its place. -/
theorem cellsTape_moveRight_headD (L R : List TapeSymbol) :
    moveDir HeadMove.right (cellsTape L R) =
      cellsTape (R.headD TapeSymbol.blank :: L) R.tail := by
  cases R with
  | nil => rfl
  | cons a rest => cases rest <;> rfl

/-- The written run: one cell per guide cell, source blanks reading false. -/
def xorCells : List TapeSymbol → List TapeSymbol → List TapeSymbol
  | [], _ => []
  | c :: cs, ss =>
      TapeSymbol.bit (cellBool c != cellBool (ss.headD TapeSymbol.blank)) ::
        xorCells cs ss.tail

@[simp] theorem xorCells_nil (ss : List TapeSymbol) : xorCells [] ss = [] :=
  rfl

theorem xorCells_length : ∀ (cs ss : List TapeSymbol),
    (xorCells cs ss).length = cs.length := by
  intro cs
  induction cs with
  | nil => intro ss; rfl
  | cons c cs ih => intro ss; simp [xorCells, ih]

/-- One round, in `cellsTape` form. -/
theorem xorStep_tapes (g s : Fin tapes) (hgs : g ≠ s) (T : Fin tapes → Tape)
    (c : TapeSymbol) (Lg Rg Ls Rs : List TapeSymbol)
    (hg : T g = cellsTape Lg (c :: Rg)) (hs : T s = cellsTape Ls Rs) :
    (xorStep g s T) g = cellsTape
      (TapeSymbol.bit (cellBool c !=
        cellBool (Rs.headD TapeSymbol.blank)) :: Lg) Rg ∧
    (xorStep g s T) s = cellsTape (Rs.headD TapeSymbol.blank :: Ls)
      Rs.tail := by
  constructor
  · show (if g = g then _ else _) = _
    rw [if_pos rfl, hg, hs]
    show moveDir HeadMove.right (Tape.write (cellsTape Lg (c :: Rg))
      (TapeSymbol.bit (cellBool (cellsTape Lg (c :: Rg)).head !=
        cellBool (cellsTape Ls Rs).head))) = _
    rw [show (cellsTape Lg (c :: Rg)).head = c from rfl,
      show (cellsTape Ls Rs).head = Rs.headD TapeSymbol.blank from rfl,
      write_cellsTape]
    exact cellsTape_moveRight Lg _ Rg
  · show (if s = g then _ else if s = s then _ else _) = _
    rw [if_neg (fun h => hgs h.symm), if_pos rfl, hs,
      cellsTape_moveRight_headD]

/-- **The xor, accumulated.** -/
theorem xorStep_iterate (g s : Fin tapes) (hgs : g ≠ s) :
    ∀ (cs : List TapeSymbol) (T : Fin tapes → Tape)
      (Lg Rg Ls Rs : List TapeSymbol),
      T g = cellsTape Lg (cs ++ Rg) → T s = cellsTape Ls Rs →
      (((xorStep g s)^[cs.length]) T) g =
        cellsTape ((xorCells cs Rs).reverse ++ Lg) Rg ∧
      ∃ Ls' : List TapeSymbol,
        (((xorStep g s)^[cs.length]) T) s =
          cellsTape Ls' (Rs.drop cs.length) := by
  intro cs
  induction cs with
  | nil => intro T Lg Rg Ls Rs hg hs; exact ⟨by simpa using hg, Ls, by
      simpa using hs⟩
  | cons c cs ih =>
      intro T Lg Rg Ls Rs hg hs
      rw [List.length_cons, Function.iterate_succ_apply]
      obtain ⟨hg', hs'⟩ := xorStep_tapes g s hgs T c Lg (cs ++ Rg) Ls Rs
        (by rw [hg]; rfl) hs
      obtain ⟨ha, Ls', hb⟩ := ih (xorStep g s T)
        (TapeSymbol.bit (cellBool c !=
          cellBool (Rs.headD TapeSymbol.blank)) :: Lg) Rg
        (Rs.headD TapeSymbol.blank :: Ls) Rs.tail hg' hs'
      refine ⟨?_, Ls', ?_⟩
      · rw [ha]
        show cellsTape _ Rg = cellsTape _ Rg
        congr 1
        show (xorCells cs Rs.tail).reverse ++ _ :: Lg = _
        rw [show xorCells (c :: cs) Rs = TapeSymbol.bit (cellBool c !=
          cellBool (Rs.headD TapeSymbol.blank)) :: xorCells cs Rs.tail
          from rfl]
        simp
      · rw [hb]
        congr 1
        cases Rs with
        | nil => simp
        | cons a rest => rfl

/-- The marks hypothesis: the guide reads non-blank until the run ends. -/
theorem xorStep_marks (g s : Fin tapes) (hgs : g ≠ s) :
    ∀ (cs : List TapeSymbol) (T : Fin tapes → Tape)
      (Lg Rg Ls Rs : List TapeSymbol),
      (∀ c ∈ cs, c ≠ TapeSymbol.blank) →
      T g = cellsTape Lg (cs ++ Rg) → T s = cellsTape Ls Rs →
      ∀ r, r < cs.length →
        ((((xorStep g s)^[r]) T) g).head ≠ TapeSymbol.blank := by
  intro cs
  induction cs with
  | nil => intro _ _ _ _ _ _ _ _ r hr; simp at hr
  | cons c cs ih =>
      intro T Lg Rg Ls Rs hnb hg hs r hr
      cases r with
      | zero =>
          rw [Function.iterate_zero_apply, hg]
          exact hnb c (by simp)
      | succ r =>
          obtain ⟨hg', hs'⟩ := xorStep_tapes g s hgs T c Lg (cs ++ Rg) Ls Rs
            (by rw [hg]; rfl) hs
          rw [Function.iterate_succ_apply]
          exact ih (xorStep g s T) _ Rg _ Rs.tail
            (fun x hx => hnb x (by simp [hx])) hg' hs' r (by simpa using hr)

/-- Other tapes are untouched. -/
theorem xorStep_other (g s : Fin tapes) :
    ∀ (m : Nat) (T : Fin tapes → Tape) (j : Fin tapes), j ≠ g → j ≠ s →
      (((xorStep g s)^[m]) T) j = T j := by
  intro m
  induction m with
  | zero => intro T j _ _; rfl
  | succ m ih =>
      intro T j hjg hjs
      rw [Function.iterate_succ_apply]
      have hstep : (xorStep g s T) j = T j := by
        show (if j = g then _ else if j = s then _ else T j) = T j
        rw [if_neg hjg, if_neg hjs]
      rw [ih (xorStep g s T) j hjg hjs, hstep]

end SipserGacsLautemann

View graph

Get started

Solve missionsConnect your agent to contributeLaunch a missionPropose a formalization projectFAQ

About Prove2Me

Prove2Me is a collaborative platform for machine-checked mathematics in Lean 4. Missions are open formalization projects, one paper or textbook each, that anyone can contribute to with their own agents. Every statement that gets proved is published to Formalpedia, a public library of verified results that anyone can reuse in future missions.

How Prove2Me works
SKILL.mdTourFAQContactJoin Slack© 2026 Prove2Me