Theorem: Turing.TM1to0.tr_respects
File: Mathlib/Computability/TuringMachine.lean

tactic: cases' l₁ with l₁
state_before: Γ : Type u_3
inst✝² : Inhabited Γ
Λ : Type u_2
inst✝¹ : Inhabited Λ
σ : Type u_1
inst✝ : Inhabited σ
M : Λ → Stmt₁
x✝ : Cfg₁
l₁ : Option Λ
v : σ
T : Tape Γ
⊢ FRespects (TM0.step (tr M)) (fun c₁ => trCfg M c₁) (trCfg M { l := l₁, var := v, Tape := T })
    (TM1.step M { l := l₁, var := v, Tape := T })

tactic: simp only [trCfg, TM1.step, FRespects, Option.map]
state_before: case some
Γ : Type u_3
inst✝² : Inhabited Γ
Λ : Type u_2
inst✝¹ : Inhabited Λ
σ : Type u_1
inst✝ : Inhabited σ
M : Λ → Stmt₁
x✝ : Cfg₁
v : σ
T : Tape Γ
l₁ : Λ
⊢ FRespects (TM0.step (tr M)) (fun c₁ => trCfg M c₁) (trCfg M { l := some l₁, var := v, Tape := T })
    (TM1.step M { l := some l₁, var := v, Tape := T })

tactic: induction' M l₁ with _ q IH _ q IH _ q IH generalizing v T
state_before: case some
Γ : Type u_3
inst✝² : Inhabited Γ
Λ : Type u_2
inst✝¹ : Inhabited Λ
σ : Type u_1
inst✝ : Inhabited σ
M : Λ → Stmt₁
x✝ : Cfg₁
v : σ
T : Tape Γ
l₁ : Λ
⊢ Reaches₁ (TM0.step (tr M)) { q := (some (M l₁), v), Tape := T }
    {
      q :=
        (match (TM1.stepAux (M l₁) v T).l with
          | some x => some (M x)
          | none => none,
          (TM1.stepAux (M l₁) v T).var),
      Tape := (TM1.stepAux (M l₁) v T).Tape }

tactic: case move d q IH => exact TransGen.head rfl (IH _ _)
state_before: case some.move
Γ : Type u_3
inst✝² : Inhabited Γ
Λ : Type u_2
inst✝¹ : Inhabited Λ
σ : Type u_1
inst✝ : Inhabited σ
M : Λ → Stmt₁
x✝ : Cfg₁
v✝ : σ
T✝ : Tape Γ
l₁ : Λ
a✝ : Dir
q : Stmt₁
IH :
  ∀ (v : σ) (T : Tape Γ),
    Reaches₁ (TM0.step (tr M)) { q := (some q, v), Tape := T }
      {
        q :=
          (match (TM1.stepAux q v T).l with
            | some x => some (M x)
            | none => none,
            (TM1.stepAux q v T).var),
        Tape := (TM1.stepAux q v T).Tape }
v : σ
T : Tape Γ
⊢ Reaches₁ (TM0.step (tr M)) { q := (some (TM1.Stmt.move a✝ q), v), Tape := T }
    {
      q :=
        (match (TM1.stepAux (TM1.Stmt.move a✝ q) v T).l with
          | some x => some (M x)
          | none => none,
          (TM1.stepAux (TM1.Stmt.move a✝ q) v T).var),
      Tape := (TM1.stepAux (TM1.Stmt.move a✝ q) v T).Tape }

case some.write
Γ : Type u_3
inst✝² : Inhabited Γ
Λ : Type u_2
inst✝¹ : Inhabited Λ
σ : Type u_1
inst✝ : Inhabited σ
M : Λ → Stmt₁
x✝ : Cfg₁
v✝ : σ
T✝ : Tape Γ
l₁ : Λ
a✝ : Γ → σ → Γ
q : Stmt₁
IH :
  ∀ (v : σ) (T : Tape Γ),
    Reaches₁ (TM0.step (tr M)) { q := (some q, v), Tape := T }
      {
        q :=
          (match (TM1.stepAux q v T).l with
            | some x => some (M x)
            | none => none,
            (TM1.stepAux q v T).var),
        Tape := (TM1.stepAux q v T).Tape }
v : σ
T : Tape Γ
⊢ Reaches₁ (TM0.step (tr M)) { q := (some (TM1.Stmt.write a✝ q), v), Tape := T }
    {
      q :=
        (match (TM1.stepAux (TM1.Stmt.write a✝ q) v T).l with
          | some x => some (M x)
          | none => none,
          (TM1.stepAux (TM1.Stmt.write a✝ q) v T).var),
      Tape := (TM1.stepAux (TM1.Stmt.write a✝ q) v T).Tape }

case some.load
Γ : Type u_3
inst✝² : Inhabited Γ
Λ : Type u_2
inst✝¹ : Inhabited Λ
σ : Type u_1
inst✝ : Inhabited σ
M : Λ → Stmt₁
x✝ : Cfg₁
v✝ : σ
T✝ : Tape Γ
l₁ : Λ
a✝ : Γ → σ → σ
q : Stmt₁
IH :
  ∀ (v : σ) (T : Tape Γ),
    Reaches₁ (TM0.step (tr M)) { q := (some q, v), Tape := T }
      {
        q :=
          (match (TM1.stepAux q v T).l with
            | some x => some (M x)
            | none => none,
            (TM1.stepAux q v T).var),
        Tape := (TM1.stepAux q v T).Tape }
