l3lab/ntp-mathlib huggingface dataset:
theorem eval_maximal₁ {σ} {f : σ → Option σ} {a b} (h : b ∈ eval f a) (c) : ¬Reaches₁ f b c
  | bc => by
    let ⟨_, b0⟩ := mem_eval.1 h
    

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✝
left✝ : Reaches f a b
b0 : f b = none
⊢ False

Next tactic:
let ⟨b', h', _⟩ := TransGen.head'_iff.1 bc
theorem eval_maximal₁ {σ} {f : σ → Option σ} {a b} (h : b ∈ eval f a) (c) : ¬Reaches₁ f b c
  | bc => by
    let ⟨_, b0⟩ := mem_eval.1 h
    let ⟨b', h', _⟩ := TransGen.head'_iff.1 bc
    

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✝
left✝ : Reaches f a b
b0 : f b = none
b' : σ
h' : b' ∈ f b
right✝ : ReflTransGen (fun a b => b ∈ f a) b' c
⊢ False

Next tactic:
cases b0.symm.trans h'
theorem eval_maximal {σ} {f : σ → Option σ} {a b} (h : b ∈ eval f a) {c} : Reaches f b c ↔ c = b :=
  let ⟨_, b0⟩ := mem_eval.1 h
  reflTransGen_iff_eq fun b' h' ↦ by 

Proof state:
σ : Type u_1
f : σ → Option σ
a b : σ
h : b ∈ eval f a
c : σ
left✝ : Reaches f a b
b0 : f b = none
b' : σ
h' : b' ∈ f b
⊢ False

Next tactic:
cases b0.symm.trans h'
theorem reaches_eval {σ} {f : σ → Option σ} {a b} (ab : Reaches f a b) : eval f a = eval f b := by
  

Proof state:
σ : Type u_1
f : σ → Option σ
a b : σ
ab : Reaches f a b
⊢ eval f a = eval f b

Next tactic:
refine' Part.ext fun _ ↦ ⟨fun h ↦ _, fun h ↦ _⟩
theorem reaches_eval {σ} {f : σ → Option σ} {a b} (ab : Reaches f a b) : eval f a = eval f b := by
  refine' Part.ext fun _ ↦ ⟨fun h ↦ _, fun h ↦ _⟩
  · 

Proof state:
case refine'_1
σ : Type u_1
f : σ → Option σ
a b : σ
ab : Reaches f a b
x✝ : σ
h : x✝ ∈ eval f a
⊢ x✝ ∈ eval f b

Next tactic:
have ⟨ac, c0⟩ := mem_eval.1 h
theorem reaches_eval {σ} {f : σ → Option σ} {a b} (ab : Reaches f a b) : eval f a = eval f b := by
  refine' Part.ext fun _ ↦ ⟨fun h ↦ _, fun h ↦ _⟩
  · have ⟨ac, c0⟩ := mem_eval.1 h
    

Proof state:
case refine'_1
σ : Type u_1
f : σ → Option σ
a b : σ
ab : Reaches f a b
x✝ : σ
h : x✝ ∈ eval f a
ac : Reaches f a x✝
c0 : f x✝ = none
⊢ x✝ ∈ eval f b

Next tactic:
exact mem_eval.2 ⟨(or_iff_left_of_imp fun cb ↦ (eval_maximal h).1 cb ▸ ReflTransGen.refl).1
      (reaches_total ab ac), c0⟩
theorem reaches_eval {σ} {f : σ → Option σ} {a b} (ab : Reaches f a b) : eval f a = eval f b := by
  refine' Part.ext fun _ ↦ ⟨fun h ↦ _, fun h ↦ _⟩
  · have ⟨ac, c0⟩ := mem_eval.1 h
    exact mem_eval.2 ⟨(or_iff_left_of_imp fun cb ↦ (eval_maximal h).1 cb ▸ ReflTransGen.refl).1
      (reaches_total ab ac), c0⟩
  · 

Proof state:
case refine'_2
σ : Type u_1
f : σ → Option σ
a b : σ
ab : Reaches f a b
x✝ : σ
h : x✝ ∈ eval f b
⊢ x✝ ∈ eval f a

Next tactic:
have ⟨bc, c0⟩ := mem_eval.1 h
theorem reaches_eval {σ} {f : σ → Option σ} {a b} (ab : Reaches f a b) : eval f a = eval f b := by
  refine' Part.ext fun _ ↦ ⟨fun h ↦ _, fun h ↦ _⟩
  · have ⟨ac, c0⟩ := mem_eval.1 h
    exact mem_eval.2 ⟨(or_iff_left_of_imp fun cb ↦ (eval_maximal h).1 cb ▸ ReflTransGen.refl).1
      (reaches_total ab ac), c0⟩
  · have ⟨bc, c0⟩ := mem_eval.1 h
    

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

Next tactic:
exact mem_eval.2 ⟨ab.trans bc, c0⟩
theorem tr_reaches₁ {σ₁ σ₂ f₁ f₂} {tr : σ₁ → σ₂ → Prop} (H : Respects f₁ f₂ tr) {a₁ a₂}
    (aa : tr a₁ a₂) {b₁} (ab : Reaches₁ f₁ a₁ b₁) : ∃ b₂, tr b₁ b₂ ∧ Reaches₁ f₂ a₂ b₂ := by
  

Proof state:
σ₁ : Type u_1
σ₂ : Type u_2
f₁ : σ₁ → Option σ₁
f₂ : σ₂ → Option σ₂
tr : σ₁ → σ₂ → Prop
H : Respects f₁ f₂ tr
a₁ : σ₁
a₂ : σ₂
aa : tr a₁ a₂
b₁ : σ₁
ab : Reaches₁ f₁ a₁ b₁
⊢ ∃ b₂, tr b₁ b₂ ∧ Reaches₁ f₂ a₂ b₂

