Theorem: Turing.PartrecToTM2.move₂_ok
File: Mathlib/Computability/TMToPartrec.lean

Proof steps:
state_before: p : Γ' → Bool
k₁ k₂ : K'
q : Λ'
s : Option Γ'
L₁ : List Γ'
o : Option Γ'
L₂ : List Γ'
S : K' → List Γ'
h₁ : k₁ ≠ rev ∧ k₂ ≠ rev ∧ k₁ ≠ k₂
h₂ : S rev = []
e : splitAtPred p (S k₁) = (L₁, o, L₂)
⊢ Reaches₁ (TM2.step tr) { l := some (move₂ p k₁ k₂ q), var := s, stk := S }
    { l := some q, var := none, stk := update (update S k₁ (o.elim id List.cons L₂)) k₂ (L₁ ++ S k₂) }
state_after: p : Γ' → Bool
k₁ k₂ : K'
q : Λ'
s : Option Γ'
L₁ : List Γ'
o : Option Γ'
L₂ : List Γ'
S : K' → List Γ'
h₁ : k₁ ≠ rev ∧ k₂ ≠ rev ∧ k₁ ≠ k₂
h₂ : S rev = []
e : splitAtPred p (S k₁) = (L₁, o, L₂)
⊢ TransGen (fun a b => b ∈ TM2.step tr a)
    (TM2.stepAux (tr (Λ'.push k₁ id (Λ'.move (fun x => false) rev k₂ q))) o
      (update (update S k₁ L₂) rev (L₁.reverseAux (S rev))))
    { l := some q, var := none, stk := update (update S k₁ (o.elim id List.cons L₂)) k₂ (L₁ ++ S k₂) }
tactic: refine (move_ok h₁.1 e).trans (TransGen.head rfl ?_)
state_before: p : Γ' → Bool
k₁ k₂ : K'
q : Λ'
s : Option Γ'
L₁ : List Γ'
o : Option Γ'
L₂ : List Γ'
S : K' → List Γ'
h₁ : k₁ ≠ rev ∧ k₂ ≠ rev ∧ k₁ ≠ k₂
h₂ : S rev = []
e : splitAtPred p (S k₁) = (L₁, o, L₂)
⊢ TransGen (fun a b => b ∈ TM2.step tr a)
    (TM2.stepAux (tr (Λ'.push k₁ id (Λ'.move (fun x => false) rev k₂ q))) o
      (update (update S k₁ L₂) rev (L₁.reverseAux (S rev))))
    { l := some q, var := none, stk := update (update S k₁ (o.elim id List.cons L₂)) k₂ (L₁ ++ S k₂) }