v : σ
T : Tape Γ
⊢ Reaches₁ (TM0.step (tr M)) { q := (some (TM1.Stmt.load a✝ q), v), Tape := T }
    {
      q :=
        (match (TM1.stepAux (TM1.Stmt.load a✝ q) v T).l with
          | some x => some (M x)
          | none => none,
          (TM1.stepAux (TM1.Stmt.load a✝ q) v T).var),
      Tape := (TM1.stepAux (TM1.Stmt.load a✝ q) v T).Tape }

case some.branch
Γ : Type u_3
inst✝² : Inhabited Γ
Λ : Type u_2
inst✝¹ : Inhabited Λ
σ : Type u_1
inst✝ : Inhabited σ
M : Λ → Stmt₁
x✝ : Cfg₁
v✝ : σ
T✝ : Tape Γ
l₁ : Λ
a✝² : Γ → σ → Bool
a✝¹ a✝ : Stmt₁
a_ih✝¹ :
  ∀ (v : σ) (T : Tape Γ),
    Reaches₁ (TM0.step (tr M)) { q := (some a✝¹, v), Tape := T }
      {
        q :=
          (match (TM1.stepAux a✝¹ v T).l with
            | some x => some (M x)
            | none => none,
            (TM1.stepAux a✝¹ v T).var),
        Tape := (TM1.stepAux a✝¹ v T).Tape }
a_ih✝ :
  ∀ (v : σ) (T : Tape Γ),
    Reaches₁ (TM0.step (tr M)) { q := (some a✝, v), Tape := T }
      {
        q :=
          (match (TM1.stepAux a✝ v T).l with
            | some x => some (M x)
            | none => none,
            (TM1.stepAux a✝ v T).var),
        Tape := (TM1.stepAux a✝ v T).Tape }
v : σ
T : Tape Γ
⊢ Reaches₁ (TM0.step (tr M)) { q := (some (TM1.Stmt.branch a✝² a✝¹ a✝), v), Tape := T }
    {
      q :=
        (match (TM1.stepAux (TM1.Stmt.branch a✝² a✝¹ a✝) v T).l with
          | some x => some (M x)
          | none => none,
          (TM1.stepAux (TM1.Stmt.branch a✝² a✝¹ a✝) v T).var),
      Tape := (TM1.stepAux (TM1.Stmt.branch a✝² a✝¹ a✝) v T).Tape }

case some.goto
Γ : Type u_3
inst✝² : Inhabited Γ
Λ : Type u_2
inst✝¹ : Inhabited Λ
σ : Type u_1
inst✝ : Inhabited σ
M : Λ → Stmt₁
x✝ : Cfg₁
v✝ : σ
T✝ : Tape Γ
l₁ : Λ
a✝ : Γ → σ → Λ
v : σ
T : Tape Γ
⊢ Reaches₁ (TM0.step (tr M)) { q := (some (TM1.Stmt.goto a✝), v), Tape := T }
    {
      q :=
        (match (TM1.stepAux (TM1.Stmt.goto a✝) v T).l with
          | some x => some (M x)
          | none => none,
          (TM1.stepAux (TM1.Stmt.goto a✝) v T).var),
      Tape := (TM1.stepAux (TM1.Stmt.goto a✝) v T).Tape }

case some.halt
Γ : Type u_3
inst✝² : Inhabited Γ
Λ : Type u_2
inst✝¹ : Inhabited Λ
σ : Type u_1
inst✝ : Inhabited σ
M : Λ → Stmt₁
x✝ : Cfg₁
v✝ : σ
T✝ : Tape Γ
l₁ : Λ
v : σ
T : Tape Γ
⊢ Reaches₁ (TM0.step (tr M)) { q := (some TM1.Stmt.halt, v), Tape := T }
    {
      q :=
        (match (TM1.stepAux TM1.Stmt.halt v T).l with
          | some x => some (M x)
          | none => none,
          (TM1.stepAux TM1.Stmt.halt v T).var),
      Tape := (TM1.stepAux TM1.Stmt.halt v T).Tape }

tactic: case write a q IH => exact TransGen.head rfl (IH _ _)
state_before: case some.write
Γ : Type u_3
inst✝² : Inhabited Γ
Λ : Type u_2
inst✝¹ : Inhabited Λ
σ : Type u_1
inst✝ : Inhabited σ
M : Λ → Stmt₁
x✝ : Cfg₁
v✝ : σ
T✝ : Tape Γ
l₁ : Λ
a✝ : Γ → σ → Γ
q : Stmt₁
IH :
  ∀ (v : σ) (T : Tape Γ),
    Reaches₁ (TM0.step (tr M)) { q := (some q, v), Tape := T }
      {
        q :=
          (match (TM1.stepAux q v T).l with
            | some x => some (M x)
            | none => none,
            (TM1.stepAux q v T).var),
        Tape := (TM1.stepAux q v T).Tape }
v : σ
T : Tape Γ
⊢ Reaches₁ (TM0.step (tr M)) { q := (some (TM1.Stmt.write a✝ q), v), Tape := T }
    {
      q :=
        (match (TM1.stepAux (TM1.Stmt.write a✝ q) v T).l with
          | some x => some (M x)
          | none => none,
          (TM1.stepAux (TM1.Stmt.write a✝ q) v T).var),
      Tape := (TM1.stepAux (TM1.Stmt.write a✝ q) v T).Tape }