Next tactic:
induction' ab with c₁ ac c₁ d₁ _ cd IH
theorem tr_reaches₁ {σ₁ σ₂ f₁ f₂} {tr : σ₁ → σ₂ → Prop} (H : Respects f₁ f₂ tr) {a₁ a₂}
    (aa : tr a₁ a₂) {b₁} (ab : Reaches₁ f₁ a₁ b₁) : ∃ b₂, tr b₁ b₂ ∧ Reaches₁ f₂ a₂ b₂ := by
  induction' ab with c₁ ac c₁ d₁ _ cd IH
  · 

Proof state:
case single
σ₁ : Type u_1
σ₂ : Type u_2
f₁ : σ₁ → Option σ₁
f₂ : σ₂ → Option σ₂
tr : σ₁ → σ₂ → Prop
H : Respects f₁ f₂ tr
a₁ : σ₁
a₂ : σ₂
aa : tr a₁ a₂
b₁ c₁ : σ₁
ac : c₁ ∈ f₁ a₁
⊢ ∃ b₂, tr c₁ b₂ ∧ Reaches₁ f₂ a₂ b₂

Next tactic:
have := H aa
theorem tr_reaches₁ {σ₁ σ₂ f₁ f₂} {tr : σ₁ → σ₂ → Prop} (H : Respects f₁ f₂ tr) {a₁ a₂}
    (aa : tr a₁ a₂) {b₁} (ab : Reaches₁ f₁ a₁ b₁) : ∃ b₂, tr b₁ b₂ ∧ Reaches₁ f₂ a₂ b₂ := by
  induction' ab with c₁ ac c₁ d₁ _ cd IH
  · have := H aa
    

Proof state:
case single
σ₁ : Type u_1
σ₂ : Type u_2
f₁ : σ₁ → Option σ₁
f₂ : σ₂ → Option σ₂
tr : σ₁ → σ₂ → Prop
H : Respects f₁ f₂ tr
a₁ : σ₁
a₂ : σ₂
aa : tr a₁ a₂
b₁ c₁ : σ₁
ac : c₁ ∈ f₁ a₁
this :
  match f₁ a₁ with
  | some b₁ => ∃ b₂, tr b₁ b₂ ∧ Reaches₁ f₂ a₂ b₂
  | none => f₂ a₂ = none
⊢ ∃ b₂, tr c₁ b₂ ∧ Reaches₁ f₂ a₂ b₂

Next tactic:
rwa [show f₁ a₁ = _ from ac] at this
theorem tr_reaches₁ {σ₁ σ₂ f₁ f₂} {tr : σ₁ → σ₂ → Prop} (H : Respects f₁ f₂ tr) {a₁ a₂}
    (aa : tr a₁ a₂) {b₁} (ab : Reaches₁ f₁ a₁ b₁) : ∃ b₂, tr b₁ b₂ ∧ Reaches₁ f₂ a₂ b₂ := by
  induction' ab with c₁ ac c₁ d₁ _ cd IH
  · have := H aa
    rwa [show f₁ a₁ = _ from ac] at this
  · 

Proof state:
case tail
σ₁ : Type u_1
σ₂ : Type u_2
f₁ : σ₁ → Option σ₁
f₂ : σ₂ → Option σ₂
tr : σ₁ → σ₂ → Prop
H : Respects f₁ f₂ tr
a₁ : σ₁
a₂ : σ₂
aa : tr a₁ a₂
b₁ c₁ d₁ : σ₁
a✝ : TransGen (fun a b => b ∈ f₁ a) a₁ c₁
cd : d₁ ∈ f₁ c₁
IH : ∃ b₂, tr c₁ b₂ ∧ Reaches₁ f₂ a₂ b₂
⊢ ∃ b₂, tr d₁ b₂ ∧ Reaches₁ f₂ a₂ b₂

Next tactic:
rcases IH with ⟨c₂, cc, ac₂⟩
theorem tr_reaches₁ {σ₁ σ₂ f₁ f₂} {tr : σ₁ → σ₂ → Prop} (H : Respects f₁ f₂ tr) {a₁ a₂}
    (aa : tr a₁ a₂) {b₁} (ab : Reaches₁ f₁ a₁ b₁) : ∃ b₂, tr b₁ b₂ ∧ Reaches₁ f₂ a₂ b₂ := by
  induction' ab with c₁ ac c₁ d₁ _ cd IH
  · have := H aa
    rwa [show f₁ a₁ = _ from ac] at this
  · rcases IH with ⟨c₂, cc, ac₂⟩
    

Proof state:
case tail.intro.intro
σ₁ : Type u_1
σ₂ : Type u_2
f₁ : σ₁ → Option σ₁
f₂ : σ₂ → Option σ₂
tr : σ₁ → σ₂ → Prop
H : Respects f₁ f₂ tr
a₁ : σ₁
a₂ : σ₂
aa : tr a₁ a₂
b₁ c₁ d₁ : σ₁
a✝ : TransGen (fun a b => b ∈ f₁ a) a₁ c₁
cd : d₁ ∈ f₁ c₁
c₂ : σ₂
cc : tr c₁ c₂
ac₂ : Reaches₁ f₂ a₂ c₂
⊢ ∃ b₂, tr d₁ b₂ ∧ Reaches₁ f₂ a₂ b₂

Next tactic:
have := H cc
theorem tr_reaches₁ {σ₁ σ₂ f₁ f₂} {tr : σ₁ → σ₂ → Prop} (H : Respects f₁ f₂ tr) {a₁ a₂}
    (aa : tr a₁ a₂) {b₁} (ab : Reaches₁ f₁ a₁ b₁) : ∃ b₂, tr b₁ b₂ ∧ Reaches₁ f₂ a₂ b₂ := by
  induction' ab with c₁ ac c₁ d₁ _ cd IH
  · have := H aa
    rwa [show f₁ a₁ = _ from ac] at this
  · rcases IH with ⟨c₂, cc, ac₂⟩
    have := H cc
    

