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

tactic: intro h₀ hh
state_before: F : PFunctor
X : Type ?u.60946
f : X → Obj F X
R : M F → M F → Prop
inst✝ : Inhabited (M F)
bisim : IsBisimulation R
s₁ s₂ : M F
ps : Path F
⊢ R s₁ s₂ →
    IsPath ps s₁ ∨ IsPath ps s₂ →
      iselect ps s₁ = iselect ps s₂ ∧
        ∃ a f f',
          isubtree ps s₁ = M.mk { fst := a, snd := f } ∧
            isubtree ps s₂ = M.mk { fst := a, snd := f' } ∧ ∀ (i : B F a), R (f i) (f' i)

tactic: induction' s₁ using PFunctor.M.casesOn' with a f
state_before: F : PFunctor
X : Type ?u.60946
f : X → Obj F X
R : M F → M F → Prop
inst✝ : Inhabited (M F)
bisim : IsBisimulation R
s₁ s₂ : M F
ps : Path F
h₀ : R s₁ s₂
hh : IsPath ps s₁ ∨ IsPath ps s₂
⊢ iselect ps s₁ = iselect ps s₂ ∧
    ∃ a f f',
      isubtree ps s₁ = M.mk { fst := a, snd := f } ∧
        isubtree ps s₂ = M.mk { fst := a, snd := f' } ∧ ∀ (i : B F a), R (f i) (f' i)

tactic: rename_i h₁ hh₁
state_before: case f
F : PFunctor
X : Type ?u.60946
f✝ : X → Obj F X
R : M F → M F → Prop
inst✝ : Inhabited (M F)
bisim : IsBisimulation R
s₁ s₂ : M F
ps : Path F
h₀✝ : R s₁ s₂
hh✝ : IsPath ps s₁ ∨ IsPath ps s₂
a : F.A
f : B F a → M F
h₀ : R (M.mk { fst := a, snd := f }) s₂
hh : IsPath ps (M.mk { fst := a, snd := f }) ∨ IsPath ps s₂
⊢ iselect ps (M.mk { fst := a, snd := f }) = iselect ps s₂ ∧
    ∃ a_1 f_1 f',
      isubtree ps (M.mk { fst := a, snd := f }) = M.mk { fst := a_1, snd := f_1 } ∧
        isubtree ps s₂ = M.mk { fst := a_1, snd := f' } ∧ ∀ (i : B F a_1), R (f_1 i) (f' i)

tactic: induction' s₂ using PFunctor.M.casesOn' with a' f'
state_before: case f
F : PFunctor
X : Type ?u.60946
f✝ : X → Obj F X
R : M F → M F → Prop
inst✝ : Inhabited (M F)
bisim : IsBisimulation R
s₁ s₂ : M F
ps : Path F
h₁ : R s₁ s₂
hh₁ : IsPath ps s₁ ∨ IsPath ps s₂
a : F.A
f : B F a → M F
h₀ : R (M.mk { fst := a, snd := f }) s₂
hh : IsPath ps (M.mk { fst := a, snd := f }) ∨ IsPath ps s₂
⊢ iselect ps (M.mk { fst := a, snd := f }) = iselect ps s₂ ∧
    ∃ a_1 f_1 f',
      isubtree ps (M.mk { fst := a, snd := f }) = M.mk { fst := a_1, snd := f_1 } ∧
        isubtree ps s₂ = M.mk { fst := a_1, snd := f' } ∧ ∀ (i : B F a_1), R (f_1 i) (f' i)