case some.load
Γ : Type u_3
inst✝² : Inhabited Γ
Λ : Type u_2
inst✝¹ : Inhabited Λ
σ : Type u_1
inst✝ : Inhabited σ
M : Λ → Stmt₁
x✝ : Cfg₁
v✝ : σ
T✝ : Tape Γ
l₁ : Λ
a✝ : Γ → σ → σ
q : Stmt₁
IH :
  ∀ (v : σ) (T : Tape Γ),
    Reaches₁ (TM0.step (tr M)) { q := (some q, v), Tape := T }
      {
        q :=
          (match (TM1.stepAux q v T).l with
            | some x => some (M x)
            | none => none,
            (TM1.stepAux q v T).var),
        Tape := (TM1.stepAux q v T).Tape }
v : σ
T : Tape Γ
⊢ Reaches₁ (TM0.step (tr M)) { q := (some (TM1.Stmt.load a✝ q), v), Tape := T }
    {
      q :=
        (match (TM1.stepAux (TM1.Stmt.load a✝ q) v T).l with
          | some x => some (M x)
          | none => none,
          (TM1.stepAux (TM1.Stmt.load a✝ q) v T).var),
      Tape := (TM1.stepAux (TM1.Stmt.load a✝ q) v T).Tape }

case some.branch
Γ : Type u_3
inst✝² : Inhabited Γ
Λ : Type u_2
inst✝¹ : Inhabited Λ
σ : Type u_1
inst✝ : Inhabited σ
M : Λ → Stmt₁
x✝ : Cfg₁
v✝ : σ
T✝ : Tape Γ
l₁ : Λ
a✝² : Γ → σ → Bool
a✝¹ a✝ : Stmt₁
a_ih✝¹ :
  ∀ (v : σ) (T : Tape Γ),
    Reaches₁ (TM0.step (tr M)) { q := (some a✝¹, v), Tape := T }
      {
        q :=
          (match (TM1.stepAux a✝¹ v T).l with
            | some x => some (M x)
            | none => none,
            (TM1.stepAux a✝¹ v T).var),
        Tape := (TM1.stepAux a✝¹ v T).Tape }
a_ih✝ :
  ∀ (v : σ) (T : Tape Γ),
    Reaches₁ (TM0.step (tr M)) { q := (some a✝, v), Tape := T }
      {
        q :=
          (match (TM1.stepAux a✝ v T).l with
            | some x => some (M x)
            | none => none,
            (TM1.stepAux a✝ v T).var),
        Tape := (TM1.stepAux a✝ v T).Tape }
v : σ
T : Tape Γ
⊢ Reaches₁ (TM0.step (tr M)) { q := (some (TM1.Stmt.branch a✝² a✝¹ a✝), v), Tape := T }
    {
      q :=
        (match (TM1.stepAux (TM1.Stmt.branch a✝² a✝¹ a✝) v T).l with
          | some x => some (M x)
          | none => none,
          (TM1.stepAux (TM1.Stmt.branch a✝² a✝¹ a✝) v T).var),
      Tape := (TM1.stepAux (TM1.Stmt.branch a✝² a✝¹ a✝) v T).Tape }

case some.goto
Γ : Type u_3
inst✝² : Inhabited Γ
Λ : Type u_2
inst✝¹ : Inhabited Λ
σ : Type u_1
inst✝ : Inhabited σ
M : Λ → Stmt₁
x✝ : Cfg₁
v✝ : σ
T✝ : Tape Γ
l₁ : Λ
a✝ : Γ → σ → Λ
v : σ
T : Tape Γ
⊢ Reaches₁ (TM0.step (tr M)) { q := (some (TM1.Stmt.goto a✝), v), Tape := T }
    {
      q :=
        (match (TM1.stepAux (TM1.Stmt.goto a✝) v T).l with
          | some x => some (M x)
          | none => none,
          (TM1.stepAux (TM1.Stmt.goto a✝) v T).var),
      Tape := (TM1.stepAux (TM1.Stmt.goto a✝) v T).Tape }

case some.halt
Γ : Type u_3
inst✝² : Inhabited Γ
Λ : Type u_2
inst✝¹ : Inhabited Λ
σ : Type u_1
inst✝ : Inhabited σ
M : Λ → Stmt₁
x✝ : Cfg₁
v✝ : σ
T✝ : Tape Γ
l₁ : Λ
v : σ
T : Tape Γ
⊢ Reaches₁ (TM0.step (tr M)) { q := (some TM1.Stmt.halt, v), Tape := T }
    {
      q :=
        (match (TM1.stepAux TM1.Stmt.halt v T).l with
          | some x => some (M x)
          | none => none,
          (TM1.stepAux TM1.Stmt.halt v T).var),
      Tape := (TM1.stepAux TM1.Stmt.halt v T).Tape }

tactic: case load a q IH => exact (reaches₁_eq (by rfl)).2 (IH _ _)
state_before: case some.load
Γ : Type u_3
inst✝² : Inhabited Γ
Λ : Type u_2
inst✝¹ : Inhabited Λ
σ : Type u_1
inst✝ : Inhabited σ
M : Λ → Stmt₁
x✝ : Cfg₁
v✝ : σ
T✝ : Tape Γ
l₁ : Λ
a✝ : Γ → σ → σ
q : Stmt₁
IH :
  ∀ (v : σ) (T : Tape Γ),
    Reaches₁ (TM0.step (tr M)) { q := (some q, v), Tape := T }
      {
        q :=
          (match (TM1.stepAux q v T).l with
            | some x => some (M x)
            | none => none,
            (TM1.stepAux q v T).var),
        Tape := (TM1.stepAux q v T).Tape }