Proof state:
case tail.intro.intro
σ₁ : Type u_1
σ₂ : Type u_2
f₁ : σ₁ → Option σ₁
f₂ : σ₂ → Option σ₂
tr : σ₁ → σ₂ → Prop
H : Respects f₁ f₂ tr
a₁ : σ₁
a₂ : σ₂
aa : tr a₁ a₂
b₁ c₁ d₁ : σ₁
a✝ : TransGen (fun a b => b ∈ f₁ a) a₁ c₁
cd : d₁ ∈ f₁ c₁
c₂ : σ₂
cc : tr c₁ c₂
ac₂ : Reaches₁ f₂ a₂ c₂
this :
  match f₁ c₁ with
  | some b₁ => ∃ b₂, tr b₁ b₂ ∧ Reaches₁ f₂ c₂ b₂
  | none => f₂ c₂ = none
⊢ ∃ b₂, tr d₁ b₂ ∧ Reaches₁ f₂ a₂ b₂

Next tactic:
rw [show f₁ c₁ = _ from cd] at this
theorem tr_reaches₁ {σ₁ σ₂ f₁ f₂} {tr : σ₁ → σ₂ → Prop} (H : Respects f₁ f₂ tr) {a₁ a₂}
    (aa : tr a₁ a₂) {b₁} (ab : Reaches₁ f₁ a₁ b₁) : ∃ b₂, tr b₁ b₂ ∧ Reaches₁ f₂ a₂ b₂ := by
  induction' ab with c₁ ac c₁ d₁ _ cd IH
  · have := H aa
    rwa [show f₁ a₁ = _ from ac] at this
  · rcases IH with ⟨c₂, cc, ac₂⟩
    have := H cc
    rw [show f₁ c₁ = _ from cd] at this
    

Proof state:
case tail.intro.intro
σ₁ : Type u_1
σ₂ : Type u_2
f₁ : σ₁ → Option σ₁
f₂ : σ₂ → Option σ₂
tr : σ₁ → σ₂ → Prop
H : Respects f₁ f₂ tr
a₁ : σ₁
a₂ : σ₂
aa : tr a₁ a₂
b₁ c₁ d₁ : σ₁
a✝ : TransGen (fun a b => b ∈ f₁ a) a₁ c₁
cd : d₁ ∈ f₁ c₁
c₂ : σ₂
cc : tr c₁ c₂
ac₂ : Reaches₁ f₂ a₂ c₂
this :
  match some d₁ with
  | some b₁ => ∃ b₂, tr b₁ b₂ ∧ Reaches₁ f₂ c₂ b₂
  | none => f₂ c₂ = none
⊢ ∃ b₂, tr d₁ b₂ ∧ Reaches₁ f₂ a₂ b₂

Next tactic:
rcases this with ⟨d₂, dd, cd₂⟩
theorem tr_reaches₁ {σ₁ σ₂ f₁ f₂} {tr : σ₁ → σ₂ → Prop} (H : Respects f₁ f₂ tr) {a₁ a₂}
    (aa : tr a₁ a₂) {b₁} (ab : Reaches₁ f₁ a₁ b₁) : ∃ b₂, tr b₁ b₂ ∧ Reaches₁ f₂ a₂ b₂ := by
  induction' ab with c₁ ac c₁ d₁ _ cd IH
  · have := H aa
    rwa [show f₁ a₁ = _ from ac] at this
  · rcases IH with ⟨c₂, cc, ac₂⟩
    have := H cc
    rw [show f₁ c₁ = _ from cd] at this
    rcases this with ⟨d₂, dd, cd₂⟩
    

Proof state:
case tail.intro.intro.intro.intro
σ₁ : Type u_1
σ₂ : Type u_2
f₁ : σ₁ → Option σ₁
f₂ : σ₂ → Option σ₂
tr : σ₁ → σ₂ → Prop
H : Respects f₁ f₂ tr
a₁ : σ₁
a₂ : σ₂
aa : tr a₁ a₂
b₁ c₁ d₁ : σ₁
a✝ : TransGen (fun a b => b ∈ f₁ a) a₁ c₁
cd : d₁ ∈ f₁ c₁
c₂ : σ₂
cc : tr c₁ c₂
ac₂ : Reaches₁ f₂ a₂ c₂
d₂ : σ₂
dd : tr d₁ d₂
cd₂ : Reaches₁ f₂ c₂ d₂
⊢ ∃ b₂, tr d₁ b₂ ∧ Reaches₁ f₂ a₂ b₂

Next tactic:
exact ⟨_, dd, ac₂.trans cd₂⟩
theorem tr_reaches {σ₁ σ₂ f₁ f₂} {tr : σ₁ → σ₂ → Prop} (H : Respects f₁ f₂ tr) {a₁ a₂}
    (aa : tr a₁ a₂) {b₁} (ab : Reaches f₁ a₁ b₁) : ∃ b₂, tr b₁ b₂ ∧ Reaches f₂ a₂ b₂ := by
  

Proof state:
σ₁ : Type u_1
σ₂ : Type u_2
f₁ : σ₁ → Option σ₁
f₂ : σ₂ → Option σ₂
tr : σ₁ → σ₂ → Prop
H : Respects f₁ f₂ tr
a₁ : σ₁
a₂ : σ₂
aa : tr a₁ a₂
b₁ : σ₁
ab : Reaches f₁ a₁ b₁
⊢ ∃ b₂, tr b₁ b₂ ∧ Reaches f₂ a₂ b₂

Next tactic:
rcases reflTransGen_iff_eq_or_transGen.1 ab with (rfl | ab)
theorem tr_reaches {σ₁ σ₂ f₁ f₂} {tr : σ₁ → σ₂ → Prop} (H : Respects f₁ f₂ tr) {a₁ a₂}
    (aa : tr a₁ a₂) {b₁} (ab : Reaches f₁ a₁ b₁) : ∃ b₂, tr b₁ b₂ ∧ Reaches f₂ a₂ b₂ := by
  rcases reflTransGen_iff_eq_or_transGen.1 ab with (rfl | ab)
  · 