state_after: p : Γ' → Bool
k₁ k₂ : K'
q : Λ'
s : Option Γ'
L₁ : List Γ'
o : Option Γ'
L₂ : List Γ'
S : K' → List Γ'
h₁ : k₁ ≠ rev ∧ k₂ ≠ rev ∧ k₁ ≠ k₂
h₂ : S rev = []
e : splitAtPred p (S k₁) = (L₁, o, L₂)
⊢ TransGen
    (fun a b =>
      (match a with
        | { l := none, var := var, stk := stk } => none
        | { l := some l, var := v, stk := S } => some (TM2.stepAux (tr l) v S)) =
        some b)
    (bif o.isSome then
      { l := some (Λ'.move (fun x => false) rev k₂ q), var := o,
        stk :=
          update (update (update S k₁ L₂) rev (L₁.reverseAux (S rev))) k₁
            (o.iget :: update (update S k₁ L₂) rev (L₁.reverseAux (S rev)) k₁) }
    else
      { l := some (Λ'.move (fun x => false) rev k₂ q), var := o,
        stk := update (update S k₁ L₂) rev (L₁.reverseAux (S rev)) })
    { l := some q, var := none,
      stk :=
        update
          (update S k₁
            ((match (motive := Option Γ' → (List Γ' → List Γ') → (Γ' → List Γ' → List Γ') → List Γ' → List Γ') o, id,
                List.cons with
              | some x, x_1, f => f x
              | none, y, x => y)
              L₂))
          k₂ (L₁ ++ S k₂) }
tactic: simp only [TM2.step, Option.mem_def, TM2.stepAux, id_eq, ne_eq, Option.elim]
state_before: p : Γ' → Bool
k₁ k₂ : K'
q : Λ'
s : Option Γ'
L₁ : List Γ'
o : Option Γ'
L₂ : List Γ'
S : K' → List Γ'
h₁ : k₁ ≠ rev ∧ k₂ ≠ rev ∧ k₁ ≠ k₂
h₂ : S rev = []
e : splitAtPred p (S k₁) = (L₁, o, L₂)
⊢ TransGen
    (fun a b =>
      (match a with
        | { l := none, var := var, stk := stk } => none
        | { l := some l, var := v, stk := S } => some (TM2.stepAux (tr l) v S)) =
        some b)
    (bif o.isSome then
      { l := some (Λ'.move (fun x => false) rev k₂ q), var := o,
        stk :=
          update (update (update S k₁ L₂) rev (L₁.reverseAux (S rev))) k₁
            (o.iget :: update (update S k₁ L₂) rev (L₁.reverseAux (S rev)) k₁) }
    else
      { l := some (Λ'.move (fun x => false) rev k₂ q), var := o,
        stk := update (update S k₁ L₂) rev (L₁.reverseAux (S rev)) })
    { l := some q, var := none,
      stk :=
        update
          (update S k₁
            ((match (motive := Option Γ' → (List Γ' → List Γ') → (Γ' → List Γ' → List Γ') → List Γ' → List Γ') o, id,
                List.cons with
              | some x, x_1, f => f x
              | none, y, x => y)
              L₂))
          k₂ (L₁ ++ S k₂) }
state_after: case none
p : Γ' → Bool
k₁ k₂ : K'
q : Λ'
s : Option Γ'
L₁ L₂ : List Γ'
S : K' → List Γ'
h₁ : k₁ ≠ rev ∧ k₂ ≠ rev ∧ k₁ ≠ k₂
h₂ : S rev = []
e : splitAtPred p (S k₁) = (L₁, none, L₂)
⊢ TransGen
    (fun a b =>
      (match a with
        | { l := none, var := var, stk := stk } => none
        | { l := some l, var := v, stk := S } => some (TM2.stepAux (tr l) v S)) =
        some b)
    (bif none.isSome then
      { l := some (Λ'.move (fun x => false) rev k₂ q), var := none,
        stk :=
          update (update (update S k₁ L₂) rev (L₁.reverseAux (S rev))) k₁
            (none.iget :: update (update S k₁ L₂) rev (L₁.reverseAux (S rev)) k₁) }
    else
      { l := some (Λ'.move (fun x => false) rev k₂ q), var := none,
        stk := update (update S k₁ L₂) rev (L₁.reverseAux (S rev)) })
    { l := some q, var := none, stk := update (update S k₁ L₂) k₂ (L₁ ++ S k₂) }

case some
p : Γ' → Bool
k₁ k₂ : K'
q : Λ'
s : Option Γ'
L₁ L₂ : List Γ'
S : K' → List Γ'
h₁ : k₁ ≠ rev ∧ k₂ ≠ rev ∧ k₁ ≠ k₂
h₂ : S rev = []
val✝ : Γ'
e : splitAtPred p (S k₁) = (L₁, some val✝, L₂)
⊢ TransGen
    (fun a b =>
      (match a with
        | { l := none, var := var, stk := stk } => none
        | { l := some l, var := v, stk := S } => some (TM2.stepAux (tr l) v S)) =
        some b)
    (bif (some val✝).isSome then
      { l := some (Λ'.move (fun x => false) rev k₂ q), var := some val✝,
        stk :=
          update (update (update S k₁ L₂) rev (L₁.reverseAux (S rev))) k₁
            ((some val✝).iget :: update (update S k₁ L₂) rev (L₁.reverseAux (S rev)) k₁) }
    else
      { l := some (Λ'.move (fun x => false) rev k₂ q), var := some val✝,
        stk := update (update S k₁ L₂) rev (L₁.reverseAux (S rev)) })
    { l := some q, var := none, stk := update (update S k₁ (val✝ :: L₂)) k₂ (L₁ ++ S k₂) }
tactic: cases o <;> simp only [Option.elim, id]