v : σ
T : Tape Γ
⊢ Reaches₁ (TM0.step (tr M)) { q := (some (TM1.Stmt.load a✝ q), v), Tape := T }
    {
      q :=
        (match (TM1.stepAux (TM1.Stmt.load a✝ q) v T).l with
          | some x => some (M x)
          | none => none,
          (TM1.stepAux (TM1.Stmt.load a✝ q) v T).var),
      Tape := (TM1.stepAux (TM1.Stmt.load a✝ q) v T).Tape }

case some.branch
Γ : Type u_3
inst✝² : Inhabited Γ
Λ : Type u_2
inst✝¹ : Inhabited Λ
σ : Type u_1
inst✝ : Inhabited σ
M : Λ → Stmt₁
x✝ : Cfg₁
v✝ : σ
T✝ : Tape Γ
l₁ : Λ
a✝² : Γ → σ → Bool
a✝¹ a✝ : Stmt₁
a_ih✝¹ :
  ∀ (v : σ) (T : Tape Γ),
    Reaches₁ (TM0.step (tr M)) { q := (some a✝¹, v), Tape := T }
      {
        q :=
          (match (TM1.stepAux a✝¹ v T).l with
            | some x => some (M x)
            | none => none,
            (TM1.stepAux a✝¹ v T).var),
        Tape := (TM1.stepAux a✝¹ v T).Tape }
a_ih✝ :
  ∀ (v : σ) (T : Tape Γ),
    Reaches₁ (TM0.step (tr M)) { q := (some a✝, v), Tape := T }
      {
        q :=
          (match (TM1.stepAux a✝ v T).l with
            | some x => some (M x)
            | none => none,
            (TM1.stepAux a✝ v T).var),
        Tape := (TM1.stepAux a✝ v T).Tape }
v : σ
T : Tape Γ
⊢ Reaches₁ (TM0.step (tr M)) { q := (some (TM1.Stmt.branch a✝² a✝¹ a✝), v), Tape := T }
    {
      q :=
        (match (TM1.stepAux (TM1.Stmt.branch a✝² a✝¹ a✝) v T).l with
          | some x => some (M x)
          | none => none,
          (TM1.stepAux (TM1.Stmt.branch a✝² a✝¹ a✝) v T).var),
      Tape := (TM1.stepAux (TM1.Stmt.branch a✝² a✝¹ a✝) v T).Tape }

case some.goto
Γ : Type u_3
inst✝² : Inhabited Γ
Λ : Type u_2
inst✝¹ : Inhabited Λ
σ : Type u_1
inst✝ : Inhabited σ
M : Λ → Stmt₁
x✝ : Cfg₁
v✝ : σ
T✝ : Tape Γ
l₁ : Λ
a✝ : Γ → σ → Λ
v : σ
T : Tape Γ
⊢ Reaches₁ (TM0.step (tr M)) { q := (some (TM1.Stmt.goto a✝), v), Tape := T }
    {
      q :=
        (match (TM1.stepAux (TM1.Stmt.goto a✝) v T).l with
          | some x => some (M x)
          | none => none,
          (TM1.stepAux (TM1.Stmt.goto a✝) v T).var),
      Tape := (TM1.stepAux (TM1.Stmt.goto a✝) v T).Tape }

case some.halt
Γ : Type u_3
inst✝² : Inhabited Γ
Λ : Type u_2
inst✝¹ : Inhabited Λ
σ : Type u_1
inst✝ : Inhabited σ
M : Λ → Stmt₁
x✝ : Cfg₁
v✝ : σ
T✝ : Tape Γ
l₁ : Λ
v : σ
T : Tape Γ
⊢ Reaches₁ (TM0.step (tr M)) { q := (some TM1.Stmt.halt, v), Tape := T }
    {
      q :=
        (match (TM1.stepAux TM1.Stmt.halt v T).l with
          | some x => some (M x)
          | none => none,
          (TM1.stepAux TM1.Stmt.halt v T).var),
      Tape := (TM1.stepAux TM1.Stmt.halt v T).Tape }

tactic: iterate 2
  exact TransGen.single (congr_arg some (congr (congr_arg TM0.Cfg.mk rfl) (Tape.write_self T)))
state_before: case some.goto
Γ : Type u_3
inst✝² : Inhabited Γ
Λ : Type u_2
inst✝¹ : Inhabited Λ
σ : Type u_1
inst✝ : Inhabited σ
M : Λ → Stmt₁
x✝ : Cfg₁
v✝ : σ
T✝ : Tape Γ
l₁ : Λ
a✝ : Γ → σ → Λ
v : σ
T : Tape Γ
⊢ Reaches₁ (TM0.step (tr M)) { q := (some (TM1.Stmt.goto a✝), v), Tape := T }
    {
      q :=
        (match (TM1.stepAux (TM1.Stmt.goto a✝) v T).l with
          | some x => some (M x)
          | none => none,
          (TM1.stepAux (TM1.Stmt.goto a✝) v T).var),
      Tape := (TM1.stepAux (TM1.Stmt.goto a✝) v T).Tape }