Proof state:
case inl
σ₁ : Type u_1
σ₂ : Type u_2
f₁ : σ₁ → Option σ₁
f₂ : σ₂ → Option σ₂
tr : σ₁ → σ₂ → Prop
H : Respects f₁ f₂ tr
a₂ : σ₂
b₁ : σ₁
aa : tr b₁ a₂
ab : Reaches f₁ b₁ b₁
⊢ ∃ b₂, tr b₁ b₂ ∧ Reaches f₂ a₂ b₂

Next tactic:
exact ⟨_, aa, ReflTransGen.refl⟩
theorem tr_reaches {σ₁ σ₂ f₁ f₂} {tr : σ₁ → σ₂ → Prop} (H : Respects f₁ f₂ tr) {a₁ a₂}
    (aa : tr a₁ a₂) {b₁} (ab : Reaches f₁ a₁ b₁) : ∃ b₂, tr b₁ b₂ ∧ Reaches f₂ a₂ b₂ := by
  rcases reflTransGen_iff_eq_or_transGen.1 ab with (rfl | ab)
  · exact ⟨_, aa, ReflTransGen.refl⟩
  · 

Proof state:
case inr
σ₁ : Type u_1
σ₂ : Type u_2
f₁ : σ₁ → Option σ₁
f₂ : σ₂ → Option σ₂
tr : σ₁ → σ₂ → Prop
H : Respects f₁ f₂ tr
a₁ : σ₁
a₂ : σ₂
aa : tr a₁ a₂
b₁ : σ₁
ab✝ : Reaches f₁ a₁ b₁
ab : TransGen (fun a b => b ∈ f₁ a) a₁ b₁
⊢ ∃ b₂, tr b₁ b₂ ∧ Reaches f₂ a₂ b₂

Next tactic:
have ⟨b₂, bb, h⟩ := tr_reaches₁ H aa ab
theorem tr_reaches {σ₁ σ₂ f₁ f₂} {tr : σ₁ → σ₂ → Prop} (H : Respects f₁ f₂ tr) {a₁ a₂}
    (aa : tr a₁ a₂) {b₁} (ab : Reaches f₁ a₁ b₁) : ∃ b₂, tr b₁ b₂ ∧ Reaches f₂ a₂ b₂ := by
  rcases reflTransGen_iff_eq_or_transGen.1 ab with (rfl | ab)
  · exact ⟨_, aa, ReflTransGen.refl⟩
  · have ⟨b₂, bb, h⟩ := tr_reaches₁ H aa ab
    

Proof state:
case inr
σ₁ : Type u_1
σ₂ : Type u_2
f₁ : σ₁ → Option σ₁
f₂ : σ₂ → Option σ₂
tr : σ₁ → σ₂ → Prop
H : Respects f₁ f₂ tr
a₁ : σ₁
a₂ : σ₂
aa : tr a₁ a₂
b₁ : σ₁
ab✝ : Reaches f₁ a₁ b₁
ab : TransGen (fun a b => b ∈ f₁ a) a₁ b₁
b₂ : σ₂
bb : tr b₁ b₂
h : Reaches₁ f₂ a₂ b₂
⊢ ∃ b₂, tr b₁ b₂ ∧ Reaches f₂ a₂ b₂

Next tactic:
exact ⟨b₂, bb, h.to_reflTransGen⟩
theorem tr_reaches_rev {σ₁ σ₂ f₁ f₂} {tr : σ₁ → σ₂ → Prop} (H : Respects f₁ f₂ tr) {a₁ a₂}
    (aa : tr a₁ a₂) {b₂} (ab : Reaches f₂ a₂ b₂) :
    ∃ c₁ c₂, Reaches f₂ b₂ c₂ ∧ tr c₁ c₂ ∧ Reaches f₁ a₁ c₁ := by
  

Proof state:
σ₁ : Type u_1
σ₂ : Type u_2
f₁ : σ₁ → Option σ₁
f₂ : σ₂ → Option σ₂
tr : σ₁ → σ₂ → Prop
H : Respects f₁ f₂ tr
a₁ : σ₁
a₂ : σ₂
aa : tr a₁ a₂
b₂ : σ₂
ab : Reaches f₂ a₂ b₂
⊢ ∃ c₁ c₂, Reaches f₂ b₂ c₂ ∧ tr c₁ c₂ ∧ Reaches f₁ a₁ c₁

Next tactic:
induction' ab with c₂ d₂ _ cd IH
theorem tr_reaches_rev {σ₁ σ₂ f₁ f₂} {tr : σ₁ → σ₂ → Prop} (H : Respects f₁ f₂ tr) {a₁ a₂}
    (aa : tr a₁ a₂) {b₂} (ab : Reaches f₂ a₂ b₂) :
    ∃ c₁ c₂, Reaches f₂ b₂ c₂ ∧ tr c₁ c₂ ∧ Reaches f₁ a₁ c₁ := by
  induction' ab with c₂ d₂ _ cd IH
  · 

Proof state:
case refl
σ₁ : Type u_1
σ₂ : Type u_2
f₁ : σ₁ → Option σ₁
f₂ : σ₂ → Option σ₂
tr : σ₁ → σ₂ → Prop
H : Respects f₁ f₂ tr
a₁ : σ₁
a₂ : σ₂
aa : tr a₁ a₂
b₂ : σ₂
⊢ ∃ c₁ c₂, Reaches f₂ a₂ c₂ ∧ tr c₁ c₂ ∧ Reaches f₁ a₁ c₁

