Theorem: PFunctor.M.bisim
File: Mathlib/Data/PFunctor/Univariate/M.lean

tactic: introv h'
state_before: F : PFunctor
X : Type ?u.72703
f : X → Obj F X
P : PFunctor
α : Type u
R : M P → M P → Prop
h :
  ∀ (x y : M P),
    R x y → ∃ a f f', dest x = { fst := a, snd := f } ∧ dest y = { fst := a, snd := f' } ∧ ∀ (i : B P a), R (f i) (f' i)
⊢ ∀ (x y : M P), R x y → x = y

tactic: haveI := Inhabited.mk x.head
state_before: F : PFunctor
X : Type ?u.72703
f : X → Obj F X
P : PFunctor
α : Type u
R : M P → M P → Prop
h :
  ∀ (x y : M P),
    R x y → ∃ a f f', dest x = { fst := a, snd := f } ∧ dest y = { fst := a, snd := f' } ∧ ∀ (i : B P a), R (f i) (f' i)
x y : M P
h' : R x y
⊢ x = y

tactic: apply eq_of_bisim R _ _ _ h'
state_before: F : PFunctor
X : Type ?u.72703
f : X → Obj F X
P : PFunctor
α : Type u
R : M P → M P → Prop
h :
  ∀ (x y : M P),
    R x y → ∃ a f f', dest x = { fst := a, snd := f } ∧ dest y = { fst := a, snd := f' } ∧ ∀ (i : B P a), R (f i) (f' i)
x y : M P
h' : R x y
this : Inhabited P.A
⊢ x = y

tactic: clear h' x y
state_before: F : PFunctor
X : Type ?u.72703
f : X → Obj F X
P : PFunctor
α : Type u
R : M P → M P → Prop
h :
  ∀ (x y : M P),
    R x y → ∃ a f f', dest x = { fst := a, snd := f } ∧ dest y = { fst := a, snd := f' } ∧ ∀ (i : B P a), R (f i) (f' i)
x y : M P
h' : R x y
this : Inhabited P.A
⊢ IsBisimulation R

tactic: constructor <;> introv ih <;> rcases h _ _ ih with ⟨a'', g, g', h₀, h₁, h₂⟩ <;> clear h
state_before: F : PFunctor
X : Type ?u.72703
f : X → Obj F X
P : PFunctor
α : Type u
R : M P → M P → Prop
h :
  ∀ (x y : M P),
    R x y → ∃ a f f', dest x = { fst := a, snd := f } ∧ dest y = { fst := a, snd := f' } ∧ ∀ (i : B P a), R (f i) (f' i)
this : Inhabited P.A
⊢ IsBisimulation R

tactic: replace h₀ := congr_arg Sigma.fst h₀
state_before: case head.intro.intro.intro.intro.intro
F : PFunctor
X : Type ?u.72703
f✝ : X → Obj F X
P : PFunctor
α : Type u
R : M P → M P → Prop
this : Inhabited P.A
a a' : P.A
f : B P a → M P
f' : B P a' → M P
ih : R (M.mk { fst := a, snd := f }) (M.mk { fst := a', snd := f' })
a'' : P.A
g g' : B P a'' → M P
h₀ : dest (M.mk { fst := a, snd := f }) = { fst := a'', snd := g }
h₁ : dest (M.mk { fst := a', snd := f' }) = { fst := a'', snd := g' }
h₂ : ∀ (i : B P a''), R (g i) (g' i)
⊢ a = a'

tactic: replace h₁ := congr_arg Sigma.fst h₁
state_before: case head.intro.intro.intro.intro.intro
F : PFunctor
X : Type ?u.72703
f✝ : X → Obj F X
P : PFunctor
α : Type u
R : M P → M P → Prop
this : Inhabited P.A
a a' : P.A
f : B P a → M P
f' : B P a' → M P
ih : R (M.mk { fst := a, snd := f }) (M.mk { fst := a', snd := f' })
a'' : P.A
g g' : B P a'' → M P
h₁ : dest (M.mk { fst := a', snd := f' }) = { fst := a'', snd := g' }
h₂ : ∀ (i : B P a''), R (g i) (g' i)
h₀ : (dest (M.mk { fst := a, snd := f })).fst = { fst := a'', snd := g }.fst
⊢ a = a'

tactic: simp only [dest_mk] at h₀ h₁
state_before: case head.intro.intro.intro.intro.intro
F : PFunctor
X : Type ?u.72703
f✝ : X → Obj F X
P : PFunctor
α : Type u
R : M P → M P → Prop
this : Inhabited P.A
a a' : P.A
f : B P a → M P
f' : B P a' → M P
ih : R (M.mk { fst := a, snd := f }) (M.mk { fst := a', snd := f' })
a'' : P.A
g g' : B P a'' → M P
h₂ : ∀ (i : B P a''), R (g i) (g' i)
h₀ : (dest (M.mk { fst := a, snd := f })).fst = { fst := a'', snd := g }.fst
h₁ : (dest (M.mk { fst := a', snd := f' })).fst = { fst := a'', snd := g' }.fst
⊢ a = a'

tactic: rw [h₀, h₁]
state_before: case head.intro.intro.intro.intro.intro
F : PFunctor
X : Type ?u.72703
f✝ : X → Obj F X
P : PFunctor
α : Type u
R : M P → M P → Prop
this : Inhabited P.A
a a' : P.A
f : B P a → M P
f' : B P a' → M P
ih : R (M.mk { fst := a, snd := f }) (M.mk { fst := a', snd := f' })
a'' : P.A
g g' : B P a'' → M P
h₂ : ∀ (i : B P a''), R (g i) (g' i)
h₀ : a = a''
h₁ : a' = a''
⊢ a = a'

tactic: simp only [dest_mk] at h₀ h₁
state_before: case tail.intro.intro.intro.intro.intro
F : PFunctor
X : Type ?u.72703
f✝ : X → Obj F X
P : PFunctor
α : Type u
R : M P → M P → Prop
this : Inhabited P.A
a : P.A
f f' : B P a → M P
ih : R (M.mk { fst := a, snd := f }) (M.mk { fst := a, snd := f' })
i : B P a
a'' : P.A
g g' : B P a'' → M P
h₀ : dest (M.mk { fst := a, snd := f }) = { fst := a'', snd := g }
h₁ : dest (M.mk { fst := a, snd := f' }) = { fst := a'', snd := g' }
h₂ : ∀ (i : B P a''), R (g i) (g' i)
⊢ R (f i) (f' i)

tactic: cases h₀
state_before: case tail.intro.intro.intro.intro.intro
F : PFunctor
X : Type ?u.72703
f✝ : X → Obj F X
P : PFunctor
α : Type u
R : M P → M P → Prop
this : Inhabited P.A
a : P.A
f f' : B P a → M P
ih : R (M.mk { fst := a, snd := f }) (M.mk { fst := a, snd := f' })
i : B P a
a'' : P.A
g g' : B P a'' → M P
h₀ : { fst := a, snd := f } = { fst := a'', snd := g }
h₁ : { fst := a, snd := f' } = { fst := a'', snd := g' }
h₂ : ∀ (i : B P a''), R (g i) (g' i)
⊢ R (f i) (f' i)

tactic: cases h₁
state_before: case tail.intro.intro.intro.intro.intro.refl
F : PFunctor
X : Type ?u.72703
f✝ : X → Obj F X
P : PFunctor
α : Type u
R : M P → M P → Prop
this : Inhabited P.A
a : P.A
f f' : B P a → M P
ih : R (M.mk { fst := a, snd := f }) (M.mk { fst := a, snd := f' })
i : B P a
g' : B P a → M P
h₁ : { fst := a, snd := f' } = { fst := a, snd := g' }
h₂ : ∀ (i : B P a), R (f i) (g' i)
⊢ R (f i) (f' i)

tactic: apply h₂
state_before: case tail.intro.intro.intro.intro.intro.refl.refl
F : PFunctor
X : Type ?u.72703
f✝ : X → Obj F X
P : PFunctor
α : Type u
R : M P → M P → Prop
this : Inhabited P.A
a : P.A
f f' : B P a → M P
ih : R (M.mk { fst := a, snd := f }) (M.mk { fst := a, snd := f' })
i : B P a
h₂ : ∀ (i : B P a), R (f i) (f' i)
⊢ R (f i) (f' i)