l3lab/ntp-mathlib huggingface dataset:
theorem Tape.map_move {Γ Γ'} [Inhabited Γ] [Inhabited Γ'] (f : PointedMap Γ Γ') (T : Tape Γ) (d) :
    (T.move d).map f = (T.map f).move d := by
  cases T
  

Proof state:
case mk
Γ : Type u_1
Γ' : Type u_2
inst✝¹ : Inhabited Γ
inst✝ : Inhabited Γ'
f : PointedMap Γ Γ'
d : Dir
head✝ : Γ
left✝ right✝ : ListBlank Γ
⊢ map f (move d { head := head✝, left := left✝, right := right✝ }) =
    move d (map f { head := head✝, left := left✝, right := right✝ })

Next tactic:
cases d
theorem Tape.map_move {Γ Γ'} [Inhabited Γ] [Inhabited Γ'] (f : PointedMap Γ Γ') (T : Tape Γ) (d) :
    (T.move d).map f = (T.map f).move d := by
  cases T
  cases d <;> 

Proof state:
case mk.left
Γ : Type u_1
Γ' : Type u_2
inst✝¹ : Inhabited Γ
inst✝ : Inhabited Γ'
f : PointedMap Γ Γ'
head✝ : Γ
left✝ right✝ : ListBlank Γ
⊢ map f (move Dir.left { head := head✝, left := left✝, right := right✝ }) =
    move Dir.left (map f { head := head✝, left := left✝, right := right✝ })

Next tactic:
simp only [Tape.move, Tape.map, ListBlank.head_map, eq_self_iff_true,
    ListBlank.map_cons, and_self_iff, ListBlank.tail_map]
theorem Tape.map_move {Γ Γ'} [Inhabited Γ] [Inhabited Γ'] (f : PointedMap Γ Γ') (T : Tape Γ) (d) :
    (T.move d).map f = (T.map f).move d := by
  cases T
  cases d <;> 

Proof state:
case mk.right
Γ : Type u_1
Γ' : Type u_2
inst✝¹ : Inhabited Γ
inst✝ : Inhabited Γ'
f : PointedMap Γ Γ'
head✝ : Γ
left✝ right✝ : ListBlank Γ
⊢ map f (move Dir.right { head := head✝, left := left✝, right := right✝ }) =
    move Dir.right (map f { head := head✝, left := left✝, right := right✝ })

Next tactic:
simp only [Tape.move, Tape.map, ListBlank.head_map, eq_self_iff_true,
    ListBlank.map_cons, and_self_iff, ListBlank.tail_map]
theorem Tape.map_mk' {Γ Γ'} [Inhabited Γ] [Inhabited Γ'] (f : PointedMap Γ Γ') (L R : ListBlank Γ) :
    (Tape.mk' L R).map f = Tape.mk' (L.map f) (R.map f) := by
  

Proof state:
Γ : Type u_1
Γ' : Type u_2
inst✝¹ : Inhabited Γ
inst✝ : Inhabited Γ'
f : PointedMap Γ Γ'
L R : ListBlank Γ
⊢ map f (mk' L R) = mk' (ListBlank.map f L) (ListBlank.map f R)

Next tactic:
simp only [Tape.mk', Tape.map, ListBlank.head_map, eq_self_iff_true, and_self_iff,
    ListBlank.tail_map]
theorem Tape.map_mk₂ {Γ Γ'} [Inhabited Γ] [Inhabited Γ'] (f : PointedMap Γ Γ') (L R : List Γ) :
    (Tape.mk₂ L R).map f = Tape.mk₂ (L.map f) (R.map f) := by
  

Proof state:
Γ : Type u_1
Γ' : Type u_2
inst✝¹ : Inhabited Γ
inst✝ : Inhabited Γ'
f : PointedMap Γ Γ'
L R : List Γ
⊢ map f (mk₂ L R) = mk₂ (List.map f.f L) (List.map f.f R)

Next tactic:
simp only [Tape.mk₂, Tape.map_mk', ListBlank.map_mk]
theorem reaches₁_eq {σ} {f : σ → Option σ} {a b c} (h : f a = f b) :
    Reaches₁ f a c ↔ Reaches₁ f b c :=
  TransGen.head'_iff.trans (TransGen.head'_iff.trans <| by 

Proof state:
σ : Type u_1
f : σ → Option σ
a b c : σ
h : f a = f b
⊢ (∃ b_1 ∈ f b, ReflTransGen (fun a b => b ∈ f a) b_1 c) ↔ ∃ b ∈ f a, ReflTransGen (fun a b => b ∈ f a) b c

Next tactic:
rw [h]
theorem reaches₁_fwd {σ} {f : σ → Option σ} {a b c} (h₁ : Reaches₁ f a c) (h₂ : b ∈ f a) :
    Reaches f b c := by
  

Proof state:
σ : Type u_1
f : σ → Option σ
a b c : σ
h₁ : Reaches₁ f a c
h₂ : b ∈ f a
⊢ Reaches f b c

Next tactic:
rcases TransGen.head'_iff.1 h₁ with ⟨b', hab, hbc⟩
theorem reaches₁_fwd {σ} {f : σ → Option σ} {a b c} (h₁ : Reaches₁ f a c) (h₂ : b ∈ f a) :
    Reaches f b c := by
  rcases TransGen.head'_iff.1 h₁ with ⟨b', hab, hbc⟩
  

Proof state:
case intro.intro
σ : Type u_1
f : σ → Option σ
a b c : σ
h₁ : Reaches₁ f a c
h₂ : b ∈ f a
b' : σ
hab : b' ∈ f a
hbc : ReflTransGen (fun a b => b ∈ f a) b' c
⊢ Reaches f b c

Next tactic:
cases Option.mem_unique hab h₂
theorem reaches₁_fwd {σ} {f : σ → Option σ} {a b c} (h₁ : Reaches₁ f a c) (h₂ : b ∈ f a) :
    Reaches f b c := by
  rcases TransGen.head'_iff.1 h₁ with ⟨b', hab, hbc⟩
  cases Option.mem_unique hab h₂; 

Proof state:
case intro.intro.refl
σ : Type u_1
f : σ → Option σ
a b c : σ
h₁ : Reaches₁ f a c
h₂ hab : b ∈ f a
hbc : ReflTransGen (fun a b => b ∈ f a) b c
⊢ Reaches f b c

Next tactic:
exact hbc
/-- (co-)Induction principle for `eval`. If a property `C` holds of any point `a` evaluating to `b`
which is either terminal (meaning `a = b`) or where the next point also satisfies `C`, then it
holds of any point where `eval f a` evaluates to `b`. This formalizes the notion that if
`eval f a` evaluates to `b` then it reaches terminal state `b` in finitely many steps. -/
@[elab_as_elim]
def evalInduction {σ} {f : σ → Option σ} {b : σ} {C : σ → Sort*} {a : σ}
    (h : b ∈ eval f a) (H : ∀ a, b ∈ eval f a → (∀ a', f a = some a' → C a') → C a) : C a :=
  PFun.fixInduction h fun a' ha' h' ↦
    H _ ha' fun b' e ↦ h' _ <| Part.mem_some_iff.2 <| by 

Proof state:
σ : Type ?u.65507
f : σ → Option σ
b : σ
C : σ → Sort u_1
a : σ
h : b ∈ eval f a
H : (a : σ) → b ∈ eval f a → ((a' : σ) → f a = some a' → C a') → C a
a' : σ
ha' : b ∈ PFun.fix (fun s => Part.some (Option.elim (f s) (Sum.inl s) Sum.inr)) a'
h' : (a'' : σ) → Sum.inr a'' ∈ Part.some (Option.elim (f a') (Sum.inl a') Sum.inr) → C a''
b' : σ
e : f a' = some b'
⊢ Sum.inr b' = Option.elim (f a') (Sum.inl a') Sum.inr

Next tactic:
rw [e]
/-- (co-)Induction principle for `eval`. If a property `C` holds of any point `a` evaluating to `b`
which is either terminal (meaning `a = b`) or where the next point also satisfies `C`, then it
holds of any point where `eval f a` evaluates to `b`. This formalizes the notion that if
`eval f a` evaluates to `b` then it reaches terminal state `b` in finitely many steps. -/
@[elab_as_elim]
def evalInduction {σ} {f : σ → Option σ} {b : σ} {C : σ → Sort*} {a : σ}
    (h : b ∈ eval f a) (H : ∀ a, b ∈ eval f a → (∀ a', f a = some a' → C a') → C a) : C a :=
  PFun.fixInduction h fun a' ha' h' ↦
    H _ ha' fun b' e ↦ h' _ <| Part.mem_some_iff.2 <| by rw [e]; 

Proof state:
σ : Type ?u.65507
f : σ → Option σ
b : σ
C : σ → Sort u_1
a : σ
h : b ∈ eval f a
H : (a : σ) → b ∈ eval f a → ((a' : σ) → f a = some a' → C a') → C a
a' : σ
ha' : b ∈ PFun.fix (fun s => Part.some (Option.elim (f s) (Sum.inl s) Sum.inr)) a'
h' : (a'' : σ) → Sum.inr a'' ∈ Part.some (Option.elim (f a') (Sum.inl a') Sum.inr) → C a''
b' : σ
e : f a' = some b'
⊢ Sum.inr b' = Option.elim (some b') (Sum.inl a') Sum.inr

Next tactic:
rfl
theorem mem_eval {σ} {f : σ → Option σ} {a b} : b ∈ eval f a ↔ Reaches f a b ∧ f b = none := by
  

Proof state:
σ : Type u_1
f : σ → Option σ
a b : σ
⊢ b ∈ eval f a ↔ Reaches f a b ∧ f b = none

Next tactic:
refine' ⟨fun h ↦ _, fun ⟨h₁, h₂⟩ ↦ _⟩
theorem mem_eval {σ} {f : σ → Option σ} {a b} : b ∈ eval f a ↔ Reaches f a b ∧ f b = none := by
  refine' ⟨fun h ↦ _, fun ⟨h₁, h₂⟩ ↦ _⟩
  · -- Porting note: Explicitly specify `c`.
    

Proof state:
case refine'_1
σ : Type u_1
f : σ → Option σ
a b : σ
h : b ∈ eval f a
⊢ Reaches f a b ∧ f b = none

Next tactic:
refine' @evalInduction _ _ _ (fun a ↦ Reaches f a b ∧ f b = none) _ h fun a h IH ↦ _
theorem mem_eval {σ} {f : σ → Option σ} {a b} : b ∈ eval f a ↔ Reaches f a b ∧ f b = none := by
  refine' ⟨fun h ↦ _, fun ⟨h₁, h₂⟩ ↦ _⟩
  · -- Porting note: Explicitly specify `c`.
    refine' @evalInduction _ _ _ (fun a ↦ Reaches f a b ∧ f b = none) _ h fun a h IH ↦ _
    

Proof state:
case refine'_1
σ : Type u_1
f : σ → Option σ
a✝ b : σ
h✝ : b ∈ eval f a✝
a : σ
h : b ∈ eval f a
IH : ∀ (a' : σ), f a = some a' → (fun a => Reaches f a b ∧ f b = none) a'
⊢ (fun a => Reaches f a b ∧ f b = none) a

Next tactic:
cases' e : f a with a'
theorem mem_eval {σ} {f : σ → Option σ} {a b} : b ∈ eval f a ↔ Reaches f a b ∧ f b = none := by
  refine' ⟨fun h ↦ _, fun ⟨h₁, h₂⟩ ↦ _⟩
  · -- Porting note: Explicitly specify `c`.
    refine' @evalInduction _ _ _ (fun a ↦ Reaches f a b ∧ f b = none) _ h fun a h IH ↦ _
    cases' e : f a with a'
    · 

Proof state:
case refine'_1.none
σ : Type u_1
f : σ → Option σ
a✝ b : σ
h✝ : b ∈ eval f a✝
a : σ
h : b ∈ eval f a
IH : ∀ (a' : σ), f a = some a' → (fun a => Reaches f a b ∧ f b = none) a'
e : f a = none
⊢ Reaches f a b ∧ f b = none

Next tactic:
rw [Part.mem_unique h
          (PFun.mem_fix_iff.2 <| Or.inl <| Part.mem_some_iff.2 <| by rw [e] <;> rfl)]
theorem mem_eval {σ} {f : σ → Option σ} {a b} : b ∈ eval f a ↔ Reaches f a b ∧ f b = none := by
  refine' ⟨fun h ↦ _, fun ⟨h₁, h₂⟩ ↦ _⟩
  · -- Porting note: Explicitly specify `c`.
    refine' @evalInduction _ _ _ (fun a ↦ Reaches f a b ∧ f b = none) _ h fun a h IH ↦ _
    cases' e : f a with a'
    · rw [Part.mem_unique h
          (PFun.mem_fix_iff.2 <| Or.inl <| Part.mem_some_iff.2 <| by 

Proof state:
σ : Type u_1
f : σ → Option σ
a✝ b : σ
h✝ : b ∈ eval f a✝
a : σ
h : b ∈ eval f a
IH : ∀ (a' : σ), f a = some a' → (fun a => Reaches f a b ∧ f b = none) a'
e : f a = none
⊢ Sum.inl ?m.66413 = Option.elim (f a) (Sum.inl a) Sum.inr

Next tactic:
rw [e]
theorem mem_eval {σ} {f : σ → Option σ} {a b} : b ∈ eval f a ↔ Reaches f a b ∧ f b = none := by
  refine' ⟨fun h ↦ _, fun ⟨h₁, h₂⟩ ↦ _⟩
  · -- Porting note: Explicitly specify `c`.
    refine' @evalInduction _ _ _ (fun a ↦ Reaches f a b ∧ f b = none) _ h fun a h IH ↦ _
    cases' e : f a with a'
    · rw [Part.mem_unique h
          (PFun.mem_fix_iff.2 <| Or.inl <| Part.mem_some_iff.2 <| by rw [e] <;> 

Proof state:
σ : Type u_1
f : σ → Option σ
a✝ b : σ
h✝ : b ∈ eval f a✝
a : σ
h : b ∈ eval f a
IH : ∀ (a' : σ), f a = some a' → (fun a => Reaches f a b ∧ f b = none) a'
e : f a = none
⊢ Sum.inl ?m.66413 = Option.elim none (Sum.inl a) Sum.inr

Next tactic:
rfl
theorem mem_eval {σ} {f : σ → Option σ} {a b} : b ∈ eval f a ↔ Reaches f a b ∧ f b = none := by
  refine' ⟨fun h ↦ _, fun ⟨h₁, h₂⟩ ↦ _⟩
  · -- Porting note: Explicitly specify `c`.
    refine' @evalInduction _ _ _ (fun a ↦ Reaches f a b ∧ f b = none) _ h fun a h IH ↦ _
    cases' e : f a with a'
    · rw [Part.mem_unique h
          (PFun.mem_fix_iff.2 <| Or.inl <| Part.mem_some_iff.2 <| by rw [e] <;> rfl)]
      

Proof state:
case refine'_1.none
σ : Type u_1
f : σ → Option σ
a✝ b : σ
h✝ : b ∈ eval f a✝
a : σ
h : b ∈ eval f a
IH : ∀ (a' : σ), f a = some a' → (fun a => Reaches f a b ∧ f b = none) a'
e : f a = none
⊢ Reaches f a a ∧ f a = none

Next tactic:
exact ⟨ReflTransGen.refl, e⟩
theorem mem_eval {σ} {f : σ → Option σ} {a b} : b ∈ eval f a ↔ Reaches f a b ∧ f b = none := by
  refine' ⟨fun h ↦ _, fun ⟨h₁, h₂⟩ ↦ _⟩
  · -- Porting note: Explicitly specify `c`.
    refine' @evalInduction _ _ _ (fun a ↦ Reaches f a b ∧ f b = none) _ h fun a h IH ↦ _
    cases' e : f a with a'
    · rw [Part.mem_unique h
          (PFun.mem_fix_iff.2 <| Or.inl <| Part.mem_some_iff.2 <| by rw [e] <;> rfl)]
      exact ⟨ReflTransGen.refl, e⟩
    · 

Proof state:
case refine'_1.some
σ : Type u_1
f : σ → Option σ
a✝ b : σ
h✝ : b ∈ eval f a✝
a : σ
h : b ∈ eval f a
IH : ∀ (a' : σ), f a = some a' → (fun a => Reaches f a b ∧ f b = none) a'
a' : σ
e : f a = some a'
⊢ Reaches f a b ∧ f b = none

Next tactic:
rcases PFun.mem_fix_iff.1 h with (h | ⟨_, h, _⟩)
theorem mem_eval {σ} {f : σ → Option σ} {a b} : b ∈ eval f a ↔ Reaches f a b ∧ f b = none := by
  refine' ⟨fun h ↦ _, fun ⟨h₁, h₂⟩ ↦ _⟩
  · -- Porting note: Explicitly specify `c`.
    refine' @evalInduction _ _ _ (fun a ↦ Reaches f a b ∧ f b = none) _ h fun a h IH ↦ _
    cases' e : f a with a'
    · rw [Part.mem_unique h
          (PFun.mem_fix_iff.2 <| Or.inl <| Part.mem_some_iff.2 <| by rw [e] <;> rfl)]
      exact ⟨ReflTransGen.refl, e⟩
    · rcases PFun.mem_fix_iff.1 h with (h | ⟨_, h, _⟩) <;> 

Proof state:
case refine'_1.some.inl
σ : Type u_1
f : σ → Option σ
a✝ b : σ
h✝¹ : b ∈ eval f a✝
a : σ
h✝ : b ∈ eval f a
IH : ∀ (a' : σ), f a = some a' → (fun a => Reaches f a b ∧ f b = none) a'
a' : σ
e : f a = some a'
h : Sum.inl b ∈ Part.some (Option.elim (f a) (Sum.inl a) Sum.inr)
⊢ Reaches f a b ∧ f b = none

Next tactic:
rw [e] at h
theorem mem_eval {σ} {f : σ → Option σ} {a b} : b ∈ eval f a ↔ Reaches f a b ∧ f b = none := by
  refine' ⟨fun h ↦ _, fun ⟨h₁, h₂⟩ ↦ _⟩
  · -- Porting note: Explicitly specify `c`.
    refine' @evalInduction _ _ _ (fun a ↦ Reaches f a b ∧ f b = none) _ h fun a h IH ↦ _
    cases' e : f a with a'
    · rw [Part.mem_unique h
          (PFun.mem_fix_iff.2 <| Or.inl <| Part.mem_some_iff.2 <| by rw [e] <;> rfl)]
      exact ⟨ReflTransGen.refl, e⟩
    · rcases PFun.mem_fix_iff.1 h with (h | ⟨_, h, _⟩) <;> 

Proof state:
case refine'_1.some.inr.intro.intro
σ : Type u_1
f : σ → Option σ
a✝ b : σ
h✝¹ : b ∈ eval f a✝
a : σ
h✝ : b ∈ eval f a
IH : ∀ (a' : σ), f a = some a' → (fun a => Reaches f a b ∧ f b = none) a'
a' : σ
e : f a = some a'
w✝ : σ
h : Sum.inr w✝ ∈ Part.some (Option.elim (f a) (Sum.inl a) Sum.inr)
right✝ : b ∈ PFun.fix (fun s => Part.some (Option.elim (f s) (Sum.inl s) Sum.inr)) w✝
⊢ Reaches f a b ∧ f b = none

Next tactic:
rw [e] at h
theorem mem_eval {σ} {f : σ → Option σ} {a b} : b ∈ eval f a ↔ Reaches f a b ∧ f b = none := by
  refine' ⟨fun h ↦ _, fun ⟨h₁, h₂⟩ ↦ _⟩
  · -- Porting note: Explicitly specify `c`.
    refine' @evalInduction _ _ _ (fun a ↦ Reaches f a b ∧ f b = none) _ h fun a h IH ↦ _
    cases' e : f a with a'
    · rw [Part.mem_unique h
          (PFun.mem_fix_iff.2 <| Or.inl <| Part.mem_some_iff.2 <| by rw [e] <;> rfl)]
      exact ⟨ReflTransGen.refl, e⟩
    · rcases PFun.mem_fix_iff.1 h with (h | ⟨_, h, _⟩) <;> rw [e] at h <;>
        

Proof state:
case refine'_1.some.inl
σ : Type u_1
f : σ → Option σ
a✝ b : σ
h✝¹ : b ∈ eval f a✝
a : σ
h✝ : b ∈ eval f a
IH : ∀ (a' : σ), f a = some a' → (fun a => Reaches f a b ∧ f b = none) a'
a' : σ
e : f a = some a'
h : Sum.inl b ∈ Part.some (Option.elim (some a') (Sum.inl a) Sum.inr)
⊢ Reaches f a b ∧ f b = none

Next tactic:
cases Part.mem_some_iff.1 h
theorem mem_eval {σ} {f : σ → Option σ} {a b} : b ∈ eval f a ↔ Reaches f a b ∧ f b = none := by
  refine' ⟨fun h ↦ _, fun ⟨h₁, h₂⟩ ↦ _⟩
  · -- Porting note: Explicitly specify `c`.
    refine' @evalInduction _ _ _ (fun a ↦ Reaches f a b ∧ f b = none) _ h fun a h IH ↦ _
    cases' e : f a with a'
    · rw [Part.mem_unique h
          (PFun.mem_fix_iff.2 <| Or.inl <| Part.mem_some_iff.2 <| by rw [e] <;> rfl)]
      exact ⟨ReflTransGen.refl, e⟩
    · rcases PFun.mem_fix_iff.1 h with (h | ⟨_, h, _⟩) <;> rw [e] at h <;>
        

Proof state:
case refine'_1.some.inr.intro.intro
σ : Type u_1
f : σ → Option σ
a✝ b : σ
h✝¹ : b ∈ eval f a✝
a : σ
h✝ : b ∈ eval f a
IH : ∀ (a' : σ), f a = some a' → (fun a => Reaches f a b ∧ f b = none) a'
a' : σ
e : f a = some a'
w✝ : σ
h : Sum.inr w✝ ∈ Part.some (Option.elim (some a') (Sum.inl a) Sum.inr)
right✝ : b ∈ PFun.fix (fun s => Part.some (Option.elim (f s) (Sum.inl s) Sum.inr)) w✝
⊢ Reaches f a b ∧ f b = none

Next tactic:
cases Part.mem_some_iff.1 h
theorem mem_eval {σ} {f : σ → Option σ} {a b} : b ∈ eval f a ↔ Reaches f a b ∧ f b = none := by
  refine' ⟨fun h ↦ _, fun ⟨h₁, h₂⟩ ↦ _⟩
  · -- Porting note: Explicitly specify `c`.
    refine' @evalInduction _ _ _ (fun a ↦ Reaches f a b ∧ f b = none) _ h fun a h IH ↦ _
    cases' e : f a with a'
    · rw [Part.mem_unique h
          (PFun.mem_fix_iff.2 <| Or.inl <| Part.mem_some_iff.2 <| by rw [e] <;> rfl)]
      exact ⟨ReflTransGen.refl, e⟩
    · rcases PFun.mem_fix_iff.1 h with (h | ⟨_, h, _⟩) <;> rw [e] at h <;>
        cases Part.mem_some_iff.1 h
      

Proof state:
case refine'_1.some.inr.intro.intro.refl
σ : Type u_1
f : σ → Option σ
a✝ b : σ
h✝¹ : b ∈ eval f a✝
a : σ
h✝ : b ∈ eval f a
IH : ∀ (a' : σ), f a = some a' → (fun a => Reaches f a b ∧ f b = none) a'
a' : σ
e : f a = some a'
h : Sum.inr a' ∈ Part.some (Option.elim (some a') (Sum.inl a) Sum.inr)
right✝ : b ∈ PFun.fix (fun s => Part.some (Option.elim (f s) (Sum.inl s) Sum.inr)) a'
⊢ Reaches f a b ∧ f b = none

Next tactic:
cases' IH a' e with h₁ h₂
theorem mem_eval {σ} {f : σ → Option σ} {a b} : b ∈ eval f a ↔ Reaches f a b ∧ f b = none := by
  refine' ⟨fun h ↦ _, fun ⟨h₁, h₂⟩ ↦ _⟩
  · -- Porting note: Explicitly specify `c`.
    refine' @evalInduction _ _ _ (fun a ↦ Reaches f a b ∧ f b = none) _ h fun a h IH ↦ _
    cases' e : f a with a'
    · rw [Part.mem_unique h
          (PFun.mem_fix_iff.2 <| Or.inl <| Part.mem_some_iff.2 <| by rw [e] <;> rfl)]
      exact ⟨ReflTransGen.refl, e⟩
    · rcases PFun.mem_fix_iff.1 h with (h | ⟨_, h, _⟩) <;> rw [e] at h <;>
        cases Part.mem_some_iff.1 h
      cases' IH a' e with h₁ h₂
      

Proof state:
case refine'_1.some.inr.intro.intro.refl.intro
σ : Type u_1
f : σ → Option σ
a✝ b : σ
h✝¹ : b ∈ eval f a✝
a : σ
h✝ : b ∈ eval f a
IH : ∀ (a' : σ), f a = some a' → (fun a => Reaches f a b ∧ f b = none) a'
a' : σ
e : f a = some a'
h : Sum.inr a' ∈ Part.some (Option.elim (some a') (Sum.inl a) Sum.inr)
right✝ : b ∈ PFun.fix (fun s => Part.some (Option.elim (f s) (Sum.inl s) Sum.inr)) a'
h₁ : Reaches f a' b
h₂ : f b = none
⊢ Reaches f a b ∧ f b = none

Next tactic:
exact ⟨ReflTransGen.head e h₁, h₂⟩
theorem mem_eval {σ} {f : σ → Option σ} {a b} : b ∈ eval f a ↔ Reaches f a b ∧ f b = none := by
  refine' ⟨fun h ↦ _, fun ⟨h₁, h₂⟩ ↦ _⟩
  · -- Porting note: Explicitly specify `c`.
    refine' @evalInduction _ _ _ (fun a ↦ Reaches f a b ∧ f b = none) _ h fun a h IH ↦ _
    cases' e : f a with a'
    · rw [Part.mem_unique h
          (PFun.mem_fix_iff.2 <| Or.inl <| Part.mem_some_iff.2 <| by rw [e] <;> rfl)]
      exact ⟨ReflTransGen.refl, e⟩
    · rcases PFun.mem_fix_iff.1 h with (h | ⟨_, h, _⟩) <;> rw [e] at h <;>
        cases Part.mem_some_iff.1 h
      cases' IH a' e with h₁ h₂
      exact ⟨ReflTransGen.head e h₁, h₂⟩
  · 

Proof state:
case refine'_2
σ : Type u_1
f : σ → Option σ
a b : σ
x✝ : Reaches f a b ∧ f b = none
h₁ : Reaches f a b
h₂ : f b = none
⊢ b ∈ eval f a

Next tactic:
refine' ReflTransGen.head_induction_on h₁ _ fun h _ IH ↦ _
theorem mem_eval {σ} {f : σ → Option σ} {a b} : b ∈ eval f a ↔ Reaches f a b ∧ f b = none := by
  refine' ⟨fun h ↦ _, fun ⟨h₁, h₂⟩ ↦ _⟩
  · -- Porting note: Explicitly specify `c`.
    refine' @evalInduction _ _ _ (fun a ↦ Reaches f a b ∧ f b = none) _ h fun a h IH ↦ _
    cases' e : f a with a'
    · rw [Part.mem_unique h
          (PFun.mem_fix_iff.2 <| Or.inl <| Part.mem_some_iff.2 <| by rw [e] <;> rfl)]
      exact ⟨ReflTransGen.refl, e⟩
    · rcases PFun.mem_fix_iff.1 h with (h | ⟨_, h, _⟩) <;> rw [e] at h <;>
        cases Part.mem_some_iff.1 h
      cases' IH a' e with h₁ h₂
      exact ⟨ReflTransGen.head e h₁, h₂⟩
  · refine' ReflTransGen.head_induction_on h₁ _ fun h _ IH ↦ _
    · 

Proof state:
case refine'_2.refine'_1
σ : Type u_1
f : σ → Option σ
a b : σ
x✝ : Reaches f a b ∧ f b = none
h₁ : Reaches f a b
h₂ : f b = none
⊢ b ∈ eval f b

Next tactic:
refine' PFun.mem_fix_iff.2 (Or.inl _)
theorem mem_eval {σ} {f : σ → Option σ} {a b} : b ∈ eval f a ↔ Reaches f a b ∧ f b = none := by
  refine' ⟨fun h ↦ _, fun ⟨h₁, h₂⟩ ↦ _⟩
  · -- Porting note: Explicitly specify `c`.
    refine' @evalInduction _ _ _ (fun a ↦ Reaches f a b ∧ f b = none) _ h fun a h IH ↦ _
    cases' e : f a with a'
    · rw [Part.mem_unique h
          (PFun.mem_fix_iff.2 <| Or.inl <| Part.mem_some_iff.2 <| by rw [e] <;> rfl)]
      exact ⟨ReflTransGen.refl, e⟩
    · rcases PFun.mem_fix_iff.1 h with (h | ⟨_, h, _⟩) <;> rw [e] at h <;>
        cases Part.mem_some_iff.1 h
      cases' IH a' e with h₁ h₂
      exact ⟨ReflTransGen.head e h₁, h₂⟩
  · refine' ReflTransGen.head_induction_on h₁ _ fun h _ IH ↦ _
    · refine' PFun.mem_fix_iff.2 (Or.inl _)
      

Proof state:
case refine'_2.refine'_1
σ : Type u_1
f : σ → Option σ
a b : σ
x✝ : Reaches f a b ∧ f b = none
h₁ : Reaches f a b
h₂ : f b = none
⊢ Sum.inl b ∈ Part.some (Option.elim (f b) (Sum.inl b) Sum.inr)

Next tactic:
rw [h₂]
theorem mem_eval {σ} {f : σ → Option σ} {a b} : b ∈ eval f a ↔ Reaches f a b ∧ f b = none := by
  refine' ⟨fun h ↦ _, fun ⟨h₁, h₂⟩ ↦ _⟩
  · -- Porting note: Explicitly specify `c`.
    refine' @evalInduction _ _ _ (fun a ↦ Reaches f a b ∧ f b = none) _ h fun a h IH ↦ _
    cases' e : f a with a'
    · rw [Part.mem_unique h
          (PFun.mem_fix_iff.2 <| Or.inl <| Part.mem_some_iff.2 <| by rw [e] <;> rfl)]
      exact ⟨ReflTransGen.refl, e⟩
    · rcases PFun.mem_fix_iff.1 h with (h | ⟨_, h, _⟩) <;> rw [e] at h <;>
        cases Part.mem_some_iff.1 h
      cases' IH a' e with h₁ h₂
      exact ⟨ReflTransGen.head e h₁, h₂⟩
  · refine' ReflTransGen.head_induction_on h₁ _ fun h _ IH ↦ _
    · refine' PFun.mem_fix_iff.2 (Or.inl _)
      rw [h₂]
      

Proof state:
case refine'_2.refine'_1
σ : Type u_1
f : σ → Option σ
a b : σ
x✝ : Reaches f a b ∧ f b = none
h₁ : Reaches f a b
h₂ : f b = none
⊢ Sum.inl b ∈ Part.some (Option.elim none (Sum.inl b) Sum.inr)

Next tactic:
apply Part.mem_some
theorem mem_eval {σ} {f : σ → Option σ} {a b} : b ∈ eval f a ↔ Reaches f a b ∧ f b = none := by
  refine' ⟨fun h ↦ _, fun ⟨h₁, h₂⟩ ↦ _⟩
  · -- Porting note: Explicitly specify `c`.
    refine' @evalInduction _ _ _ (fun a ↦ Reaches f a b ∧ f b = none) _ h fun a h IH ↦ _
    cases' e : f a with a'
    · rw [Part.mem_unique h
          (PFun.mem_fix_iff.2 <| Or.inl <| Part.mem_some_iff.2 <| by rw [e] <;> rfl)]
      exact ⟨ReflTransGen.refl, e⟩
    · rcases PFun.mem_fix_iff.1 h with (h | ⟨_, h, _⟩) <;> rw [e] at h <;>
        cases Part.mem_some_iff.1 h
      cases' IH a' e with h₁ h₂
      exact ⟨ReflTransGen.head e h₁, h₂⟩
  · refine' ReflTransGen.head_induction_on h₁ _ fun h _ IH ↦ _
    · refine' PFun.mem_fix_iff.2 (Or.inl _)
      rw [h₂]
      apply Part.mem_some
    · 

Proof state:
case refine'_2.refine'_2
σ : Type u_1
f : σ → Option σ
a b : σ
x✝¹ : Reaches f a b ∧ f b = none
h₁ : Reaches f a b
h₂ : f b = none
a✝ c✝ : σ
h : c✝ ∈ f a✝
x✝ : ReflTransGen (fun a b => b ∈ f a) c✝ b
IH : b ∈ eval f c✝
⊢ b ∈ eval f a✝

Next tactic:
refine' PFun.mem_fix_iff.2 (Or.inr ⟨_, _, IH⟩)
theorem mem_eval {σ} {f : σ → Option σ} {a b} : b ∈ eval f a ↔ Reaches f a b ∧ f b = none := by
  refine' ⟨fun h ↦ _, fun ⟨h₁, h₂⟩ ↦ _⟩
  · -- Porting note: Explicitly specify `c`.
    refine' @evalInduction _ _ _ (fun a ↦ Reaches f a b ∧ f b = none) _ h fun a h IH ↦ _
    cases' e : f a with a'
    · rw [Part.mem_unique h
          (PFun.mem_fix_iff.2 <| Or.inl <| Part.mem_some_iff.2 <| by rw [e] <;> rfl)]
      exact ⟨ReflTransGen.refl, e⟩
    · rcases PFun.mem_fix_iff.1 h with (h | ⟨_, h, _⟩) <;> rw [e] at h <;>
        cases Part.mem_some_iff.1 h
      cases' IH a' e with h₁ h₂
      exact ⟨ReflTransGen.head e h₁, h₂⟩
  · refine' ReflTransGen.head_induction_on h₁ _ fun h _ IH ↦ _
    · refine' PFun.mem_fix_iff.2 (Or.inl _)
      rw [h₂]
      apply Part.mem_some
    · refine' PFun.mem_fix_iff.2 (Or.inr ⟨_, _, IH⟩)
      

Proof state:
case refine'_2.refine'_2
σ : Type u_1
f : σ → Option σ
a b : σ
x✝¹ : Reaches f a b ∧ f b = none
h₁ : Reaches f a b
h₂ : f b = none
a✝ c✝ : σ
h : c✝ ∈ f a✝
x✝ : ReflTransGen (fun a b => b ∈ f a) c✝ b
IH : b ∈ eval f c✝
⊢ Sum.inr c✝ ∈ Part.some (Option.elim (f a✝) (Sum.inl a✝) Sum.inr)

Next tactic:
rw [h]
theorem mem_eval {σ} {f : σ → Option σ} {a b} : b ∈ eval f a ↔ Reaches f a b ∧ f b = none := by
  refine' ⟨fun h ↦ _, fun ⟨h₁, h₂⟩ ↦ _⟩
  · -- Porting note: Explicitly specify `c`.
    refine' @evalInduction _ _ _ (fun a ↦ Reaches f a b ∧ f b = none) _ h fun a h IH ↦ _
    cases' e : f a with a'
    · rw [Part.mem_unique h
          (PFun.mem_fix_iff.2 <| Or.inl <| Part.mem_some_iff.2 <| by rw [e] <;> rfl)]
      exact ⟨ReflTransGen.refl, e⟩
    · rcases PFun.mem_fix_iff.1 h with (h | ⟨_, h, _⟩) <;> rw [e] at h <;>
        cases Part.mem_some_iff.1 h
      cases' IH a' e with h₁ h₂
      exact ⟨ReflTransGen.head e h₁, h₂⟩
  · refine' ReflTransGen.head_induction_on h₁ _ fun h _ IH ↦ _
    · refine' PFun.mem_fix_iff.2 (Or.inl _)
      rw [h₂]
      apply Part.mem_some
    · refine' PFun.mem_fix_iff.2 (Or.inr ⟨_, _, IH⟩)
      rw [h]
      

Proof state:
case refine'_2.refine'_2
σ : Type u_1
f : σ → Option σ
a b : σ
x✝¹ : Reaches f a b ∧ f b = none
h₁ : Reaches f a b
h₂ : f b = none
a✝ c✝ : σ
h : c✝ ∈ f a✝
x✝ : ReflTransGen (fun a b => b ∈ f a) c✝ b
IH : b ∈ eval f c✝
⊢ Sum.inr c✝ ∈ Part.some (Option.elim (some c✝) (Sum.inl a✝) Sum.inr)

Next tactic:
apply Part.mem_some
theorem eval_maximal₁ {σ} {f : σ → Option σ} {a b} (h : b ∈ eval f a) (c) : ¬Reaches₁ f b c
  | bc => by
    

Proof state:
σ : Type u_1
f : σ → Option σ
a b : σ
h : b ∈ eval f a
c : σ
x✝ : Reaches₁ f b c
bc : Reaches₁ f b c := x✝
⊢ False

Next tactic:
let ⟨_, b0⟩ := mem_eval.1 h