Next tactic:
exact ⟨_, _, ReflTransGen.refl, aa, ReflTransGen.refl⟩
theorem tr_reaches_rev {σ₁ σ₂ f₁ f₂} {tr : σ₁ → σ₂ → Prop} (H : Respects f₁ f₂ tr) {a₁ a₂}
    (aa : tr a₁ a₂) {b₂} (ab : Reaches f₂ a₂ b₂) :
    ∃ c₁ c₂, Reaches f₂ b₂ c₂ ∧ tr c₁ c₂ ∧ Reaches f₁ a₁ c₁ := by
  induction' ab with c₂ d₂ _ cd IH
  · exact ⟨_, _, ReflTransGen.refl, aa, ReflTransGen.refl⟩
  · 

Proof state:
case tail
σ₁ : Type u_1
σ₂ : Type u_2
f₁ : σ₁ → Option σ₁
f₂ : σ₂ → Option σ₂
tr : σ₁ → σ₂ → Prop
H : Respects f₁ f₂ tr
a₁ : σ₁
a₂ : σ₂
aa : tr a₁ a₂
b₂ c₂ d₂ : σ₂
a✝ : ReflTransGen (fun a b => b ∈ f₂ a) a₂ c₂
cd : d₂ ∈ f₂ c₂
IH : ∃ c₁ c₂_1, Reaches f₂ c₂ c₂_1 ∧ tr c₁ c₂_1 ∧ Reaches f₁ a₁ c₁
⊢ ∃ c₁ c₂, Reaches f₂ d₂ c₂ ∧ tr c₁ c₂ ∧ Reaches f₁ a₁ c₁

Next tactic:
rcases IH with ⟨e₁, e₂, ce, ee, ae⟩
theorem tr_reaches_rev {σ₁ σ₂ f₁ f₂} {tr : σ₁ → σ₂ → Prop} (H : Respects f₁ f₂ tr) {a₁ a₂}
    (aa : tr a₁ a₂) {b₂} (ab : Reaches f₂ a₂ b₂) :
    ∃ c₁ c₂, Reaches f₂ b₂ c₂ ∧ tr c₁ c₂ ∧ Reaches f₁ a₁ c₁ := by
  induction' ab with c₂ d₂ _ cd IH
  · exact ⟨_, _, ReflTransGen.refl, aa, ReflTransGen.refl⟩
  · rcases IH with ⟨e₁, e₂, ce, ee, ae⟩
    

Proof state:
case tail.intro.intro.intro.intro
σ₁ : Type u_1
σ₂ : Type u_2
f₁ : σ₁ → Option σ₁
f₂ : σ₂ → Option σ₂
tr : σ₁ → σ₂ → Prop
H : Respects f₁ f₂ tr
a₁ : σ₁
a₂ : σ₂
aa : tr a₁ a₂
b₂ c₂ d₂ : σ₂
a✝ : ReflTransGen (fun a b => b ∈ f₂ a) a₂ c₂
cd : d₂ ∈ f₂ c₂
e₁ : σ₁
e₂ : σ₂
ce : Reaches f₂ c₂ e₂
ee : tr e₁ e₂
ae : Reaches f₁ a₁ e₁
⊢ ∃ c₁ c₂, Reaches f₂ d₂ c₂ ∧ tr c₁ c₂ ∧ Reaches f₁ a₁ c₁

Next tactic:
rcases ReflTransGen.cases_head ce with (rfl | ⟨d', cd', de⟩)
theorem tr_reaches_rev {σ₁ σ₂ f₁ f₂} {tr : σ₁ → σ₂ → Prop} (H : Respects f₁ f₂ tr) {a₁ a₂}
    (aa : tr a₁ a₂) {b₂} (ab : Reaches f₂ a₂ b₂) :
    ∃ c₁ c₂, Reaches f₂ b₂ c₂ ∧ tr c₁ c₂ ∧ Reaches f₁ a₁ c₁ := by
  induction' ab with c₂ d₂ _ cd IH
  · exact ⟨_, _, ReflTransGen.refl, aa, ReflTransGen.refl⟩
  · rcases IH with ⟨e₁, e₂, ce, ee, ae⟩
    rcases ReflTransGen.cases_head ce with (rfl | ⟨d', cd', de⟩)
    · 

Proof state:
case tail.intro.intro.intro.intro.inl
σ₁ : Type u_1
σ₂ : Type u_2
f₁ : σ₁ → Option σ₁
f₂ : σ₂ → Option σ₂
tr : σ₁ → σ₂ → Prop
H : Respects f₁ f₂ tr
a₁ : σ₁
a₂ : σ₂
aa : tr a₁ a₂
b₂ c₂ d₂ : σ₂
a✝ : ReflTransGen (fun a b => b ∈ f₂ a) a₂ c₂
cd : d₂ ∈ f₂ c₂
e₁ : σ₁
ae : Reaches f₁ a₁ e₁
ce : Reaches f₂ c₂ c₂
ee : tr e₁ c₂
⊢ ∃ c₁ c₂, Reaches f₂ d₂ c₂ ∧ tr c₁ c₂ ∧ Reaches f₁ a₁ c₁

Next tactic:
have := H ee
theorem tr_reaches_rev {σ₁ σ₂ f₁ f₂} {tr : σ₁ → σ₂ → Prop} (H : Respects f₁ f₂ tr) {a₁ a₂}
    (aa : tr a₁ a₂) {b₂} (ab : Reaches f₂ a₂ b₂) :
    ∃ c₁ c₂, Reaches f₂ b₂ c₂ ∧ tr c₁ c₂ ∧ Reaches f₁ a₁ c₁ := by
  induction' ab with c₂ d₂ _ cd IH
  · exact ⟨_, _, ReflTransGen.refl, aa, ReflTransGen.refl⟩
  · rcases IH with ⟨e₁, e₂, ce, ee, ae⟩
    rcases ReflTransGen.cases_head ce with (rfl | ⟨d', cd', de⟩)
    · have := H ee
      