case some.halt
Γ : Type u_3
inst✝² : Inhabited Γ
Λ : Type u_2
inst✝¹ : Inhabited Λ
σ : Type u_1
inst✝ : Inhabited σ
M : Λ → Stmt₁
x✝ : Cfg₁
v✝ : σ
T✝ : Tape Γ
l₁ : Λ
v : σ
T : Tape Γ
⊢ Reaches₁ (TM0.step (tr M)) { q := (some TM1.Stmt.halt, v), Tape := T }
    {
      q :=
        (match (TM1.stepAux TM1.Stmt.halt v T).l with
          | some x => some (M x)
          | none => none,
          (TM1.stepAux TM1.Stmt.halt v T).var),
      Tape := (TM1.stepAux TM1.Stmt.halt v T).Tape }

tactic: exact rfl
state_before: case none
Γ : Type u_3
inst✝² : Inhabited Γ
Λ : Type u_2
inst✝¹ : Inhabited Λ
σ : Type u_1
inst✝ : Inhabited σ
M : Λ → Stmt₁
x✝ : Cfg₁
v : σ
T : Tape Γ
⊢ FRespects (TM0.step (tr M)) (fun c₁ => trCfg M c₁) (trCfg M { l := none, var := v, Tape := T })
    (TM1.step M { l := none, var := v, Tape := T })

tactic: exact TransGen.head rfl (IH _ _)
state_before: Γ : Type u_3
inst✝² : Inhabited Γ
Λ : Type u_2
inst✝¹ : Inhabited Λ
σ : Type u_1
inst✝ : Inhabited σ
M : Λ → Stmt₁
x✝ : Cfg₁
d : σ
q✝ : Tape Γ
l₁ : Λ
IH✝ : Dir
q : Stmt₁
IH :
  ∀ (v : σ) (T : Tape Γ),
    Reaches₁ (TM0.step (tr M)) { q := (some q, v), Tape := T }
      {
        q :=
          (match (TM1.stepAux q v T).l with
            | some x => some (M x)
            | none => none,
            (TM1.stepAux q v T).var),
        Tape := (TM1.stepAux q v T).Tape }
v : σ
T : Tape Γ
⊢ Reaches₁ (TM0.step (tr M)) { q := (some (TM1.Stmt.move IH✝ q), v), Tape := T }
    {
      q :=
        (match (TM1.stepAux (TM1.Stmt.move IH✝ q) v T).l with
          | some x => some (M x)
          | none => none,
          (TM1.stepAux (TM1.Stmt.move IH✝ q) v T).var),
      Tape := (TM1.stepAux (TM1.Stmt.move IH✝ q) v T).Tape }

tactic: exact TransGen.head rfl (IH _ _)
state_before: Γ : Type u_3
inst✝² : Inhabited Γ
Λ : Type u_2
inst✝¹ : Inhabited Λ
σ : Type u_1
inst✝ : Inhabited σ
M : Λ → Stmt₁
x✝ : Cfg₁
a : σ
q✝ : Tape Γ
l₁ : Λ
IH✝ : Γ → σ → Γ
q : Stmt₁
IH :
  ∀ (v : σ) (T : Tape Γ),
    Reaches₁ (TM0.step (tr M)) { q := (some q, v), Tape := T }
      {
        q :=
          (match (TM1.stepAux q v T).l with
            | some x => some (M x)
            | none => none,
            (TM1.stepAux q v T).var),
        Tape := (TM1.stepAux q v T).Tape }
v : σ
T : Tape Γ
⊢ Reaches₁ (TM0.step (tr M)) { q := (some (TM1.Stmt.write IH✝ q), v), Tape := T }
    {
      q :=
        (match (TM1.stepAux (TM1.Stmt.write IH✝ q) v T).l with
          | some x => some (M x)
          | none => none,
          (TM1.stepAux (TM1.Stmt.write IH✝ q) v T).var),
      Tape := (TM1.stepAux (TM1.Stmt.write IH✝ q) v T).Tape }

tactic: exact (reaches₁_eq (by rfl)).2 (IH _ _)
state_before: Γ : Type u_3
inst✝² : Inhabited Γ
Λ : Type u_2
inst✝¹ : Inhabited Λ
σ : Type u_1
inst✝ : Inhabited σ
M : Λ → Stmt₁
x✝ : Cfg₁
a : σ
q✝ : Tape Γ
l₁ : Λ
IH✝ : Γ → σ → σ
q : Stmt₁
IH :
  ∀ (v : σ) (T : Tape Γ),
    Reaches₁ (TM0.step (tr M)) { q := (some q, v), Tape := T }
      {
        q :=
          (match (TM1.stepAux q v T).l with
            | some x => some (M x)
            | none => none,
            (TM1.stepAux q v T).var),
        Tape := (TM1.stepAux q v T).Tape }
v : σ
T : Tape Γ
⊢ Reaches₁ (TM0.step (tr M)) { q := (some (TM1.Stmt.load IH✝ q), v), Tape := T }
    {
      q :=
        (match (TM1.stepAux (TM1.Stmt.load IH✝ q) v T).l with
          | some x => some (M x)
          | none => none,
          (TM1.stepAux (TM1.Stmt.load IH✝ q) v T).var),
      Tape := (TM1.stepAux (TM1.Stmt.load IH✝ q) v T).Tape }

