Theorem: MvPFunctor.M.bisim
File: Mathlib/Data/PFunctor/Multivariate/M.lean

tactic: cases' x with a₁ f₁
state_before: n : ℕ
P : MvPFunctor (n + 1)
α : TypeVec n
R : M P α → M P α → Prop
h :
  ∀ (x y : M P α),
    R x y →
      ∃ a f f₁ f₂,
        dest P x = { fst := a, snd := splitFun f f₁ } ∧
          dest P y = { fst := a, snd := splitFun f f₂ } ∧ ∀ (i : TypeVec.last (B P a)), R (f₁ i) (f₂ i)
x y : M P α
r : R x y
⊢ x = y

tactic: cases' y with a₂ f₂
state_before: case mk
n : ℕ
P : MvPFunctor (n + 1)
α : TypeVec n
R : M P α → M P α → Prop
h :
  ∀ (x y : M P α),
    R x y →
      ∃ a f f₁ f₂,
        dest P x = { fst := a, snd := splitFun f f₁ } ∧
          dest P y = { fst := a, snd := splitFun f f₂ } ∧ ∀ (i : TypeVec.last (B P a)), R (f₁ i) (f₂ i)
y : M P α
a₁ : (mp P).A
f₁ : B (mp P) a₁ ⟹ α
r : R { fst := a₁, snd := f₁ } y
⊢ { fst := a₁, snd := f₁ } = y

tactic: dsimp [mp] at *
state_before: case mk.mk
n : ℕ
P : MvPFunctor (n + 1)
α : TypeVec n
R : M P α → M P α → Prop
h :
  ∀ (x y : M P α),
    R x y →
      ∃ a f f₁ f₂,
        dest P x = { fst := a, snd := splitFun f f₁ } ∧
          dest P y = { fst := a, snd := splitFun f f₂ } ∧ ∀ (i : TypeVec.last (B P a)), R (f₁ i) (f₂ i)
a₁ : (mp P).A
f₁ : B (mp P) a₁ ⟹ α
a₂ : (mp P).A
f₂ : B (mp P) a₂ ⟹ α
r : R { fst := a₁, snd := f₁ } { fst := a₂, snd := f₂ }
⊢ { fst := a₁, snd := f₁ } = { fst := a₂, snd := f₂ }

tactic: have : a₁ = a₂ := by
  refine'
    PFunctor.M.bisim (fun a₁ a₂ => ∃ x y, R x y ∧ x.1 = a₁ ∧ y.1 = a₂) _ _ _
      ⟨⟨a₁, f₁⟩, ⟨a₂, f₂⟩, r, rfl, rfl⟩
  rintro _ _ ⟨⟨a₁, f₁⟩, ⟨a₂, f₂⟩, r, rfl, rfl⟩
  rcases h _ _ r with ⟨a', f', f₁', f₂', e₁, e₂, h'⟩
  rcases M.bisim_lemma P e₁ with ⟨g₁', e₁', rfl, rfl⟩
  rcases M.bisim_lemma P e₂ with ⟨g₂', e₂', _, rfl⟩
  rw [e₁', e₂']
  exact ⟨_, _, _, rfl, rfl, fun b => ⟨_, _, h' b, rfl, rfl⟩⟩
state_before: case mk.mk
n : ℕ
P : MvPFunctor (n + 1)
α : TypeVec n
R : M P α → M P α → Prop
h :
  ∀ (x y : M P α),
    R x y →
      ∃ a f f₁ f₂,
        dest P x = { fst := a, snd := splitFun f f₁ } ∧
          dest P y = { fst := a, snd := splitFun f f₂ } ∧ ∀ (i : TypeVec.last (B P a)), R (f₁ i) (f₂ i)
a₁ : (mp P).A
f₁ : B (mp P) a₁ ⟹ α
a₂ : (mp P).A
f₂ : B (mp P) a₂ ⟹ α
r : R { fst := a₁, snd := f₁ } { fst := a₂, snd := f₂ }
⊢ { fst := a₁, snd := f₁ } = { fst := a₂, snd := f₂ }

tactic: subst this
state_before: case mk.mk
n : ℕ
P : MvPFunctor (n + 1)
α : TypeVec n
R : M P α → M P α → Prop
h :
  ∀ (x y : M P α),
    R x y →
      ∃ a f f₁ f₂,
        dest P x = { fst := a, snd := splitFun f f₁ } ∧
          dest P y = { fst := a, snd := splitFun f f₂ } ∧ ∀ (i : TypeVec.last (B P a)), R (f₁ i) (f₂ i)
a₁ : (mp P).A
f₁ : B (mp P) a₁ ⟹ α
a₂ : (mp P).A
f₂ : B (mp P) a₂ ⟹ α
r : R { fst := a₁, snd := f₁ } { fst := a₂, snd := f₂ }
this : a₁ = a₂
⊢ { fst := a₁, snd := f₁ } = { fst := a₂, snd := f₂ }