Proof state:
case tail.intro.intro.intro.intro.inl
σ₁ : Type u_1
σ₂ : Type u_2
f₁ : σ₁ → Option σ₁
f₂ : σ₂ → Option σ₂
tr : σ₁ → σ₂ → Prop
H : Respects f₁ f₂ tr
a₁ : σ₁
a₂ : σ₂
aa : tr a₁ a₂
b₂ c₂ d₂ : σ₂
a✝ : ReflTransGen (fun a b => b ∈ f₂ a) a₂ c₂
cd : d₂ ∈ f₂ c₂
e₁ : σ₁
ae : Reaches f₁ a₁ e₁
ce : Reaches f₂ c₂ c₂
ee : tr e₁ c₂
this :
  match f₁ e₁ with
  | some b₁ => ∃ b₂, tr b₁ b₂ ∧ Reaches₁ f₂ c₂ b₂
  | none => f₂ c₂ = none
⊢ ∃ c₁ c₂, Reaches f₂ d₂ c₂ ∧ tr c₁ c₂ ∧ Reaches f₁ a₁ c₁

Next tactic:
revert this
theorem tr_reaches_rev {σ₁ σ₂ f₁ f₂} {tr : σ₁ → σ₂ → Prop} (H : Respects f₁ f₂ tr) {a₁ a₂}
    (aa : tr a₁ a₂) {b₂} (ab : Reaches f₂ a₂ b₂) :
    ∃ c₁ c₂, Reaches f₂ b₂ c₂ ∧ tr c₁ c₂ ∧ Reaches f₁ a₁ c₁ := by
  induction' ab with c₂ d₂ _ cd IH
  · exact ⟨_, _, ReflTransGen.refl, aa, ReflTransGen.refl⟩
  · rcases IH with ⟨e₁, e₂, ce, ee, ae⟩
    rcases ReflTransGen.cases_head ce with (rfl | ⟨d', cd', de⟩)
    · have := H ee
      revert this
      

Proof state:
case tail.intro.intro.intro.intro.inl
σ₁ : Type u_1
σ₂ : Type u_2
f₁ : σ₁ → Option σ₁
f₂ : σ₂ → Option σ₂
tr : σ₁ → σ₂ → Prop
H : Respects f₁ f₂ tr
a₁ : σ₁
a₂ : σ₂
aa : tr a₁ a₂
b₂ c₂ d₂ : σ₂
a✝ : ReflTransGen (fun a b => b ∈ f₂ a) a₂ c₂
cd : d₂ ∈ f₂ c₂
e₁ : σ₁
ae : Reaches f₁ a₁ e₁
ce : Reaches f₂ c₂ c₂
ee : tr e₁ c₂
⊢ (match f₁ e₁ with
    | some b₁ => ∃ b₂, tr b₁ b₂ ∧ Reaches₁ f₂ c₂ b₂
    | none => f₂ c₂ = none) →
    ∃ c₁ c₂, Reaches f₂ d₂ c₂ ∧ tr c₁ c₂ ∧ Reaches f₁ a₁ c₁

Next tactic:
cases' eg : f₁ e₁ with g₁
theorem tr_reaches_rev {σ₁ σ₂ f₁ f₂} {tr : σ₁ → σ₂ → Prop} (H : Respects f₁ f₂ tr) {a₁ a₂}
    (aa : tr a₁ a₂) {b₂} (ab : Reaches f₂ a₂ b₂) :
    ∃ c₁ c₂, Reaches f₂ b₂ c₂ ∧ tr c₁ c₂ ∧ Reaches f₁ a₁ c₁ := by
  induction' ab with c₂ d₂ _ cd IH
  · exact ⟨_, _, ReflTransGen.refl, aa, ReflTransGen.refl⟩
  · rcases IH with ⟨e₁, e₂, ce, ee, ae⟩
    rcases ReflTransGen.cases_head ce with (rfl | ⟨d', cd', de⟩)
    · have := H ee
      revert this
      cases' eg : f₁ e₁ with g₁ <;> 

Proof state:
case tail.intro.intro.intro.intro.inl.none
σ₁ : Type u_1
σ₂ : Type u_2
f₁ : σ₁ → Option σ₁
f₂ : σ₂ → Option σ₂
tr : σ₁ → σ₂ → Prop
H : Respects f₁ f₂ tr
a₁ : σ₁
a₂ : σ₂
aa : tr a₁ a₂
b₂ c₂ d₂ : σ₂
a✝ : ReflTransGen (fun a b => b ∈ f₂ a) a₂ c₂
cd : d₂ ∈ f₂ c₂
e₁ : σ₁
ae : Reaches f₁ a₁ e₁
ce : Reaches f₂ c₂ c₂
ee : tr e₁ c₂
eg : f₁ e₁ = none
⊢ (match none with
    | some b₁ => ∃ b₂, tr b₁ b₂ ∧ Reaches₁ f₂ c₂ b₂
    | none => f₂ c₂ = none) →
    ∃ c₁ c₂, Reaches f₂ d₂ c₂ ∧ tr c₁ c₂ ∧ Reaches f₁ a₁ c₁

Next tactic:
simp only [Respects, and_imp, exists_imp]
theorem tr_reaches_rev {σ₁ σ₂ f₁ f₂} {tr : σ₁ → σ₂ → Prop} (H : Respects f₁ f₂ tr) {a₁ a₂}
    (aa : tr a₁ a₂) {b₂} (ab : Reaches f₂ a₂ b₂) :
    ∃ c₁ c₂, Reaches f₂ b₂ c₂ ∧ tr c₁ c₂ ∧ Reaches f₁ a₁ c₁ := by
  induction' ab with c₂ d₂ _ cd IH
  · exact ⟨_, _, ReflTransGen.refl, aa, ReflTransGen.refl⟩
  · rcases IH with ⟨e₁, e₂, ce, ee, ae⟩
    rcases ReflTransGen.cases_head ce with (rfl | ⟨d', cd', de⟩)
    · have := H ee
      revert this
      cases' eg : f₁ e₁ with g₁ <;> 