tactic: rfl
state_before: Γ : Type u_3
inst✝² : Inhabited Γ
Λ : Type u_2
inst✝¹ : Inhabited Λ
σ : Type u_1
inst✝ : Inhabited σ
M : Λ → Stmt₁
x✝ : Cfg₁
a : σ
q✝ : Tape Γ
l₁ : Λ
IH✝ : Γ → σ → σ
q : Stmt₁
IH :
  ∀ (v : σ) (T : Tape Γ),
    Reaches₁ (TM0.step (tr M)) { q := (some q, v), Tape := T }
      {
        q :=
          (match (TM1.stepAux q v T).l with
            | some x => some (M x)
            | none => none,
            (TM1.stepAux q v T).var),
        Tape := (TM1.stepAux q v T).Tape }
v : σ
T : Tape Γ
⊢ TM0.step (tr M) { q := (some (TM1.Stmt.load IH✝ q), v), Tape := T } =
    TM0.step (tr M) { q := (some q, IH✝ T.head v), Tape := T }

tactic: unfold TM1.stepAux
state_before: Γ : Type u_3
inst✝² : Inhabited Γ
Λ : Type u_2
inst✝¹ : Inhabited Λ
σ : Type u_1
inst✝ : Inhabited σ
M : Λ → Stmt₁
x✝ : Cfg₁
v✝ : σ
T✝ : Tape Γ
l₁ : Λ
p : Γ → σ → Bool
q₁ q₂ : Stmt₁
IH₁ :
  ∀ (v : σ) (T : Tape Γ),
    Reaches₁ (TM0.step (tr M)) { q := (some q₁, v), Tape := T }
      {
        q :=
          (match (TM1.stepAux q₁ v T).l with
            | some x => some (M x)
            | none => none,
            (TM1.stepAux q₁ v T).var),
        Tape := (TM1.stepAux q₁ v T).Tape }
IH₂ :
  ∀ (v : σ) (T : Tape Γ),
    Reaches₁ (TM0.step (tr M)) { q := (some q₂, v), Tape := T }
      {
        q :=
          (match (TM1.stepAux q₂ v T).l with
            | some x => some (M x)
            | none => none,
            (TM1.stepAux q₂ v T).var),
        Tape := (TM1.stepAux q₂ v T).Tape }
v : σ
T : Tape Γ
⊢ Reaches₁ (TM0.step (tr M)) { q := (some (TM1.Stmt.branch p q₁ q₂), v), Tape := T }
    {
      q :=
        (match (TM1.stepAux (TM1.Stmt.branch p q₁ q₂) v T).l with
          | some x => some (M x)
          | none => none,
          (TM1.stepAux (TM1.Stmt.branch p q₁ q₂) v T).var),
      Tape := (TM1.stepAux (TM1.Stmt.branch p q₁ q₂) v T).Tape }

tactic: cases e : p T.1 v
state_before: Γ : Type u_3
inst✝² : Inhabited Γ
Λ : Type u_2
inst✝¹ : Inhabited Λ
σ : Type u_1
inst✝ : Inhabited σ
M : Λ → Stmt₁
x✝ : Cfg₁
v✝ : σ
T✝ : Tape Γ
l₁ : Λ
p : Γ → σ → Bool
q₁ q₂ : Stmt₁
IH₁ :
  ∀ (v : σ) (T : Tape Γ),
    Reaches₁ (TM0.step (tr M)) { q := (some q₁, v), Tape := T }
      {
        q :=
          (match (TM1.stepAux q₁ v T).l with
            | some x => some (M x)
            | none => none,
            (TM1.stepAux q₁ v T).var),
        Tape := (TM1.stepAux q₁ v T).Tape }
IH₂ :
  ∀ (v : σ) (T : Tape Γ),
    Reaches₁ (TM0.step (tr M)) { q := (some q₂, v), Tape := T }
      {
        q :=
          (match (TM1.stepAux q₂ v T).l with
            | some x => some (M x)
            | none => none,
            (TM1.stepAux q₂ v T).var),
        Tape := (TM1.stepAux q₂ v T).Tape }
v : σ
T : Tape Γ
⊢ Reaches₁ (TM0.step (tr M)) { q := (some (TM1.Stmt.branch p q₁ q₂), v), Tape := T }
    {
      q :=
        (match (bif p T.head v then TM1.stepAux q₁ v T else TM1.stepAux q₂ v T).l with
          | some x => some (M x)
          | none => none,
          (bif p T.head v then TM1.stepAux q₁ v T else TM1.stepAux q₂ v T).var),
      Tape := (bif p T.head v then TM1.stepAux q₁ v T else TM1.stepAux q₂ v T).Tape }

tactic: exact (reaches₁_eq (by simp only [TM0.step, tr, trAux, e]; rfl)).2 (IH₂ _ _)
state_before: case false
Γ : Type u_3
inst✝² : Inhabited Γ
Λ : Type u_2
inst✝¹ : Inhabited Λ
σ : Type u_1
inst✝ : Inhabited σ
M : Λ → Stmt₁
x✝ : Cfg₁
v✝ : σ
T✝ : Tape Γ
l₁ : Λ
p : Γ → σ → Bool
q₁ q₂ : Stmt₁
IH₁ :
  ∀ (v : σ) (T : Tape Γ),
    Reaches₁ (TM0.step (tr M)) { q := (some q₁, v), Tape := T }
      {
        q :=
          (match (TM1.stepAux q₁ v T).l with
            | some x => some (M x)
            | none => none,
            (TM1.stepAux q₁ v T).var),
        Tape := (TM1.stepAux q₁ v T).Tape }
