l3lab/ntp-mathlib huggingface dataset:
theorem Machine.map_step {S : Set Λ} (f₂₁ : Function.RightInverse f₁ f₂)
    (g₂₁ : ∀ q ∈ S, g₂ (g₁ q) = q) :
    ∀ c : Cfg Γ Λ,
      c.q ∈ S → (step M c).map (Cfg.map f₁ g₁) = step (M.map f₁ f₂ g₁ g₂) (Cfg.map f₁ g₁ c)
  | ⟨q, T⟩, h => by
    

Proof state:
Γ : Type u_1
inst✝³ : Inhabited Γ
Γ' : Type u_2
inst✝² : Inhabited Γ'
Λ : Type u_3
inst✝¹ : Inhabited Λ
Λ' : Type u_4
inst✝ : Inhabited Λ'
M : Machine Γ Λ
f₁ : PointedMap Γ Γ'
f₂ : PointedMap Γ' Γ
g₁ : Λ → Λ'
g₂ : Λ' → Λ
S : Set Λ
f₂₁ : Function.RightInverse f₁.f f₂.f
g₂₁ : ∀ q ∈ S, g₂ (g₁ q) = q
q : Λ
T : Tape Γ
h : { q := q, Tape := T }.q ∈ S
⊢ Option.map (Cfg.map f₁ g₁) (step M { q := q, Tape := T }) =
    step (map M f₁ f₂ g₁ g₂) (Cfg.map f₁ g₁ { q := q, Tape := T })

Next tactic:
unfold step Machine.map Cfg.map
theorem Machine.map_step {S : Set Λ} (f₂₁ : Function.RightInverse f₁ f₂)
    (g₂₁ : ∀ q ∈ S, g₂ (g₁ q) = q) :
    ∀ c : Cfg Γ Λ,
      c.q ∈ S → (step M c).map (Cfg.map f₁ g₁) = step (M.map f₁ f₂ g₁ g₂) (Cfg.map f₁ g₁ c)
  | ⟨q, T⟩, h => by
    unfold step Machine.map Cfg.map
    