tactic: congr with (i p)
state_before: case mk.mk
n : ℕ
P : MvPFunctor (n + 1)
α : TypeVec n
R : M P α → M P α → Prop
h :
  ∀ (x y : M P α),
    R x y →
      ∃ a f f₁ f₂,
        dest P x = { fst := a, snd := splitFun f f₁ } ∧
          dest P y = { fst := a, snd := splitFun f f₂ } ∧ ∀ (i : TypeVec.last (B P a)), R (f₁ i) (f₂ i)
a₁ : (mp P).A
f₁ f₂ : B (mp P) a₁ ⟹ α
r : R { fst := a₁, snd := f₁ } { fst := a₁, snd := f₂ }
⊢ { fst := a₁, snd := f₁ } = { fst := a₁, snd := f₂ }

tactic: induction' p with x a f h' i c x a f h' i c p IH <;>
  try
    rcases h _ _ r with ⟨a', f', f₁', f₂', e₁, e₂, h''⟩
    rcases M.bisim_lemma P e₁ with ⟨g₁', e₁', rfl, rfl⟩
    rcases M.bisim_lemma P e₂ with ⟨g₂', e₂', e₃, rfl⟩
    cases h'.symm.trans e₁'
    cases h'.symm.trans e₂'
state_before: case mk.mk.e_snd.a.h
n : ℕ
P : MvPFunctor (n + 1)
α : TypeVec n
R : M P α → M P α → Prop
h :
  ∀ (x y : M P α),
    R x y →
      ∃ a f f₁ f₂,
        dest P x = { fst := a, snd := splitFun f f₁ } ∧
          dest P y = { fst := a, snd := splitFun f f₂ } ∧ ∀ (i : TypeVec.last (B P a)), R (f₁ i) (f₂ i)
a₁ : (mp P).A
f₁ f₂ : B (mp P) a₁ ⟹ α
r : R { fst := a₁, snd := f₁ } { fst := a₁, snd := f₂ }
i : Fin2 n
p : B (mp P) a₁ i
⊢ f₁ i p = f₂ i p

tactic: refine'
  PFunctor.M.bisim (fun a₁ a₂ => ∃ x y, R x y ∧ x.1 = a₁ ∧ y.1 = a₂) _ _ _
    ⟨⟨a₁, f₁⟩, ⟨a₂, f₂⟩, r, rfl, rfl⟩
state_before: n : ℕ
P : MvPFunctor (n + 1)
α : TypeVec n
R : M P α → M P α → Prop
h :
  ∀ (x y : M P α),
    R x y →
      ∃ a f f₁ f₂,
        dest P x = { fst := a, snd := splitFun f f₁ } ∧
          dest P y = { fst := a, snd := splitFun f f₂ } ∧ ∀ (i : TypeVec.last (B P a)), R (f₁ i) (f₂ i)
a₁ : (mp P).A
f₁ : B (mp P) a₁ ⟹ α
a₂ : (mp P).A
f₂ : B (mp P) a₂ ⟹ α
r : R { fst := a₁, snd := f₁ } { fst := a₂, snd := f₂ }
⊢ a₁ = a₂

tactic: rintro _ _ ⟨⟨a₁, f₁⟩, ⟨a₂, f₂⟩, r, rfl, rfl⟩
state_before: n : ℕ
P : MvPFunctor (n + 1)
α : TypeVec n
R : M P α → M P α → Prop
h :
  ∀ (x y : M P α),
    R x y →
      ∃ a f f₁ f₂,
        dest P x = { fst := a, snd := splitFun f f₁ } ∧
          dest P y = { fst := a, snd := splitFun f f₂ } ∧ ∀ (i : TypeVec.last (B P a)), R (f₁ i) (f₂ i)