IH₂ :
  ∀ (v : σ) (T : Tape Γ),
    Reaches₁ (TM0.step (tr M)) { q := (some q₂, v), Tape := T }
      {
        q :=
          (match (TM1.stepAux q₂ v T).l with
            | some x => some (M x)
            | none => none,
            (TM1.stepAux q₂ v T).var),
        Tape := (TM1.stepAux q₂ v T).Tape }
v : σ
T : Tape Γ
e : p T.head v = false
⊢ Reaches₁ (TM0.step (tr M)) { q := (some (TM1.Stmt.branch p q₁ q₂), v), Tape := T }
    {
      q :=
        (match (bif false then TM1.stepAux q₁ v T else TM1.stepAux q₂ v T).l with
          | some x => some (M x)
          | none => none,
          (bif false then TM1.stepAux q₁ v T else TM1.stepAux q₂ v T).var),
      Tape := (bif false then TM1.stepAux q₁ v T else TM1.stepAux q₂ v T).Tape }

tactic: simp only [TM0.step, tr, trAux, e]
state_before: Γ : Type u_3
inst✝² : Inhabited Γ
Λ : Type u_2
inst✝¹ : Inhabited Λ
σ : Type u_1
inst✝ : Inhabited σ
M : Λ → Stmt₁
x✝ : Cfg₁
v✝ : σ
T✝ : Tape Γ
l₁ : Λ
p : Γ → σ → Bool
q₁ q₂ : Stmt₁
IH₁ :
  ∀ (v : σ) (T : Tape Γ),
    Reaches₁ (TM0.step (tr M)) { q := (some q₁, v), Tape := T }
      {
        q :=
          (match (TM1.stepAux q₁ v T).l with
            | some x => some (M x)
            | none => none,
            (TM1.stepAux q₁ v T).var),
        Tape := (TM1.stepAux q₁ v T).Tape }
IH₂ :
  ∀ (v : σ) (T : Tape Γ),
    Reaches₁ (TM0.step (tr M)) { q := (some q₂, v), Tape := T }
      {
        q :=
          (match (TM1.stepAux q₂ v T).l with
            | some x => some (M x)
            | none => none,
            (TM1.stepAux q₂ v T).var),
        Tape := (TM1.stepAux q₂ v T).Tape }
v : σ
T : Tape Γ
e : p T.head v = false
⊢ TM0.step (tr M) { q := (some (TM1.Stmt.branch p q₁ q₂), v), Tape := T } =
    TM0.step (tr M) { q := (some q₂, v), Tape := T }

tactic: rfl
state_before: Γ : Type u_3
inst✝² : Inhabited Γ
Λ : Type u_2
inst✝¹ : Inhabited Λ
σ : Type u_1
inst✝ : Inhabited σ
M : Λ → Stmt₁
x✝ : Cfg₁
v✝ : σ
T✝ : Tape Γ
l₁ : Λ
p : Γ → σ → Bool
q₁ q₂ : Stmt₁
IH₁ :
  ∀ (v : σ) (T : Tape Γ),
    Reaches₁ (TM0.step (tr M)) { q := (some q₁, v), Tape := T }
      {
        q :=
          (match (TM1.stepAux q₁ v T).l with
            | some x => some (M x)
            | none => none,
            (TM1.stepAux q₁ v T).var),
        Tape := (TM1.stepAux q₁ v T).Tape }
IH₂ :
  ∀ (v : σ) (T : Tape Γ),
    Reaches₁ (TM0.step (tr M)) { q := (some q₂, v), Tape := T }
      {
        q :=
          (match (TM1.stepAux q₂ v T).l with
            | some x => some (M x)
            | none => none,
            (TM1.stepAux q₂ v T).var),
        Tape := (TM1.stepAux q₂ v T).Tape }
v : σ
T : Tape Γ
e : p T.head v = false
⊢ Option.map
      (fun x =>
        { q := x.fst,
          Tape :=
            match x.snd with
            | move d => Tape.move d T
            | write a => Tape.write a T })
      (some (bif false then trAux M T.head q₁ v else trAux M T.head q₂ v)) =
    Option.map
      (fun x =>
        { q := x.fst,
          Tape :=
            match x.snd with
            | move d => Tape.move d T
            | write a => Tape.write a T })
      (some (trAux M T.head q₂ v))

tactic: exact (reaches₁_eq (by simp only [TM0.step, tr, trAux, e]; rfl)).2 (IH₁ _ _)
state_before: case true
Γ : Type u_3
inst✝² : Inhabited Γ
Λ : Type u_2
inst✝¹ : Inhabited Λ
σ : Type u_1
inst✝ : Inhabited σ
M : Λ → Stmt₁
x✝ : Cfg₁
v✝ : σ
T✝ : Tape Γ
l₁ : Λ
p : Γ → σ → Bool
q₁ q₂ : Stmt₁
IH₁ :
  ∀ (v : σ) (T : Tape Γ),
    Reaches₁ (TM0.step (tr M)) { q := (some q₁, v), Tape := T }
      {
        q :=
          (match (TM1.stepAux q₁ v T).l with
            | some x => some (M x)
            | none => none,
            (TM1.stepAux q₁ v T).var),
        Tape := (TM1.stepAux q₁ v T).Tape }