Proof state:
Γ : Type u_1
inst✝³ : Inhabited Γ
Γ' : Type u_2
inst✝² : Inhabited Γ'
Λ : Type u_3
inst✝¹ : Inhabited Λ
Λ' : Type u_4
inst✝ : Inhabited Λ'
M : Machine Γ Λ
f₁ : PointedMap Γ Γ'
f₂ : PointedMap Γ' Γ
g₁ : Λ → Λ'
g₂ : Λ' → Λ
S : Set Λ
f₂₁ : Function.RightInverse f₁.f f₂.f
g₂₁ : ∀ q ∈ S, g₂ (g₁ q) = q
q : Λ
T : Tape Γ
h : { q := q, Tape := T }.q ∈ S
⊢ Option.map
      (fun x =>
        match x with
        | { q := q, Tape := T } => { q := g₁ q, Tape := Tape.map f₁ T })
      (match { q := q, Tape := T } with
      | { q := q, Tape := T } =>
        Option.map
          (fun x =>
            match x with
            | (q', a) =>
              { q := q',
                Tape :=
                  match a with
                  | Stmt.move d => Tape.move d T
                  | Stmt.write a => Tape.write a T })
          (M q T.head)) =
    match
      match { q := q, Tape := T } with
      | { q := q, Tape := T } => { q := g₁ q, Tape := Tape.map f₁ T } with
    | { q := q, Tape := T } =>
      Option.map
        (fun x =>
          match x with
          | (q', a) =>
            { q := q',
              Tape :=
                match a with
                | Stmt.move d => Tape.move d T
                | Stmt.write a => Tape.write a T })
        (match q, T.head with
        | q, l => Option.map (Prod.map g₁ (Stmt.map f₁)) (M (g₂ q) (PointedMap.f f₂ l)))

Next tactic:
simp only [Turing.Tape.map_fst, g₂₁ q h, f₂₁ _]
theorem Machine.map_step {S : Set Λ} (f₂₁ : Function.RightInverse f₁ f₂)
    (g₂₁ : ∀ q ∈ S, g₂ (g₁ q) = q) :
    ∀ c : Cfg Γ Λ,
      c.q ∈ S → (step M c).map (Cfg.map f₁ g₁) = step (M.map f₁ f₂ g₁ g₂) (Cfg.map f₁ g₁ c)
  | ⟨q, T⟩, h => by
    unfold step Machine.map Cfg.map
    simp only [Turing.Tape.map_fst, g₂₁ q h, f₂₁ _]
    

Proof state:
Γ : Type u_1
inst✝³ : Inhabited Γ
Γ' : Type u_2
inst✝² : Inhabited Γ'
Λ : Type u_3
inst✝¹ : Inhabited Λ
Λ' : Type u_4
inst✝ : Inhabited Λ'
M : Machine Γ Λ
f₁ : PointedMap Γ Γ'
f₂ : PointedMap Γ' Γ
g₁ : Λ → Λ'
g₂ : Λ' → Λ
S : Set Λ
f₂₁ : Function.RightInverse f₁.f f₂.f
g₂₁ : ∀ q ∈ S, g₂ (g₁ q) = q
q : Λ
T : Tape Γ
h : { q := q, Tape := T }.q ∈ S
⊢ Option.map (fun x => { q := g₁ x.q, Tape := Tape.map f₁ x.Tape })
      (Option.map
        (fun x =>
          { q := x.1,
            Tape :=
              match x.2 with
              | Stmt.move d => Tape.move d T
              | Stmt.write a => Tape.write a T })
        (M q T.head)) =
    Option.map
      (fun x =>
        { q := x.1,
          Tape :=
            match x.2 with
            | Stmt.move d => Tape.move d (Tape.map f₁ T)
            | Stmt.write a => Tape.write a (Tape.map f₁ T) })
      (Option.map (Prod.map g₁ (Stmt.map f₁)) (M q T.head))

Next tactic:
rcases M q T.1 with (_ | ⟨q', d | a⟩)
theorem Machine.map_step {S : Set Λ} (f₂₁ : Function.RightInverse f₁ f₂)
    (g₂₁ : ∀ q ∈ S, g₂ (g₁ q) = q) :
    ∀ c : Cfg Γ Λ,
      c.q ∈ S → (step M c).map (Cfg.map f₁ g₁) = step (M.map f₁ f₂ g₁ g₂) (Cfg.map f₁ g₁ c)
  | ⟨q, T⟩, h => by
    unfold step Machine.map Cfg.map
    simp only [Turing.Tape.map_fst, g₂₁ q h, f₂₁ _]
    rcases M q T.1 with (_ | ⟨q', d | a⟩); · 

Proof state:
case none
Γ : Type u_1
inst✝³ : Inhabited Γ
Γ' : Type u_2
inst✝² : Inhabited Γ'
Λ : Type u_3
inst✝¹ : Inhabited Λ
Λ' : Type u_4
inst✝ : Inhabited Λ'
M : Machine Γ Λ
f₁ : PointedMap Γ Γ'
f₂ : PointedMap Γ' Γ
g₁ : Λ → Λ'
g₂ : Λ' → Λ
S : Set Λ
f₂₁ : Function.RightInverse f₁.f f₂.f
g₂₁ : ∀ q ∈ S, g₂ (g₁ q) = q
q : Λ
T : Tape Γ
h : { q := q, Tape := T }.q ∈ S
⊢ Option.map (fun x => { q := g₁ x.q, Tape := Tape.map f₁ x.Tape })
      (Option.map
        (fun x =>
          { q := x.1,
            Tape :=
              match x.2 with
              | Stmt.move d => Tape.move d T
              | Stmt.write a => Tape.write a T })
        none) =
    Option.map
      (fun x =>
        { q := x.1,
          Tape :=
            match x.2 with
            | Stmt.move d => Tape.move d (Tape.map f₁ T)
            | Stmt.write a => Tape.write a (Tape.map f₁ T) })
      (Option.map (Prod.map g₁ (Stmt.map f₁)) none)

Next tactic:
rfl
theorem Machine.map_step {S : Set Λ} (f₂₁ : Function.RightInverse f₁ f₂)
    (g₂₁ : ∀ q ∈ S, g₂ (g₁ q) = q) :
    ∀ c : Cfg Γ Λ,
      c.q ∈ S → (step M c).map (Cfg.map f₁ g₁) = step (M.map f₁ f₂ g₁ g₂) (Cfg.map f₁ g₁ c)
  | ⟨q, T⟩, h => by
    unfold step Machine.map Cfg.map
    simp only [Turing.Tape.map_fst, g₂₁ q h, f₂₁ _]
    rcases M q T.1 with (_ | ⟨q', d | a⟩); · rfl
    · 

Proof state:
case some.mk.move
Γ : Type u_1
inst✝³ : Inhabited Γ
Γ' : Type u_2
inst✝² : Inhabited Γ'
Λ : Type u_3
inst✝¹ : Inhabited Λ
Λ' : Type u_4
inst✝ : Inhabited Λ'
M : Machine Γ Λ
f₁ : PointedMap Γ Γ'
f₂ : PointedMap Γ' Γ
g₁ : Λ → Λ'
g₂ : Λ' → Λ
S : Set Λ
f₂₁ : Function.RightInverse f₁.f f₂.f
g₂₁ : ∀ q ∈ S, g₂ (g₁ q) = q
q : Λ
T : Tape Γ
h : { q := q, Tape := T }.q ∈ S
q' : Λ
d : Dir
⊢ Option.map (fun x => { q := g₁ x.q, Tape := Tape.map f₁ x.Tape })
      (Option.map
        (fun x =>
          { q := x.1,
            Tape :=
              match x.2 with
              | Stmt.move d => Tape.move d T
              | Stmt.write a => Tape.write a T })
        (some (q', Stmt.move d))) =
    Option.map
      (fun x =>
        { q := x.1,
          Tape :=
            match x.2 with
            | Stmt.move d => Tape.move d (Tape.map f₁ T)
            | Stmt.write a => Tape.write a (Tape.map f₁ T) })
      (Option.map (Prod.map g₁ (Stmt.map f₁)) (some (q', Stmt.move d)))

Next tactic:
simp only [step, Cfg.map, Option.map_some', Tape.map_move f₁]
theorem Machine.map_step {S : Set Λ} (f₂₁ : Function.RightInverse f₁ f₂)
    (g₂₁ : ∀ q ∈ S, g₂ (g₁ q) = q) :
    ∀ c : Cfg Γ Λ,
      c.q ∈ S → (step M c).map (Cfg.map f₁ g₁) = step (M.map f₁ f₂ g₁ g₂) (Cfg.map f₁ g₁ c)
  | ⟨q, T⟩, h => by
    unfold step Machine.map Cfg.map
    simp only [Turing.Tape.map_fst, g₂₁ q h, f₂₁ _]
    rcases M q T.1 with (_ | ⟨q', d | a⟩); · rfl
    · simp only [step, Cfg.map, Option.map_some', Tape.map_move f₁]
      

Proof state:
case some.mk.move
Γ : Type u_1
inst✝³ : Inhabited Γ
Γ' : Type u_2
inst✝² : Inhabited Γ'
Λ : Type u_3
inst✝¹ : Inhabited Λ
Λ' : Type u_4
inst✝ : Inhabited Λ'
M : Machine Γ Λ
f₁ : PointedMap Γ Γ'
f₂ : PointedMap Γ' Γ
g₁ : Λ → Λ'
g₂ : Λ' → Λ
S : Set Λ
f₂₁ : Function.RightInverse f₁.f f₂.f
g₂₁ : ∀ q ∈ S, g₂ (g₁ q) = q
q : Λ
T : Tape Γ
h : { q := q, Tape := T }.q ∈ S
q' : Λ
d : Dir
⊢ some { q := g₁ q', Tape := Tape.move d (Tape.map f₁ T) } =
    some
      { q := (Prod.map g₁ (Stmt.map f₁) (q', Stmt.move d)).1,
        Tape :=
          match (Prod.map g₁ (Stmt.map f₁) (q', Stmt.move d)).2 with
          | Stmt.move d => Tape.move d (Tape.map f₁ T)
          | Stmt.write a => Tape.write a (Tape.map f₁ T) }

Next tactic:
rfl
theorem Machine.map_step {S : Set Λ} (f₂₁ : Function.RightInverse f₁ f₂)
    (g₂₁ : ∀ q ∈ S, g₂ (g₁ q) = q) :
    ∀ c : Cfg Γ Λ,
      c.q ∈ S → (step M c).map (Cfg.map f₁ g₁) = step (M.map f₁ f₂ g₁ g₂) (Cfg.map f₁ g₁ c)
  | ⟨q, T⟩, h => by
    unfold step Machine.map Cfg.map
    simp only [Turing.Tape.map_fst, g₂₁ q h, f₂₁ _]
    rcases M q T.1 with (_ | ⟨q', d | a⟩); · rfl
    · simp only [step, Cfg.map, Option.map_some', Tape.map_move f₁]
      rfl
    · 

Proof state:
case some.mk.write
Γ : Type u_1
inst✝³ : Inhabited Γ
Γ' : Type u_2
inst✝² : Inhabited Γ'
Λ : Type u_3
inst✝¹ : Inhabited Λ
Λ' : Type u_4
inst✝ : Inhabited Λ'
M : Machine Γ Λ
f₁ : PointedMap Γ Γ'
f₂ : PointedMap Γ' Γ
g₁ : Λ → Λ'
g₂ : Λ' → Λ
S : Set Λ
f₂₁ : Function.RightInverse f₁.f f₂.f
g₂₁ : ∀ q ∈ S, g₂ (g₁ q) = q
q : Λ
T : Tape Γ
h : { q := q, Tape := T }.q ∈ S
q' : Λ
a : Γ
⊢ Option.map (fun x => { q := g₁ x.q, Tape := Tape.map f₁ x.Tape })
      (Option.map
        (fun x =>
          { q := x.1,
            Tape :=
              match x.2 with
              | Stmt.move d => Tape.move d T
              | Stmt.write a => Tape.write a T })
        (some (q', Stmt.write a))) =
    Option.map
      (fun x =>
        { q := x.1,
          Tape :=
            match x.2 with
            | Stmt.move d => Tape.move d (Tape.map f₁ T)
            | Stmt.write a => Tape.write a (Tape.map f₁ T) })
      (Option.map (Prod.map g₁ (Stmt.map f₁)) (some (q', Stmt.write a)))

Next tactic:
simp only [step, Cfg.map, Option.map_some', Tape.map_write]
theorem Machine.map_step {S : Set Λ} (f₂₁ : Function.RightInverse f₁ f₂)
    (g₂₁ : ∀ q ∈ S, g₂ (g₁ q) = q) :
    ∀ c : Cfg Γ Λ,
      c.q ∈ S → (step M c).map (Cfg.map f₁ g₁) = step (M.map f₁ f₂ g₁ g₂) (Cfg.map f₁ g₁ c)
  | ⟨q, T⟩, h => by
    unfold step Machine.map Cfg.map
    simp only [Turing.Tape.map_fst, g₂₁ q h, f₂₁ _]
    rcases M q T.1 with (_ | ⟨q', d | a⟩); · rfl
    · simp only [step, Cfg.map, Option.map_some', Tape.map_move f₁]
      rfl
    · simp only [step, Cfg.map, Option.map_some', Tape.map_write]
      

Proof state:
case some.mk.write
Γ : Type u_1
inst✝³ : Inhabited Γ
Γ' : Type u_2
inst✝² : Inhabited Γ'
Λ : Type u_3
inst✝¹ : Inhabited Λ
Λ' : Type u_4
inst✝ : Inhabited Λ'
M : Machine Γ Λ
f₁ : PointedMap Γ Γ'
f₂ : PointedMap Γ' Γ
g₁ : Λ → Λ'
g₂ : Λ' → Λ
S : Set Λ
f₂₁ : Function.RightInverse f₁.f f₂.f
g₂₁ : ∀ q ∈ S, g₂ (g₁ q) = q
q : Λ
T : Tape Γ
h : { q := q, Tape := T }.q ∈ S
q' : Λ
a : Γ
⊢ some { q := g₁ q', Tape := Tape.write (PointedMap.f f₁ a) (Tape.map f₁ T) } =
    some
      { q := (Prod.map g₁ (Stmt.map f₁) (q', Stmt.write a)).1,
        Tape :=
          match (Prod.map g₁ (Stmt.map f₁) (q', Stmt.write a)).2 with
          | Stmt.move d => Tape.move d (Tape.map f₁ T)
          | Stmt.write a => Tape.write a (Tape.map f₁ T) }

Next tactic:
rfl
theorem Machine.map_respects (g₁ : PointedMap Λ Λ') (g₂ : Λ' → Λ) {S} (ss : Supports M S)
    (f₂₁ : Function.RightInverse f₁ f₂) (g₂₁ : ∀ q ∈ S, g₂ (g₁ q) = q) :
    Respects (step M) (step (M.map f₁ f₂ g₁ g₂)) fun a b ↦ a.q ∈ S ∧ Cfg.map f₁ g₁ a = b := by
  

Proof state:
Γ : Type u_1
inst✝³ : Inhabited Γ
Γ' : Type u_2
inst✝² : Inhabited Γ'
Λ : Type u_3
inst✝¹ : Inhabited Λ
Λ' : Type u_4
inst✝ : Inhabited Λ'
M : Machine Γ Λ
f₁ : PointedMap Γ Γ'
f₂ : PointedMap Γ' Γ
g₁✝ : Λ → Λ'
g₂✝ : Λ' → Λ
g₁ : PointedMap Λ Λ'
g₂ : Λ' → Λ
S : Set Λ
ss : Supports M S
f₂₁ : Function.RightInverse f₁.f f₂.f
g₂₁ : ∀ q ∈ S, g₂ (PointedMap.f g₁ q) = q
⊢ Respects (step M) (step (map M f₁ f₂ g₁.f g₂)) fun a b => a.q ∈ S ∧ Cfg.map f₁ g₁.f a = b

Next tactic:
intro c _ ⟨cs, rfl⟩
theorem Machine.map_respects (g₁ : PointedMap Λ Λ') (g₂ : Λ' → Λ) {S} (ss : Supports M S)
    (f₂₁ : Function.RightInverse f₁ f₂) (g₂₁ : ∀ q ∈ S, g₂ (g₁ q) = q) :
    Respects (step M) (step (M.map f₁ f₂ g₁ g₂)) fun a b ↦ a.q ∈ S ∧ Cfg.map f₁ g₁ a = b := by
  intro c _ ⟨cs, rfl⟩
  

Proof state:
Γ : Type u_1
inst✝³ : Inhabited Γ
Γ' : Type u_2
inst✝² : Inhabited Γ'
Λ : Type u_3
inst✝¹ : Inhabited Λ
Λ' : Type u_4
inst✝ : Inhabited Λ'
M : Machine Γ Λ
f₁ : PointedMap Γ Γ'
f₂ : PointedMap Γ' Γ
g₁✝ : Λ → Λ'
g₂✝ : Λ' → Λ
g₁ : PointedMap Λ Λ'
g₂ : Λ' → Λ
S : Set Λ
ss : Supports M S
f₂₁ : Function.RightInverse f₁.f f₂.f
g₂₁ : ∀ q ∈ S, g₂ (PointedMap.f g₁ q) = q
c : Cfg Γ Λ
a₂✝ : Cfg Γ' Λ'
cs : c.q ∈ S
⊢ match step M c with
  | some b₁ =>
    ∃ b₂,
      (fun a b => a.q ∈ S ∧ Cfg.map f₁ g₁.f a = b) b₁ b₂ ∧ Reaches₁ (step (map M f₁ f₂ g₁.f g₂)) (Cfg.map f₁ g₁.f c) b₂
  | none => step (map M f₁ f₂ g₁.f g₂) (Cfg.map f₁ g₁.f c) = none

Next tactic:
cases e : step M c
theorem Machine.map_respects (g₁ : PointedMap Λ Λ') (g₂ : Λ' → Λ) {S} (ss : Supports M S)
    (f₂₁ : Function.RightInverse f₁ f₂) (g₂₁ : ∀ q ∈ S, g₂ (g₁ q) = q) :
    Respects (step M) (step (M.map f₁ f₂ g₁ g₂)) fun a b ↦ a.q ∈ S ∧ Cfg.map f₁ g₁ a = b := by
  intro c _ ⟨cs, rfl⟩
  cases e : step M c
  · 

Proof state:
case none
Γ : Type u_1
inst✝³ : Inhabited Γ
Γ' : Type u_2
inst✝² : Inhabited Γ'
Λ : Type u_3
inst✝¹ : Inhabited Λ
Λ' : Type u_4
inst✝ : Inhabited Λ'
M : Machine Γ Λ
f₁ : PointedMap Γ Γ'
f₂ : PointedMap Γ' Γ
g₁✝ : Λ → Λ'
g₂✝ : Λ' → Λ
g₁ : PointedMap Λ Λ'
g₂ : Λ' → Λ
S : Set Λ
ss : Supports M S
f₂₁ : Function.RightInverse f₁.f f₂.f
g₂₁ : ∀ q ∈ S, g₂ (PointedMap.f g₁ q) = q
c : Cfg Γ Λ
a₂✝ : Cfg Γ' Λ'
cs : c.q ∈ S
e : step M c = none
⊢ match none with
  | some b₁ =>
    ∃ b₂,
      (fun a b => a.q ∈ S ∧ Cfg.map f₁ g₁.f a = b) b₁ b₂ ∧ Reaches₁ (step (map M f₁ f₂ g₁.f g₂)) (Cfg.map f₁ g₁.f c) b₂
  | none => step (map M f₁ f₂ g₁.f g₂) (Cfg.map f₁ g₁.f c) = none

Next tactic:
rw [← M.map_step f₁ f₂ g₁ g₂ f₂₁ g₂₁ _ cs, e]
theorem Machine.map_respects (g₁ : PointedMap Λ Λ') (g₂ : Λ' → Λ) {S} (ss : Supports M S)
    (f₂₁ : Function.RightInverse f₁ f₂) (g₂₁ : ∀ q ∈ S, g₂ (g₁ q) = q) :
    Respects (step M) (step (M.map f₁ f₂ g₁ g₂)) fun a b ↦ a.q ∈ S ∧ Cfg.map f₁ g₁ a = b := by
  intro c _ ⟨cs, rfl⟩
  cases e : step M c
  · rw [← M.map_step f₁ f₂ g₁ g₂ f₂₁ g₂₁ _ cs, e]
    

Proof state:
case none
Γ : Type u_1
inst✝³ : Inhabited Γ
Γ' : Type u_2
inst✝² : Inhabited Γ'
Λ : Type u_3
inst✝¹ : Inhabited Λ
Λ' : Type u_4
inst✝ : Inhabited Λ'
M : Machine Γ Λ
f₁ : PointedMap Γ Γ'
f₂ : PointedMap Γ' Γ
g₁✝ : Λ → Λ'
g₂✝ : Λ' → Λ
g₁ : PointedMap Λ Λ'
g₂ : Λ' → Λ
S : Set Λ
ss : Supports M S
f₂₁ : Function.RightInverse f₁.f f₂.f
g₂₁ : ∀ q ∈ S, g₂ (PointedMap.f g₁ q) = q
c : Cfg Γ Λ
a₂✝ : Cfg Γ' Λ'
cs : c.q ∈ S
e : step M c = none
⊢ match none with
  | some b₁ =>
    ∃ b₂,
      (fun a b => a.q ∈ S ∧ Cfg.map f₁ g₁.f a = b) b₁ b₂ ∧ Reaches₁ (step (map M f₁ f₂ g₁.f g₂)) (Cfg.map f₁ g₁.f c) b₂
  | none => Option.map (Cfg.map f₁ g₁.f) none = none

Next tactic:
rfl
theorem Machine.map_respects (g₁ : PointedMap Λ Λ') (g₂ : Λ' → Λ) {S} (ss : Supports M S)
    (f₂₁ : Function.RightInverse f₁ f₂) (g₂₁ : ∀ q ∈ S, g₂ (g₁ q) = q) :
    Respects (step M) (step (M.map f₁ f₂ g₁ g₂)) fun a b ↦ a.q ∈ S ∧ Cfg.map f₁ g₁ a = b := by
  intro c _ ⟨cs, rfl⟩
  cases e : step M c
  · rw [← M.map_step f₁ f₂ g₁ g₂ f₂₁ g₂₁ _ cs, e]
    rfl
  · 

Proof state:
case some
Γ : Type u_1
inst✝³ : Inhabited Γ
Γ' : Type u_2
inst✝² : Inhabited Γ'
Λ : Type u_3
inst✝¹ : Inhabited Λ
Λ' : Type u_4
inst✝ : Inhabited Λ'
M : Machine Γ Λ
f₁ : PointedMap Γ Γ'
f₂ : PointedMap Γ' Γ
g₁✝ : Λ → Λ'
g₂✝ : Λ' → Λ
g₁ : PointedMap Λ Λ'
g₂ : Λ' → Λ
S : Set Λ
ss : Supports M S
f₂₁ : Function.RightInverse f₁.f f₂.f
g₂₁ : ∀ q ∈ S, g₂ (PointedMap.f g₁ q) = q
c : Cfg Γ Λ
a₂✝ : Cfg Γ' Λ'
cs : c.q ∈ S
val✝ : Cfg Γ Λ
e : step M c = some val✝
⊢ match some val✝ with
  | some b₁ =>
    ∃ b₂,
      (fun a b => a.q ∈ S ∧ Cfg.map f₁ g₁.f a = b) b₁ b₂ ∧ Reaches₁ (step (map M f₁ f₂ g₁.f g₂)) (Cfg.map f₁ g₁.f c) b₂
  | none => step (map M f₁ f₂ g₁.f g₂) (Cfg.map f₁ g₁.f c) = none

Next tactic:
refine' ⟨_, ⟨step_supports M ss e cs, rfl⟩, TransGen.single _⟩
theorem Machine.map_respects (g₁ : PointedMap Λ Λ') (g₂ : Λ' → Λ) {S} (ss : Supports M S)
    (f₂₁ : Function.RightInverse f₁ f₂) (g₂₁ : ∀ q ∈ S, g₂ (g₁ q) = q) :
    Respects (step M) (step (M.map f₁ f₂ g₁ g₂)) fun a b ↦ a.q ∈ S ∧ Cfg.map f₁ g₁ a = b := by
  intro c _ ⟨cs, rfl⟩
  cases e : step M c
  · rw [← M.map_step f₁ f₂ g₁ g₂ f₂₁ g₂₁ _ cs, e]
    rfl
  · refine' ⟨_, ⟨step_supports M ss e cs, rfl⟩, TransGen.single _⟩
    

Proof state:
case some
Γ : Type u_1
inst✝³ : Inhabited Γ
Γ' : Type u_2
inst✝² : Inhabited Γ'
Λ : Type u_3
inst✝¹ : Inhabited Λ
Λ' : Type u_4
inst✝ : Inhabited Λ'
M : Machine Γ Λ
f₁ : PointedMap Γ Γ'
f₂ : PointedMap Γ' Γ
g₁✝ : Λ → Λ'
g₂✝ : Λ' → Λ
g₁ : PointedMap Λ Λ'
g₂ : Λ' → Λ
S : Set Λ
ss : Supports M S
f₂₁ : Function.RightInverse f₁.f f₂.f
g₂₁ : ∀ q ∈ S, g₂ (PointedMap.f g₁ q) = q
c : Cfg Γ Λ
a₂✝ : Cfg Γ' Λ'
cs : c.q ∈ S
val✝ : Cfg Γ Λ
e : step M c = some val✝
⊢ Cfg.map f₁ g₁.f val✝ ∈ step (map M f₁ f₂ g₁.f g₂) (Cfg.map f₁ g₁.f c)

Next tactic:
rw [← M.map_step f₁ f₂ g₁ g₂ f₂₁ g₂₁ _ cs, e]
theorem Machine.map_respects (g₁ : PointedMap Λ Λ') (g₂ : Λ' → Λ) {S} (ss : Supports M S)
    (f₂₁ : Function.RightInverse f₁ f₂) (g₂₁ : ∀ q ∈ S, g₂ (g₁ q) = q) :
    Respects (step M) (step (M.map f₁ f₂ g₁ g₂)) fun a b ↦ a.q ∈ S ∧ Cfg.map f₁ g₁ a = b := by
  intro c _ ⟨cs, rfl⟩
  cases e : step M c
  · rw [← M.map_step f₁ f₂ g₁ g₂ f₂₁ g₂₁ _ cs, e]
    rfl
  · refine' ⟨_, ⟨step_supports M ss e cs, rfl⟩, TransGen.single _⟩
    rw [← M.map_step f₁ f₂ g₁ g₂ f₂₁ g₂₁ _ cs, e]
    

Proof state:
case some
Γ : Type u_1
inst✝³ : Inhabited Γ
Γ' : Type u_2
inst✝² : Inhabited Γ'
Λ : Type u_3
inst✝¹ : Inhabited Λ
Λ' : Type u_4
inst✝ : Inhabited Λ'
M : Machine Γ Λ
f₁ : PointedMap Γ Γ'
f₂ : PointedMap Γ' Γ
g₁✝ : Λ → Λ'
g₂✝ : Λ' → Λ
g₁ : PointedMap Λ Λ'
g₂ : Λ' → Λ
S : Set Λ
ss : Supports M S
f₂₁ : Function.RightInverse f₁.f f₂.f
g₂₁ : ∀ q ∈ S, g₂ (PointedMap.f g₁ q) = q
c : Cfg Γ Λ
a₂✝ : Cfg Γ' Λ'
cs : c.q ∈ S
val✝ : Cfg Γ Λ
e : step M c = some val✝
⊢ Cfg.map f₁ g₁.f val✝ ∈ Option.map (Cfg.map f₁ g₁.f) (some val✝)

Next tactic:
rfl
theorem stmts₁_self {q : Stmt₁} : q ∈ stmts₁ q := by
  

Proof state:
Γ : Type u_1
inst✝ : Inhabited Γ
Λ : Type u_2
σ : Type u_3
q : Stmt₁
⊢ q ∈ stmts₁ q

Next tactic:
cases q
theorem stmts₁_self {q : Stmt₁} : q ∈ stmts₁ q := by
  cases q <;> 

Proof state:
case move
Γ : Type u_1
inst✝ : Inhabited Γ
Λ : Type u_2
σ : Type u_3
a✝¹ : Dir
a✝ : Stmt₁
⊢ move a✝¹ a✝ ∈ stmts₁ (move a✝¹ a✝)

Next tactic:
simp only [stmts₁, Finset.mem_insert_self, Finset.mem_singleton_self]
theorem stmts₁_self {q : Stmt₁} : q ∈ stmts₁ q := by
  cases q <;> 

Proof state:
case write
Γ : Type u_1
inst✝ : Inhabited Γ
Λ : Type u_2
σ : Type u_3
a✝¹ : Γ → σ → Γ
a✝ : Stmt₁
⊢ write a✝¹ a✝ ∈ stmts₁ (write a✝¹ a✝)

Next tactic:
simp only [stmts₁, Finset.mem_insert_self, Finset.mem_singleton_self]
theorem stmts₁_self {q : Stmt₁} : q ∈ stmts₁ q := by
  cases q <;> 

Proof state:
case load
Γ : Type u_1
inst✝ : Inhabited Γ
Λ : Type u_2
σ : Type u_3
a✝¹ : Γ → σ → σ
a✝ : Stmt₁
⊢ load a✝¹ a✝ ∈ stmts₁ (load a✝¹ a✝)

Next tactic:
simp only [stmts₁, Finset.mem_insert_self, Finset.mem_singleton_self]
theorem stmts₁_self {q : Stmt₁} : q ∈ stmts₁ q := by
  cases q <;> 

Proof state:
case branch
Γ : Type u_1
inst✝ : Inhabited Γ
Λ : Type u_2
σ : Type u_3
a✝² : Γ → σ → Bool
a✝¹ a✝ : Stmt₁
⊢ branch a✝² a✝¹ a✝ ∈ stmts₁ (branch a✝² a✝¹ a✝)

Next tactic:
simp only [stmts₁, Finset.mem_insert_self, Finset.mem_singleton_self]
theorem stmts₁_self {q : Stmt₁} : q ∈ stmts₁ q := by
  cases q <;> 

Proof state:
case goto
Γ : Type u_1
inst✝ : Inhabited Γ
Λ : Type u_2
σ : Type u_3
a✝ : Γ → σ → Λ
⊢ goto a✝ ∈ stmts₁ (goto a✝)

Next tactic:
simp only [stmts₁, Finset.mem_insert_self, Finset.mem_singleton_self]
theorem stmts₁_self {q : Stmt₁} : q ∈ stmts₁ q := by
  cases q <;> 

Proof state:
case halt
Γ : Type u_1
inst✝ : Inhabited Γ
Λ : Type u_2
σ : Type u_3
⊢ halt ∈ stmts₁ halt

Next tactic:
simp only [stmts₁, Finset.mem_insert_self, Finset.mem_singleton_self]
theorem stmts₁_trans {q₁ q₂ : Stmt₁} : q₁ ∈ stmts₁ q₂ → stmts₁ q₁ ⊆ stmts₁ q₂ := by
  

Proof state:
Γ : Type u_1
inst✝ : Inhabited Γ
Λ : Type u_2
σ : Type u_3
q₁ q₂ : Stmt₁
⊢ q₁ ∈ stmts₁ q₂ → stmts₁ q₁ ⊆ stmts₁ q₂

Next tactic:
intro h₁₂ q₀ h₀₁
theorem stmts₁_trans {q₁ q₂ : Stmt₁} : q₁ ∈ stmts₁ q₂ → stmts₁ q₁ ⊆ stmts₁ q₂ := by
  intro h₁₂ q₀ h₀₁
  

Proof state:
Γ : Type u_1
inst✝ : Inhabited Γ
Λ : Type u_2
σ : Type u_3
q₁ q₂ : Stmt₁
h₁₂ : q₁ ∈ stmts₁ q₂
q₀ : Stmt₁
h₀₁ : q₀ ∈ stmts₁ q₁
⊢ q₀ ∈ stmts₁ q₂

Next tactic:
induction' q₂ with _ q IH _ q IH _ q IH
theorem stmts₁_trans {q₁ q₂ : Stmt₁} : q₁ ∈ stmts₁ q₂ → stmts₁ q₁ ⊆ stmts₁ q₂ := by
  intro h₁₂ q₀ h₀₁
  induction' q₂ with _ q IH _ q IH _ q IH <;> 

Proof state:
case move
Γ : Type u_1
inst✝ : Inhabited Γ
Λ : Type u_2
σ : Type u_3
q₁ q₀ : Stmt₁
h₀₁ : q₀ ∈ stmts₁ q₁
a✝ : Dir
q : Stmt₁
IH : q₁ ∈ stmts₁ q → q₀ ∈ stmts₁ q
h₁₂ : q₁ ∈ stmts₁ (move a✝ q)
⊢ q₀ ∈ stmts₁ (move a✝ q)

Next tactic:
simp only [stmts₁] at h₁₂ ⊢
theorem stmts₁_trans {q₁ q₂ : Stmt₁} : q₁ ∈ stmts₁ q₂ → stmts₁ q₁ ⊆ stmts₁ q₂ := by
  intro h₁₂ q₀ h₀₁
  induction' q₂ with _ q IH _ q IH _ q IH <;> 

Proof state:
case write
Γ : Type u_1
inst✝ : Inhabited Γ
Λ : Type u_2
σ : Type u_3
q₁ q₀ : Stmt₁
h₀₁ : q₀ ∈ stmts₁ q₁
a✝ : Γ → σ → Γ
q : Stmt₁
IH : q₁ ∈ stmts₁ q → q₀ ∈ stmts₁ q
h₁₂ : q₁ ∈ stmts₁ (write a✝ q)
⊢ q₀ ∈ stmts₁ (write a✝ q)

Next tactic:
simp only [stmts₁] at h₁₂ ⊢
theorem stmts₁_trans {q₁ q₂ : Stmt₁} : q₁ ∈ stmts₁ q₂ → stmts₁ q₁ ⊆ stmts₁ q₂ := by
  intro h₁₂ q₀ h₀₁
  induction' q₂ with _ q IH _ q IH _ q IH <;> 

Proof state:
case load
Γ : Type u_1
inst✝ : Inhabited Γ
Λ : Type u_2
σ : Type u_3
q₁ q₀ : Stmt₁
h₀₁ : q₀ ∈ stmts₁ q₁
a✝ : Γ → σ → σ
q : Stmt₁
IH : q₁ ∈ stmts₁ q → q₀ ∈ stmts₁ q
h₁₂ : q₁ ∈ stmts₁ (load a✝ q)
⊢ q₀ ∈ stmts₁ (load a✝ q)

Next tactic:
simp only [stmts₁] at h₁₂ ⊢
theorem stmts₁_trans {q₁ q₂ : Stmt₁} : q₁ ∈ stmts₁ q₂ → stmts₁ q₁ ⊆ stmts₁ q₂ := by
  intro h₁₂ q₀ h₀₁
  induction' q₂ with _ q IH _ q IH _ q IH <;> 

Proof state:
case branch
Γ : Type u_1
inst✝ : Inhabited Γ
Λ : Type u_2
σ : Type u_3
q₁ q₀ : Stmt₁
h₀₁ : q₀ ∈ stmts₁ q₁
a✝² : Γ → σ → Bool
a✝¹ a✝ : Stmt₁
a_ih✝¹ : q₁ ∈ stmts₁ a✝¹ → q₀ ∈ stmts₁ a✝¹
a_ih✝ : q₁ ∈ stmts₁ a✝ → q₀ ∈ stmts₁ a✝
h₁₂ : q₁ ∈ stmts₁ (branch a✝² a✝¹ a✝)
⊢ q₀ ∈ stmts₁ (branch a✝² a✝¹ a✝)

Next tactic:
simp only [stmts₁] at h₁₂ ⊢
theorem stmts₁_trans {q₁ q₂ : Stmt₁} : q₁ ∈ stmts₁ q₂ → stmts₁ q₁ ⊆ stmts₁ q₂ := by
  intro h₁₂ q₀ h₀₁
  induction' q₂ with _ q IH _ q IH _ q IH <;> 

Proof state:
case goto
Γ : Type u_1
inst✝ : Inhabited Γ
Λ : Type u_2
σ : Type u_3
q₁ q₀ : Stmt₁
h₀₁ : q₀ ∈ stmts₁ q₁
a✝ : Γ → σ → Λ
h₁₂ : q₁ ∈ stmts₁ (goto a✝)
⊢ q₀ ∈ stmts₁ (goto a✝)

Next tactic:
simp only [stmts₁] at h₁₂ ⊢
theorem stmts₁_trans {q₁ q₂ : Stmt₁} : q₁ ∈ stmts₁ q₂ → stmts₁ q₁ ⊆ stmts₁ q₂ := by
  intro h₁₂ q₀ h₀₁
  induction' q₂ with _ q IH _ q IH _ q IH <;> 

Proof state:
case halt
Γ : Type u_1
inst✝ : Inhabited Γ
Λ : Type u_2
σ : Type u_3
q₁ q₀ : Stmt₁
h₀₁ : q₀ ∈ stmts₁ q₁
h₁₂ : q₁ ∈ stmts₁ halt
⊢ q₀ ∈ stmts₁ halt

Next tactic:
simp only [stmts₁] at h₁₂ ⊢
theorem stmts₁_trans {q₁ q₂ : Stmt₁} : q₁ ∈ stmts₁ q₂ → stmts₁ q₁ ⊆ stmts₁ q₂ := by
  intro h₁₂ q₀ h₀₁
  induction' q₂ with _ q IH _ q IH _ q IH <;> simp only [stmts₁] at h₁₂ ⊢ <;>
    

Proof state:
case move
Γ : Type u_1
inst✝ : Inhabited Γ
Λ : Type u_2
σ : Type u_3
q₁ q₀ : Stmt₁
h₀₁ : q₀ ∈ stmts₁ q₁
a✝ : Dir
q : Stmt₁
IH : q₁ ∈ stmts₁ q → q₀ ∈ stmts₁ q
h₁₂ : q₁ ∈ insert (move a✝ q) (stmts₁ q)
⊢ q₀ ∈ insert (move a✝ q) (stmts₁ q)

Next tactic:
simp only [Finset.mem_insert, Finset.mem_union, Finset.mem_singleton] at h₁₂
theorem stmts₁_trans {q₁ q₂ : Stmt₁} : q₁ ∈ stmts₁ q₂ → stmts₁ q₁ ⊆ stmts₁ q₂ := by
  intro h₁₂ q₀ h₀₁
  induction' q₂ with _ q IH _ q IH _ q IH <;> simp only [stmts₁] at h₁₂ ⊢ <;>
    

Proof state:
case write
Γ : Type u_1
inst✝ : Inhabited Γ
Λ : Type u_2
σ : Type u_3
q₁ q₀ : Stmt₁
h₀₁ : q₀ ∈ stmts₁ q₁
a✝ : Γ → σ → Γ
q : Stmt₁
IH : q₁ ∈ stmts₁ q → q₀ ∈ stmts₁ q
h₁₂ : q₁ ∈ insert (write a✝ q) (stmts₁ q)
⊢ q₀ ∈ insert (write a✝ q) (stmts₁ q)

Next tactic:
simp only [Finset.mem_insert, Finset.mem_union, Finset.mem_singleton] at h₁₂
theorem stmts₁_trans {q₁ q₂ : Stmt₁} : q₁ ∈ stmts₁ q₂ → stmts₁ q₁ ⊆ stmts₁ q₂ := by
  intro h₁₂ q₀ h₀₁
  induction' q₂ with _ q IH _ q IH _ q IH <;> simp only [stmts₁] at h₁₂ ⊢ <;>
    

Proof state:
case load
Γ : Type u_1
inst✝ : Inhabited Γ
Λ : Type u_2
σ : Type u_3
q₁ q₀ : Stmt₁
h₀₁ : q₀ ∈ stmts₁ q₁
a✝ : Γ → σ → σ
q : Stmt₁
IH : q₁ ∈ stmts₁ q → q₀ ∈ stmts₁ q
h₁₂ : q₁ ∈ insert (load a✝ q) (stmts₁ q)
⊢ q₀ ∈ insert (load a✝ q) (stmts₁ q)

Next tactic:
simp only [Finset.mem_insert, Finset.mem_union, Finset.mem_singleton] at h₁₂