l3lab/ntp-mathlib huggingface dataset:
theorem ext [Inhabited (M F)] (x y : M F) (H : ∀ ps : Path F, iselect ps x = iselect ps y) :
    x = y := by
  apply ext'; intro i
  induction' i with i i_ih
  · cases x.approx 0
    cases y.approx 0
    constructor
  · apply ext_aux x y x
    · rw [← agree_iff_agree']
      apply x.consistent
    · rw [← agree_iff_agree', i_ih]
      apply y.consistent
    introv H'
    

Proof state:
case H.succ.hrec
F : PFunctor.{u}
X : Type u_1
f : X → ↑F X
inst✝ : Inhabited (M F)
x y : M F
H : ∀ (ps : Path F), iselect ps x = iselect ps y
i : ℕ
i_ih : MIntl.approx x i = MIntl.approx y i
ps : Path F
H' : i = length ps
⊢ iselect ps x = iselect ps y

Next tactic:
dsimp only [iselect] at H
theorem ext [Inhabited (M F)] (x y : M F) (H : ∀ ps : Path F, iselect ps x = iselect ps y) :
    x = y := by
  apply ext'; intro i
  induction' i with i i_ih
  · cases x.approx 0
    cases y.approx 0
    constructor
  · apply ext_aux x y x
    · rw [← agree_iff_agree']
      apply x.consistent
    · rw [← agree_iff_agree', i_ih]
      apply y.consistent
    introv H'
    dsimp only [iselect] at H
    

Proof state:
case H.succ.hrec
F : PFunctor.{u}
X : Type u_1
f : X → ↑F X
inst✝ : Inhabited (M F)
x y : M F
H : ∀ (ps : Path F), head (isubtree ps x) = head (isubtree ps y)
i : ℕ
i_ih : MIntl.approx x i = MIntl.approx y i
ps : Path F
H' : i = length ps
⊢ iselect ps x = iselect ps y

Next tactic:
cases H'
theorem ext [Inhabited (M F)] (x y : M F) (H : ∀ ps : Path F, iselect ps x = iselect ps y) :
    x = y := by
  apply ext'; intro i
  induction' i with i i_ih
  · cases x.approx 0
    cases y.approx 0
    constructor
  · apply ext_aux x y x
    · rw [← agree_iff_agree']
      apply x.consistent
    · rw [← agree_iff_agree', i_ih]
      apply y.consistent
    introv H'
    dsimp only [iselect] at H
    cases H'
    

Proof state:
case H.succ.hrec.refl
F : PFunctor.{u}
X : Type u_1
f : X → ↑F X
inst✝ : Inhabited (M F)
x y : M F
H : ∀ (ps : Path F), head (isubtree ps x) = head (isubtree ps y)
ps : Path F
i_ih : MIntl.approx x (length ps) = MIntl.approx y (length ps)
⊢ iselect ps x = iselect ps y

Next tactic:
apply H ps
theorem nth_of_bisim [Inhabited (M F)] (bisim : IsBisimulation R) (s₁ s₂) (ps : Path F) :
    (R s₁ s₂) →
      IsPath ps s₁ ∨ IsPath ps s₂ →
        iselect ps s₁ = iselect ps s₂ ∧
          ∃ (a : _) (f f' : F.B a → M F),
            isubtree ps s₁ = M.mk ⟨a, f⟩ ∧
              isubtree ps s₂ = M.mk ⟨a, f'⟩ ∧ ∀ i : F.B a, f i ~ f' i := by
  

Proof state:
F : PFunctor.{u}
X : Type u_1
f : X → ↑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)

Next tactic:
intro h₀ hh
theorem nth_of_bisim [Inhabited (M F)] (bisim : IsBisimulation R) (s₁ s₂) (ps : Path F) :
    (R s₁ s₂) →
      IsPath ps s₁ ∨ IsPath ps s₂ →
        iselect ps s₁ = iselect ps s₂ ∧
          ∃ (a : _) (f f' : F.B a → M F),
            isubtree ps s₁ = M.mk ⟨a, f⟩ ∧
              isubtree ps s₂ = M.mk ⟨a, f'⟩ ∧ ∀ i : F.B a, f i ~ f' i := by
  intro h₀ hh
  

Proof state:
F : PFunctor.{u}
X : Type u_1
f : X → ↑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)

Next tactic:
induction' s₁ using PFunctor.M.casesOn' with a f
theorem nth_of_bisim [Inhabited (M F)] (bisim : IsBisimulation R) (s₁ s₂) (ps : Path F) :
    (R s₁ s₂) →
      IsPath ps s₁ ∨ IsPath ps s₂ →
        iselect ps s₁ = iselect ps s₂ ∧
          ∃ (a : _) (f f' : F.B a → M F),
            isubtree ps s₁ = M.mk ⟨a, f⟩ ∧
              isubtree ps s₂ = M.mk ⟨a, f'⟩ ∧ ∀ i : F.B a, f i ~ f' i := by
  intro h₀ hh
  induction' s₁ using PFunctor.M.casesOn' with a f
  

Proof state:
case f
F : PFunctor.{u}
X : Type u_1
f✝ : X → ↑F X
R : M F → M F → Prop
inst✝ : Inhabited (M F)
bisim : IsBisimulation R
s₂ : M F
ps : Path F
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)

Next tactic:
induction' s₂ using PFunctor.M.casesOn' with a' f'
theorem nth_of_bisim [Inhabited (M F)] (bisim : IsBisimulation R) (s₁ s₂) (ps : Path F) :
    (R s₁ s₂) →
      IsPath ps s₁ ∨ IsPath ps s₂ →
        iselect ps s₁ = iselect ps s₂ ∧
          ∃ (a : _) (f f' : F.B a → M F),
            isubtree ps s₁ = M.mk ⟨a, f⟩ ∧
              isubtree ps s₂ = M.mk ⟨a, f'⟩ ∧ ∀ i : F.B a, f i ~ f' i := by
  intro h₀ hh
  induction' s₁ using PFunctor.M.casesOn' with a f
  induction' s₂ using PFunctor.M.casesOn' with a' f'
  

Proof state:
case f.f
F : PFunctor.{u}
X : Type u_1
f✝ : X → ↑F X
R : M F → M F → Prop
inst✝ : Inhabited (M F)
bisim : IsBisimulation R
ps : Path F
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)

Next tactic:
obtain rfl : a = a' := bisim.head h₀
theorem nth_of_bisim [Inhabited (M F)] (bisim : IsBisimulation R) (s₁ s₂) (ps : Path F) :
    (R s₁ s₂) →
      IsPath ps s₁ ∨ IsPath ps s₂ →
        iselect ps s₁ = iselect ps s₂ ∧
          ∃ (a : _) (f f' : F.B a → M F),
            isubtree ps s₁ = M.mk ⟨a, f⟩ ∧
              isubtree ps s₂ = M.mk ⟨a, f'⟩ ∧ ∀ i : F.B a, f i ~ f' i := by
  intro h₀ hh
  induction' s₁ using PFunctor.M.casesOn' with a f
  induction' s₂ using PFunctor.M.casesOn' with a' f'
  obtain rfl : a = a' := bisim.head h₀
  

Proof state:
case f.f
F : PFunctor.{u}
X : Type u_1
f✝ : X → ↑F X
R : M F → M F → Prop
inst✝ : Inhabited (M F)
bisim : IsBisimulation R
ps : Path 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 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)

Next tactic:
induction' ps with i ps ps_ih generalizing a f f'
theorem nth_of_bisim [Inhabited (M F)] (bisim : IsBisimulation R) (s₁ s₂) (ps : Path F) :
    (R s₁ s₂) →
      IsPath ps s₁ ∨ IsPath ps s₂ →
        iselect ps s₁ = iselect ps s₂ ∧
          ∃ (a : _) (f f' : F.B a → M F),
            isubtree ps s₁ = M.mk ⟨a, f⟩ ∧
              isubtree ps s₂ = M.mk ⟨a, f'⟩ ∧ ∀ i : F.B a, f i ~ f' i := by
  intro h₀ hh
  induction' s₁ using PFunctor.M.casesOn' with a f
  induction' s₂ using PFunctor.M.casesOn' with a' f'
  obtain rfl : a = a' := bisim.head h₀
  induction' ps with i ps ps_ih generalizing a f f'
  · 

Proof state:
case f.f.nil
F : PFunctor.{u}
X : Type u_1
f✝ : X → ↑F X
R : M F → M F → Prop
inst✝ : Inhabited (M F)
bisim : IsBisimulation R
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)

Next tactic:
exists rfl, a, f, f', rfl, rfl
theorem nth_of_bisim [Inhabited (M F)] (bisim : IsBisimulation R) (s₁ s₂) (ps : Path F) :
    (R s₁ s₂) →
      IsPath ps s₁ ∨ IsPath ps s₂ →
        iselect ps s₁ = iselect ps s₂ ∧
          ∃ (a : _) (f f' : F.B a → M F),
            isubtree ps s₁ = M.mk ⟨a, f⟩ ∧
              isubtree ps s₂ = M.mk ⟨a, f'⟩ ∧ ∀ i : F.B a, f i ~ f' i := by
  intro h₀ hh
  induction' s₁ using PFunctor.M.casesOn' with a f
  induction' s₂ using PFunctor.M.casesOn' with a' f'
  obtain rfl : a = a' := bisim.head h₀
  induction' ps with i ps ps_ih generalizing a f f'
  · exists rfl, a, f, f', rfl, rfl
    

Proof state:
case f.f.nil
F : PFunctor.{u}
X : Type u_1
f✝ : X → ↑F X
R : M F → M F → Prop
inst✝ : Inhabited (M F)
bisim : IsBisimulation R
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)

Next tactic:
apply bisim.tail h₀
theorem nth_of_bisim [Inhabited (M F)] (bisim : IsBisimulation R) (s₁ s₂) (ps : Path F) :
    (R s₁ s₂) →
      IsPath ps s₁ ∨ IsPath ps s₂ →
        iselect ps s₁ = iselect ps s₂ ∧
          ∃ (a : _) (f f' : F.B a → M F),
            isubtree ps s₁ = M.mk ⟨a, f⟩ ∧
              isubtree ps s₂ = M.mk ⟨a, f'⟩ ∧ ∀ i : F.B a, f i ~ f' i := by
  intro h₀ hh
  induction' s₁ using PFunctor.M.casesOn' with a f
  induction' s₂ using PFunctor.M.casesOn' with a' f'
  obtain rfl : a = a' := bisim.head h₀
  induction' ps with i ps ps_ih generalizing a f f'
  · exists rfl, a, f, f', rfl, rfl
    apply bisim.tail h₀
  

Proof state:
case f.f.cons
F : PFunctor.{u}
X : Type u_1
f✝ : X → ↑F X
R : M F → M F → Prop
inst✝ : Inhabited (M F)
bisim : IsBisimulation R
i : Idx F
ps : List (Idx 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)

Next tactic:
cases' i with a' i
theorem nth_of_bisim [Inhabited (M F)] (bisim : IsBisimulation R) (s₁ s₂) (ps : Path F) :
    (R s₁ s₂) →
      IsPath ps s₁ ∨ IsPath ps s₂ →
        iselect ps s₁ = iselect ps s₂ ∧
          ∃ (a : _) (f f' : F.B a → M F),
            isubtree ps s₁ = M.mk ⟨a, f⟩ ∧
              isubtree ps s₂ = M.mk ⟨a, f'⟩ ∧ ∀ i : F.B a, f i ~ f' i := by
  intro h₀ hh
  induction' s₁ using PFunctor.M.casesOn' with a f
  induction' s₂ using PFunctor.M.casesOn' with a' f'
  obtain rfl : a = a' := bisim.head h₀
  induction' ps with i ps ps_ih generalizing a f f'
  · exists rfl, a, f, f', rfl, rfl
    apply bisim.tail h₀
  cases' i with a' i
  

Proof state:
case f.f.cons.mk
F : PFunctor.{u}
X : Type u_1
f✝ : X → ↑F X
R : M F → M F → Prop
inst✝ : Inhabited (M F)
bisim : IsBisimulation R
ps : List (Idx 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)

Next tactic:
obtain rfl : a = a' := by rcases hh with hh|hh <;> cases isPath_cons hh <;> rfl
theorem nth_of_bisim [Inhabited (M F)] (bisim : IsBisimulation R) (s₁ s₂) (ps : Path F) :
    (R s₁ s₂) →
      IsPath ps s₁ ∨ IsPath ps s₂ →
        iselect ps s₁ = iselect ps s₂ ∧
          ∃ (a : _) (f f' : F.B a → M F),
            isubtree ps s₁ = M.mk ⟨a, f⟩ ∧
              isubtree ps s₂ = M.mk ⟨a, f'⟩ ∧ ∀ i : F.B a, f i ~ f' i := by
  intro h₀ hh
  induction' s₁ using PFunctor.M.casesOn' with a f
  induction' s₂ using PFunctor.M.casesOn' with a' f'
  obtain rfl : a = a' := bisim.head h₀
  induction' ps with i ps ps_ih generalizing a f f'
  · exists rfl, a, f, f', rfl, rfl
    apply bisim.tail h₀
  cases' i with a' i
  obtain rfl : a = a' := by 

Proof state:
F : PFunctor.{u}
X : Type u_1
f✝ : X → ↑F X
R : M F → M F → Prop
inst✝ : Inhabited (M F)
bisim : IsBisimulation R
ps : List (Idx 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'

Next tactic:
rcases hh with hh|hh
theorem nth_of_bisim [Inhabited (M F)] (bisim : IsBisimulation R) (s₁ s₂) (ps : Path F) :
    (R s₁ s₂) →
      IsPath ps s₁ ∨ IsPath ps s₂ →
        iselect ps s₁ = iselect ps s₂ ∧
          ∃ (a : _) (f f' : F.B a → M F),
            isubtree ps s₁ = M.mk ⟨a, f⟩ ∧
              isubtree ps s₂ = M.mk ⟨a, f'⟩ ∧ ∀ i : F.B a, f i ~ f' i := by
  intro h₀ hh
  induction' s₁ using PFunctor.M.casesOn' with a f
  induction' s₂ using PFunctor.M.casesOn' with a' f'
  obtain rfl : a = a' := bisim.head h₀
  induction' ps with i ps ps_ih generalizing a f f'
  · exists rfl, a, f, f', rfl, rfl
    apply bisim.tail h₀
  cases' i with a' i
  obtain rfl : a = a' := by rcases hh with hh|hh <;> 

Proof state:
case inl
F : PFunctor.{u}
X : Type u_1
f✝ : X → ↑F X
R : M F → M F → Prop
inst✝ : Inhabited (M F)
bisim : IsBisimulation R
ps : List (Idx 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 })
⊢ a = a'

Next tactic:
cases isPath_cons hh
theorem nth_of_bisim [Inhabited (M F)] (bisim : IsBisimulation R) (s₁ s₂) (ps : Path F) :
    (R s₁ s₂) →
      IsPath ps s₁ ∨ IsPath ps s₂ →
        iselect ps s₁ = iselect ps s₂ ∧
          ∃ (a : _) (f f' : F.B a → M F),
            isubtree ps s₁ = M.mk ⟨a, f⟩ ∧
              isubtree ps s₂ = M.mk ⟨a, f'⟩ ∧ ∀ i : F.B a, f i ~ f' i := by
  intro h₀ hh
  induction' s₁ using PFunctor.M.casesOn' with a f
  induction' s₂ using PFunctor.M.casesOn' with a' f'
  obtain rfl : a = a' := bisim.head h₀
  induction' ps with i ps ps_ih generalizing a f f'
  · exists rfl, a, f, f', rfl, rfl
    apply bisim.tail h₀
  cases' i with a' i
  obtain rfl : a = a' := by rcases hh with hh|hh <;> 

Proof state:
case inr
F : PFunctor.{u}
X : Type u_1
f✝ : X → ↑F X
R : M F → M F → Prop
inst✝ : Inhabited (M F)
bisim : IsBisimulation R
ps : List (Idx 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' })
⊢ a = a'

Next tactic:
cases isPath_cons hh
theorem nth_of_bisim [Inhabited (M F)] (bisim : IsBisimulation R) (s₁ s₂) (ps : Path F) :
    (R s₁ s₂) →
      IsPath ps s₁ ∨ IsPath ps s₂ →
        iselect ps s₁ = iselect ps s₂ ∧
          ∃ (a : _) (f f' : F.B a → M F),
            isubtree ps s₁ = M.mk ⟨a, f⟩ ∧
              isubtree ps s₂ = M.mk ⟨a, f'⟩ ∧ ∀ i : F.B a, f i ~ f' i := by
  intro h₀ hh
  induction' s₁ using PFunctor.M.casesOn' with a f
  induction' s₂ using PFunctor.M.casesOn' with a' f'
  obtain rfl : a = a' := bisim.head h₀
  induction' ps with i ps ps_ih generalizing a f f'
  · exists rfl, a, f, f', rfl, rfl
    apply bisim.tail h₀
  cases' i with a' i
  obtain rfl : a = a' := by rcases hh with hh|hh <;> cases isPath_cons hh <;> 

Proof state:
case inl.refl
F : PFunctor.{u}
X : Type u_1
f✝ : X → ↑F X
R : M F → M F → Prop
inst✝ : Inhabited (M F)
bisim : IsBisimulation R
ps : List (Idx 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 })
⊢ a = a

Next tactic:
rfl
theorem nth_of_bisim [Inhabited (M F)] (bisim : IsBisimulation R) (s₁ s₂) (ps : Path F) :
    (R s₁ s₂) →
      IsPath ps s₁ ∨ IsPath ps s₂ →
        iselect ps s₁ = iselect ps s₂ ∧
          ∃ (a : _) (f f' : F.B a → M F),
            isubtree ps s₁ = M.mk ⟨a, f⟩ ∧
              isubtree ps s₂ = M.mk ⟨a, f'⟩ ∧ ∀ i : F.B a, f i ~ f' i := by
  intro h₀ hh
  induction' s₁ using PFunctor.M.casesOn' with a f
  induction' s₂ using PFunctor.M.casesOn' with a' f'
  obtain rfl : a = a' := bisim.head h₀
  induction' ps with i ps ps_ih generalizing a f f'
  · exists rfl, a, f, f', rfl, rfl
    apply bisim.tail h₀
  cases' i with a' i
  obtain rfl : a = a' := by rcases hh with hh|hh <;> cases isPath_cons hh <;> 

Proof state:
case inr.refl
F : PFunctor.{u}
X : Type u_1
f✝ : X → ↑F X
R : M F → M F → Prop
inst✝ : Inhabited (M F)
bisim : IsBisimulation R
ps : List (Idx 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' })
⊢ a = a

Next tactic:
rfl
theorem nth_of_bisim [Inhabited (M F)] (bisim : IsBisimulation R) (s₁ s₂) (ps : Path F) :
    (R s₁ s₂) →
      IsPath ps s₁ ∨ IsPath ps s₂ →
        iselect ps s₁ = iselect ps s₂ ∧
          ∃ (a : _) (f f' : F.B a → M F),
            isubtree ps s₁ = M.mk ⟨a, f⟩ ∧
              isubtree ps s₂ = M.mk ⟨a, f'⟩ ∧ ∀ i : F.B a, f i ~ f' i := by
  intro h₀ hh
  induction' s₁ using PFunctor.M.casesOn' with a f
  induction' s₂ using PFunctor.M.casesOn' with a' f'
  obtain rfl : a = a' := bisim.head h₀
  induction' ps with i ps ps_ih generalizing a f f'
  · exists rfl, a, f, f', rfl, rfl
    apply bisim.tail h₀
  cases' i with a' i
  obtain rfl : a = a' := by rcases hh with hh|hh <;> cases isPath_cons hh <;> rfl
  

Proof state:
case f.f.cons.mk
F : PFunctor.{u}
X : Type u_1
f✝ : X → ↑F X
R : M F → M F → Prop
inst✝ : Inhabited (M F)
bisim : IsBisimulation R
ps : List (Idx 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)

Next tactic:
dsimp only [iselect] at ps_ih ⊢