Proof state:
case tail.intro.intro.intro.intro.inl.some
σ₁ : Type u_1
σ₂ : Type u_2
f₁ : σ₁ → Option σ₁
f₂ : σ₂ → Option σ₂
tr : σ₁ → σ₂ → Prop
H : Respects f₁ f₂ tr
a₁ : σ₁
a₂ : σ₂
aa : tr a₁ a₂
b₂ c₂ d₂ : σ₂
a✝ : ReflTransGen (fun a b => b ∈ f₂ a) a₂ c₂
cd : d₂ ∈ f₂ c₂
e₁ : σ₁
ae : Reaches f₁ a₁ e₁
ce : Reaches f₂ c₂ c₂
ee : tr e₁ c₂
g₁ : σ₁
eg : f₁ e₁ = some g₁
⊢ (match some g₁ with
    | some b₁ => ∃ b₂, tr b₁ b₂ ∧ Reaches₁ f₂ c₂ b₂
    | none => f₂ c₂ = none) →
    ∃ c₁ c₂, Reaches f₂ d₂ c₂ ∧ tr c₁ c₂ ∧ Reaches f₁ a₁ c₁

Next tactic:
simp only [Respects, and_imp, exists_imp]
theorem tr_reaches_rev {σ₁ σ₂ f₁ f₂} {tr : σ₁ → σ₂ → Prop} (H : Respects f₁ f₂ tr) {a₁ a₂}
    (aa : tr a₁ a₂) {b₂} (ab : Reaches f₂ a₂ b₂) :
    ∃ c₁ c₂, Reaches f₂ b₂ c₂ ∧ tr c₁ c₂ ∧ Reaches f₁ a₁ c₁ := by
  induction' ab with c₂ d₂ _ cd IH
  · exact ⟨_, _, ReflTransGen.refl, aa, ReflTransGen.refl⟩
  · rcases IH with ⟨e₁, e₂, ce, ee, ae⟩
    rcases ReflTransGen.cases_head ce with (rfl | ⟨d', cd', de⟩)
    · have := H ee
      revert this
      cases' eg : f₁ e₁ with g₁ <;> simp only [Respects, and_imp, exists_imp]
      · 

Proof state:
case tail.intro.intro.intro.intro.inl.none
σ₁ : Type u_1
σ₂ : Type u_2
f₁ : σ₁ → Option σ₁
f₂ : σ₂ → Option σ₂
tr : σ₁ → σ₂ → Prop
H : Respects f₁ f₂ tr
a₁ : σ₁
a₂ : σ₂
aa : tr a₁ a₂
b₂ c₂ d₂ : σ₂
a✝ : ReflTransGen (fun a b => b ∈ f₂ a) a₂ c₂
cd : d₂ ∈ f₂ c₂
e₁ : σ₁
ae : Reaches f₁ a₁ e₁
ce : Reaches f₂ c₂ c₂
ee : tr e₁ c₂
eg : f₁ e₁ = none
⊢ f₂ c₂ = none → ∃ c₁ c₂, Reaches f₂ d₂ c₂ ∧ tr c₁ c₂ ∧ Reaches f₁ a₁ c₁

Next tactic:
intro c0
theorem tr_reaches_rev {σ₁ σ₂ f₁ f₂} {tr : σ₁ → σ₂ → Prop} (H : Respects f₁ f₂ tr) {a₁ a₂}
    (aa : tr a₁ a₂) {b₂} (ab : Reaches f₂ a₂ b₂) :
    ∃ c₁ c₂, Reaches f₂ b₂ c₂ ∧ tr c₁ c₂ ∧ Reaches f₁ a₁ c₁ := by
  induction' ab with c₂ d₂ _ cd IH
  · exact ⟨_, _, ReflTransGen.refl, aa, ReflTransGen.refl⟩
  · rcases IH with ⟨e₁, e₂, ce, ee, ae⟩
    rcases ReflTransGen.cases_head ce with (rfl | ⟨d', cd', de⟩)
    · have := H ee
      revert this
      cases' eg : f₁ e₁ with g₁ <;> simp only [Respects, and_imp, exists_imp]
      · intro c0
        

Proof state:
case tail.intro.intro.intro.intro.inl.none
σ₁ : Type u_1
σ₂ : Type u_2
f₁ : σ₁ → Option σ₁
f₂ : σ₂ → Option σ₂
tr : σ₁ → σ₂ → Prop
H : Respects f₁ f₂ tr
a₁ : σ₁
a₂ : σ₂
aa : tr a₁ a₂
b₂ c₂ d₂ : σ₂
a✝ : ReflTransGen (fun a b => b ∈ f₂ a) a₂ c₂
cd : d₂ ∈ f₂ c₂
e₁ : σ₁
ae : Reaches f₁ a₁ e₁
ce : Reaches f₂ c₂ c₂
ee : tr e₁ c₂
eg : f₁ e₁ = none
c0 : f₂ c₂ = none
⊢ ∃ c₁ c₂, Reaches f₂ d₂ c₂ ∧ tr c₁ c₂ ∧ Reaches f₁ a₁ c₁

Next tactic:
cases cd.symm.trans c0
theorem tr_reaches_rev {σ₁ σ₂ f₁ f₂} {tr : σ₁ → σ₂ → Prop} (H : Respects f₁ f₂ tr) {a₁ a₂}
    (aa : tr a₁ a₂) {b₂} (ab : Reaches f₂ a₂ b₂) :
    ∃ c₁ c₂, Reaches f₂ b₂ c₂ ∧ tr c₁ c₂ ∧ Reaches f₁ a₁ c₁ := by
  induction' ab with c₂ d₂ _ cd IH
  · exact ⟨_, _, ReflTransGen.refl, aa, ReflTransGen.refl⟩
  · rcases IH with ⟨e₁, e₂, ce, ee, ae⟩
    rcases ReflTransGen.cases_head ce with (rfl | ⟨d', cd', de⟩)
    · have := H ee
      revert this
      cases' eg : f₁ e₁ with g₁ <;> simp only [Respects, and_imp, exists_imp]
      · intro c0
        cases cd.symm.trans c0
      · 