tactic: rename_i h₁' hh₁' h₂ hh₂
state_before: case f.f
F : PFunctor
X : Type ?u.60946
f✝ : X → Obj F X
R : M F → M F → Prop
inst✝ : Inhabited (M F)
bisim : IsBisimulation R
s₁ s₂ : M F
ps : Path F
h₁✝ : R s₁ s₂
hh₁✝ : IsPath ps s₁ ∨ IsPath ps s₂
a : F.A
f : B F a → M F
h₀✝ : R (M.mk { fst := a, snd := f }) s₂
hh✝ : IsPath ps (M.mk { fst := a, snd := f }) ∨ IsPath ps s₂
a' : F.A
f' : B F a' → M F
h₁ : R s₁ (M.mk { fst := a', snd := f' })
hh₁ : IsPath ps s₁ ∨ IsPath ps (M.mk { fst := a', snd := f' })
h₀ : R (M.mk { fst := a, snd := f }) (M.mk { fst := a', snd := f' })
hh : IsPath ps (M.mk { fst := a, snd := f }) ∨ IsPath ps (M.mk { fst := a', snd := f' })
⊢ iselect ps (M.mk { fst := a, snd := f }) = iselect ps (M.mk { fst := a', snd := f' }) ∧
    ∃ a_1 f_1 f'_1,
      isubtree ps (M.mk { fst := a, snd := f }) = M.mk { fst := a_1, snd := f_1 } ∧
        isubtree ps (M.mk { fst := a', snd := f' }) = M.mk { fst := a_1, snd := f'_1 } ∧
          ∀ (i : B F a_1), R (f_1 i) (f'_1 i)

tactic: clear h₁ hh₁ h₂ hh₂ hh₁'
state_before: case f.f
F : PFunctor
X : Type ?u.60946
f✝ : X → Obj F X
R : M F → M F → Prop
inst✝ : Inhabited (M F)
bisim : IsBisimulation R
s₁ s₂ : M F
ps : Path F
h₁' : R s₁ s₂
hh₁' : IsPath ps s₁ ∨ IsPath ps s₂
a : F.A
f : B F a → M F
h₂ : R (M.mk { fst := a, snd := f }) s₂
hh₂ : IsPath ps (M.mk { fst := a, snd := f }) ∨ IsPath ps s₂
a' : F.A
f' : B F a' → M F
h₁ : R s₁ (M.mk { fst := a', snd := f' })
hh₁ : IsPath ps s₁ ∨ IsPath ps (M.mk { fst := a', snd := f' })
h₀ : R (M.mk { fst := a, snd := f }) (M.mk { fst := a', snd := f' })
hh : IsPath ps (M.mk { fst := a, snd := f }) ∨ IsPath ps (M.mk { fst := a', snd := f' })
⊢ iselect ps (M.mk { fst := a, snd := f }) = iselect ps (M.mk { fst := a', snd := f' }) ∧
    ∃ a_1 f_1 f'_1,
      isubtree ps (M.mk { fst := a, snd := f }) = M.mk { fst := a_1, snd := f_1 } ∧
        isubtree ps (M.mk { fst := a', snd := f' }) = M.mk { fst := a_1, snd := f'_1 } ∧
          ∀ (i : B F a_1), R (f_1 i) (f'_1 i)

tactic: obtain rfl : a = a' := bisim.head h₀
state_before: case f.f
F : PFunctor
X : Type ?u.60946
f✝ : X → Obj F X
R : M F → M F → Prop
inst✝ : Inhabited (M F)
bisim : IsBisimulation R
s₁ s₂ : M F
ps : Path F
h₁' : R s₁ s₂
a : F.A
f : B F a → M F
a' : F.A
f' : B F a' → M F
h₀ : R (M.mk { fst := a, snd := f }) (M.mk { fst := a', snd := f' })
hh : IsPath ps (M.mk { fst := a, snd := f }) ∨ IsPath ps (M.mk { fst := a', snd := f' })
⊢ iselect ps (M.mk { fst := a, snd := f }) = iselect ps (M.mk { fst := a', snd := f' }) ∧
    ∃ a_1 f_1 f'_1,
      isubtree ps (M.mk { fst := a, snd := f }) = M.mk { fst := a_1, snd := f_1 } ∧
        isubtree ps (M.mk { fst := a', snd := f' }) = M.mk { fst := a_1, snd := f'_1 } ∧
          ∀ (i : B F a_1), R (f_1 i) (f'_1 i)

tactic: induction' ps with i ps ps_ih generalizing a f f'
state_before: case f.f
F : PFunctor
X : Type ?u.60946
f✝ : X → Obj F X
R : M F → M F → Prop
inst✝ : Inhabited (M F)
bisim : IsBisimulation R
s₁ s₂ : M F
ps : Path F
h₁' : R s₁ s₂
a : F.A
f f' : B F a → M F
h₀ : R (M.mk { fst := a, snd := f }) (M.mk { fst := a, snd := f' })
hh : IsPath ps (M.mk { fst := a, snd := f }) ∨ IsPath ps (M.mk { fst := a, snd := f' })
⊢ iselect ps (M.mk { fst := a, snd := f }) = iselect ps (M.mk { fst := a, snd := f' }) ∧
    ∃ a_1 f_1 f'_1,
      isubtree ps (M.mk { fst := a, snd := f }) = M.mk { fst := a_1, snd := f_1 } ∧
        isubtree ps (M.mk { fst := a, snd := f' }) = M.mk { fst := a_1, snd := f'_1 } ∧
          ∀ (i : B F a_1), R (f_1 i) (f'_1 i)

tactic: cases' i with a' i
state_before: case f.f.cons
F : PFunctor
X : Type ?u.60946
f✝¹ : X → Obj F X
R : M F → M F → Prop
inst✝ : Inhabited (M F)
bisim : IsBisimulation R
s₁ s₂ : M F
ps✝ : Path F
h₁' : R s₁ s₂
a✝ : F.A
f✝ f'✝ : B F a✝ → M F
h₀✝ : R (M.mk { fst := a✝, snd := f✝ }) (M.mk { fst := a✝, snd := f'✝ })
hh✝ : IsPath ps✝ (M.mk { fst := a✝, snd := f✝ }) ∨ IsPath ps✝ (M.mk { fst := a✝, snd := f'✝ })
i : IdxCat F
ps : List (IdxCat F)
ps_ih :
  ∀ (a : F.A) (f f' : B F a → M F),
    R (M.mk { fst := a, snd := f }) (M.mk { fst := a, snd := f' }) →
      IsPath ps (M.mk { fst := a, snd := f }) ∨ IsPath ps (M.mk { fst := a, snd := f' }) →
        iselect ps (M.mk { fst := a, snd := f }) = iselect ps (M.mk { fst := a, snd := f' }) ∧
          ∃ a_1 f_1 f'_1,
            isubtree ps (M.mk { fst := a, snd := f }) = M.mk { fst := a_1, snd := f_1 } ∧
              isubtree ps (M.mk { fst := a, snd := f' }) = M.mk { fst := a_1, snd := f'_1 } ∧
                ∀ (i : B F a_1), R (f_1 i) (f'_1 i)
a : F.A
f f' : B F a → M F
h₀ : R (M.mk { fst := a, snd := f }) (M.mk { fst := a, snd := f' })
hh : IsPath (i :: ps) (M.mk { fst := a, snd := f }) ∨ IsPath (i :: ps) (M.mk { fst := a, snd := f' })
⊢ iselect (i :: ps) (M.mk { fst := a, snd := f }) = iselect (i :: ps) (M.mk { fst := a, snd := f' }) ∧
    ∃ a_1 f_1 f'_1,
      isubtree (i :: ps) (M.mk { fst := a, snd := f }) = M.mk { fst := a_1, snd := f_1 } ∧
        isubtree (i :: ps) (M.mk { fst := a, snd := f' }) = M.mk { fst := a_1, snd := f'_1 } ∧
          ∀ (i : B F a_1), R (f_1 i) (f'_1 i)

tactic: obtain rfl : a = a' := by rcases hh with hh|hh <;> cases isPath_cons hh <;> rfl
state_before: case f.f.cons.mk
F : PFunctor
X : Type ?u.60946
f✝¹ : X → Obj F X
R : M F → M F → Prop
inst✝ : Inhabited (M F)
bisim : IsBisimulation R
s₁ s₂ : M F
ps✝ : Path F
h₁' : R s₁ s₂
a✝ : F.A
f✝ f'✝ : B F a✝ → M F
h₀✝ : R (M.mk { fst := a✝, snd := f✝ }) (M.mk { fst := a✝, snd := f'✝ })
hh✝ : IsPath ps✝ (M.mk { fst := a✝, snd := f✝ }) ∨ IsPath ps✝ (M.mk { fst := a✝, snd := f'✝ })
ps : List (IdxCat F)
ps_ih :
  ∀ (a : F.A) (f f' : B F a → M F),
    R (M.mk { fst := a, snd := f }) (M.mk { fst := a, snd := f' }) →
      IsPath ps (M.mk { fst := a, snd := f }) ∨ IsPath ps (M.mk { fst := a, snd := f' }) →
        iselect ps (M.mk { fst := a, snd := f }) = iselect ps (M.mk { fst := a, snd := f' }) ∧
          ∃ a_1 f_1 f'_1,
            isubtree ps (M.mk { fst := a, snd := f }) = M.mk { fst := a_1, snd := f_1 } ∧
              isubtree ps (M.mk { fst := a, snd := f' }) = M.mk { fst := a_1, snd := f'_1 } ∧
                ∀ (i : B F a_1), R (f_1 i) (f'_1 i)
a : F.A
f f' : B F a → M F
h₀ : R (M.mk { fst := a, snd := f }) (M.mk { fst := a, snd := f' })
a' : F.A
i : B F a'
hh :
  IsPath ({ fst := a', snd := i } :: ps) (M.mk { fst := a, snd := f }) ∨
    IsPath ({ fst := a', snd := i } :: ps) (M.mk { fst := a, snd := f' })
⊢ iselect ({ fst := a', snd := i } :: ps) (M.mk { fst := a, snd := f }) =
      iselect ({ fst := a', snd := i } :: ps) (M.mk { fst := a, snd := f' }) ∧
    ∃ a_1 f_1 f'_1,
      isubtree ({ fst := a', snd := i } :: ps) (M.mk { fst := a, snd := f }) = M.mk { fst := a_1, snd := f_1 } ∧
        isubtree ({ fst := a', snd := i } :: ps) (M.mk { fst := a, snd := f' }) = M.mk { fst := a_1, snd := f'_1 } ∧
          ∀ (i : B F a_1), R (f_1 i) (f'_1 i)

tactic: dsimp only [iselect] at ps_ih⊢
state_before: case f.f.cons.mk
F : PFunctor
X : Type ?u.60946
f✝¹ : X → Obj F X
R : M F → M F → Prop
inst✝ : Inhabited (M F)
bisim : IsBisimulation R
s₁ s₂ : M F
ps✝ : Path F
h₁' : R s₁ s₂
a✝ : F.A
f✝ f'✝ : B F a✝ → M F
h₀✝ : R (M.mk { fst := a✝, snd := f✝ }) (M.mk { fst := a✝, snd := f'✝ })
hh✝ : IsPath ps✝ (M.mk { fst := a✝, snd := f✝ }) ∨ IsPath ps✝ (M.mk { fst := a✝, snd := f'✝ })
ps : List (IdxCat F)
ps_ih :
  ∀ (a : F.A) (f f' : B F a → M F),
    R (M.mk { fst := a, snd := f }) (M.mk { fst := a, snd := f' }) →
      IsPath ps (M.mk { fst := a, snd := f }) ∨ IsPath ps (M.mk { fst := a, snd := f' }) →
        iselect ps (M.mk { fst := a, snd := f }) = iselect ps (M.mk { fst := a, snd := f' }) ∧
          ∃ a_1 f_1 f'_1,
            isubtree ps (M.mk { fst := a, snd := f }) = M.mk { fst := a_1, snd := f_1 } ∧
              isubtree ps (M.mk { fst := a, snd := f' }) = M.mk { fst := a_1, snd := f'_1 } ∧
                ∀ (i : B F a_1), R (f_1 i) (f'_1 i)
a : F.A
f f' : B F a → M F
h₀ : R (M.mk { fst := a, snd := f }) (M.mk { fst := a, snd := f' })
i : B F a
hh :
  IsPath ({ fst := a, snd := i } :: ps) (M.mk { fst := a, snd := f }) ∨
    IsPath ({ fst := a, snd := i } :: ps) (M.mk { fst := a, snd := f' })
⊢ iselect ({ fst := a, snd := i } :: ps) (M.mk { fst := a, snd := f }) =
      iselect ({ fst := a, snd := i } :: ps) (M.mk { fst := a, snd := f' }) ∧
    ∃ a_1 f_1 f'_1,
      isubtree ({ fst := a, snd := i } :: ps) (M.mk { fst := a, snd := f }) = M.mk { fst := a_1, snd := f_1 } ∧
        isubtree ({ fst := a, snd := i } :: ps) (M.mk { fst := a, snd := f' }) = M.mk { fst := a_1, snd := f'_1 } ∧
          ∀ (i : B F a_1), R (f_1 i) (f'_1 i)

tactic: have h₁ := bisim.tail h₀ i
state_before: case f.f.cons.mk
F : PFunctor
X : Type ?u.60946
f✝¹ : X → Obj F X
R : M F → M F → Prop
inst✝ : Inhabited (M F)
bisim : IsBisimulation R
s₁ s₂ : M F
ps✝ : Path F
h₁' : R s₁ s₂
a✝ : F.A
f✝ f'✝ : B F a✝ → M F
h₀✝ : R (M.mk { fst := a✝, snd := f✝ }) (M.mk { fst := a✝, snd := f'✝ })
hh✝ : IsPath ps✝ (M.mk { fst := a✝, snd := f✝ }) ∨ IsPath ps✝ (M.mk { fst := a✝, snd := f'✝ })
ps : List (IdxCat F)
ps_ih :
  ∀ (a : F.A) (f f' : B F a → M F),
    R (M.mk { fst := a, snd := f }) (M.mk { fst := a, snd := f' }) →
      IsPath ps (M.mk { fst := a, snd := f }) ∨ IsPath ps (M.mk { fst := a, snd := f' }) →
        head (isubtree ps (M.mk { fst := a, snd := f })) = head (isubtree ps (M.mk { fst := a, snd := f' })) ∧
          ∃ a_1 f_1 f'_1,
            isubtree ps (M.mk { fst := a, snd := f }) = M.mk { fst := a_1, snd := f_1 } ∧
              isubtree ps (M.mk { fst := a, snd := f' }) = M.mk { fst := a_1, snd := f'_1 } ∧
                ∀ (i : B F a_1), R (f_1 i) (f'_1 i)
a : F.A
f f' : B F a → M F
h₀ : R (M.mk { fst := a, snd := f }) (M.mk { fst := a, snd := f' })
i : B F a
hh :
  IsPath ({ fst := a, snd := i } :: ps) (M.mk { fst := a, snd := f }) ∨
    IsPath ({ fst := a, snd := i } :: ps) (M.mk { fst := a, snd := f' })
⊢ head (isubtree ({ fst := a, snd := i } :: ps) (M.mk { fst := a, snd := f })) =
      head (isubtree ({ fst := a, snd := i } :: ps) (M.mk { fst := a, snd := f' })) ∧
    ∃ a_1 f_1 f'_1,
      isubtree ({ fst := a, snd := i } :: ps) (M.mk { fst := a, snd := f }) = M.mk { fst := a_1, snd := f_1 } ∧
        isubtree ({ fst := a, snd := i } :: ps) (M.mk { fst := a, snd := f' }) = M.mk { fst := a_1, snd := f'_1 } ∧
          ∀ (i : B F a_1), R (f_1 i) (f'_1 i)

tactic: induction' h : f i using PFunctor.M.casesOn' with a₀ f₀
state_before: case f.f.cons.mk
F : PFunctor
X : Type ?u.60946
f✝¹ : X → Obj F X
R : M F → M F → Prop
inst✝ : Inhabited (M F)
bisim : IsBisimulation R
s₁ s₂ : M F
ps✝ : Path F
h₁' : R s₁ s₂
a✝ : F.A
f✝ f'✝ : B F a✝ → M F
h₀✝ : R (M.mk { fst := a✝, snd := f✝ }) (M.mk { fst := a✝, snd := f'✝ })
hh✝ : IsPath ps✝ (M.mk { fst := a✝, snd := f✝ }) ∨ IsPath ps✝ (M.mk { fst := a✝, snd := f'✝ })
ps : List (IdxCat F)
ps_ih :
  ∀ (a : F.A) (f f' : B F a → M F),
    R (M.mk { fst := a, snd := f }) (M.mk { fst := a, snd := f' }) →
      IsPath ps (M.mk { fst := a, snd := f }) ∨ IsPath ps (M.mk { fst := a, snd := f' }) →
        head (isubtree ps (M.mk { fst := a, snd := f })) = head (isubtree ps (M.mk { fst := a, snd := f' })) ∧
          ∃ a_1 f_1 f'_1,
            isubtree ps (M.mk { fst := a, snd := f }) = M.mk { fst := a_1, snd := f_1 } ∧
              isubtree ps (M.mk { fst := a, snd := f' }) = M.mk { fst := a_1, snd := f'_1 } ∧
                ∀ (i : B F a_1), R (f_1 i) (f'_1 i)
a : F.A
f f' : B F a → M F
h₀ : R (M.mk { fst := a, snd := f }) (M.mk { fst := a, snd := f' })
i : B F a
hh :
  IsPath ({ fst := a, snd := i } :: ps) (M.mk { fst := a, snd := f }) ∨
    IsPath ({ fst := a, snd := i } :: ps) (M.mk { fst := a, snd := f' })
h₁ : R (f i) (f' i)
⊢ head (isubtree ({ fst := a, snd := i } :: ps) (M.mk { fst := a, snd := f })) =
      head (isubtree ({ fst := a, snd := i } :: ps) (M.mk { fst := a, snd := f' })) ∧
    ∃ a_1 f_1 f'_1,
      isubtree ({ fst := a, snd := i } :: ps) (M.mk { fst := a, snd := f }) = M.mk { fst := a_1, snd := f_1 } ∧
        isubtree ({ fst := a, snd := i } :: ps) (M.mk { fst := a, snd := f' }) = M.mk { fst := a_1, snd := f'_1 } ∧
          ∀ (i : B F a_1), R (f_1 i) (f'_1 i)

tactic: induction' h' : f' i using PFunctor.M.casesOn' with a₁ f₁
state_before: case f.f.cons.mk.f
F : PFunctor
X : Type ?u.60946
f✝¹ : X → Obj F X
R : M F → M F → Prop
inst✝ : Inhabited (M F)
bisim : IsBisimulation R
s₁ s₂ : M F
ps✝ : Path F
h₁' : R s₁ s₂
a✝ : F.A
f✝ f'✝ : B F a✝ → M F
h₀✝ : R (M.mk { fst := a✝, snd := f✝ }) (M.mk { fst := a✝, snd := f'✝ })
hh✝ : IsPath ps✝ (M.mk { fst := a✝, snd := f✝ }) ∨ IsPath ps✝ (M.mk { fst := a✝, snd := f'✝ })
ps : List (IdxCat F)
ps_ih :
  ∀ (a : F.A) (f f' : B F a → M F),
    R (M.mk { fst := a, snd := f }) (M.mk { fst := a, snd := f' }) →
      IsPath ps (M.mk { fst := a, snd := f }) ∨ IsPath ps (M.mk { fst := a, snd := f' }) →
        head (isubtree ps (M.mk { fst := a, snd := f })) = head (isubtree ps (M.mk { fst := a, snd := f' })) ∧
          ∃ a_1 f_1 f'_1,
            isubtree ps (M.mk { fst := a, snd := f }) = M.mk { fst := a_1, snd := f_1 } ∧
              isubtree ps (M.mk { fst := a, snd := f' }) = M.mk { fst := a_1, snd := f'_1 } ∧
                ∀ (i : B F a_1), R (f_1 i) (f'_1 i)
a : F.A
f f' : B F a → M F
h₀ : R (M.mk { fst := a, snd := f }) (M.mk { fst := a, snd := f' })
i : B F a
hh :
  IsPath ({ fst := a, snd := i } :: ps) (M.mk { fst := a, snd := f }) ∨
    IsPath ({ fst := a, snd := i } :: ps) (M.mk { fst := a, snd := f' })
h₁ : R (f i) (f' i)
x✝ : M F
h✝ : f i = x✝
a₀ : F.A
f₀ : B F a₀ → M F
h : f i = M.mk { fst := a₀, snd := f₀ }
⊢ head (isubtree ({ fst := a, snd := i } :: ps) (M.mk { fst := a, snd := f })) =
      head (isubtree ({ fst := a, snd := i } :: ps) (M.mk { fst := a, snd := f' })) ∧
    ∃ a_1 f_1 f'_1,
      isubtree ({ fst := a, snd := i } :: ps) (M.mk { fst := a, snd := f }) = M.mk { fst := a_1, snd := f_1 } ∧
        isubtree ({ fst := a, snd := i } :: ps) (M.mk { fst := a, snd := f' }) = M.mk { fst := a_1, snd := f'_1 } ∧
          ∀ (i : B F a_1), R (f_1 i) (f'_1 i)

tactic: simp only [h, h', isubtree_cons] at ps_ih⊢
state_before: case f.f.cons.mk.f.f
F : PFunctor
X : Type ?u.60946
f✝¹ : X → Obj F X
R : M F → M F → Prop
inst✝ : Inhabited (M F)
bisim : IsBisimulation R
s₁ s₂ : M F
ps✝ : Path F
h₁' : R s₁ s₂
a✝ : F.A
f✝ f'✝ : B F a✝ → M F
h₀✝ : R (M.mk { fst := a✝, snd := f✝ }) (M.mk { fst := a✝, snd := f'✝ })
hh✝ : IsPath ps✝ (M.mk { fst := a✝, snd := f✝ }) ∨ IsPath ps✝ (M.mk { fst := a✝, snd := f'✝ })
ps : List (IdxCat F)
ps_ih :
  ∀ (a : F.A) (f f' : B F a → M F),
    R (M.mk { fst := a, snd := f }) (M.mk { fst := a, snd := f' }) →
      IsPath ps (M.mk { fst := a, snd := f }) ∨ IsPath ps (M.mk { fst := a, snd := f' }) →
        head (isubtree ps (M.mk { fst := a, snd := f })) = head (isubtree ps (M.mk { fst := a, snd := f' })) ∧
          ∃ a_1 f_1 f'_1,
            isubtree ps (M.mk { fst := a, snd := f }) = M.mk { fst := a_1, snd := f_1 } ∧
              isubtree ps (M.mk { fst := a, snd := f' }) = M.mk { fst := a_1, snd := f'_1 } ∧
                ∀ (i : B F a_1), R (f_1 i) (f'_1 i)
a : F.A
f f' : B F a → M F
h₀ : R (M.mk { fst := a, snd := f }) (M.mk { fst := a, snd := f' })
i : B F a
hh :
  IsPath ({ fst := a, snd := i } :: ps) (M.mk { fst := a, snd := f }) ∨
    IsPath ({ fst := a, snd := i } :: ps) (M.mk { fst := a, snd := f' })
h₁ : R (f i) (f' i)
x✝¹ : M F
h✝ : f i = x✝¹
a₀ : F.A
f₀ : B F a₀ → M F
h : f i = M.mk { fst := a₀, snd := f₀ }
x✝ : M F
h'✝ : f' i = x✝
a₁ : F.A
f₁ : B F a₁ → M F
h' : f' i = M.mk { fst := a₁, snd := f₁ }
⊢ head (isubtree ({ fst := a, snd := i } :: ps) (M.mk { fst := a, snd := f })) =
      head (isubtree ({ fst := a, snd := i } :: ps) (M.mk { fst := a, snd := f' })) ∧
    ∃ a_1 f_1 f'_1,
      isubtree ({ fst := a, snd := i } :: ps) (M.mk { fst := a, snd := f }) = M.mk { fst := a_1, snd := f_1 } ∧
        isubtree ({ fst := a, snd := i } :: ps) (M.mk { fst := a, snd := f' }) = M.mk { fst := a_1, snd := f'_1 } ∧
          ∀ (i : B F a_1), R (f_1 i) (f'_1 i)

tactic: rw [h, h'] at h₁
state_before: case f.f.cons.mk.f.f
F : PFunctor
X : Type ?u.60946
f✝¹ : X → Obj F X
R : M F → M F → Prop
inst✝ : Inhabited (M F)
bisim : IsBisimulation R
s₁ s₂ : M F
ps✝ : Path F
h₁' : R s₁ s₂
a✝ : F.A
f✝ f'✝ : B F a✝ → M F
h₀✝ : R (M.mk { fst := a✝, snd := f✝ }) (M.mk { fst := a✝, snd := f'✝ })
hh✝ : IsPath ps✝ (M.mk { fst := a✝, snd := f✝ }) ∨ IsPath ps✝ (M.mk { fst := a✝, snd := f'✝ })
ps : List (IdxCat F)
ps_ih :
  ∀ (a : F.A) (f f' : B F a → M F),
    R (M.mk { fst := a, snd := f }) (M.mk { fst := a, snd := f' }) →
      IsPath ps (M.mk { fst := a, snd := f }) ∨ IsPath ps (M.mk { fst := a, snd := f' }) →
        head (isubtree ps (M.mk { fst := a, snd := f })) = head (isubtree ps (M.mk { fst := a, snd := f' })) ∧
          ∃ a_1 f_1 f'_1,
            isubtree ps (M.mk { fst := a, snd := f }) = M.mk { fst := a_1, snd := f_1 } ∧
              isubtree ps (M.mk { fst := a, snd := f' }) = M.mk { fst := a_1, snd := f'_1 } ∧
                ∀ (i : B F a_1), R (f_1 i) (f'_1 i)
a : F.A
f f' : B F a → M F
h₀ : R (M.mk { fst := a, snd := f }) (M.mk { fst := a, snd := f' })
i : B F a
hh :
  IsPath ({ fst := a, snd := i } :: ps) (M.mk { fst := a, snd := f }) ∨
    IsPath ({ fst := a, snd := i } :: ps) (M.mk { fst := a, snd := f' })
h₁ : R (f i) (f' i)
x✝¹ : M F
h✝ : f i = x✝¹
a₀ : F.A
f₀ : B F a₀ → M F
h : f i = M.mk { fst := a₀, snd := f₀ }
x✝ : M F
h'✝ : f' i = x✝
a₁ : F.A
f₁ : B F a₁ → M F
h' : f' i = M.mk { fst := a₁, snd := f₁ }
⊢ head (isubtree ps (M.mk { fst := a₀, snd := f₀ })) = head (isubtree ps (M.mk { fst := a₁, snd := f₁ })) ∧
    ∃ a f f',
      isubtree ps (M.mk { fst := a₀, snd := f₀ }) = M.mk { fst := a, snd := f } ∧
        isubtree ps (M.mk { fst := a₁, snd := f₁ }) = M.mk { fst := a, snd := f' } ∧ ∀ (i : B F a), R (f i) (f' i)

tactic: obtain rfl : a₀ = a₁ := bisim.head h₁
state_before: case f.f.cons.mk.f.f
F : PFunctor
X : Type ?u.60946
f✝¹ : X → Obj F X
R : M F → M F → Prop
inst✝ : Inhabited (M F)
bisim : IsBisimulation R
s₁ s₂ : M F
ps✝ : Path F
h₁' : R s₁ s₂
a✝ : F.A
f✝ f'✝ : B F a✝ → M F
h₀✝ : R (M.mk { fst := a✝, snd := f✝ }) (M.mk { fst := a✝, snd := f'✝ })
hh✝ : IsPath ps✝ (M.mk { fst := a✝, snd := f✝ }) ∨ IsPath ps✝ (M.mk { fst := a✝, snd := f'✝ })
ps : List (IdxCat F)
ps_ih :
  ∀ (a : F.A) (f f' : B F a → M F),
    R (M.mk { fst := a, snd := f }) (M.mk { fst := a, snd := f' }) →
      IsPath ps (M.mk { fst := a, snd := f }) ∨ IsPath ps (M.mk { fst := a, snd := f' }) →
        head (isubtree ps (M.mk { fst := a, snd := f })) = head (isubtree ps (M.mk { fst := a, snd := f' })) ∧
          ∃ a_1 f_1 f'_1,
            isubtree ps (M.mk { fst := a, snd := f }) = M.mk { fst := a_1, snd := f_1 } ∧
              isubtree ps (M.mk { fst := a, snd := f' }) = M.mk { fst := a_1, snd := f'_1 } ∧
                ∀ (i : B F a_1), R (f_1 i) (f'_1 i)
a : F.A
f f' : B F a → M F
h₀ : R (M.mk { fst := a, snd := f }) (M.mk { fst := a, snd := f' })
i : B F a
hh :
  IsPath ({ fst := a, snd := i } :: ps) (M.mk { fst := a, snd := f }) ∨
    IsPath ({ fst := a, snd := i } :: ps) (M.mk { fst := a, snd := f' })
x✝¹ : M F
h✝ : f i = x✝¹
a₀ : F.A
f₀ : B F a₀ → M F
h : f i = M.mk { fst := a₀, snd := f₀ }
x✝ : M F
h'✝ : f' i = x✝
a₁ : F.A
f₁ : B F a₁ → M F
h₁ : R (M.mk { fst := a₀, snd := f₀ }) (M.mk { fst := a₁, snd := f₁ })
h' : f' i = M.mk { fst := a₁, snd := f₁ }
⊢ head (isubtree ps (M.mk { fst := a₀, snd := f₀ })) = head (isubtree ps (M.mk { fst := a₁, snd := f₁ })) ∧
    ∃ a f f',
      isubtree ps (M.mk { fst := a₀, snd := f₀ }) = M.mk { fst := a, snd := f } ∧
        isubtree ps (M.mk { fst := a₁, snd := f₁ }) = M.mk { fst := a, snd := f' } ∧ ∀ (i : B F a), R (f i) (f' i)

tactic: apply ps_ih _ _ _ h₁
state_before: case f.f.cons.mk.f.f
F : PFunctor
X : Type ?u.60946
f✝¹ : X → Obj F X
R : M F → M F → Prop
inst✝ : Inhabited (M F)
bisim : IsBisimulation R
s₁ s₂ : M F
ps✝ : Path F
h₁' : R s₁ s₂
a✝ : F.A
f✝ f'✝ : B F a✝ → M F
h₀✝ : R (M.mk { fst := a✝, snd := f✝ }) (M.mk { fst := a✝, snd := f'✝ })
hh✝ : IsPath ps✝ (M.mk { fst := a✝, snd := f✝ }) ∨ IsPath ps✝ (M.mk { fst := a✝, snd := f'✝ })
ps : List (IdxCat F)
ps_ih :
  ∀ (a : F.A) (f f' : B F a → M F),
    R (M.mk { fst := a, snd := f }) (M.mk { fst := a, snd := f' }) →
      IsPath ps (M.mk { fst := a, snd := f }) ∨ IsPath ps (M.mk { fst := a, snd := f' }) →
        head (isubtree ps (M.mk { fst := a, snd := f })) = head (isubtree ps (M.mk { fst := a, snd := f' })) ∧
          ∃ a_1 f_1 f'_1,
            isubtree ps (M.mk { fst := a, snd := f }) = M.mk { fst := a_1, snd := f_1 } ∧
              isubtree ps (M.mk { fst := a, snd := f' }) = M.mk { fst := a_1, snd := f'_1 } ∧
                ∀ (i : B F a_1), R (f_1 i) (f'_1 i)
a : F.A
f f' : B F a → M F
h₀ : R (M.mk { fst := a, snd := f }) (M.mk { fst := a, snd := f' })
i : B F a
hh :
  IsPath ({ fst := a, snd := i } :: ps) (M.mk { fst := a, snd := f }) ∨
    IsPath ({ fst := a, snd := i } :: ps) (M.mk { fst := a, snd := f' })
x✝¹ : M F
h✝ : f i = x✝¹
a₀ : F.A
f₀ : B F a₀ → M F
h : f i = M.mk { fst := a₀, snd := f₀ }
x✝ : M F
h'✝ : f' i = x✝
f₁ : B F a₀ → M F
h₁ : R (M.mk { fst := a₀, snd := f₀ }) (M.mk { fst := a₀, snd := f₁ })
h' : f' i = M.mk { fst := a₀, snd := f₁ }
⊢ head (isubtree ps (M.mk { fst := a₀, snd := f₀ })) = head (isubtree ps (M.mk { fst := a₀, snd := f₁ })) ∧
    ∃ a f f',
      isubtree ps (M.mk { fst := a₀, snd := f₀ }) = M.mk { fst := a, snd := f } ∧
        isubtree ps (M.mk { fst := a₀, snd := f₁ }) = M.mk { fst := a, snd := f' } ∧ ∀ (i : B F a), R (f i) (f' i)

tactic: rw [← h, ← h']
state_before: case f.f.cons.mk.f.f
F : PFunctor
X : Type ?u.60946
f✝¹ : X → Obj F X
R : M F → M F → Prop
inst✝ : Inhabited (M F)
bisim : IsBisimulation R
s₁ s₂ : M F
ps✝ : Path F
h₁' : R s₁ s₂
a✝ : F.A
f✝ f'✝ : B F a✝ → M F
h₀✝ : R (M.mk { fst := a✝, snd := f✝ }) (M.mk { fst := a✝, snd := f'✝ })
hh✝ : IsPath ps✝ (M.mk { fst := a✝, snd := f✝ }) ∨ IsPath ps✝ (M.mk { fst := a✝, snd := f'✝ })
ps : List (IdxCat F)
ps_ih :
  ∀ (a : F.A) (f f' : B F a → M F),
    R (M.mk { fst := a, snd := f }) (M.mk { fst := a, snd := f' }) →
      IsPath ps (M.mk { fst := a, snd := f }) ∨ IsPath ps (M.mk { fst := a, snd := f' }) →
        head (isubtree ps (M.mk { fst := a, snd := f })) = head (isubtree ps (M.mk { fst := a, snd := f' })) ∧
          ∃ a_1 f_1 f'_1,
            isubtree ps (M.mk { fst := a, snd := f }) = M.mk { fst := a_1, snd := f_1 } ∧
              isubtree ps (M.mk { fst := a, snd := f' }) = M.mk { fst := a_1, snd := f'_1 } ∧
                ∀ (i : B F a_1), R (f_1 i) (f'_1 i)
a : F.A
f f' : B F a → M F
h₀ : R (M.mk { fst := a, snd := f }) (M.mk { fst := a, snd := f' })
i : B F a
hh :
  IsPath ({ fst := a, snd := i } :: ps) (M.mk { fst := a, snd := f }) ∨
    IsPath ({ fst := a, snd := i } :: ps) (M.mk { fst := a, snd := f' })
x✝¹ : M F
h✝ : f i = x✝¹
a₀ : F.A
f₀ : B F a₀ → M F
h : f i = M.mk { fst := a₀, snd := f₀ }
x✝ : M F
h'✝ : f' i = x✝
f₁ : B F a₀ → M F
h₁ : R (M.mk { fst := a₀, snd := f₀ }) (M.mk { fst := a₀, snd := f₁ })
h' : f' i = M.mk { fst := a₀, snd := f₁ }
⊢ IsPath ps (M.mk { fst := a₀, snd := f₀ }) ∨ IsPath ps (M.mk { fst := a₀, snd := f₁ })

tactic: apply Or.imp isPath_cons' isPath_cons' hh
state_before: case f.f.cons.mk.f.f
F : PFunctor
X : Type ?u.60946
f✝¹ : X → Obj F X
R : M F → M F → Prop
inst✝ : Inhabited (M F)
bisim : IsBisimulation R
s₁ s₂ : M F
ps✝ : Path F
h₁' : R s₁ s₂
a✝ : F.A
f✝ f'✝ : B F a✝ → M F
h₀✝ : R (M.mk { fst := a✝, snd := f✝ }) (M.mk { fst := a✝, snd := f'✝ })
hh✝ : IsPath ps✝ (M.mk { fst := a✝, snd := f✝ }) ∨ IsPath ps✝ (M.mk { fst := a✝, snd := f'✝ })
ps : List (IdxCat F)
ps_ih :
  ∀ (a : F.A) (f f' : B F a → M F),
    R (M.mk { fst := a, snd := f }) (M.mk { fst := a, snd := f' }) →
      IsPath ps (M.mk { fst := a, snd := f }) ∨ IsPath ps (M.mk { fst := a, snd := f' }) →
        head (isubtree ps (M.mk { fst := a, snd := f })) = head (isubtree ps (M.mk { fst := a, snd := f' })) ∧
          ∃ a_1 f_1 f'_1,
            isubtree ps (M.mk { fst := a, snd := f }) = M.mk { fst := a_1, snd := f_1 } ∧
              isubtree ps (M.mk { fst := a, snd := f' }) = M.mk { fst := a_1, snd := f'_1 } ∧
                ∀ (i : B F a_1), R (f_1 i) (f'_1 i)
a : F.A
f f' : B F a → M F
h₀ : R (M.mk { fst := a, snd := f }) (M.mk { fst := a, snd := f' })
i : B F a
hh :
  IsPath ({ fst := a, snd := i } :: ps) (M.mk { fst := a, snd := f }) ∨
    IsPath ({ fst := a, snd := i } :: ps) (M.mk { fst := a, snd := f' })
x✝¹ : M F
h✝ : f i = x✝¹
a₀ : F.A
f₀ : B F a₀ → M F
h : f i = M.mk { fst := a₀, snd := f₀ }
x✝ : M F
h'✝ : f' i = x✝
f₁ : B F a₀ → M F
h₁ : R (M.mk { fst := a₀, snd := f₀ }) (M.mk { fst := a₀, snd := f₁ })
h' : f' i = M.mk { fst := a₀, snd := f₁ }
⊢ IsPath ps (f i) ∨ IsPath ps (f' i)

tactic: exists rfl, a, f, f', rfl, rfl
state_before: case f.f.nil
F : PFunctor
X : Type ?u.60946
f✝¹ : X → Obj F X
R : M F → M F → Prop
inst✝ : Inhabited (M F)
bisim : IsBisimulation R
s₁ s₂ : M F
ps : Path F
h₁' : R s₁ s₂
a✝ : F.A
f✝ f'✝ : B F a✝ → M F
h₀✝ : R (M.mk { fst := a✝, snd := f✝ }) (M.mk { fst := a✝, snd := f'✝ })
hh✝ : IsPath ps (M.mk { fst := a✝, snd := f✝ }) ∨ IsPath ps (M.mk { fst := a✝, snd := f'✝ })
a : F.A
f f' : B F a → M F
h₀ : R (M.mk { fst := a, snd := f }) (M.mk { fst := a, snd := f' })
hh : IsPath [] (M.mk { fst := a, snd := f }) ∨ IsPath [] (M.mk { fst := a, snd := f' })
⊢ iselect [] (M.mk { fst := a, snd := f }) = iselect [] (M.mk { fst := a, snd := f' }) ∧
    ∃ a_1 f_1 f'_1,
      isubtree [] (M.mk { fst := a, snd := f }) = M.mk { fst := a_1, snd := f_1 } ∧
        isubtree [] (M.mk { fst := a, snd := f' }) = M.mk { fst := a_1, snd := f'_1 } ∧
          ∀ (i : B F a_1), R (f_1 i) (f'_1 i)

tactic: apply bisim.tail h₀
state_before: case f.f.nil
F : PFunctor
X : Type ?u.60946
f✝¹ : X → Obj F X
R : M F → M F → Prop
inst✝ : Inhabited (M F)
bisim : IsBisimulation R
s₁ s₂ : M F
ps : Path F
h₁' : R s₁ s₂
a✝ : F.A
f✝ f'✝ : B F a✝ → M F
h₀✝ : R (M.mk { fst := a✝, snd := f✝ }) (M.mk { fst := a✝, snd := f'✝ })
hh✝ : IsPath ps (M.mk { fst := a✝, snd := f✝ }) ∨ IsPath ps (M.mk { fst := a✝, snd := f'✝ })
a : F.A
f f' : B F a → M F
h₀ : R (M.mk { fst := a, snd := f }) (M.mk { fst := a, snd := f' })
hh : IsPath [] (M.mk { fst := a, snd := f }) ∨ IsPath [] (M.mk { fst := a, snd := f' })
⊢ ∀ (i : B F a), R (f i) (f' i)

tactic: rcases hh with hh|hh <;> cases isPath_cons hh <;> rfl
state_before: F : PFunctor
X : Type ?u.60946
f✝¹ : X → Obj F X
R : M F → M F → Prop
inst✝ : Inhabited (M F)
bisim : IsBisimulation R
s₁ s₂ : M F
ps✝ : Path F
h₁' : R s₁ s₂
a✝ : F.A
f✝ f'✝ : B F a✝ → M F
h₀✝ : R (M.mk { fst := a✝, snd := f✝ }) (M.mk { fst := a✝, snd := f'✝ })
hh✝ : IsPath ps✝ (M.mk { fst := a✝, snd := f✝ }) ∨ IsPath ps✝ (M.mk { fst := a✝, snd := f'✝ })
ps : List (IdxCat F)
ps_ih :
  ∀ (a : F.A) (f f' : B F a → M F),
    R (M.mk { fst := a, snd := f }) (M.mk { fst := a, snd := f' }) →
      IsPath ps (M.mk { fst := a, snd := f }) ∨ IsPath ps (M.mk { fst := a, snd := f' }) →
        iselect ps (M.mk { fst := a, snd := f }) = iselect ps (M.mk { fst := a, snd := f' }) ∧
          ∃ a_1 f_1 f'_1,
            isubtree ps (M.mk { fst := a, snd := f }) = M.mk { fst := a_1, snd := f_1 } ∧
              isubtree ps (M.mk { fst := a, snd := f' }) = M.mk { fst := a_1, snd := f'_1 } ∧
                ∀ (i : B F a_1), R (f_1 i) (f'_1 i)
a : F.A
f f' : B F a → M F
h₀ : R (M.mk { fst := a, snd := f }) (M.mk { fst := a, snd := f' })
a' : F.A
i : B F a'
hh :
  IsPath ({ fst := a', snd := i } :: ps) (M.mk { fst := a, snd := f }) ∨
    IsPath ({ fst := a', snd := i } :: ps) (M.mk { fst := a, snd := f' })
⊢ a = a'