IH₂ :
  ∀ (v : σ) (T : Tape Γ),
    Reaches₁ (TM0.step (tr M)) { q := (some q₂, v), Tape := T }
      {
        q :=
          (match (TM1.stepAux q₂ v T).l with
            | some x => some (M x)
            | none => none,
            (TM1.stepAux q₂ v T).var),
        Tape := (TM1.stepAux q₂ v T).Tape }
v : σ
T : Tape Γ
e : p T.head v = true
⊢ Reaches₁ (TM0.step (tr M)) { q := (some (TM1.Stmt.branch p q₁ q₂), v), Tape := T }
    {
      q :=
        (match (bif true then TM1.stepAux q₁ v T else TM1.stepAux q₂ v T).l with
          | some x => some (M x)
          | none => none,
          (bif true then TM1.stepAux q₁ v T else TM1.stepAux q₂ v T).var),
      Tape := (bif true then TM1.stepAux q₁ v T else TM1.stepAux q₂ v T).Tape }

tactic: simp only [TM0.step, tr, trAux, e]
state_before: Γ : Type u_3
inst✝² : Inhabited Γ
Λ : Type u_2
inst✝¹ : Inhabited Λ
σ : Type u_1
inst✝ : Inhabited σ
M : Λ → Stmt₁
x✝ : Cfg₁
v✝ : σ
T✝ : Tape Γ
l₁ : Λ
p : Γ → σ → Bool
q₁ q₂ : Stmt₁
IH₁ :
  ∀ (v : σ) (T : Tape Γ),
    Reaches₁ (TM0.step (tr M)) { q := (some q₁, v), Tape := T }
      {
        q :=
          (match (TM1.stepAux q₁ v T).l with
            | some x => some (M x)
            | none => none,
            (TM1.stepAux q₁ v T).var),
        Tape := (TM1.stepAux q₁ v T).Tape }
IH₂ :
  ∀ (v : σ) (T : Tape Γ),
    Reaches₁ (TM0.step (tr M)) { q := (some q₂, v), Tape := T }
      {
        q :=
          (match (TM1.stepAux q₂ v T).l with
            | some x => some (M x)
            | none => none,
            (TM1.stepAux q₂ v T).var),
        Tape := (TM1.stepAux q₂ v T).Tape }
v : σ
T : Tape Γ
e : p T.head v = true
⊢ TM0.step (tr M) { q := (some (TM1.Stmt.branch p q₁ q₂), v), Tape := T } =
    TM0.step (tr M) { q := (some q₁, v), Tape := T }

tactic: rfl
state_before: Γ : Type u_3
inst✝² : Inhabited Γ
Λ : Type u_2
inst✝¹ : Inhabited Λ
σ : Type u_1
inst✝ : Inhabited σ
M : Λ → Stmt₁
x✝ : Cfg₁
v✝ : σ
T✝ : Tape Γ
l₁ : Λ
p : Γ → σ → Bool
q₁ q₂ : Stmt₁
IH₁ :
  ∀ (v : σ) (T : Tape Γ),
    Reaches₁ (TM0.step (tr M)) { q := (some q₁, v), Tape := T }
      {
        q :=
          (match (TM1.stepAux q₁ v T).l with
            | some x => some (M x)
            | none => none,
            (TM1.stepAux q₁ v T).var),
        Tape := (TM1.stepAux q₁ v T).Tape }
IH₂ :
  ∀ (v : σ) (T : Tape Γ),
    Reaches₁ (TM0.step (tr M)) { q := (some q₂, v), Tape := T }
      {
        q :=
          (match (TM1.stepAux q₂ v T).l with
            | some x => some (M x)
            | none => none,
            (TM1.stepAux q₂ v T).var),
        Tape := (TM1.stepAux q₂ v T).Tape }
v : σ
T : Tape Γ
e : p T.head v = true
⊢ Option.map
      (fun x =>
        { q := x.fst,
          Tape :=
            match x.snd with
            | move d => Tape.move d T
            | write a => Tape.write a T })
      (some (bif true then trAux M T.head q₁ v else trAux M T.head q₂ v)) =
    Option.map
      (fun x =>
        { q := x.fst,
          Tape :=
            match x.snd with
            | move d => Tape.move d T
            | write a => Tape.write a T })
      (some (trAux M T.head q₁ v))

tactic: exact TransGen.single (congr_arg some (congr (congr_arg TM0.Cfg.mk rfl) (Tape.write_self T)))
state_before: case some.halt
Γ : Type u_3
inst✝² : Inhabited Γ
Λ : Type u_2
inst✝¹ : Inhabited Λ
σ : Type u_1
inst✝ : Inhabited σ
M : Λ → Stmt₁
x✝ : Cfg₁
v✝ : σ
T✝ : Tape Γ
l₁ : Λ
v : σ
T : Tape Γ
⊢ Reaches₁ (TM0.step (tr M)) { q := (some TM1.Stmt.halt, v), Tape := T }
    {
      q :=
        (match (TM1.stepAux TM1.Stmt.halt v T).l with
          | some x => some (M x)
          | none => none,
          (TM1.stepAux TM1.Stmt.halt v T).var),
      Tape := (TM1.stepAux TM1.Stmt.halt v T).Tape }