Proof state:
case tail.intro.intro.intro.intro.inl.some
σ₁ : Type u_1
σ₂ : Type u_2
f₁ : σ₁ → Option σ₁
f₂ : σ₂ → Option σ₂
tr : σ₁ → σ₂ → Prop
H : Respects f₁ f₂ tr
a₁ : σ₁
a₂ : σ₂
aa : tr a₁ a₂
b₂ c₂ d₂ : σ₂
a✝ : ReflTransGen (fun a b => b ∈ f₂ a) a₂ c₂
cd : d₂ ∈ f₂ c₂
e₁ : σ₁
ae : Reaches f₁ a₁ e₁
ce : Reaches f₂ c₂ c₂
ee : tr e₁ c₂
g₁ : σ₁
eg : f₁ e₁ = some g₁
⊢ ∀ (x : σ₂), tr g₁ x → Reaches₁ f₂ c₂ x → ∃ c₁ c₂, Reaches f₂ d₂ c₂ ∧ tr c₁ c₂ ∧ Reaches f₁ a₁ c₁

Next tactic:
intro g₂ gg cg
theorem tr_reaches_rev {σ₁ σ₂ f₁ f₂} {tr : σ₁ → σ₂ → Prop} (H : Respects f₁ f₂ tr) {a₁ a₂}
    (aa : tr a₁ a₂) {b₂} (ab : Reaches f₂ a₂ b₂) :
    ∃ c₁ c₂, Reaches f₂ b₂ c₂ ∧ tr c₁ c₂ ∧ Reaches f₁ a₁ c₁ := by
  induction' ab with c₂ d₂ _ cd IH
  · exact ⟨_, _, ReflTransGen.refl, aa, ReflTransGen.refl⟩
  · rcases IH with ⟨e₁, e₂, ce, ee, ae⟩
    rcases ReflTransGen.cases_head ce with (rfl | ⟨d', cd', de⟩)
    · have := H ee
      revert this
      cases' eg : f₁ e₁ with g₁ <;> simp only [Respects, and_imp, exists_imp]
      · intro c0
        cases cd.symm.trans c0
      · intro g₂ gg cg
        

Proof state:
case tail.intro.intro.intro.intro.inl.some
σ₁ : Type u_1
σ₂ : Type u_2
f₁ : σ₁ → Option σ₁
f₂ : σ₂ → Option σ₂
tr : σ₁ → σ₂ → Prop
H : Respects f₁ f₂ tr
a₁ : σ₁
a₂ : σ₂
aa : tr a₁ a₂
b₂ c₂ d₂ : σ₂
a✝ : ReflTransGen (fun a b => b ∈ f₂ a) a₂ c₂
cd : d₂ ∈ f₂ c₂
e₁ : σ₁
ae : Reaches f₁ a₁ e₁
ce : Reaches f₂ c₂ c₂
ee : tr e₁ c₂
g₁ : σ₁
eg : f₁ e₁ = some g₁
g₂ : σ₂
gg : tr g₁ g₂
cg : Reaches₁ f₂ c₂ g₂
⊢ ∃ c₁ c₂, Reaches f₂ d₂ c₂ ∧ tr c₁ c₂ ∧ Reaches f₁ a₁ c₁

Next tactic:
rcases TransGen.head'_iff.1 cg with ⟨d', cd', dg⟩
theorem tr_reaches_rev {σ₁ σ₂ f₁ f₂} {tr : σ₁ → σ₂ → Prop} (H : Respects f₁ f₂ tr) {a₁ a₂}
    (aa : tr a₁ a₂) {b₂} (ab : Reaches f₂ a₂ b₂) :
    ∃ c₁ c₂, Reaches f₂ b₂ c₂ ∧ tr c₁ c₂ ∧ Reaches f₁ a₁ c₁ := by
  induction' ab with c₂ d₂ _ cd IH
  · exact ⟨_, _, ReflTransGen.refl, aa, ReflTransGen.refl⟩
  · rcases IH with ⟨e₁, e₂, ce, ee, ae⟩
    rcases ReflTransGen.cases_head ce with (rfl | ⟨d', cd', de⟩)
    · have := H ee
      revert this
      cases' eg : f₁ e₁ with g₁ <;> simp only [Respects, and_imp, exists_imp]
      · intro c0
        cases cd.symm.trans c0
      · intro g₂ gg cg
        rcases TransGen.head'_iff.1 cg with ⟨d', cd', dg⟩
        

Proof state:
case tail.intro.intro.intro.intro.inl.some.intro.intro
σ₁ : Type u_1
σ₂ : Type u_2
f₁ : σ₁ → Option σ₁
f₂ : σ₂ → Option σ₂
tr : σ₁ → σ₂ → Prop
H : Respects f₁ f₂ tr
a₁ : σ₁
a₂ : σ₂
aa : tr a₁ a₂
b₂ c₂ d₂ : σ₂
a✝ : ReflTransGen (fun a b => b ∈ f₂ a) a₂ c₂
cd : d₂ ∈ f₂ c₂
e₁ : σ₁
ae : Reaches f₁ a₁ e₁
ce : Reaches f₂ c₂ c₂
ee : tr e₁ c₂
g₁ : σ₁
eg : f₁ e₁ = some g₁
g₂ : σ₂
gg : tr g₁ g₂
cg : Reaches₁ f₂ c₂ g₂
d' : σ₂
cd' : d' ∈ f₂ c₂
dg : ReflTransGen (fun a b => b ∈ f₂ a) d' g₂
⊢ ∃ c₁ c₂, Reaches f₂ d₂ c₂ ∧ tr c₁ c₂ ∧ Reaches f₁ a₁ c₁

Next tactic:
cases Option.mem_unique cd cd'