a₁ : (mp P).A
f₁ : B (mp P) a₁ ⟹ α
a₂ : (mp P).A
f₂ : B (mp P) a₂ ⟹ α
r : R { fst := a₁, snd := f₁ } { fst := a₂, snd := f₂ }
⊢ ∀ (x y : PFunctor.M (last P)),
    (fun a₁ a₂ => ∃ x y, R x y ∧ x.fst = a₁ ∧ y.fst = a₂) x y →
      ∃ a f f',
        PFunctor.M.dest x = { fst := a, snd := f } ∧
          PFunctor.M.dest y = { fst := a, snd := f' } ∧
            ∀ (i : PFunctor.B (last P) a), (fun a₁ a₂ => ∃ x y, R x y ∧ x.fst = a₁ ∧ y.fst = a₂) (f i) (f' i)

tactic: rcases h _ _ r with ⟨a', f', f₁', f₂', e₁, e₂, h'⟩
state_before: case intro.mk.intro.mk.intro.intro
n : ℕ
P : MvPFunctor (n + 1)
α : TypeVec n
R : M P α → M P α → Prop
h :
  ∀ (x y : M P α),
    R x y →
      ∃ a f f₁ f₂,
        dest P x = { fst := a, snd := splitFun f f₁ } ∧
          dest P y = { fst := a, snd := splitFun f f₂ } ∧ ∀ (i : TypeVec.last (B P a)), R (f₁ i) (f₂ i)
a₁✝ : (mp P).A
f₁✝ : B (mp P) a₁✝ ⟹ α
a₂✝ : (mp P).A
f₂✝ : B (mp P) a₂✝ ⟹ α
r✝ : R { fst := a₁✝, snd := f₁✝ } { fst := a₂✝, snd := f₂✝ }
a₁ : (mp P).A
f₁ : B (mp P) a₁ ⟹ α
a₂ : (mp P).A
f₂ : B (mp P) a₂ ⟹ α
r : R { fst := a₁, snd := f₁ } { fst := a₂, snd := f₂ }
⊢ ∃ a f f',
    PFunctor.M.dest { fst := a₁, snd := f₁ }.fst = { fst := a, snd := f } ∧
      PFunctor.M.dest { fst := a₂, snd := f₂ }.fst = { fst := a, snd := f' } ∧
        ∀ (i : PFunctor.B (last P) a), (fun a₁ a₂ => ∃ x y, R x y ∧ x.fst = a₁ ∧ y.fst = a₂) (f i) (f' i)

tactic: rcases M.bisim_lemma P e₁ with ⟨g₁', e₁', rfl, rfl⟩
state_before: case intro.mk.intro.mk.intro.intro.intro.intro.intro.intro.intro.intro
n : ℕ
P : MvPFunctor (n + 1)
α : TypeVec n
R : M P α → M P α → Prop
h :
  ∀ (x y : M P α),
    R x y →
      ∃ a f f₁ f₂,
        dest P x = { fst := a, snd := splitFun f f₁ } ∧
          dest P y = { fst := a, snd := splitFun f f₂ } ∧ ∀ (i : TypeVec.last (B P a)), R (f₁ i) (f₂ i)
a₁✝ : (mp P).A
f₁✝ : B (mp P) a₁✝ ⟹ α
a₂✝ : (mp P).A
f₂✝ : B (mp P) a₂✝ ⟹ α
r✝ : R { fst := a₁✝, snd := f₁✝ } { fst := a₂✝, snd := f₂✝ }
a₁ : (mp P).A
f₁ : B (mp P) a₁ ⟹ α
a₂ : (mp P).A
f₂ : B (mp P) a₂ ⟹ α
r : R { fst := a₁, snd := f₁ } { fst := a₂, snd := f₂ }
a' : P.A
f' : TypeVec.drop (B P a') ⟹ TypeVec.drop (α ::: M P α)
f₁' f₂' : TypeVec.last (B P a') → TypeVec.last (α ::: M P α)
e₁ : dest P { fst := a₁, snd := f₁ } = { fst := a', snd := splitFun f' f₁' }
e₂ : dest P { fst := a₂, snd := f₂ } = { fst := a', snd := splitFun f' f₂' }
h' : ∀ (i : TypeVec.last (B P a')), R (f₁' i) (f₂' i)
⊢ ∃ a f f',
    PFunctor.M.dest { fst := a₁, snd := f₁ }.fst = { fst := a, snd := f } ∧
      PFunctor.M.dest { fst := a₂, snd := f₂ }.fst = { fst := a, snd := f' } ∧
        ∀ (i : PFunctor.B (last P) a), (fun a₁ a₂ => ∃ x y, R x y ∧ x.fst = a₁ ∧ y.fst = a₂) (f i) (f' i)

tactic: rcases M.bisim_lemma P e₂ with ⟨g₂', e₂', _, rfl⟩
state_before: case intro.mk.intro.mk.intro.intro.intro.intro.intro.intro.intro.intro.intro.intro.intro
n : ℕ
P : MvPFunctor (n + 1)
α : TypeVec n
R : M P α → M P α → Prop
h :
  ∀ (x y : M P α),
    R x y →
      ∃ a f f₁ f₂,
        dest P x = { fst := a, snd := splitFun f f₁ } ∧
          dest P y = { fst := a, snd := splitFun f f₂ } ∧ ∀ (i : TypeVec.last (B P a)), R (f₁ i) (f₂ i)
a₁✝ : (mp P).A
f₁✝ : B (mp P) a₁✝ ⟹ α
a₂✝ : (mp P).A
f₂✝ : B (mp P) a₂✝ ⟹ α
r✝ : R { fst := a₁✝, snd := f₁✝ } { fst := a₂✝, snd := f₂✝ }
a₁ : (mp P).A
f₁ : B (mp P) a₁ ⟹ α
a₂ : (mp P).A
f₂ : B (mp P) a₂ ⟹ α
r : R { fst := a₁, snd := f₁ } { fst := a₂, snd := f₂ }
a' : P.A
f₂' : TypeVec.last (B P a') → TypeVec.last (α ::: M P α)
g₁' : PFunctor.B (last P) a' → PFunctor.M (last P)
e₁' : PFunctor.M.dest a₁ = { fst := a', snd := g₁' }
e₂ : dest P { fst := a₂, snd := f₂ } = { fst := a', snd := splitFun (pathDestLeft P e₁' f₁) f₂' }
h' : ∀ (i : TypeVec.last (B P a')), R ((fun x => { fst := g₁' x, snd := pathDestRight P e₁' f₁ x }) i) (f₂' i)
e₁ :
  dest P { fst := a₁, snd := f₁ } =
    { fst := a', snd := splitFun (pathDestLeft P e₁' f₁) fun x => { fst := g₁' x, snd := pathDestRight P e₁' f₁ x } }
⊢ ∃ a f f',
    PFunctor.M.dest { fst := a₁, snd := f₁ }.fst = { fst := a, snd := f } ∧
      PFunctor.M.dest { fst := a₂, snd := f₂ }.fst = { fst := a, snd := f' } ∧
        ∀ (i : PFunctor.B (last P) a), (fun a₁ a₂ => ∃ x y, R x y ∧ x.fst = a₁ ∧ y.fst = a₂) (f i) (f' i)

tactic: rw [e₁', e₂']
state_before: case intro.mk.intro.mk.intro.intro.intro.intro.intro.intro.intro.intro.intro.intro.intro.intro.intro.intro
n : ℕ
P : MvPFunctor (n + 1)
α : TypeVec n
R : M P α → M P α → Prop
h :
  ∀ (x y : M P α),
    R x y →
      ∃ a f f₁ f₂,
        dest P x = { fst := a, snd := splitFun f f₁ } ∧
          dest P y = { fst := a, snd := splitFun f f₂ } ∧ ∀ (i : TypeVec.last (B P a)), R (f₁ i) (f₂ i)
a₁✝ : (mp P).A
f₁✝ : B (mp P) a₁✝ ⟹ α
a₂✝ : (mp P).A
f₂✝ : B (mp P) a₂✝ ⟹ α
r✝ : R { fst := a₁✝, snd := f₁✝ } { fst := a₂✝, snd := f₂✝ }
a₁ : (mp P).A
f₁ : B (mp P) a₁ ⟹ α
a₂ : (mp P).A
f₂ : B (mp P) a₂ ⟹ α
r : R { fst := a₁, snd := f₁ } { fst := a₂, snd := f₂ }
a' : P.A
g₁' : PFunctor.B (last P) a' → PFunctor.M (last P)
e₁' : PFunctor.M.dest a₁ = { fst := a', snd := g₁' }
e₁ :
  dest P { fst := a₁, snd := f₁ } =
    { fst := a', snd := splitFun (pathDestLeft P e₁' f₁) fun x => { fst := g₁' x, snd := pathDestRight P e₁' f₁ x } }
g₂' : PFunctor.B (last P) a' → PFunctor.M (last P)
e₂' : PFunctor.M.dest a₂ = { fst := a', snd := g₂' }
left✝ : pathDestLeft P e₁' f₁ = pathDestLeft P e₂' f₂
e₂ :
  dest P { fst := a₂, snd := f₂ } =
    { fst := a', snd := splitFun (pathDestLeft P e₁' f₁) fun x => { fst := g₂' x, snd := pathDestRight P e₂' f₂ x } }
h' :
  ∀ (i : TypeVec.last (B P a')),
    R ((fun x => { fst := g₁' x, snd := pathDestRight P e₁' f₁ x }) i)
      ((fun x => { fst := g₂' x, snd := pathDestRight P e₂' f₂ x }) i)
⊢ ∃ a f f',
    PFunctor.M.dest { fst := a₁, snd := f₁ }.fst = { fst := a, snd := f } ∧
      PFunctor.M.dest { fst := a₂, snd := f₂ }.fst = { fst := a, snd := f' } ∧
        ∀ (i : PFunctor.B (last P) a), (fun a₁ a₂ => ∃ x y, R x y ∧ x.fst = a₁ ∧ y.fst = a₂) (f i) (f' i)

tactic: exact ⟨_, _, _, rfl, rfl, fun b => ⟨_, _, h' b, rfl, rfl⟩⟩
state_before: case intro.mk.intro.mk.intro.intro.intro.intro.intro.intro.intro.intro.intro.intro.intro.intro.intro.intro
n : ℕ
P : MvPFunctor (n + 1)
α : TypeVec n
R : M P α → M P α → Prop
h :
  ∀ (x y : M P α),
    R x y →
      ∃ a f f₁ f₂,
        dest P x = { fst := a, snd := splitFun f f₁ } ∧
          dest P y = { fst := a, snd := splitFun f f₂ } ∧ ∀ (i : TypeVec.last (B P a)), R (f₁ i) (f₂ i)
a₁✝ : (mp P).A
f₁✝ : B (mp P) a₁✝ ⟹ α
a₂✝ : (mp P).A
f₂✝ : B (mp P) a₂✝ ⟹ α
r✝ : R { fst := a₁✝, snd := f₁✝ } { fst := a₂✝, snd := f₂✝ }
a₁ : (mp P).A
f₁ : B (mp P) a₁ ⟹ α
a₂ : (mp P).A
f₂ : B (mp P) a₂ ⟹ α
r : R { fst := a₁, snd := f₁ } { fst := a₂, snd := f₂ }
a' : P.A
g₁' : PFunctor.B (last P) a' → PFunctor.M (last P)
e₁' : PFunctor.M.dest a₁ = { fst := a', snd := g₁' }
e₁ :
  dest P { fst := a₁, snd := f₁ } =
    { fst := a', snd := splitFun (pathDestLeft P e₁' f₁) fun x => { fst := g₁' x, snd := pathDestRight P e₁' f₁ x } }
g₂' : PFunctor.B (last P) a' → PFunctor.M (last P)
e₂' : PFunctor.M.dest a₂ = { fst := a', snd := g₂' }
left✝ : pathDestLeft P e₁' f₁ = pathDestLeft P e₂' f₂
e₂ :
  dest P { fst := a₂, snd := f₂ } =
    { fst := a', snd := splitFun (pathDestLeft P e₁' f₁) fun x => { fst := g₂' x, snd := pathDestRight P e₂' f₂ x } }
h' :
  ∀ (i : TypeVec.last (B P a')),
    R ((fun x => { fst := g₁' x, snd := pathDestRight P e₁' f₁ x }) i)
      ((fun x => { fst := g₂' x, snd := pathDestRight P e₂' f₂ x }) i)
⊢ ∃ a f f',
    { fst := a', snd := g₁' } = { fst := a, snd := f } ∧
      { fst := a', snd := g₂' } = { fst := a, snd := f' } ∧
        ∀ (i : PFunctor.B (last P) a), (fun a₁ a₂ => ∃ x y, R x y ∧ x.fst = a₁ ∧ y.fst = a₂) (f i) (f' i)

tactic: rcases h _ _ r with ⟨a', f', f₁', f₂', e₁, e₂, h''⟩
state_before: case mk.mk.e_snd.a.h.child
n : ℕ
P : MvPFunctor (n + 1)
α : TypeVec n
R : M P α → M P α → Prop
h :
  ∀ (x y : M P α),
    R x y →
      ∃ a f f₁ f₂,
        dest P x = { fst := a, snd := splitFun f f₁ } ∧
          dest P y = { fst := a, snd := splitFun f f₂ } ∧ ∀ (i : TypeVec.last (B P a)), R (f₁ i) (f₂ i)
a₁ : (mp P).A
f₁✝ f₂✝ : B (mp P) a₁ ⟹ α
r✝ : R { fst := a₁, snd := f₁✝ } { fst := a₁, snd := f₂✝ }
i✝ : Fin2 n
x : PFunctor.M (last P)
a : P.A
f : PFunctor.B (last P) a → PFunctor.M (last P)
h' : PFunctor.M.dest x = { fst := a, snd := f }
i : PFunctor.B (last P) a
c : Fin2 n
p : Path P (f i) c
IH : ∀ (f₁ f₂ : B (mp P) (f i) ⟹ α), R { fst := f i, snd := f₁ } { fst := f i, snd := f₂ } → f₁ c p = f₂ c p
f₁ f₂ : B (mp P) x ⟹ α
r : R { fst := x, snd := f₁ } { fst := x, snd := f₂ }
⊢ f₁ c (Path.child x a f h' i c p) = f₂ c (Path.child x a f h' i c p)

tactic: rcases M.bisim_lemma P e₁ with ⟨g₁', e₁', rfl, rfl⟩
state_before: case mk.mk.e_snd.a.h.child.intro.intro.intro.intro.intro.intro
n : ℕ
P : MvPFunctor (n + 1)
α : TypeVec n
R : M P α → M P α → Prop
h :
  ∀ (x y : M P α),
    R x y →
      ∃ a f f₁ f₂,
        dest P x = { fst := a, snd := splitFun f f₁ } ∧
          dest P y = { fst := a, snd := splitFun f f₂ } ∧ ∀ (i : TypeVec.last (B P a)), R (f₁ i) (f₂ i)
a₁ : (mp P).A
f₁✝ f₂✝ : B (mp P) a₁ ⟹ α
r✝ : R { fst := a₁, snd := f₁✝ } { fst := a₁, snd := f₂✝ }
i✝ : Fin2 n
x : PFunctor.M (last P)
a : P.A
f : PFunctor.B (last P) a → PFunctor.M (last P)
h' : PFunctor.M.dest x = { fst := a, snd := f }
i : PFunctor.B (last P) a
c : Fin2 n
p : Path P (f i) c
IH : ∀ (f₁ f₂ : B (mp P) (f i) ⟹ α), R { fst := f i, snd := f₁ } { fst := f i, snd := f₂ } → f₁ c p = f₂ c p
f₁ f₂ : B (mp P) x ⟹ α
r : R { fst := x, snd := f₁ } { fst := x, snd := f₂ }
a' : P.A
f' : TypeVec.drop (B P a') ⟹ TypeVec.drop (α ::: M P α)
f₁' f₂' : TypeVec.last (B P a') → TypeVec.last (α ::: M P α)
e₁ : dest P { fst := x, snd := f₁ } = { fst := a', snd := splitFun f' f₁' }
e₂ : dest P { fst := x, snd := f₂ } = { fst := a', snd := splitFun f' f₂' }
h'' : ∀ (i : TypeVec.last (B P a')), R (f₁' i) (f₂' i)
⊢ f₁ c (Path.child x a f h' i c p) = f₂ c (Path.child x a f h' i c p)

tactic: rcases M.bisim_lemma P e₂ with ⟨g₂', e₂', e₃, rfl⟩
state_before: case mk.mk.e_snd.a.h.child.intro.intro.intro.intro.intro.intro.intro.intro.intro
n : ℕ
P : MvPFunctor (n + 1)
α : TypeVec n
R : M P α → M P α → Prop
h :
  ∀ (x y : M P α),
    R x y →
      ∃ a f f₁ f₂,
        dest P x = { fst := a, snd := splitFun f f₁ } ∧
          dest P y = { fst := a, snd := splitFun f f₂ } ∧ ∀ (i : TypeVec.last (B P a)), R (f₁ i) (f₂ i)
a₁ : (mp P).A
f₁✝ f₂✝ : B (mp P) a₁ ⟹ α
r✝ : R { fst := a₁, snd := f₁✝ } { fst := a₁, snd := f₂✝ }
i✝ : Fin2 n
x : PFunctor.M (last P)
a : P.A
f : PFunctor.B (last P) a → PFunctor.M (last P)
h' : PFunctor.M.dest x = { fst := a, snd := f }
i : PFunctor.B (last P) a
c : Fin2 n
p : Path P (f i) c
IH : ∀ (f₁ f₂ : B (mp P) (f i) ⟹ α), R { fst := f i, snd := f₁ } { fst := f i, snd := f₂ } → f₁ c p = f₂ c p
f₁ f₂ : B (mp P) x ⟹ α
r : R { fst := x, snd := f₁ } { fst := x, snd := f₂ }
a' : P.A
f₂' : TypeVec.last (B P a') → TypeVec.last (α ::: M P α)
g₁' : PFunctor.B (last P) a' → PFunctor.M (last P)
e₁' : PFunctor.M.dest x = { fst := a', snd := g₁' }
e₂ : dest P { fst := x, snd := f₂ } = { fst := a', snd := splitFun (pathDestLeft P e₁' f₁) f₂' }
h'' : ∀ (i : TypeVec.last (B P a')), R ((fun x_1 => { fst := g₁' x_1, snd := pathDestRight P e₁' f₁ x_1 }) i) (f₂' i)
e₁ :
  dest P { fst := x, snd := f₁ } =
    { fst := a',
      snd := splitFun (pathDestLeft P e₁' f₁) fun x_1 => { fst := g₁' x_1, snd := pathDestRight P e₁' f₁ x_1 } }
⊢ f₁ c (Path.child x a f h' i c p) = f₂ c (Path.child x a f h' i c p)

tactic: cases h'.symm.trans e₁'
state_before: case mk.mk.e_snd.a.h.child.intro.intro.intro.intro.intro.intro.intro.intro.intro.intro.intro.intro
n : ℕ
P : MvPFunctor (n + 1)
α : TypeVec n
R : M P α → M P α → Prop
h :
  ∀ (x y : M P α),
    R x y →
      ∃ a f f₁ f₂,
        dest P x = { fst := a, snd := splitFun f f₁ } ∧
          dest P y = { fst := a, snd := splitFun f f₂ } ∧ ∀ (i : TypeVec.last (B P a)), R (f₁ i) (f₂ i)
a₁ : (mp P).A
f₁✝ f₂✝ : B (mp P) a₁ ⟹ α
r✝ : R { fst := a₁, snd := f₁✝ } { fst := a₁, snd := f₂✝ }
i✝ : Fin2 n
x : PFunctor.M (last P)
a : P.A
f : PFunctor.B (last P) a → PFunctor.M (last P)
h' : PFunctor.M.dest x = { fst := a, snd := f }
i : PFunctor.B (last P) a
c : Fin2 n
p : Path P (f i) c
IH : ∀ (f₁ f₂ : B (mp P) (f i) ⟹ α), R { fst := f i, snd := f₁ } { fst := f i, snd := f₂ } → f₁ c p = f₂ c p
f₁ f₂ : B (mp P) x ⟹ α
r : R { fst := x, snd := f₁ } { fst := x, snd := f₂ }
a' : P.A
g₁' : PFunctor.B (last P) a' → PFunctor.M (last P)
e₁' : PFunctor.M.dest x = { fst := a', snd := g₁' }
e₁ :
  dest P { fst := x, snd := f₁ } =
    { fst := a',
      snd := splitFun (pathDestLeft P e₁' f₁) fun x_1 => { fst := g₁' x_1, snd := pathDestRight P e₁' f₁ x_1 } }
g₂' : PFunctor.B (last P) a' → PFunctor.M (last P)
e₂' : PFunctor.M.dest x = { fst := a', snd := g₂' }
e₃ : pathDestLeft P e₁' f₁ = pathDestLeft P e₂' f₂
e₂ :
  dest P { fst := x, snd := f₂ } =
    { fst := a',
      snd := splitFun (pathDestLeft P e₁' f₁) fun x_1 => { fst := g₂' x_1, snd := pathDestRight P e₂' f₂ x_1 } }
h'' :
  ∀ (i : TypeVec.last (B P a')),
    R ((fun x_1 => { fst := g₁' x_1, snd := pathDestRight P e₁' f₁ x_1 }) i)
      ((fun x_1 => { fst := g₂' x_1, snd := pathDestRight P e₂' f₂ x_1 }) i)
⊢ f₁ c (Path.child x a f h' i c p) = f₂ c (Path.child x a f h' i c p)

tactic: cases h'.symm.trans e₂'
state_before: case mk.mk.e_snd.a.h.child.intro.intro.intro.intro.intro.intro.intro.intro.intro.intro.intro.intro.refl
n : ℕ
P : MvPFunctor (n + 1)
α : TypeVec n
R : M P α → M P α → Prop
h :
  ∀ (x y : M P α),
    R x y →
      ∃ a f f₁ f₂,
        dest P x = { fst := a, snd := splitFun f f₁ } ∧
          dest P y = { fst := a, snd := splitFun f f₂ } ∧ ∀ (i : TypeVec.last (B P a)), R (f₁ i) (f₂ i)
a₁ : (mp P).A
f₁✝ f₂✝ : B (mp P) a₁ ⟹ α
r✝ : R { fst := a₁, snd := f₁✝ } { fst := a₁, snd := f₂✝ }
i✝ : Fin2 n
x : PFunctor.M (last P)
a : P.A
f : PFunctor.B (last P) a → PFunctor.M (last P)
h' : PFunctor.M.dest x = { fst := a, snd := f }
i : PFunctor.B (last P) a
c : Fin2 n
p : Path P (f i) c
IH : ∀ (f₁ f₂ : B (mp P) (f i) ⟹ α), R { fst := f i, snd := f₁ } { fst := f i, snd := f₂ } → f₁ c p = f₂ c p
f₁ f₂ : B (mp P) x ⟹ α
r : R { fst := x, snd := f₁ } { fst := x, snd := f₂ }
g₂' : PFunctor.B (last P) a → PFunctor.M (last P)
e₂' : PFunctor.M.dest x = { fst := a, snd := g₂' }
e₁' : PFunctor.M.dest x = { fst := a, snd := f }
e₁ :
  dest P { fst := x, snd := f₁ } =
    { fst := a, snd := splitFun (pathDestLeft P e₁' f₁) fun x_1 => { fst := f x_1, snd := pathDestRight P e₁' f₁ x_1 } }
e₃ : pathDestLeft P e₁' f₁ = pathDestLeft P e₂' f₂
e₂ :
  dest P { fst := x, snd := f₂ } =
    { fst := a,
      snd := splitFun (pathDestLeft P e₁' f₁) fun x_1 => { fst := g₂' x_1, snd := pathDestRight P e₂' f₂ x_1 } }
h'' :
  ∀ (i : TypeVec.last (B P a)),
    R ((fun x_1 => { fst := f x_1, snd := pathDestRight P e₁' f₁ x_1 }) i)
      ((fun x_1 => { fst := g₂' x_1, snd := pathDestRight P e₂' f₂ x_1 }) i)
⊢ f₁ c (Path.child x a f h' i c p) = f₂ c (Path.child x a f h' i c p)

tactic: exact (congr_fun (congr_fun e₃ i) c : _)
state_before: case mk.mk.e_snd.a.h.root.intro.intro.intro.intro.intro.intro.intro.intro.intro.intro.intro.intro.refl.refl
n : ℕ
P : MvPFunctor (n + 1)
α : TypeVec n
R : M P α → M P α → Prop
h :
  ∀ (x y : M P α),
    R x y →
      ∃ a f f₁ f₂,
        dest P x = { fst := a, snd := splitFun f f₁ } ∧
          dest P y = { fst := a, snd := splitFun f f₂ } ∧ ∀ (i : TypeVec.last (B P a)), R (f₁ i) (f₂ i)
a₁ : (mp P).A
f₁✝ f₂✝ : B (mp P) a₁ ⟹ α
r✝ : R { fst := a₁, snd := f₁✝ } { fst := a₁, snd := f₂✝ }
i✝ : Fin2 n
x : PFunctor.M (last P)
a : P.A
f : PFunctor.B (last P) a → PFunctor.M (last P)
h' : PFunctor.M.dest x = { fst := a, snd := f }
i : Fin2 n
c : B (drop P) a i
f₁ f₂ : B (mp P) x ⟹ α
r : R { fst := x, snd := f₁ } { fst := x, snd := f₂ }
e₁' : PFunctor.M.dest x = { fst := a, snd := f }
e₁ :
  dest P { fst := x, snd := f₁ } =
    { fst := a, snd := splitFun (pathDestLeft P e₁' f₁) fun x_1 => { fst := f x_1, snd := pathDestRight P e₁' f₁ x_1 } }
e₂' : PFunctor.M.dest x = { fst := a, snd := f }
e₃ : pathDestLeft P e₁' f₁ = pathDestLeft P e₂' f₂
e₂ :
  dest P { fst := x, snd := f₂ } =
    { fst := a, snd := splitFun (pathDestLeft P e₁' f₁) fun x_1 => { fst := f x_1, snd := pathDestRight P e₂' f₂ x_1 } }
h'' :
  ∀ (i : TypeVec.last (B P a)),
    R ((fun x_1 => { fst := f x_1, snd := pathDestRight P e₁' f₁ x_1 }) i)
      ((fun x_1 => { fst := f x_1, snd := pathDestRight P e₂' f₂ x_1 }) i)
⊢ f₁ i (Path.root x a f h' i c) = f₂ i (Path.root x a f h' i c)

tactic: exact IH _ _ (h'' _)
state_before: case mk.mk.e_snd.a.h.child.intro.intro.intro.intro.intro.intro.intro.intro.intro.intro.intro.intro.refl.refl
n : ℕ
P : MvPFunctor (n + 1)
α : TypeVec n
R : M P α → M P α → Prop
h :
  ∀ (x y : M P α),
    R x y →
      ∃ a f f₁ f₂,
        dest P x = { fst := a, snd := splitFun f f₁ } ∧
          dest P y = { fst := a, snd := splitFun f f₂ } ∧ ∀ (i : TypeVec.last (B P a)), R (f₁ i) (f₂ i)
a₁ : (mp P).A
f₁✝ f₂✝ : B (mp P) a₁ ⟹ α
r✝ : R { fst := a₁, snd := f₁✝ } { fst := a₁, snd := f₂✝ }
i✝ : Fin2 n
x : PFunctor.M (last P)
a : P.A
f : PFunctor.B (last P) a → PFunctor.M (last P)
h' : PFunctor.M.dest x = { fst := a, snd := f }
i : PFunctor.B (last P) a
c : Fin2 n
p : Path P (f i) c
IH : ∀ (f₁ f₂ : B (mp P) (f i) ⟹ α), R { fst := f i, snd := f₁ } { fst := f i, snd := f₂ } → f₁ c p = f₂ c p
f₁ f₂ : B (mp P) x ⟹ α
r : R { fst := x, snd := f₁ } { fst := x, snd := f₂ }
e₁' : PFunctor.M.dest x = { fst := a, snd := f }
e₁ :
  dest P { fst := x, snd := f₁ } =
    { fst := a, snd := splitFun (pathDestLeft P e₁' f₁) fun x_1 => { fst := f x_1, snd := pathDestRight P e₁' f₁ x_1 } }
e₂' : PFunctor.M.dest x = { fst := a, snd := f }
e₃ : pathDestLeft P e₁' f₁ = pathDestLeft P e₂' f₂
e₂ :
  dest P { fst := x, snd := f₂ } =
    { fst := a, snd := splitFun (pathDestLeft P e₁' f₁) fun x_1 => { fst := f x_1, snd := pathDestRight P e₂' f₂ x_1 } }
h'' :
  ∀ (i : TypeVec.last (B P a)),
    R ((fun x_1 => { fst := f x_1, snd := pathDestRight P e₁' f₁ x_1 }) i)
      ((fun x_1 => { fst := f x_1, snd := pathDestRight P e₂' f₂ x_1 }) i)
⊢ f₁ c (Path.child x a f h' i c p) = f₂ c (Path.child x a f h' i c p)