[GOAL]
α : Type u_1
s : Finset α
f : α → ℕ
a b : α
n : ℕ
⊢ multinomial ∅ f = 1
[PROOFSTEP]
dsimp [multinomial]
[GOAL]
α : Type u_1
s : Finset α
f : α → ℕ
a b : α
n : ℕ
⊢ 1 / 1 = 1
[PROOFSTEP]
rfl
[GOAL]
α : Type u_1
s : Finset α
f : α → ℕ
a b : α
n : ℕ
⊢ multinomial {a} f = 1
[PROOFSTEP]
simp [multinomial, Nat.div_self (factorial_pos (f a))]
[GOAL]
α : Type u_1
s : Finset α
f : α → ℕ
a b : α
n : ℕ
inst✝ : DecidableEq α
h : ¬a ∈ s
h₁ : f a = 1
⊢ multinomial (insert a s) f = succ (Finset.sum s f) * multinomial s f
[PROOFSTEP]
simp only [multinomial, one_mul, factorial]
[GOAL]
α : Type u_1
s : Finset α
f : α → ℕ
a b : α
n : ℕ
inst✝ : DecidableEq α
h : ¬a ∈ s
h₁ : f a = 1
⊢ (∑ i in insert a s, f i)! / ∏ i in insert a s, (f i)! = succ (Finset.sum s f) * ((∑ i in s, f i)! / ∏ i in s, (f i)!)
[PROOFSTEP]
rw [Finset.sum_insert h, Finset.prod_insert h, h₁, add_comm, ← succ_eq_add_one, factorial_succ]
[GOAL]
α : Type u_1
s : Finset α
f : α → ℕ
a b : α
n : ℕ
inst✝ : DecidableEq α
h : ¬a ∈ s
h₁ : f a = 1
⊢ (∑ x in s, f x + 1) * (∑ x in s, f x)! / (1! * ∏ x in s, (f x)!) =
    succ (Finset.sum s f) * ((∑ i in s, f i)! / ∏ i in s, (f i)!)
[PROOFSTEP]
simp only [factorial_one, one_mul, Function.comp_apply, factorial, mul_one, ← one_eq_succ_zero]
[GOAL]
α : Type u_1
s : Finset α
f : α → ℕ
a b : α
n : ℕ
inst✝ : DecidableEq α
h : ¬a ∈ s
h₁ : f a = 1
⊢ (∑ x in s, f x + 1) * (∑ x in s, f x)! / ∏ x in s, (f x)! =
    succ (Finset.sum s f) * ((∑ x in s, f x)! / ∏ x in s, (f x)!)
[PROOFSTEP]
rw [Nat.mul_div_assoc _ (prod_factorial_dvd_factorial_sum _ _)]
[GOAL]
α : Type u_1
s : Finset α
f : α → ℕ
a b : α
n : ℕ
inst✝ : DecidableEq α
h : ¬a ∈ s
⊢ multinomial (insert a s) f = choose (f a + Finset.sum s f) (f a) * multinomial s f
[PROOFSTEP]
rw [choose_eq_factorial_div_factorial (le.intro rfl)]
[GOAL]
α : Type u_1
s : Finset α
f : α → ℕ
a b : α
n : ℕ
inst✝ : DecidableEq α
h : ¬a ∈ s
⊢ multinomial (insert a s) f = (f a + Finset.sum s f)! / ((f a)! * (f a + Finset.sum s f - f a)!) * multinomial s f
[PROOFSTEP]
simp only [multinomial, Nat.add_sub_cancel_left, Finset.sum_insert h, Finset.prod_insert h, Function.comp_apply]
[GOAL]
α : Type u_1
s : Finset α
f : α → ℕ
a b : α
n : ℕ
inst✝ : DecidableEq α
h : ¬a ∈ s
⊢ (f a + ∑ i in s, f i)! / ((f a)! * ∏ i in s, (f i)!) =
    (f a + Finset.sum s f)! / ((f a)! * (Finset.sum s f)!) * ((∑ i in s, f i)! / ∏ i in s, (f i)!)
[PROOFSTEP]
rw [div_mul_div_comm ((f a).factorial_mul_factorial_dvd_factorial_add (s.sum f)) (prod_factorial_dvd_factorial_sum _ _),
  mul_comm (f a)! (s.sum f)!, mul_assoc, mul_comm _ (s.sum f)!, Nat.mul_div_mul_left _ _ (factorial_pos _)]
[GOAL]
α : Type u_1
s : Finset α
f✝ : α → ℕ
a b : α
n : ℕ
f g : α → ℕ
h : ∀ (a : α), a ∈ s → f a = g a
⊢ multinomial s f = multinomial s g
[PROOFSTEP]
simp only [multinomial]
[GOAL]
α : Type u_1
s : Finset α
f✝ : α → ℕ
a b : α
n : ℕ
f g : α → ℕ
h : ∀ (a : α), a ∈ s → f a = g a
⊢ (∑ i in s, f i)! / ∏ i in s, (f i)! = (∑ i in s, g i)! / ∏ i in s, (g i)!
[PROOFSTEP]
congr 1
[GOAL]
case e_a
α : Type u_1
s : Finset α
f✝ : α → ℕ
a b : α
n : ℕ
f g : α → ℕ
h : ∀ (a : α), a ∈ s → f a = g a
⊢ (∑ i in s, f i)! = (∑ i in s, g i)!
[PROOFSTEP]
rw [Finset.sum_congr rfl h]
[GOAL]
case e_a
α : Type u_1
s : Finset α
f✝ : α → ℕ
a b : α
n : ℕ
f g : α → ℕ
h : ∀ (a : α), a ∈ s → f a = g a
⊢ ∏ i in s, (f i)! = ∏ i in s, (g i)!
[PROOFSTEP]
exact Finset.prod_congr rfl fun a ha => by rw [h a ha]
[GOAL]
α : Type u_1
s : Finset α
f✝ : α → ℕ
a✝ b : α
n : ℕ
f g : α → ℕ
h : ∀ (a : α), a ∈ s → f a = g a
a : α
ha : a ∈ s
⊢ (f a)! = (g a)!
[PROOFSTEP]
rw [h a ha]
[GOAL]
α : Type u_1
s : Finset α
f : α → ℕ
a b : α
n : ℕ
inst✝ : DecidableEq α
h : a ≠ b
⊢ multinomial {a, b} f = (f a + f b)! / ((f a)! * (f b)!)
[PROOFSTEP]
simp [multinomial, Finset.sum_pair h, Finset.prod_pair h]
[GOAL]
α : Type u_1
s : Finset α
f : α → ℕ
a b : α
n : ℕ
inst✝ : DecidableEq α
h : a ≠ b
⊢ multinomial {a, b} f = choose (f a + f b) (f a)
[PROOFSTEP]
simp [binomial_eq _ h, choose_eq_factorial_div_factorial (Nat.le_add_right _ _)]
[GOAL]
α : Type u_1
s : Finset α
f : α → ℕ
a b : α
n : ℕ
inst✝ : DecidableEq α
hab : a ≠ b
⊢ (f a)! * (f b)! * multinomial {a, b} f = (f a + f b)!
[PROOFSTEP]
simpa [Finset.sum_pair hab, Finset.prod_pair hab] using multinomial_spec { a, b } f
[GOAL]
α : Type u_1
s : Finset α
f : α → ℕ
a b : α
n : ℕ
inst✝ : DecidableEq α
h : a ≠ b
h₁ : f a = 1
⊢ multinomial {a, b} f = succ (f b)
[PROOFSTEP]
simp [multinomial_insert_one { b } f (Finset.not_mem_singleton.mpr h) h₁]
[GOAL]
α : Type u_1
s : Finset α
f : α → ℕ
a b : α
n : ℕ
inst✝ : DecidableEq α
h : a ≠ b
⊢ multinomial {a, b} (Function.update (Function.update f a (succ (f a))) b (succ (f b))) =
    multinomial {a, b} (Function.update f a (succ (f a))) + multinomial {a, b} (Function.update f b (succ (f b)))
[PROOFSTEP]
simp only [binomial_eq_choose, Function.update_apply, h, Ne.def, ite_true, ite_false]
[GOAL]
α : Type u_1
s : Finset α
f : α → ℕ
a b : α
n : ℕ
inst✝ : DecidableEq α
h : a ≠ b
⊢ choose (succ (f a) + succ (f b)) (succ (f a)) =
    choose (succ (f a) + if b = a then succ (f a) else f b) (succ (f a)) + choose (f a + succ (f b)) (f a)
[PROOFSTEP]
rw [if_neg h.symm]
[GOAL]
α : Type u_1
s : Finset α
f : α → ℕ
a b : α
n : ℕ
inst✝ : DecidableEq α
h : a ≠ b
⊢ choose (succ (f a) + succ (f b)) (succ (f a)) =
    choose (succ (f a) + f b) (succ (f a)) + choose (f a + succ (f b)) (f a)
[PROOFSTEP]
rw [add_succ, choose_succ_succ, succ_add_eq_succ_add]
[GOAL]
α : Type u_1
s : Finset α
f : α → ℕ
a b : α
n : ℕ
inst✝ : DecidableEq α
h : a ≠ b
⊢ choose (f a + succ (f b)) (f a) + choose (f a + succ (f b)) (succ (f a)) =
    choose (f a + succ (f b)) (succ (f a)) + choose (f a + succ (f b)) (f a)
[PROOFSTEP]
ring
[GOAL]
α : Type u_1
s : Finset α
f : α → ℕ
a b : α
n : ℕ
inst✝ : DecidableEq α
h : a ≠ b
⊢ succ (f a + f b) * multinomial {a, b} f = succ (f a) * multinomial {a, b} (Function.update f a (succ (f a)))
[PROOFSTEP]
rw [binomial_eq_choose _ h, binomial_eq_choose _ h, mul_comm (f a).succ, Function.update_same,
  Function.update_noteq (ne_comm.mp h)]
[GOAL]
α : Type u_1
s : Finset α
f : α → ℕ
a b : α
n : ℕ
inst✝ : DecidableEq α
h : a ≠ b
⊢ succ (f a + f b) * choose (f a + f b) (f a) = choose (succ (f a) + f b) (succ (f a)) * succ (f a)
[PROOFSTEP]
rw [succ_mul_choose_eq (f a + f b) (f a), succ_add (f a) (f b)]
[GOAL]
α : Type u_1
s : Finset α
f : α → ℕ
a✝ b✝ : α
n a b : ℕ
⊢ multinomial Finset.univ ![a, b] = (a + b)! / (a ! * b !)
[PROOFSTEP]
rw [multinomial, Fin.sum_univ_two, Fin.prod_univ_two, Matrix.cons_val_zero, Matrix.cons_val_one, Matrix.head_cons]
[GOAL]
α : Type u_1
s : Finset α
f : α → ℕ
a✝ b✝ : α
n a b c : ℕ
⊢ multinomial Finset.univ ![a, b, c] = (a + b + c)! / (a ! * b ! * c !)
[PROOFSTEP]
rw [multinomial, Fin.sum_univ_three, Fin.prod_univ_three]
[GOAL]
α : Type u_1
s : Finset α
f : α → ℕ
a✝ b✝ : α
n a b c : ℕ
⊢ (Matrix.vecCons a ![b, c] 0 + Matrix.vecCons a ![b, c] 1 + Matrix.vecCons a ![b, c] 2)! /
      ((Matrix.vecCons a ![b, c] 0)! * (Matrix.vecCons a ![b, c] 1)! * (Matrix.vecCons a ![b, c] 2)!) =
    (a + b + c)! / (a ! * b ! * c !)
[PROOFSTEP]
rfl
[GOAL]
α : Type u_1
a : α
f : α →₀ ℕ
⊢ multinomial f = choose (sum f fun x => id) (↑f a) * multinomial (update f a 0)
[PROOFSTEP]
simp only [multinomial_eq]
[GOAL]
α : Type u_1
a : α
f : α →₀ ℕ
⊢ Nat.multinomial f.support ↑f =
    choose (sum f fun x => id) (↑f a) * Nat.multinomial (update f a 0).support ↑(update f a 0)
[PROOFSTEP]
classical
by_cases a ∈ f.support
· rw [← Finset.insert_erase h, Nat.multinomial_insert _ f (Finset.not_mem_erase a _), Finset.add_sum_erase _ f h,
    support_update_zero]
  congr 1
  exact Nat.multinomial_congr _ fun _ h => (Function.update_noteq (Finset.mem_erase.1 h).1 0 f).symm
rw [not_mem_support_iff] at h
rw [h, Nat.choose_zero_right, one_mul, ← h, update_self]
[GOAL]
α : Type u_1
a : α
f : α →₀ ℕ
⊢ Nat.multinomial f.support ↑f =
    choose (sum f fun x => id) (↑f a) * Nat.multinomial (update f a 0).support ↑(update f a 0)
[PROOFSTEP]
by_cases a ∈ f.support
[GOAL]
α : Type u_1
a : α
f : α →₀ ℕ
⊢ Nat.multinomial f.support ↑f =
    choose (sum f fun x => id) (↑f a) * Nat.multinomial (update f a 0).support ↑(update f a 0)
[PROOFSTEP]
by_cases a ∈ f.support
[GOAL]
case pos
α : Type u_1
a : α
f : α →₀ ℕ
h : a ∈ f.support
⊢ Nat.multinomial f.support ↑f =
    choose (sum f fun x => id) (↑f a) * Nat.multinomial (update f a 0).support ↑(update f a 0)
[PROOFSTEP]
rw [← Finset.insert_erase h, Nat.multinomial_insert _ f (Finset.not_mem_erase a _), Finset.add_sum_erase _ f h,
  support_update_zero]
[GOAL]
case pos
α : Type u_1
a : α
f : α →₀ ℕ
h : a ∈ f.support
⊢ choose (∑ x in f.support, ↑f x) (↑f a) * Nat.multinomial (Finset.erase f.support a) ↑f =
    choose (sum f fun x => id) (↑f a) * Nat.multinomial (Finset.erase f.support a) ↑(update f a 0)
[PROOFSTEP]
congr 1
[GOAL]
case pos.e_a
α : Type u_1
a : α
f : α →₀ ℕ
h : a ∈ f.support
⊢ Nat.multinomial (Finset.erase f.support a) ↑f = Nat.multinomial (Finset.erase f.support a) ↑(update f a 0)
[PROOFSTEP]
exact Nat.multinomial_congr _ fun _ h => (Function.update_noteq (Finset.mem_erase.1 h).1 0 f).symm
[GOAL]
case neg
α : Type u_1
a : α
f : α →₀ ℕ
h : ¬a ∈ f.support
⊢ Nat.multinomial f.support ↑f =
    choose (sum f fun x => id) (↑f a) * Nat.multinomial (update f a 0).support ↑(update f a 0)
[PROOFSTEP]
rw [not_mem_support_iff] at h
[GOAL]
case neg
α : Type u_1
a : α
f : α →₀ ℕ
h : ↑f a = 0
⊢ Nat.multinomial f.support ↑f =
    choose (sum f fun x => id) (↑f a) * Nat.multinomial (update f a 0).support ↑(update f a 0)
[PROOFSTEP]
rw [h, Nat.choose_zero_right, one_mul, ← h, update_self]
[GOAL]
α : Type u_1
inst✝ : DecidableEq α
a : α
m : Multiset α
⊢ multinomial m = Nat.choose (↑card m) (count a m) * multinomial (filter ((fun x x_1 => x ≠ x_1) a) m)
[PROOFSTEP]
dsimp only [multinomial]
[GOAL]
α : Type u_1
inst✝ : DecidableEq α
a : α
m : Multiset α
⊢ Finsupp.multinomial (↑toFinsupp m) =
    Nat.choose (↑card m) (count a m) * Finsupp.multinomial (↑toFinsupp (filter (fun x => a ≠ x) m))
[PROOFSTEP]
convert Finsupp.multinomial_update a _
[GOAL]
case h.e'_3.h.e'_5.h.e'_1
α : Type u_1
inst✝ : DecidableEq α
a : α
m : Multiset α
⊢ ↑card m = Finsupp.sum (↑toFinsupp m) fun x => id
[PROOFSTEP]
rw [← Finsupp.card_toMultiset, m.toFinsupp_toMultiset]
[GOAL]
case h.e'_3.h.e'_6.h.e'_2
α : Type u_1
inst✝ : DecidableEq α
a : α
m : Multiset α
⊢ ↑toFinsupp (filter (fun x => a ≠ x) m) = Finsupp.update (↑toFinsupp m) a 0
[PROOFSTEP]
ext1 a
[GOAL]
case h.e'_3.h.e'_6.h.e'_2.h
α : Type u_1
inst✝ : DecidableEq α
a✝ : α
m : Multiset α
a : α
⊢ ↑(↑toFinsupp (filter (fun x => a✝ ≠ x) m)) a = ↑(Finsupp.update (↑toFinsupp m) a✝ 0) a
[PROOFSTEP]
rw [toFinsupp_apply, count_filter, Finsupp.coe_update]
[GOAL]
case h.e'_3.h.e'_6.h.e'_2.h
α : Type u_1
inst✝ : DecidableEq α
a✝ : α
m : Multiset α
a : α
⊢ (if a✝ ≠ a then count a m else 0) = Function.update (↑(↑toFinsupp m)) a✝ 0 a
[PROOFSTEP]
split_ifs with h
[GOAL]
case pos
α : Type u_1
inst✝ : DecidableEq α
a✝ : α
m : Multiset α
a : α
h : a✝ ≠ a
⊢ count a m = Function.update (↑(↑toFinsupp m)) a✝ 0 a
[PROOFSTEP]
rw [Function.update_noteq h.symm, toFinsupp_apply]
[GOAL]
case neg
α : Type u_1
inst✝ : DecidableEq α
a✝ : α
m : Multiset α
a : α
h : ¬a✝ ≠ a
⊢ 0 = Function.update (↑(↑toFinsupp m)) a✝ 0 a
[PROOFSTEP]
rw [not_ne_iff.1 h, Function.update_same]
[GOAL]
α : Type u_1
inst✝¹ : DecidableEq α
s : Finset α
R : Type u_2
inst✝ : Semiring R
x : α → R
hc : Set.Pairwise ↑s fun i j => Commute (x i) (x j)
⊢ ∀ (n : ℕ),
    Finset.sum s x ^ n =
      ∑ k : { x // x ∈ Finset.sym s n },
        ↑(Multiset.multinomial ↑↑k) *
          Multiset.noncommProd (Multiset.map x ↑↑k) (_ : Set.Pairwise {b | b ∈ Multiset.map x ↑↑k} Commute)
[PROOFSTEP]
induction' s using Finset.induction with a s ha ih
[GOAL]
case empty
α : Type u_1
inst✝¹ : DecidableEq α
s : Finset α
R : Type u_2
inst✝ : Semiring R
x : α → R
hc✝ : Set.Pairwise ↑s fun i j => Commute (x i) (x j)
hc : Set.Pairwise ↑∅ fun i j => Commute (x i) (x j)
⊢ ∀ (n : ℕ),
    Finset.sum ∅ x ^ n =
      ∑ k : { x // x ∈ Finset.sym ∅ n },
        ↑(Multiset.multinomial ↑↑k) *
          Multiset.noncommProd (Multiset.map x ↑↑k) (_ : Set.Pairwise {b | b ∈ Multiset.map x ↑↑k} Commute)
[PROOFSTEP]
rw [sum_empty]
[GOAL]
case empty
α : Type u_1
inst✝¹ : DecidableEq α
s : Finset α
R : Type u_2
inst✝ : Semiring R
x : α → R
hc✝ : Set.Pairwise ↑s fun i j => Commute (x i) (x j)
hc : Set.Pairwise ↑∅ fun i j => Commute (x i) (x j)
⊢ ∀ (n : ℕ),
    0 ^ n =
      ∑ k : { x // x ∈ Finset.sym ∅ n },
        ↑(Multiset.multinomial ↑↑k) *
          Multiset.noncommProd (Multiset.map x ↑↑k) (_ : Set.Pairwise {b | b ∈ Multiset.map x ↑↑k} Commute)
[PROOFSTEP]
rintro
  (_ | n)
      -- Porting note : Lean cannot infer this instance by itself
[GOAL]
case empty.zero
α : Type u_1
inst✝¹ : DecidableEq α
s : Finset α
R : Type u_2
inst✝ : Semiring R
x : α → R
hc✝ : Set.Pairwise ↑s fun i j => Commute (x i) (x j)
hc : Set.Pairwise ↑∅ fun i j => Commute (x i) (x j)
⊢ 0 ^ zero =
    ∑ k : { x // x ∈ Finset.sym ∅ zero },
      ↑(Multiset.multinomial ↑↑k) *
        Multiset.noncommProd (Multiset.map x ↑↑k) (_ : Set.Pairwise {b | b ∈ Multiset.map x ↑↑k} Commute)
[PROOFSTEP]
haveI : Subsingleton (Sym α 0) := Unique.instSubsingleton
[GOAL]
case empty.zero
α : Type u_1
inst✝¹ : DecidableEq α
s : Finset α
R : Type u_2
inst✝ : Semiring R
x : α → R
hc✝ : Set.Pairwise ↑s fun i j => Commute (x i) (x j)
hc : Set.Pairwise ↑∅ fun i j => Commute (x i) (x j)
this : Subsingleton (Sym α 0)
⊢ 0 ^ zero =
    ∑ k : { x // x ∈ Finset.sym ∅ zero },
      ↑(Multiset.multinomial ↑↑k) *
        Multiset.noncommProd (Multiset.map x ↑↑k) (_ : Set.Pairwise {b | b ∈ Multiset.map x ↑↑k} Commute)
[PROOFSTEP]
rw [_root_.pow_zero, Fintype.sum_subsingleton]
[GOAL]
case empty.zero
α : Type u_1
inst✝¹ : DecidableEq α
s : Finset α
R : Type u_2
inst✝ : Semiring R
x : α → R
hc✝ : Set.Pairwise ↑s fun i j => Commute (x i) (x j)
hc : Set.Pairwise ↑∅ fun i j => Commute (x i) (x j)
this : Subsingleton (Sym α 0)
⊢ 1 =
    ↑(Multiset.multinomial ↑↑?empty.zero.a) *
      Multiset.noncommProd (Multiset.map x ↑↑?empty.zero.a)
        (_ : Set.Pairwise {b | b ∈ Multiset.map x ↑↑?empty.zero.a} Commute)
case empty.zero.a
α : Type u_1
inst✝¹ : DecidableEq α
s : Finset α
R : Type u_2
inst✝ : Semiring R
x : α → R
hc✝ : Set.Pairwise ↑s fun i j => Commute (x i) (x j)
hc : Set.Pairwise ↑∅ fun i j => Commute (x i) (x j)
this : Subsingleton (Sym α 0)
⊢ { x // x ∈ Finset.sym ∅ zero }
[PROOFSTEP]
swap
  -- Porting note : Lean cannot infer this instance by itself
[GOAL]
case empty.zero.a
α : Type u_1
inst✝¹ : DecidableEq α
s : Finset α
R : Type u_2
inst✝ : Semiring R
x : α → R
hc✝ : Set.Pairwise ↑s fun i j => Commute (x i) (x j)
hc : Set.Pairwise ↑∅ fun i j => Commute (x i) (x j)
this : Subsingleton (Sym α 0)
⊢ { x // x ∈ Finset.sym ∅ zero }
[PROOFSTEP]
have : Zero (Sym α 0) := Sym.instZeroSym
[GOAL]
case empty.zero.a
α : Type u_1
inst✝¹ : DecidableEq α
s : Finset α
R : Type u_2
inst✝ : Semiring R
x : α → R
hc✝ : Set.Pairwise ↑s fun i j => Commute (x i) (x j)
hc : Set.Pairwise ↑∅ fun i j => Commute (x i) (x j)
this✝ : Subsingleton (Sym α 0)
this : Zero (Sym α 0)
⊢ { x // x ∈ Finset.sym ∅ zero }
[PROOFSTEP]
exact ⟨0, by simp⟩
[GOAL]
α : Type u_1
inst✝¹ : DecidableEq α
s : Finset α
R : Type u_2
inst✝ : Semiring R
x : α → R
hc✝ : Set.Pairwise ↑s fun i j => Commute (x i) (x j)
hc : Set.Pairwise ↑∅ fun i j => Commute (x i) (x j)
this✝ : Subsingleton (Sym α 0)
this : Zero (Sym α 0)
⊢ 0 ∈ Finset.sym ∅ zero
[PROOFSTEP]
simp
[GOAL]
case empty.zero
α : Type u_1
inst✝¹ : DecidableEq α
s : Finset α
R : Type u_2
inst✝ : Semiring R
x : α → R
hc✝ : Set.Pairwise ↑s fun i j => Commute (x i) (x j)
hc : Set.Pairwise ↑∅ fun i j => Commute (x i) (x j)
this : Subsingleton (Sym α 0)
⊢ 1 =
    ↑(Multiset.multinomial
          ↑↑(let_fun this_1 := Sym.instZeroSym;
              { val := 0, property := (_ : 0 ∈ {∅}) })) *
      Multiset.noncommProd
        (Multiset.map x
          ↑↑(let_fun this_1 := Sym.instZeroSym;
              { val := 0, property := (_ : 0 ∈ {∅}) }))
        (_ :
          Set.Pairwise
            {b |
              b ∈
                Multiset.map x
                  ↑↑(let_fun this_1 := Sym.instZeroSym;
                      { val := 0, property := (_ : 0 ∈ {∅}) })}
            Commute)
[PROOFSTEP]
convert (@one_mul R _ _).symm
[GOAL]
case h.e'_3.h.e'_5
α : Type u_1
inst✝¹ : DecidableEq α
s : Finset α
R : Type u_2
inst✝ : Semiring R
x : α → R
hc✝ : Set.Pairwise ↑s fun i j => Commute (x i) (x j)
hc : Set.Pairwise ↑∅ fun i j => Commute (x i) (x j)
this : Subsingleton (Sym α 0)
⊢ ↑(Multiset.multinomial
        ↑↑(let_fun this_1 := Sym.instZeroSym;
            { val := 0, property := (_ : 0 ∈ {∅}) })) =
    1
[PROOFSTEP]
dsimp only
[GOAL]
case h.e'_3.h.e'_5
α : Type u_1
inst✝¹ : DecidableEq α
s : Finset α
R : Type u_2
inst✝ : Semiring R
x : α → R
hc✝ : Set.Pairwise ↑s fun i j => Commute (x i) (x j)
hc : Set.Pairwise ↑∅ fun i j => Commute (x i) (x j)
this : Subsingleton (Sym α 0)
⊢ ↑(Multiset.multinomial ↑0) = 1
[PROOFSTEP]
convert @Nat.cast_one R _
[GOAL]
case empty.succ
α : Type u_1
inst✝¹ : DecidableEq α
s : Finset α
R : Type u_2
inst✝ : Semiring R
x : α → R
hc✝ : Set.Pairwise ↑s fun i j => Commute (x i) (x j)
hc : Set.Pairwise ↑∅ fun i j => Commute (x i) (x j)
n : ℕ
⊢ 0 ^ succ n =
    ∑ k : { x // x ∈ Finset.sym ∅ (succ n) },
      ↑(Multiset.multinomial ↑↑k) *
        Multiset.noncommProd (Multiset.map x ↑↑k) (_ : Set.Pairwise {b | b ∈ Multiset.map x ↑↑k} Commute)
[PROOFSTEP]
rw [_root_.pow_succ, zero_mul]
  -- Porting note : Lean cannot infer this instance by itself
[GOAL]
case empty.succ
α : Type u_1
inst✝¹ : DecidableEq α
s : Finset α
R : Type u_2
inst✝ : Semiring R
x : α → R
hc✝ : Set.Pairwise ↑s fun i j => Commute (x i) (x j)
hc : Set.Pairwise ↑∅ fun i j => Commute (x i) (x j)
n : ℕ
⊢ 0 =
    ∑ k : { x // x ∈ Finset.sym ∅ (succ n) },
      ↑(Multiset.multinomial ↑↑k) *
        Multiset.noncommProd (Multiset.map x ↑↑k) (_ : Set.Pairwise {b | b ∈ Multiset.map x ↑↑k} Commute)
[PROOFSTEP]
haveI : IsEmpty (Finset.sym (∅ : Finset α) (succ n)) := Finset.instIsEmpty
[GOAL]
case empty.succ
α : Type u_1
inst✝¹ : DecidableEq α
s : Finset α
R : Type u_2
inst✝ : Semiring R
x : α → R
hc✝ : Set.Pairwise ↑s fun i j => Commute (x i) (x j)
hc : Set.Pairwise ↑∅ fun i j => Commute (x i) (x j)
n : ℕ
this : IsEmpty { x // x ∈ Finset.sym ∅ (succ n) }
⊢ 0 =
    ∑ k : { x // x ∈ Finset.sym ∅ (succ n) },
      ↑(Multiset.multinomial ↑↑k) *
        Multiset.noncommProd (Multiset.map x ↑↑k) (_ : Set.Pairwise {b | b ∈ Multiset.map x ↑↑k} Commute)
[PROOFSTEP]
apply (Fintype.sum_empty _).symm
[GOAL]
case insert
α : Type u_1
inst✝¹ : DecidableEq α
s✝ : Finset α
R : Type u_2
inst✝ : Semiring R
x : α → R
hc✝ : Set.Pairwise ↑s✝ fun i j => Commute (x i) (x j)
a : α
s : Finset α
ha : ¬a ∈ s
ih :
  ∀ (hc : Set.Pairwise ↑s fun i j => Commute (x i) (x j)) (n : ℕ),
    Finset.sum s x ^ n =
      ∑ k : { x // x ∈ Finset.sym s n },
        ↑(Multiset.multinomial ↑↑k) *
          Multiset.noncommProd (Multiset.map x ↑↑k) (_ : Set.Pairwise {b | b ∈ Multiset.map x ↑↑k} Commute)
hc : Set.Pairwise ↑(insert a s) fun i j => Commute (x i) (x j)
⊢ ∀ (n : ℕ),
    Finset.sum (insert a s) x ^ n =
      ∑ k : { x // x ∈ Finset.sym (insert a s) n },
        ↑(Multiset.multinomial ↑↑k) *
          Multiset.noncommProd (Multiset.map x ↑↑k) (_ : Set.Pairwise {b | b ∈ Multiset.map x ↑↑k} Commute)
[PROOFSTEP]
intro n
[GOAL]
case insert
α : Type u_1
inst✝¹ : DecidableEq α
s✝ : Finset α
R : Type u_2
inst✝ : Semiring R
x : α → R
hc✝ : Set.Pairwise ↑s✝ fun i j => Commute (x i) (x j)
a : α
s : Finset α
ha : ¬a ∈ s
ih :
  ∀ (hc : Set.Pairwise ↑s fun i j => Commute (x i) (x j)) (n : ℕ),
    Finset.sum s x ^ n =
      ∑ k : { x // x ∈ Finset.sym s n },
        ↑(Multiset.multinomial ↑↑k) *
          Multiset.noncommProd (Multiset.map x ↑↑k) (_ : Set.Pairwise {b | b ∈ Multiset.map x ↑↑k} Commute)
hc : Set.Pairwise ↑(insert a s) fun i j => Commute (x i) (x j)
n : ℕ
⊢ Finset.sum (insert a s) x ^ n =
    ∑ k : { x // x ∈ Finset.sym (insert a s) n },
      ↑(Multiset.multinomial ↑↑k) *
        Multiset.noncommProd (Multiset.map x ↑↑k) (_ : Set.Pairwise {b | b ∈ Multiset.map x ↑↑k} Commute)
[PROOFSTEP]
specialize ih (hc.mono <| s.subset_insert a)
[GOAL]
case insert
α : Type u_1
inst✝¹ : DecidableEq α
s✝ : Finset α
R : Type u_2
inst✝ : Semiring R
x : α → R
hc✝ : Set.Pairwise ↑s✝ fun i j => Commute (x i) (x j)
a : α
s : Finset α
ha : ¬a ∈ s
hc : Set.Pairwise ↑(insert a s) fun i j => Commute (x i) (x j)
n : ℕ
ih :
  ∀ (n : ℕ),
    Finset.sum s x ^ n =
      ∑ k : { x // x ∈ Finset.sym s n },
        ↑(Multiset.multinomial ↑↑k) *
          Multiset.noncommProd (Multiset.map x ↑↑k) (_ : Set.Pairwise {b | b ∈ Multiset.map x ↑↑k} Commute)
⊢ Finset.sum (insert a s) x ^ n =
    ∑ k : { x // x ∈ Finset.sym (insert a s) n },
      ↑(Multiset.multinomial ↑↑k) *
        Multiset.noncommProd (Multiset.map x ↑↑k) (_ : Set.Pairwise {b | b ∈ Multiset.map x ↑↑k} Commute)
[PROOFSTEP]
rw [sum_insert ha, (Commute.sum_right s _ _ _).add_pow, sum_range]
[GOAL]
case insert
α : Type u_1
inst✝¹ : DecidableEq α
s✝ : Finset α
R : Type u_2
inst✝ : Semiring R
x : α → R
hc✝ : Set.Pairwise ↑s✝ fun i j => Commute (x i) (x j)
a : α
s : Finset α
ha : ¬a ∈ s
hc : Set.Pairwise ↑(insert a s) fun i j => Commute (x i) (x j)
n : ℕ
ih :
  ∀ (n : ℕ),
    Finset.sum s x ^ n =
      ∑ k : { x // x ∈ Finset.sym s n },
        ↑(Multiset.multinomial ↑↑k) *
          Multiset.noncommProd (Multiset.map x ↑↑k) (_ : Set.Pairwise {b | b ∈ Multiset.map x ↑↑k} Commute)
⊢ ∑ i : Fin (n + 1), x a ^ ↑i * (∑ i in s, x i) ^ (n - ↑i) * ↑(Nat.choose n ↑i) =
    ∑ k : { x // x ∈ Finset.sym (insert a s) n },
      ↑(Multiset.multinomial ↑↑k) *
        Multiset.noncommProd (Multiset.map x ↑↑k) (_ : Set.Pairwise {b | b ∈ Multiset.map x ↑↑k} Commute)
α : Type u_1
inst✝¹ : DecidableEq α
s✝ : Finset α
R : Type u_2
inst✝ : Semiring R
x : α → R
hc✝ : Set.Pairwise ↑s✝ fun i j => Commute (x i) (x j)
a : α
s : Finset α
ha : ¬a ∈ s
hc : Set.Pairwise ↑(insert a s) fun i j => Commute (x i) (x j)
n : ℕ
ih :
  ∀ (n : ℕ),
    Finset.sum s x ^ n =
      ∑ k : { x // x ∈ Finset.sym s n },
        ↑(Multiset.multinomial ↑↑k) *
          Multiset.noncommProd (Multiset.map x ↑↑k) (_ : Set.Pairwise {b | b ∈ Multiset.map x ↑↑k} Commute)
⊢ ∀ (i : α), i ∈ s → Commute (x a) (x i)
[PROOFSTEP]
swap
[GOAL]
α : Type u_1
inst✝¹ : DecidableEq α
s✝ : Finset α
R : Type u_2
inst✝ : Semiring R
x : α → R
hc✝ : Set.Pairwise ↑s✝ fun i j => Commute (x i) (x j)
a : α
s : Finset α
ha : ¬a ∈ s
hc : Set.Pairwise ↑(insert a s) fun i j => Commute (x i) (x j)
n : ℕ
ih :
  ∀ (n : ℕ),
    Finset.sum s x ^ n =
      ∑ k : { x // x ∈ Finset.sym s n },
        ↑(Multiset.multinomial ↑↑k) *
          Multiset.noncommProd (Multiset.map x ↑↑k) (_ : Set.Pairwise {b | b ∈ Multiset.map x ↑↑k} Commute)
⊢ ∀ (i : α), i ∈ s → Commute (x a) (x i)
[PROOFSTEP]
exact fun _ hb => hc (mem_insert_self a s) (mem_insert_of_mem hb) (ne_of_mem_of_not_mem hb ha).symm
[GOAL]
case insert
α : Type u_1
inst✝¹ : DecidableEq α
s✝ : Finset α
R : Type u_2
inst✝ : Semiring R
x : α → R
hc✝ : Set.Pairwise ↑s✝ fun i j => Commute (x i) (x j)
a : α
s : Finset α
ha : ¬a ∈ s
hc : Set.Pairwise ↑(insert a s) fun i j => Commute (x i) (x j)
n : ℕ
ih :
  ∀ (n : ℕ),
    Finset.sum s x ^ n =
      ∑ k : { x // x ∈ Finset.sym s n },
        ↑(Multiset.multinomial ↑↑k) *
          Multiset.noncommProd (Multiset.map x ↑↑k) (_ : Set.Pairwise {b | b ∈ Multiset.map x ↑↑k} Commute)
⊢ ∑ i : Fin (n + 1), x a ^ ↑i * (∑ i in s, x i) ^ (n - ↑i) * ↑(Nat.choose n ↑i) =
    ∑ k : { x // x ∈ Finset.sym (insert a s) n },
      ↑(Multiset.multinomial ↑↑k) *
        Multiset.noncommProd (Multiset.map x ↑↑k) (_ : Set.Pairwise {b | b ∈ Multiset.map x ↑↑k} Commute)
[PROOFSTEP]
simp_rw [ih, mul_sum, sum_mul, sum_sigma', univ_sigma_univ]
[GOAL]
case insert
α : Type u_1
inst✝¹ : DecidableEq α
s✝ : Finset α
R : Type u_2
inst✝ : Semiring R
x : α → R
hc✝ : Set.Pairwise ↑s✝ fun i j => Commute (x i) (x j)
a : α
s : Finset α
ha : ¬a ∈ s
hc : Set.Pairwise ↑(insert a s) fun i j => Commute (x i) (x j)
n : ℕ
ih :
  ∀ (n : ℕ),
    Finset.sum s x ^ n =
      ∑ k : { x // x ∈ Finset.sym s n },
        ↑(Multiset.multinomial ↑↑k) *
          Multiset.noncommProd (Multiset.map x ↑↑k) (_ : Set.Pairwise {b | b ∈ Multiset.map x ↑↑k} Commute)
⊢ ∑ x_1 : (i : Fin (n + 1)) × { x // x ∈ Finset.sym s (n - ↑i) },
      x a ^ ↑x_1.fst *
          (↑(Multiset.multinomial ↑↑x_1.snd) *
            Multiset.noncommProd (Multiset.map x ↑↑x_1.snd)
              (_ : Set.Pairwise {b | b ∈ Multiset.map x ↑↑x_1.snd} Commute)) *
        ↑(Nat.choose n ↑x_1.fst) =
    ∑ x_1 : { x // x ∈ Finset.sym (insert a s) n },
      ↑(Multiset.multinomial ↑↑x_1) *
        Multiset.noncommProd (Multiset.map x ↑↑x_1) (_ : Set.Pairwise {b | b ∈ Multiset.map x ↑↑x_1} Commute)
[PROOFSTEP]
refine' (Fintype.sum_equiv (symInsertEquiv ha) _ _ fun m => _).symm
[GOAL]
case insert
α : Type u_1
inst✝¹ : DecidableEq α
s✝ : Finset α
R : Type u_2
inst✝ : Semiring R
x : α → R
hc✝ : Set.Pairwise ↑s✝ fun i j => Commute (x i) (x j)
a : α
s : Finset α
ha : ¬a ∈ s
hc : Set.Pairwise ↑(insert a s) fun i j => Commute (x i) (x j)
n : ℕ
ih :
  ∀ (n : ℕ),
    Finset.sum s x ^ n =
      ∑ k : { x // x ∈ Finset.sym s n },
        ↑(Multiset.multinomial ↑↑k) *
          Multiset.noncommProd (Multiset.map x ↑↑k) (_ : Set.Pairwise {b | b ∈ Multiset.map x ↑↑k} Commute)
m : { x // x ∈ Finset.sym (insert a s) n }
⊢ ↑(Multiset.multinomial ↑↑m) *
      Multiset.noncommProd (Multiset.map x ↑↑m) (_ : Set.Pairwise {b | b ∈ Multiset.map x ↑↑m} Commute) =
    x a ^ ↑(↑(symInsertEquiv ha) m).fst *
        (↑(Multiset.multinomial ↑↑(↑(symInsertEquiv ha) m).snd) *
          Multiset.noncommProd (Multiset.map x ↑↑(↑(symInsertEquiv ha) m).snd)
            (_ : Set.Pairwise {b | b ∈ Multiset.map x ↑↑(↑(symInsertEquiv ha) m).snd} Commute)) *
      ↑(Nat.choose n ↑(↑(symInsertEquiv ha) m).fst)
[PROOFSTEP]
rw [m.1.1.multinomial_filter_ne a]
[GOAL]
case insert
α : Type u_1
inst✝¹ : DecidableEq α
s✝ : Finset α
R : Type u_2
inst✝ : Semiring R
x : α → R
hc✝ : Set.Pairwise ↑s✝ fun i j => Commute (x i) (x j)
a : α
s : Finset α
ha : ¬a ∈ s
hc : Set.Pairwise ↑(insert a s) fun i j => Commute (x i) (x j)
n : ℕ
ih :
  ∀ (n : ℕ),
    Finset.sum s x ^ n =
      ∑ k : { x // x ∈ Finset.sym s n },
        ↑(Multiset.multinomial ↑↑k) *
          Multiset.noncommProd (Multiset.map x ↑↑k) (_ : Set.Pairwise {b | b ∈ Multiset.map x ↑↑k} Commute)
m : { x // x ∈ Finset.sym (insert a s) n }
⊢ ↑(Nat.choose (↑Multiset.card ↑↑m) (Multiset.count a ↑↑m) *
          Multiset.multinomial (Multiset.filter ((fun x x_1 => x ≠ x_1) a) ↑↑m)) *
      Multiset.noncommProd (Multiset.map x ↑↑m) (_ : Set.Pairwise {b | b ∈ Multiset.map x ↑↑m} Commute) =
    x a ^ ↑(↑(symInsertEquiv ha) m).fst *
        (↑(Multiset.multinomial ↑↑(↑(symInsertEquiv ha) m).snd) *
          Multiset.noncommProd (Multiset.map x ↑↑(↑(symInsertEquiv ha) m).snd)
            (_ : Set.Pairwise {b | b ∈ Multiset.map x ↑↑(↑(symInsertEquiv ha) m).snd} Commute)) *
      ↑(Nat.choose n ↑(↑(symInsertEquiv ha) m).fst)
[PROOFSTEP]
conv in m.1.1.map _ => rw [← m.1.1.filter_add_not ((· = ·) a), Multiset.map_add]
[GOAL]
α : Type u_1
inst✝¹ : DecidableEq α
s✝ : Finset α
R : Type u_2
inst✝ : Semiring R
x : α → R
hc✝ : Set.Pairwise ↑s✝ fun i j => Commute (x i) (x j)
a : α
s : Finset α
ha : ¬a ∈ s
hc : Set.Pairwise ↑(insert a s) fun i j => Commute (x i) (x j)
n : ℕ
ih :
  ∀ (n : ℕ),
    Finset.sum s x ^ n =
      ∑ k : { x // x ∈ Finset.sym s n },
        ↑(Multiset.multinomial ↑↑k) *
          Multiset.noncommProd (Multiset.map x ↑↑k) (_ : Set.Pairwise {b | b ∈ Multiset.map x ↑↑k} Commute)
m : { x // x ∈ Finset.sym (insert a s) n }
| Multiset.map x ↑↑m
[PROOFSTEP]
rw [← m.1.1.filter_add_not ((· = ·) a), Multiset.map_add]
[GOAL]
α : Type u_1
inst✝¹ : DecidableEq α
s✝ : Finset α
R : Type u_2
inst✝ : Semiring R
x : α → R
hc✝ : Set.Pairwise ↑s✝ fun i j => Commute (x i) (x j)
a : α
s : Finset α
ha : ¬a ∈ s
hc : Set.Pairwise ↑(insert a s) fun i j => Commute (x i) (x j)
n : ℕ
ih :
  ∀ (n : ℕ),
    Finset.sum s x ^ n =
      ∑ k : { x // x ∈ Finset.sym s n },
        ↑(Multiset.multinomial ↑↑k) *
          Multiset.noncommProd (Multiset.map x ↑↑k) (_ : Set.Pairwise {b | b ∈ Multiset.map x ↑↑k} Commute)
m : { x // x ∈ Finset.sym (insert a s) n }
| Multiset.map x ↑↑m
[PROOFSTEP]
rw [← m.1.1.filter_add_not ((· = ·) a), Multiset.map_add]
[GOAL]
α : Type u_1
inst✝¹ : DecidableEq α
s✝ : Finset α
R : Type u_2
inst✝ : Semiring R
x : α → R
hc✝ : Set.Pairwise ↑s✝ fun i j => Commute (x i) (x j)
a : α
s : Finset α
ha : ¬a ∈ s
hc : Set.Pairwise ↑(insert a s) fun i j => Commute (x i) (x j)
n : ℕ
ih :
  ∀ (n : ℕ),
    Finset.sum s x ^ n =
      ∑ k : { x // x ∈ Finset.sym s n },
        ↑(Multiset.multinomial ↑↑k) *
          Multiset.noncommProd (Multiset.map x ↑↑k) (_ : Set.Pairwise {b | b ∈ Multiset.map x ↑↑k} Commute)
m : { x // x ∈ Finset.sym (insert a s) n }
| Multiset.map x ↑↑m
[PROOFSTEP]
rw [← m.1.1.filter_add_not ((· = ·) a), Multiset.map_add]
[GOAL]
case insert
α : Type u_1
inst✝¹ : DecidableEq α
s✝ : Finset α
R : Type u_2
inst✝ : Semiring R
x : α → R
hc✝ : Set.Pairwise ↑s✝ fun i j => Commute (x i) (x j)
a : α
s : Finset α
ha : ¬a ∈ s
hc : Set.Pairwise ↑(insert a s) fun i j => Commute (x i) (x j)
n : ℕ
ih :
  ∀ (n : ℕ),
    Finset.sum s x ^ n =
      ∑ k : { x // x ∈ Finset.sym s n },
        ↑(Multiset.multinomial ↑↑k) *
          Multiset.noncommProd (Multiset.map x ↑↑k) (_ : Set.Pairwise {b | b ∈ Multiset.map x ↑↑k} Commute)
m : { x // x ∈ Finset.sym (insert a s) n }
⊢ ↑(Nat.choose (↑Multiset.card ↑↑m) (Multiset.count a ↑↑m) *
          Multiset.multinomial (Multiset.filter ((fun x x_1 => x ≠ x_1) a) ↑↑m)) *
      Multiset.noncommProd
        (Multiset.map x (Multiset.filter ((fun x x_1 => x = x_1) a) ↑↑m) +
          Multiset.map x (Multiset.filter (fun a_1 => ¬(fun x x_1 => x = x_1) a a_1) ↑↑m))
        (_ :
          Set.Pairwise
            {x_1 |
              x_1 ∈
                Multiset.map x (Multiset.filter ((fun x x_2 => x = x_2) a) ↑↑m) +
                  Multiset.map x (Multiset.filter (fun a_1 => ¬(fun x x_2 => x = x_2) a a_1) ↑↑m)}
            Commute) =
    x a ^ ↑(↑(symInsertEquiv ha) m).fst *
        (↑(Multiset.multinomial ↑↑(↑(symInsertEquiv ha) m).snd) *
          Multiset.noncommProd (Multiset.map x ↑↑(↑(symInsertEquiv ha) m).snd)
            (_ : Set.Pairwise {b | b ∈ Multiset.map x ↑↑(↑(symInsertEquiv ha) m).snd} Commute)) *
      ↑(Nat.choose n ↑(↑(symInsertEquiv ha) m).fst)
[PROOFSTEP]
simp_rw [Multiset.noncommProd_add, m.1.1.filter_eq, Multiset.map_replicate, m.1.2]
[GOAL]
case insert
α : Type u_1
inst✝¹ : DecidableEq α
s✝ : Finset α
R : Type u_2
inst✝ : Semiring R
x : α → R
hc✝ : Set.Pairwise ↑s✝ fun i j => Commute (x i) (x j)
a : α
s : Finset α
ha : ¬a ∈ s
hc : Set.Pairwise ↑(insert a s) fun i j => Commute (x i) (x j)
n : ℕ
ih :
  ∀ (n : ℕ),
    Finset.sum s x ^ n =
      ∑ k : { x // x ∈ Finset.sym s n },
        ↑(Multiset.multinomial ↑↑k) *
          Multiset.noncommProd (Multiset.map x ↑↑k) (_ : Set.Pairwise {b | b ∈ Multiset.map x ↑↑k} Commute)
m : { x // x ∈ Finset.sym (insert a s) n }
⊢ ↑(Nat.choose n (Multiset.count a ↑↑m) * Multiset.multinomial (Multiset.filter (fun x => a ≠ x) ↑↑m)) *
      (Multiset.noncommProd (Multiset.replicate (Multiset.count a ↑↑m) (x a))
          (_ : Set.Pairwise {x_1 | x_1 ∈ Multiset.replicate (Multiset.count a ↑↑m) (x a)} Commute) *
        Multiset.noncommProd (Multiset.map x (Multiset.filter (fun a_1 => ¬a = a_1) ↑↑m))
          (_ : Set.Pairwise {x_1 | x_1 ∈ Multiset.map x (Multiset.filter (fun a_1 => ¬a = a_1) ↑↑m)} Commute)) =
    x a ^ ↑(↑(symInsertEquiv ha) m).fst *
        (↑(Multiset.multinomial ↑↑(↑(symInsertEquiv ha) m).snd) *
          Multiset.noncommProd (Multiset.map x ↑↑(↑(symInsertEquiv ha) m).snd)
            (_ : Set.Pairwise {b | b ∈ Multiset.map x ↑↑(↑(symInsertEquiv ha) m).snd} Commute)) *
      ↑(Nat.choose n ↑(↑(symInsertEquiv ha) m).fst)
[PROOFSTEP]
rw [Multiset.noncommProd_eq_pow_card _ _ _ fun _ => Multiset.eq_of_mem_replicate]
[GOAL]
case insert
α : Type u_1
inst✝¹ : DecidableEq α
s✝ : Finset α
R : Type u_2
inst✝ : Semiring R
x : α → R
hc✝ : Set.Pairwise ↑s✝ fun i j => Commute (x i) (x j)
a : α
s : Finset α
ha : ¬a ∈ s
hc : Set.Pairwise ↑(insert a s) fun i j => Commute (x i) (x j)
n : ℕ
ih :
  ∀ (n : ℕ),
    Finset.sum s x ^ n =
      ∑ k : { x // x ∈ Finset.sym s n },
        ↑(Multiset.multinomial ↑↑k) *
          Multiset.noncommProd (Multiset.map x ↑↑k) (_ : Set.Pairwise {b | b ∈ Multiset.map x ↑↑k} Commute)
m : { x // x ∈ Finset.sym (insert a s) n }
⊢ ↑(Nat.choose n (Multiset.count a ↑↑m) * Multiset.multinomial (Multiset.filter (fun x => a ≠ x) ↑↑m)) *
      (x a ^ ↑Multiset.card (Multiset.replicate (Multiset.count a ↑↑m) (x a)) *
        Multiset.noncommProd (Multiset.map x (Multiset.filter (fun a_1 => ¬a = a_1) ↑↑m))
          (_ : Set.Pairwise {x_1 | x_1 ∈ Multiset.map x (Multiset.filter (fun a_1 => ¬a = a_1) ↑↑m)} Commute)) =
    x a ^ ↑(↑(symInsertEquiv ha) m).fst *
        (↑(Multiset.multinomial ↑↑(↑(symInsertEquiv ha) m).snd) *
          Multiset.noncommProd (Multiset.map x ↑↑(↑(symInsertEquiv ha) m).snd)
            (_ : Set.Pairwise {b | b ∈ Multiset.map x ↑↑(↑(symInsertEquiv ha) m).snd} Commute)) *
      ↑(Nat.choose n ↑(↑(symInsertEquiv ha) m).fst)
[PROOFSTEP]
rw [Multiset.card_replicate, Nat.cast_mul, mul_assoc, Nat.cast_comm]
[GOAL]
case insert
α : Type u_1
inst✝¹ : DecidableEq α
s✝ : Finset α
R : Type u_2
inst✝ : Semiring R
x : α → R
hc✝ : Set.Pairwise ↑s✝ fun i j => Commute (x i) (x j)
a : α
s : Finset α
ha : ¬a ∈ s
hc : Set.Pairwise ↑(insert a s) fun i j => Commute (x i) (x j)
n : ℕ
ih :
  ∀ (n : ℕ),
    Finset.sum s x ^ n =
      ∑ k : { x // x ∈ Finset.sym s n },
        ↑(Multiset.multinomial ↑↑k) *
          Multiset.noncommProd (Multiset.map x ↑↑k) (_ : Set.Pairwise {b | b ∈ Multiset.map x ↑↑k} Commute)
m : { x // x ∈ Finset.sym (insert a s) n }
⊢ ↑(Multiset.multinomial (Multiset.filter (fun x => a ≠ x) ↑↑m)) *
        (x a ^ Multiset.count a ↑↑m *
          Multiset.noncommProd (Multiset.map x (Multiset.filter (fun a_1 => ¬a = a_1) ↑↑m))
            (_ : Set.Pairwise {x_1 | x_1 ∈ Multiset.map x (Multiset.filter (fun a_1 => ¬a = a_1) ↑↑m)} Commute)) *
      ↑(Nat.choose n (Multiset.count a ↑↑m)) =
    x a ^ ↑(↑(symInsertEquiv ha) m).fst *
        (↑(Multiset.multinomial ↑↑(↑(symInsertEquiv ha) m).snd) *
          Multiset.noncommProd (Multiset.map x ↑↑(↑(symInsertEquiv ha) m).snd)
            (_ : Set.Pairwise {b | b ∈ Multiset.map x ↑↑(↑(symInsertEquiv ha) m).snd} Commute)) *
      ↑(Nat.choose n ↑(↑(symInsertEquiv ha) m).fst)
[PROOFSTEP]
congr 1
[GOAL]
case insert.e_a
α : Type u_1
inst✝¹ : DecidableEq α
s✝ : Finset α
R : Type u_2
inst✝ : Semiring R
x : α → R
hc✝ : Set.Pairwise ↑s✝ fun i j => Commute (x i) (x j)
a : α
s : Finset α
ha : ¬a ∈ s
hc : Set.Pairwise ↑(insert a s) fun i j => Commute (x i) (x j)
n : ℕ
ih :
  ∀ (n : ℕ),
    Finset.sum s x ^ n =
      ∑ k : { x // x ∈ Finset.sym s n },
        ↑(Multiset.multinomial ↑↑k) *
          Multiset.noncommProd (Multiset.map x ↑↑k) (_ : Set.Pairwise {b | b ∈ Multiset.map x ↑↑k} Commute)
m : { x // x ∈ Finset.sym (insert a s) n }
⊢ ↑(Multiset.multinomial (Multiset.filter (fun x => a ≠ x) ↑↑m)) *
      (x a ^ Multiset.count a ↑↑m *
        Multiset.noncommProd (Multiset.map x (Multiset.filter (fun a_1 => ¬a = a_1) ↑↑m))
          (_ : Set.Pairwise {x_1 | x_1 ∈ Multiset.map x (Multiset.filter (fun a_1 => ¬a = a_1) ↑↑m)} Commute)) =
    x a ^ ↑(↑(symInsertEquiv ha) m).fst *
      (↑(Multiset.multinomial ↑↑(↑(symInsertEquiv ha) m).snd) *
        Multiset.noncommProd (Multiset.map x ↑↑(↑(symInsertEquiv ha) m).snd)
          (_ : Set.Pairwise {b | b ∈ Multiset.map x ↑↑(↑(symInsertEquiv ha) m).snd} Commute))
[PROOFSTEP]
simp_rw [← mul_assoc, Nat.cast_comm]
[GOAL]
case insert.e_a
α : Type u_1
inst✝¹ : DecidableEq α
s✝ : Finset α
R : Type u_2
inst✝ : Semiring R
x : α → R
hc✝ : Set.Pairwise ↑s✝ fun i j => Commute (x i) (x j)
a : α
s : Finset α
ha : ¬a ∈ s
hc : Set.Pairwise ↑(insert a s) fun i j => Commute (x i) (x j)
n : ℕ
ih :
  ∀ (n : ℕ),
    Finset.sum s x ^ n =
      ∑ k : { x // x ∈ Finset.sym s n },
        ↑(Multiset.multinomial ↑↑k) *
          Multiset.noncommProd (Multiset.map x ↑↑k) (_ : Set.Pairwise {b | b ∈ Multiset.map x ↑↑k} Commute)
m : { x // x ∈ Finset.sym (insert a s) n }
⊢ x a ^ Multiset.count a ↑↑m * ↑(Multiset.multinomial (Multiset.filter (fun x => a ≠ x) ↑↑m)) *
      Multiset.noncommProd (Multiset.map x (Multiset.filter (fun a_1 => ¬a = a_1) ↑↑m))
        (_ : Set.Pairwise {x_1 | x_1 ∈ Multiset.map x (Multiset.filter (fun a_1 => ¬a = a_1) ↑↑m)} Commute) =
    x a ^ ↑(↑(symInsertEquiv ha) m).fst * ↑(Multiset.multinomial ↑↑(↑(symInsertEquiv ha) m).snd) *
      Multiset.noncommProd (Multiset.map x ↑↑(↑(symInsertEquiv ha) m).snd)
        (_ : Set.Pairwise {b | b ∈ Multiset.map x ↑↑(↑(symInsertEquiv ha) m).snd} Commute)
[PROOFSTEP]
rfl
[GOAL]
α : Type u_1
inst✝¹ : DecidableEq α
s : Finset α
R : Type u_2
inst✝ : CommSemiring R
x : α → R
n : ℕ
⊢ Finset.sum s x ^ n = ∑ k in Finset.sym s n, ↑(Multiset.multinomial ↑k) * Multiset.prod (Multiset.map x ↑k)
[PROOFSTEP]
conv_rhs => rw [← sum_coe_sort]
[GOAL]
α : Type u_1
inst✝¹ : DecidableEq α
s : Finset α
R : Type u_2
inst✝ : CommSemiring R
x : α → R
n : ℕ
| ∑ k in Finset.sym s n, ↑(Multiset.multinomial ↑k) * Multiset.prod (Multiset.map x ↑k)
[PROOFSTEP]
rw [← sum_coe_sort]
[GOAL]
α : Type u_1
inst✝¹ : DecidableEq α
s : Finset α
R : Type u_2
inst✝ : CommSemiring R
x : α → R
n : ℕ
| ∑ k in Finset.sym s n, ↑(Multiset.multinomial ↑k) * Multiset.prod (Multiset.map x ↑k)
[PROOFSTEP]
rw [← sum_coe_sort]
[GOAL]
α : Type u_1
inst✝¹ : DecidableEq α
s : Finset α
R : Type u_2
inst✝ : CommSemiring R
x : α → R
n : ℕ
| ∑ k in Finset.sym s n, ↑(Multiset.multinomial ↑k) * Multiset.prod (Multiset.map x ↑k)
[PROOFSTEP]
rw [← sum_coe_sort]
[GOAL]
α : Type u_1
inst✝¹ : DecidableEq α
s : Finset α
R : Type u_2
inst✝ : CommSemiring R
x : α → R
n : ℕ
⊢ Finset.sum s x ^ n =
    ∑ i : { x // x ∈ Finset.sym s n }, ↑(Multiset.multinomial ↑↑i) * Multiset.prod (Multiset.map x ↑↑i)
[PROOFSTEP]
convert sum_pow_of_commute s x (fun _ _ _ _ _ => mul_comm _ _) n
[GOAL]
case h.e'_3.a.h.e'_6
α : Type u_1
inst✝¹ : DecidableEq α
s : Finset α
R : Type u_2
inst✝ : CommSemiring R
x : α → R
n : ℕ
x✝ : { x // x ∈ Finset.sym s n }
a✝ : x✝ ∈ univ
⊢ Multiset.prod (Multiset.map x ↑↑x✝) =
    Multiset.noncommProd (Multiset.map x ↑↑x✝) (_ : Set.Pairwise {b | b ∈ Multiset.map x ↑↑x✝} Commute)
[PROOFSTEP]
rw [Multiset.noncommProd_eq_prod]


[GOAL]
R : Type u_1
A : Type u_2
inst✝² : CommSemiring R
inst✝¹ : Semiring A
inst✝ : Algebra R A
S T : Subalgebra R A
⊢ ↑toSubmodule S * ↑toSubmodule T ≤ ↑toSubmodule (S ⊔ T)
[PROOFSTEP]
rw [Submodule.mul_le]
[GOAL]
R : Type u_1
A : Type u_2
inst✝² : CommSemiring R
inst✝¹ : Semiring A
inst✝ : Algebra R A
S T : Subalgebra R A
⊢ ∀ (m : A), m ∈ ↑toSubmodule S → ∀ (n : A), n ∈ ↑toSubmodule T → m * n ∈ ↑toSubmodule (S ⊔ T)
[PROOFSTEP]
intro y hy z hz
[GOAL]
R : Type u_1
A : Type u_2
inst✝² : CommSemiring R
inst✝¹ : Semiring A
inst✝ : Algebra R A
S T : Subalgebra R A
y : A
hy : y ∈ ↑toSubmodule S
z : A
hz : z ∈ ↑toSubmodule T
⊢ y * z ∈ ↑toSubmodule (S ⊔ T)
[PROOFSTEP]
show y * z ∈ S ⊔ T
[GOAL]
R : Type u_1
A : Type u_2
inst✝² : CommSemiring R
inst✝¹ : Semiring A
inst✝ : Algebra R A
S T : Subalgebra R A
y : A
hy : y ∈ ↑toSubmodule S
z : A
hz : z ∈ ↑toSubmodule T
⊢ y * z ∈ S ⊔ T
[PROOFSTEP]
exact mul_mem (Algebra.mem_sup_left hy) (Algebra.mem_sup_right hz)
[GOAL]
R : Type u_1
A : Type u_2
inst✝² : CommSemiring R
inst✝¹ : Semiring A
inst✝ : Algebra R A
S : Subalgebra R A
⊢ ↑toSubmodule S * ↑toSubmodule S = ↑toSubmodule S
[PROOFSTEP]
apply le_antisymm
[GOAL]
case a
R : Type u_1
A : Type u_2
inst✝² : CommSemiring R
inst✝¹ : Semiring A
inst✝ : Algebra R A
S : Subalgebra R A
⊢ ↑toSubmodule S * ↑toSubmodule S ≤ ↑toSubmodule S
[PROOFSTEP]
refine' (mul_toSubmodule_le _ _).trans_eq _
[GOAL]
case a
R : Type u_1
A : Type u_2
inst✝² : CommSemiring R
inst✝¹ : Semiring A
inst✝ : Algebra R A
S : Subalgebra R A
⊢ ↑toSubmodule (S ⊔ S) = ↑toSubmodule S
[PROOFSTEP]
rw [sup_idem]
[GOAL]
case a
R : Type u_1
A : Type u_2
inst✝² : CommSemiring R
inst✝¹ : Semiring A
inst✝ : Algebra R A
S : Subalgebra R A
⊢ ↑toSubmodule S ≤ ↑toSubmodule S * ↑toSubmodule S
[PROOFSTEP]
intro x hx1
[GOAL]
case a
R : Type u_1
A : Type u_2
inst✝² : CommSemiring R
inst✝¹ : Semiring A
inst✝ : Algebra R A
S : Subalgebra R A
x : A
hx1 : x ∈ ↑toSubmodule S
⊢ x ∈ ↑toSubmodule S * ↑toSubmodule S
[PROOFSTEP]
rw [← mul_one x]
[GOAL]
case a
R : Type u_1
A : Type u_2
inst✝² : CommSemiring R
inst✝¹ : Semiring A
inst✝ : Algebra R A
S : Subalgebra R A
x : A
hx1 : x ∈ ↑toSubmodule S
⊢ x * 1 ∈ ↑toSubmodule S * ↑toSubmodule S
[PROOFSTEP]
exact Submodule.mul_mem_mul hx1 (show (1 : A) ∈ S from one_mem S)
[GOAL]
R✝ : Type u_1
A✝ : Type u_2
inst✝⁵ : CommSemiring R✝
inst✝⁴ : Semiring A✝
inst✝³ : Algebra R✝ A✝
R : Type u_3
A : Type u_4
inst✝² : CommSemiring R
inst✝¹ : CommSemiring A
inst✝ : Algebra R A
S T : Subalgebra R A
⊢ ↑toSubmodule S * ↑toSubmodule T = ↑toSubmodule (S ⊔ T)
[PROOFSTEP]
refine' le_antisymm (mul_toSubmodule_le _ _) _
[GOAL]
R✝ : Type u_1
A✝ : Type u_2
inst✝⁵ : CommSemiring R✝
inst✝⁴ : Semiring A✝
inst✝³ : Algebra R✝ A✝
R : Type u_3
A : Type u_4
inst✝² : CommSemiring R
inst✝¹ : CommSemiring A
inst✝ : Algebra R A
S T : Subalgebra R A
⊢ ↑toSubmodule (S ⊔ T) ≤ ↑toSubmodule S * ↑toSubmodule T
[PROOFSTEP]
rintro x (hx : x ∈ Algebra.adjoin R (S ∪ T : Set A))
[GOAL]
R✝ : Type u_1
A✝ : Type u_2
inst✝⁵ : CommSemiring R✝
inst✝⁴ : Semiring A✝
inst✝³ : Algebra R✝ A✝
R : Type u_3
A : Type u_4
inst✝² : CommSemiring R
inst✝¹ : CommSemiring A
inst✝ : Algebra R A
S T : Subalgebra R A
x : A
hx : x ∈ Algebra.adjoin R (↑S ∪ ↑T)
⊢ x ∈ ↑toSubmodule S * ↑toSubmodule T
[PROOFSTEP]
refine' Algebra.adjoin_induction hx (fun x hx => _) (fun r => _) (fun _ _ => Submodule.add_mem _) fun x y hx hy => _
[GOAL]
case refine'_1
R✝ : Type u_1
A✝ : Type u_2
inst✝⁵ : CommSemiring R✝
inst✝⁴ : Semiring A✝
inst✝³ : Algebra R✝ A✝
R : Type u_3
A : Type u_4
inst✝² : CommSemiring R
inst✝¹ : CommSemiring A
inst✝ : Algebra R A
S T : Subalgebra R A
x✝ : A
hx✝ : x✝ ∈ Algebra.adjoin R (↑S ∪ ↑T)
x : A
hx : x ∈ ↑S ∪ ↑T
⊢ x ∈ ↑toSubmodule S * ↑toSubmodule T
[PROOFSTEP]
cases' hx with hxS hxT
[GOAL]
case refine'_1.inl
R✝ : Type u_1
A✝ : Type u_2
inst✝⁵ : CommSemiring R✝
inst✝⁴ : Semiring A✝
inst✝³ : Algebra R✝ A✝
R : Type u_3
A : Type u_4
inst✝² : CommSemiring R
inst✝¹ : CommSemiring A
inst✝ : Algebra R A
S T : Subalgebra R A
x✝ : A
hx : x✝ ∈ Algebra.adjoin R (↑S ∪ ↑T)
x : A
hxS : x ∈ ↑S
⊢ x ∈ ↑toSubmodule S * ↑toSubmodule T
[PROOFSTEP]
rw [← mul_one x]
[GOAL]
case refine'_1.inl
R✝ : Type u_1
A✝ : Type u_2
inst✝⁵ : CommSemiring R✝
inst✝⁴ : Semiring A✝
inst✝³ : Algebra R✝ A✝
R : Type u_3
A : Type u_4
inst✝² : CommSemiring R
inst✝¹ : CommSemiring A
inst✝ : Algebra R A
S T : Subalgebra R A
x✝ : A
hx : x✝ ∈ Algebra.adjoin R (↑S ∪ ↑T)
x : A
hxS : x ∈ ↑S
⊢ x * 1 ∈ ↑toSubmodule S * ↑toSubmodule T
[PROOFSTEP]
exact Submodule.mul_mem_mul hxS (show (1 : A) ∈ T from one_mem T)
[GOAL]
case refine'_1.inr
R✝ : Type u_1
A✝ : Type u_2
inst✝⁵ : CommSemiring R✝
inst✝⁴ : Semiring A✝
inst✝³ : Algebra R✝ A✝
R : Type u_3
A : Type u_4
inst✝² : CommSemiring R
inst✝¹ : CommSemiring A
inst✝ : Algebra R A
S T : Subalgebra R A
x✝ : A
hx : x✝ ∈ Algebra.adjoin R (↑S ∪ ↑T)
x : A
hxT : x ∈ ↑T
⊢ x ∈ ↑toSubmodule S * ↑toSubmodule T
[PROOFSTEP]
rw [← one_mul x]
[GOAL]
case refine'_1.inr
R✝ : Type u_1
A✝ : Type u_2
inst✝⁵ : CommSemiring R✝
inst✝⁴ : Semiring A✝
inst✝³ : Algebra R✝ A✝
R : Type u_3
A : Type u_4
inst✝² : CommSemiring R
inst✝¹ : CommSemiring A
inst✝ : Algebra R A
S T : Subalgebra R A
x✝ : A
hx : x✝ ∈ Algebra.adjoin R (↑S ∪ ↑T)
x : A
hxT : x ∈ ↑T
⊢ 1 * x ∈ ↑toSubmodule S * ↑toSubmodule T
[PROOFSTEP]
exact Submodule.mul_mem_mul (show (1 : A) ∈ S from one_mem S) hxT
[GOAL]
case refine'_2
R✝ : Type u_1
A✝ : Type u_2
inst✝⁵ : CommSemiring R✝
inst✝⁴ : Semiring A✝
inst✝³ : Algebra R✝ A✝
R : Type u_3
A : Type u_4
inst✝² : CommSemiring R
inst✝¹ : CommSemiring A
inst✝ : Algebra R A
S T : Subalgebra R A
x : A
hx : x ∈ Algebra.adjoin R (↑S ∪ ↑T)
r : R
⊢ ↑(algebraMap R A) r ∈ ↑toSubmodule S * ↑toSubmodule T
[PROOFSTEP]
rw [← one_mul (algebraMap _ _ _)]
[GOAL]
case refine'_2
R✝ : Type u_1
A✝ : Type u_2
inst✝⁵ : CommSemiring R✝
inst✝⁴ : Semiring A✝
inst✝³ : Algebra R✝ A✝
R : Type u_3
A : Type u_4
inst✝² : CommSemiring R
inst✝¹ : CommSemiring A
inst✝ : Algebra R A
S T : Subalgebra R A
x : A
hx : x ∈ Algebra.adjoin R (↑S ∪ ↑T)
r : R
⊢ 1 * ↑(algebraMap R A) r ∈ ↑toSubmodule S * ↑toSubmodule T
[PROOFSTEP]
exact Submodule.mul_mem_mul (show (1 : A) ∈ S from one_mem S) (algebraMap_mem T _)
[GOAL]
case refine'_3
R✝ : Type u_1
A✝ : Type u_2
inst✝⁵ : CommSemiring R✝
inst✝⁴ : Semiring A✝
inst✝³ : Algebra R✝ A✝
R : Type u_3
A : Type u_4
inst✝² : CommSemiring R
inst✝¹ : CommSemiring A
inst✝ : Algebra R A
S T : Subalgebra R A
x✝ : A
hx✝ : x✝ ∈ Algebra.adjoin R (↑S ∪ ↑T)
x y : A
hx : x ∈ ↑toSubmodule S * ↑toSubmodule T
hy : y ∈ ↑toSubmodule S * ↑toSubmodule T
⊢ x * y ∈ ↑toSubmodule S * ↑toSubmodule T
[PROOFSTEP]
have := Submodule.mul_mem_mul hx hy
[GOAL]
case refine'_3
R✝ : Type u_1
A✝ : Type u_2
inst✝⁵ : CommSemiring R✝
inst✝⁴ : Semiring A✝
inst✝³ : Algebra R✝ A✝
R : Type u_3
A : Type u_4
inst✝² : CommSemiring R
inst✝¹ : CommSemiring A
inst✝ : Algebra R A
S T : Subalgebra R A
x✝ : A
hx✝ : x✝ ∈ Algebra.adjoin R (↑S ∪ ↑T)
x y : A
hx : x ∈ ↑toSubmodule S * ↑toSubmodule T
hy : y ∈ ↑toSubmodule S * ↑toSubmodule T
this : x * y ∈ ↑toSubmodule S * ↑toSubmodule T * (↑toSubmodule S * ↑toSubmodule T)
⊢ x * y ∈ ↑toSubmodule S * ↑toSubmodule T
[PROOFSTEP]
rwa [mul_assoc, mul_comm _ (Subalgebra.toSubmodule T), ← mul_assoc _ _ (Subalgebra.toSubmodule S), mul_self,
  mul_comm (Subalgebra.toSubmodule T), ← mul_assoc, mul_self] at this


[GOAL]
C : Type u₁
inst✝ : Category.{v₁, u₁} C
W X Y Z : C
f : W ⟶ X
g : W ⟶ Y
h : X ⟶ Z
i : Y ⟶ Z
p : CommSq f g h i
⊢ PushoutCocone.inl (PullbackCone.op (cone p)) ≫ (Iso.refl (PullbackCone.op (cone p)).pt).hom =
    PushoutCocone.inl (cocone (_ : CommSq h.op i.op f.op g.op))
[PROOFSTEP]
aesop_cat
[GOAL]
C : Type u₁
inst✝ : Category.{v₁, u₁} C
W X Y Z : C
f : W ⟶ X
g : W ⟶ Y
h : X ⟶ Z
i : Y ⟶ Z
p : CommSq f g h i
⊢ PushoutCocone.inr (PullbackCone.op (cone p)) ≫ (Iso.refl (PullbackCone.op (cone p)).pt).hom =
    PushoutCocone.inr (cocone (_ : CommSq h.op i.op f.op g.op))
[PROOFSTEP]
aesop_cat
[GOAL]
C : Type u₁
inst✝ : Category.{v₁, u₁} C
W X Y Z : C
f : W ⟶ X
g : W ⟶ Y
h : X ⟶ Z
i : Y ⟶ Z
p : CommSq f g h i
⊢ PullbackCone.fst (PushoutCocone.op (cocone p)) =
    (Iso.refl (PushoutCocone.op (cocone p)).pt).hom ≫ PullbackCone.fst (cone (_ : CommSq h.op i.op f.op g.op))
[PROOFSTEP]
aesop_cat
[GOAL]
C : Type u₁
inst✝ : Category.{v₁, u₁} C
W X Y Z : C
f : W ⟶ X
g : W ⟶ Y
h : X ⟶ Z
i : Y ⟶ Z
p : CommSq f g h i
⊢ PullbackCone.snd (PushoutCocone.op (cocone p)) =
    (Iso.refl (PushoutCocone.op (cocone p)).pt).hom ≫ PullbackCone.snd (cone (_ : CommSq h.op i.op f.op g.op))
[PROOFSTEP]
aesop_cat
[GOAL]
C : Type u₁
inst✝ : Category.{v₁, u₁} C
W✝ X✝ Y✝ Z✝ : C
f✝ : W✝ ⟶ X✝
g✝ : W✝ ⟶ Y✝
h✝ : X✝ ⟶ Z✝
i✝ : Y✝ ⟶ Z✝
W X Y Z : Cᵒᵖ
f : W ⟶ X
g : W ⟶ Y
h : X ⟶ Z
i : Y ⟶ Z
p : CommSq f g h i
⊢ PushoutCocone.inl (PullbackCone.unop (cone p)) ≫ (Iso.refl (PullbackCone.unop (cone p)).pt).hom =
    PushoutCocone.inl (cocone (_ : CommSq h.unop i.unop f.unop g.unop))
[PROOFSTEP]
aesop_cat
[GOAL]
C : Type u₁
inst✝ : Category.{v₁, u₁} C
W✝ X✝ Y✝ Z✝ : C
f✝ : W✝ ⟶ X✝
g✝ : W✝ ⟶ Y✝
h✝ : X✝ ⟶ Z✝
i✝ : Y✝ ⟶ Z✝
W X Y Z : Cᵒᵖ
f : W ⟶ X
g : W ⟶ Y
h : X ⟶ Z
i : Y ⟶ Z
p : CommSq f g h i
⊢ PushoutCocone.inr (PullbackCone.unop (cone p)) ≫ (Iso.refl (PullbackCone.unop (cone p)).pt).hom =
    PushoutCocone.inr (cocone (_ : CommSq h.unop i.unop f.unop g.unop))
[PROOFSTEP]
aesop_cat
[GOAL]
C : Type u₁
inst✝ : Category.{v₁, u₁} C
W✝ X✝ Y✝ Z✝ : C
f✝ : W✝ ⟶ X✝
g✝ : W✝ ⟶ Y✝
h✝ : X✝ ⟶ Z✝
i✝ : Y✝ ⟶ Z✝
W X Y Z : Cᵒᵖ
f : W ⟶ X
g : W ⟶ Y
h : X ⟶ Z
i : Y ⟶ Z
p : CommSq f g h i
⊢ PullbackCone.fst (PushoutCocone.unop (cocone p)) =
    (Iso.refl (PushoutCocone.unop (cocone p)).pt).hom ≫ PullbackCone.fst (cone (_ : CommSq h.unop i.unop f.unop g.unop))
[PROOFSTEP]
aesop_cat
[GOAL]
C : Type u₁
inst✝ : Category.{v₁, u₁} C
W✝ X✝ Y✝ Z✝ : C
f✝ : W✝ ⟶ X✝
g✝ : W✝ ⟶ Y✝
h✝ : X✝ ⟶ Z✝
i✝ : Y✝ ⟶ Z✝
W X Y Z : Cᵒᵖ
f : W ⟶ X
g : W ⟶ Y
h : X ⟶ Z
i : Y ⟶ Z
p : CommSq f g h i
⊢ PullbackCone.snd (PushoutCocone.unop (cocone p)) =
    (Iso.refl (PushoutCocone.unop (cocone p)).pt).hom ≫ PullbackCone.snd (cone (_ : CommSq h.unop i.unop f.unop g.unop))
[PROOFSTEP]
aesop_cat
[GOAL]
C : Type u₁
inst✝ : Category.{v₁, u₁} C
P X Y Z : C
fst : P ⟶ X
snd : P ⟶ Y
f : X ⟶ Z
g : Y ⟶ Z
c : PullbackCone f g
h : IsLimit c
⊢ PullbackCone.fst c =
    (Iso.refl c.pt).hom ≫
      PullbackCone.fst
        (PullbackCone.mk (PullbackCone.fst c) (PullbackCone.snd c)
          (_ : PullbackCone.fst c ≫ f = PullbackCone.snd c ≫ g))
[PROOFSTEP]
aesop_cat
[GOAL]
C : Type u₁
inst✝ : Category.{v₁, u₁} C
P X Y Z : C
fst : P ⟶ X
snd : P ⟶ Y
f : X ⟶ Z
g : Y ⟶ Z
c : PullbackCone f g
h : IsLimit c
⊢ PullbackCone.snd c =
    (Iso.refl c.pt).hom ≫
      PullbackCone.snd
        (PullbackCone.mk (PullbackCone.fst c) (PullbackCone.snd c)
          (_ : PullbackCone.fst c ≫ f = PullbackCone.snd c ≫ g))
[PROOFSTEP]
aesop_cat
[GOAL]
C : Type u₁
inst✝ : Category.{v₁, u₁} C
P X Y Z : C
fst : P ⟶ X
snd : P ⟶ Y
f : X ⟶ Z
g : Y ⟶ Z
c : BinaryFan X Y
h : IsLimit c
t : IsTerminal Z
⊢ ∀ (j : Discrete WalkingPair),
    NatTrans.app c.π j =
      (Iso.refl c.pt).hom ≫
        NatTrans.app (BinaryFan.mk (c.π.1 { as := WalkingPair.left }) (c.π.1 { as := WalkingPair.right })).π j
[PROOFSTEP]
rintro ⟨⟨⟩⟩
[GOAL]
case mk.left
C : Type u₁
inst✝ : Category.{v₁, u₁} C
P X Y Z : C
fst : P ⟶ X
snd : P ⟶ Y
f : X ⟶ Z
g : Y ⟶ Z
c : BinaryFan X Y
h : IsLimit c
t : IsTerminal Z
⊢ NatTrans.app c.π { as := WalkingPair.left } =
    (Iso.refl c.pt).hom ≫
      NatTrans.app (BinaryFan.mk (c.π.1 { as := WalkingPair.left }) (c.π.1 { as := WalkingPair.right })).π
        { as := WalkingPair.left }
[PROOFSTEP]
dsimp
[GOAL]
case mk.left
C : Type u₁
inst✝ : Category.{v₁, u₁} C
P X Y Z : C
fst : P ⟶ X
snd : P ⟶ Y
f : X ⟶ Z
g : Y ⟶ Z
c : BinaryFan X Y
h : IsLimit c
t : IsTerminal Z
⊢ BinaryFan.fst c = 𝟙 c.pt ≫ BinaryFan.fst c
[PROOFSTEP]
simp
[GOAL]
case mk.right
C : Type u₁
inst✝ : Category.{v₁, u₁} C
P X Y Z : C
fst : P ⟶ X
snd : P ⟶ Y
f : X ⟶ Z
g : Y ⟶ Z
c : BinaryFan X Y
h : IsLimit c
t : IsTerminal Z
⊢ NatTrans.app c.π { as := WalkingPair.right } =
    (Iso.refl c.pt).hom ≫
      NatTrans.app (BinaryFan.mk (c.π.1 { as := WalkingPair.left }) (c.π.1 { as := WalkingPair.right })).π
        { as := WalkingPair.right }
[PROOFSTEP]
dsimp
[GOAL]
case mk.right
C : Type u₁
inst✝ : Category.{v₁, u₁} C
P X Y Z : C
fst : P ⟶ X
snd : P ⟶ Y
f : X ⟶ Z
g : Y ⟶ Z
c : BinaryFan X Y
h : IsLimit c
t : IsTerminal Z
⊢ BinaryFan.snd c = 𝟙 c.pt ≫ BinaryFan.snd c
[PROOFSTEP]
simp
[GOAL]
C : Type u₁
inst✝³ : Category.{v₁, u₁} C
P X Y Z : C
fst : P ⟶ X
snd : P ⟶ Y
f : X ⟶ Z
g : Y ⟶ Z
inst✝² : HasBinaryProduct X Y
inst✝¹ : HasZeroObject C
inst✝ : HasZeroMorphisms C
⊢ IsPullback prod.fst prod.snd 0 0
[PROOFSTEP]
convert @of_is_product _ _ X Y 0 _ (limit.isLimit _) HasZeroObject.zeroIsTerminal
[GOAL]
C : Type u₁
inst✝¹ : Category.{v₁, u₁} C
P X Y Z : C
fst : P ⟶ X
snd : P ⟶ Y
f : X ⟶ Z
g : Y ⟶ Z
h : IsPullback fst snd f g
inst✝ : HasPullback f g
⊢ (isoPullback h).hom ≫ pullback.fst = fst
[PROOFSTEP]
dsimp [isoPullback, cone, CommSq.cone]
[GOAL]
C : Type u₁
inst✝¹ : Category.{v₁, u₁} C
P X Y Z : C
fst : P ⟶ X
snd : P ⟶ Y
f : X ⟶ Z
g : Y ⟶ Z
h : IsPullback fst snd f g
inst✝ : HasPullback f g
⊢ (limit.isoLimitCone { cone := PullbackCone.mk fst snd (_ : fst ≫ f = snd ≫ g), isLimit := isLimit h }).inv ≫
      pullback.fst =
    fst
[PROOFSTEP]
simp
[GOAL]
C : Type u₁
inst✝¹ : Category.{v₁, u₁} C
P X Y Z : C
fst : P ⟶ X
snd : P ⟶ Y
f : X ⟶ Z
g : Y ⟶ Z
h : IsPullback fst snd f g
inst✝ : HasPullback f g
⊢ (isoPullback h).hom ≫ pullback.snd = snd
[PROOFSTEP]
dsimp [isoPullback, cone, CommSq.cone]
[GOAL]
C : Type u₁
inst✝¹ : Category.{v₁, u₁} C
P X Y Z : C
fst : P ⟶ X
snd : P ⟶ Y
f : X ⟶ Z
g : Y ⟶ Z
h : IsPullback fst snd f g
inst✝ : HasPullback f g
⊢ (limit.isoLimitCone { cone := PullbackCone.mk fst snd (_ : fst ≫ f = snd ≫ g), isLimit := isLimit h }).inv ≫
      pullback.snd =
    snd
[PROOFSTEP]
simp
[GOAL]
C : Type u₁
inst✝¹ : Category.{v₁, u₁} C
P X Y Z : C
fst : P ⟶ X
snd : P ⟶ Y
f : X ⟶ Z
g : Y ⟶ Z
h : IsPullback fst snd f g
inst✝ : HasPullback f g
⊢ (isoPullback h).inv ≫ fst = pullback.fst
[PROOFSTEP]
simp [Iso.inv_comp_eq]
[GOAL]
C : Type u₁
inst✝¹ : Category.{v₁, u₁} C
P X Y Z : C
fst : P ⟶ X
snd : P ⟶ Y
f : X ⟶ Z
g : Y ⟶ Z
h : IsPullback fst snd f g
inst✝ : HasPullback f g
⊢ (isoPullback h).inv ≫ snd = pullback.snd
[PROOFSTEP]
simp [Iso.inv_comp_eq]
[GOAL]
C : Type u₁
inst✝² : Category.{v₁, u₁} C
P X Y Z : C
fst : P ⟶ X
snd : P ⟶ Y
f : X ⟶ Z
g : Y ⟶ Z
inst✝¹ : IsIso fst
inst✝ : IsIso g
sq : CommSq fst snd f g
⊢ IsLimit (CommSq.cone sq)
[PROOFSTEP]
refine' PullbackCone.IsLimit.mk _ (fun s => s.fst ≫ inv fst) (by aesop_cat) (fun s => _) (by aesop_cat)
[GOAL]
C : Type u₁
inst✝² : Category.{v₁, u₁} C
P X Y Z : C
fst : P ⟶ X
snd : P ⟶ Y
f : X ⟶ Z
g : Y ⟶ Z
inst✝¹ : IsIso fst
inst✝ : IsIso g
sq : CommSq fst snd f g
⊢ ∀ (s : PullbackCone f g), (fun s => PullbackCone.fst s ≫ inv fst) s ≫ fst = PullbackCone.fst s
[PROOFSTEP]
aesop_cat
[GOAL]
C : Type u₁
inst✝² : Category.{v₁, u₁} C
P X Y Z : C
fst : P ⟶ X
snd : P ⟶ Y
f : X ⟶ Z
g : Y ⟶ Z
inst✝¹ : IsIso fst
inst✝ : IsIso g
sq : CommSq fst snd f g
⊢ ∀ (s : PullbackCone f g) (m : s.pt ⟶ P),
    m ≫ fst = PullbackCone.fst s → m ≫ snd = PullbackCone.snd s → m = (fun s => PullbackCone.fst s ≫ inv fst) s
[PROOFSTEP]
aesop_cat
[GOAL]
C : Type u₁
inst✝² : Category.{v₁, u₁} C
P X Y Z : C
fst : P ⟶ X
snd : P ⟶ Y
f : X ⟶ Z
g : Y ⟶ Z
inst✝¹ : IsIso fst
inst✝ : IsIso g
sq : CommSq fst snd f g
s : PullbackCone f g
⊢ (fun s => PullbackCone.fst s ≫ inv fst) s ≫ snd = PullbackCone.snd s
[PROOFSTEP]
simp only [← cancel_mono g, Category.assoc, ← sq.w, IsIso.inv_hom_id_assoc, s.condition]
[GOAL]
C : Type u₁
inst✝ : Category.{v₁, u₁} C
Z X Y P : C
f : Z ⟶ X
g : Z ⟶ Y
inl : X ⟶ P
inr : Y ⟶ P
c : PushoutCocone f g
h : IsColimit c
⊢ PushoutCocone.inl c ≫ (Iso.refl c.pt).hom =
    PushoutCocone.inl
      (PushoutCocone.mk (PushoutCocone.inl c) (PushoutCocone.inr c)
        (_ : f ≫ PushoutCocone.inl c = g ≫ PushoutCocone.inr c))
[PROOFSTEP]
aesop_cat
[GOAL]
C : Type u₁
inst✝ : Category.{v₁, u₁} C
Z X Y P : C
f : Z ⟶ X
g : Z ⟶ Y
inl : X ⟶ P
inr : Y ⟶ P
c : PushoutCocone f g
h : IsColimit c
⊢ PushoutCocone.inr c ≫ (Iso.refl c.pt).hom =
    PushoutCocone.inr
      (PushoutCocone.mk (PushoutCocone.inl c) (PushoutCocone.inr c)
        (_ : f ≫ PushoutCocone.inl c = g ≫ PushoutCocone.inr c))
[PROOFSTEP]
aesop_cat
[GOAL]
C : Type u₁
inst✝ : Category.{v₁, u₁} C
Z X Y P : C
f : Z ⟶ X
g : Z ⟶ Y
inl : X ⟶ P
inr : Y ⟶ P
c : BinaryCofan X Y
h : IsColimit c
t : IsInitial Z
⊢ ∀ (j : Discrete WalkingPair),
    NatTrans.app c.ι j ≫ (Iso.refl c.pt).hom =
      NatTrans.app (BinaryCofan.mk (c.ι.1 { as := WalkingPair.left }) (c.ι.1 { as := WalkingPair.right })).ι j
[PROOFSTEP]
rintro ⟨⟨⟩⟩
[GOAL]
case mk.left
C : Type u₁
inst✝ : Category.{v₁, u₁} C
Z X Y P : C
f : Z ⟶ X
g : Z ⟶ Y
inl : X ⟶ P
inr : Y ⟶ P
c : BinaryCofan X Y
h : IsColimit c
t : IsInitial Z
⊢ NatTrans.app c.ι { as := WalkingPair.left } ≫ (Iso.refl c.pt).hom =
    NatTrans.app (BinaryCofan.mk (c.ι.1 { as := WalkingPair.left }) (c.ι.1 { as := WalkingPair.right })).ι
      { as := WalkingPair.left }
[PROOFSTEP]
dsimp
[GOAL]
case mk.left
C : Type u₁
inst✝ : Category.{v₁, u₁} C
Z X Y P : C
f : Z ⟶ X
g : Z ⟶ Y
inl : X ⟶ P
inr : Y ⟶ P
c : BinaryCofan X Y
h : IsColimit c
t : IsInitial Z
⊢ BinaryCofan.inl c ≫ 𝟙 c.pt = BinaryCofan.inl c
[PROOFSTEP]
simp
[GOAL]
case mk.right
C : Type u₁
inst✝ : Category.{v₁, u₁} C
Z X Y P : C
f : Z ⟶ X
g : Z ⟶ Y
inl : X ⟶ P
inr : Y ⟶ P
c : BinaryCofan X Y
h : IsColimit c
t : IsInitial Z
⊢ NatTrans.app c.ι { as := WalkingPair.right } ≫ (Iso.refl c.pt).hom =
    NatTrans.app (BinaryCofan.mk (c.ι.1 { as := WalkingPair.left }) (c.ι.1 { as := WalkingPair.right })).ι
      { as := WalkingPair.right }
[PROOFSTEP]
dsimp
[GOAL]
case mk.right
C : Type u₁
inst✝ : Category.{v₁, u₁} C
Z X Y P : C
f : Z ⟶ X
g : Z ⟶ Y
inl : X ⟶ P
inr : Y ⟶ P
c : BinaryCofan X Y
h : IsColimit c
t : IsInitial Z
⊢ BinaryCofan.inr c ≫ 𝟙 c.pt = BinaryCofan.inr c
[PROOFSTEP]
simp
[GOAL]
C : Type u₁
inst✝³ : Category.{v₁, u₁} C
Z X Y P : C
f : Z ⟶ X
g : Z ⟶ Y
inl : X ⟶ P
inr : Y ⟶ P
inst✝² : HasBinaryCoproduct X Y
inst✝¹ : HasZeroObject C
inst✝ : HasZeroMorphisms C
⊢ IsPushout 0 0 coprod.inl coprod.inr
[PROOFSTEP]
convert @of_is_coproduct _ _ 0 X Y _ (colimit.isColimit _) HasZeroObject.zeroIsInitial
[GOAL]
C : Type u₁
inst✝¹ : Category.{v₁, u₁} C
Z X Y P : C
f : Z ⟶ X
g : Z ⟶ Y
inl : X ⟶ P
inr : Y ⟶ P
h : IsPushout f g inl inr
inst✝ : HasPushout f g
⊢ pushout.inl ≫ (isoPushout h).inv = inl
[PROOFSTEP]
dsimp [isoPushout, cocone, CommSq.cocone]
[GOAL]
C : Type u₁
inst✝¹ : Category.{v₁, u₁} C
Z X Y P : C
f : Z ⟶ X
g : Z ⟶ Y
inl : X ⟶ P
inr : Y ⟶ P
h : IsPushout f g inl inr
inst✝ : HasPushout f g
⊢ pushout.inl ≫
      (colimit.isoColimitCocone
          { cocone := PushoutCocone.mk inl inr (_ : f ≫ inl = g ≫ inr), isColimit := isColimit h }).hom =
    inl
[PROOFSTEP]
simp
[GOAL]
C : Type u₁
inst✝¹ : Category.{v₁, u₁} C
Z X Y P : C
f : Z ⟶ X
g : Z ⟶ Y
inl : X ⟶ P
inr : Y ⟶ P
h : IsPushout f g inl inr
inst✝ : HasPushout f g
⊢ pushout.inr ≫ (isoPushout h).inv = inr
[PROOFSTEP]
dsimp [isoPushout, cocone, CommSq.cocone]
[GOAL]
C : Type u₁
inst✝¹ : Category.{v₁, u₁} C
Z X Y P : C
f : Z ⟶ X
g : Z ⟶ Y
inl : X ⟶ P
inr : Y ⟶ P
h : IsPushout f g inl inr
inst✝ : HasPushout f g
⊢ pushout.inr ≫
      (colimit.isoColimitCocone
          { cocone := PushoutCocone.mk inl inr (_ : f ≫ inl = g ≫ inr), isColimit := isColimit h }).hom =
    inr
[PROOFSTEP]
simp
[GOAL]
C : Type u₁
inst✝¹ : Category.{v₁, u₁} C
Z X Y P : C
f : Z ⟶ X
g : Z ⟶ Y
inl : X ⟶ P
inr : Y ⟶ P
h : IsPushout f g inl inr
inst✝ : HasPushout f g
⊢ inl ≫ (isoPushout h).hom = pushout.inl
[PROOFSTEP]
simp [← Iso.eq_comp_inv]
[GOAL]
C : Type u₁
inst✝¹ : Category.{v₁, u₁} C
Z X Y P : C
f : Z ⟶ X
g : Z ⟶ Y
inl : X ⟶ P
inr : Y ⟶ P
h : IsPushout f g inl inr
inst✝ : HasPushout f g
⊢ inr ≫ (isoPushout h).hom = pushout.inr
[PROOFSTEP]
simp [← Iso.eq_comp_inv]
[GOAL]
C : Type u₁
inst✝² : Category.{v₁, u₁} C
P X✝ Y Z : C
fst : P ⟶ X✝
snd : P ⟶ Y
f : X✝ ⟶ Z
g : Y ⟶ Z
inst✝¹ : HasZeroObject C
inst✝ : HasZeroMorphisms C
X : C
⊢ 0 ≫ 𝟙 X = 0 ≫ 0
[PROOFSTEP]
simp
[GOAL]
C : Type u₁
inst✝² : Category.{v₁, u₁} C
P X✝ Y Z : C
fst : P ⟶ X✝
snd : P ⟶ Y
f : X✝ ⟶ Z
g : Y ⟶ Z
inst✝¹ : HasZeroObject C
inst✝ : HasZeroMorphisms C
X : C
s : Cone (cospan (𝟙 X) 0)
⊢ ∀ (j : WalkingCospan),
    (fun s => 0) s ≫ NatTrans.app (PullbackCone.mk 0 0 (_ : 0 ≫ 𝟙 X = 0 ≫ 0)).π j = NatTrans.app s.π j
[PROOFSTEP]
simpa using @PullbackCone.equalizer_ext _ _ _ _ _ _ _ s _ 0 (𝟙 _) (by simpa using (PullbackCone.condition s).symm)
[GOAL]
C : Type u₁
inst✝² : Category.{v₁, u₁} C
P X✝ Y Z : C
fst : P ⟶ X✝
snd : P ⟶ Y
f : X✝ ⟶ Z
g : Y ⟶ Z
inst✝¹ : HasZeroObject C
inst✝ : HasZeroMorphisms C
X : C
s : Cone (cospan (𝟙 X) 0)
⊢ 0 ≫ PullbackCone.fst s = 𝟙 s.pt ≫ PullbackCone.fst s
[PROOFSTEP]
simpa using (PullbackCone.condition s).symm
[GOAL]
C : Type u₁
inst✝² : Category.{v₁, u₁} C
P X✝ Y Z : C
fst : P ⟶ X✝
snd : P ⟶ Y
f : X✝ ⟶ Z
g : Y ⟶ Z
inst✝¹ : HasZeroObject C
inst✝ : HasZeroMorphisms C
X : C
⊢ CommSq 0 (𝟙 X) 0 0
[PROOFSTEP]
simp
[GOAL]
C : Type u₁
inst✝² : Category.{v₁, u₁} C
P X✝ Y Z : C
fst : P ⟶ X✝
snd : P ⟶ Y
f : X✝ ⟶ Z
g : Y ⟶ Z
inst✝¹ : HasZeroObject C
inst✝ : HasZeroMorphisms C
X : C
⊢ ((zeroProdIso X).symm ≪≫ (pullbackZeroZeroIso 0 X).symm).hom ≫ pullback.fst = 0
[PROOFSTEP]
simp
[GOAL]
C : Type u₁
inst✝² : Category.{v₁, u₁} C
P X✝ Y Z : C
fst : P ⟶ X✝
snd : P ⟶ Y
f : X✝ ⟶ Z
g : Y ⟶ Z
inst✝¹ : HasZeroObject C
inst✝ : HasZeroMorphisms C
X : C
⊢ ((zeroProdIso X).symm ≪≫ (pullbackZeroZeroIso 0 X).symm).hom ≫ pullback.snd = 𝟙 X
[PROOFSTEP]
simp
[GOAL]
C : Type u₁
inst✝² : Category.{v₁, u₁} C
P X Y Z : C
fst : P ⟶ X
snd : P ⟶ Y
f : X ⟶ Z
g : Y ⟶ Z
inst✝¹ : HasZeroObject C
inst✝ : HasZeroMorphisms C
b : BinaryBicone X Y
h : BinaryBicone.IsBilimit b
⊢ IsPullback b.fst b.snd 0 0
[PROOFSTEP]
convert IsPullback.of_is_product' h.isLimit HasZeroObject.zeroIsTerminal
[GOAL]
C : Type u₁
inst✝² : Category.{v₁, u₁} C
P X Y Z : C
fst : P ⟶ X
snd : P ⟶ Y
f : X ⟶ Z
g : Y ⟶ Z
inst✝¹ : HasZeroObject C
inst✝ : HasZeroMorphisms C
b : BinaryBicone X Y
h : BinaryBicone.IsBilimit b
⊢ IsPullback b.inl 0 b.snd 0
[PROOFSTEP]
refine' of_right _ (by simp) (of_isBilimit h)
[GOAL]
C : Type u₁
inst✝² : Category.{v₁, u₁} C
P X Y Z : C
fst : P ⟶ X
snd : P ⟶ Y
f : X ⟶ Z
g : Y ⟶ Z
inst✝¹ : HasZeroObject C
inst✝ : HasZeroMorphisms C
b : BinaryBicone X Y
h : BinaryBicone.IsBilimit b
⊢ b.inl ≫ b.snd = 0 ≫ 0
[PROOFSTEP]
simp
[GOAL]
C : Type u₁
inst✝² : Category.{v₁, u₁} C
P X Y Z : C
fst : P ⟶ X
snd : P ⟶ Y
f : X ⟶ Z
g : Y ⟶ Z
inst✝¹ : HasZeroObject C
inst✝ : HasZeroMorphisms C
b : BinaryBicone X Y
h : BinaryBicone.IsBilimit b
⊢ IsPullback (b.inl ≫ b.fst) 0 0 (0 ≫ 0)
[PROOFSTEP]
simp
[GOAL]
C : Type u₁
inst✝² : Category.{v₁, u₁} C
P X Y Z : C
fst : P ⟶ X
snd : P ⟶ Y
f : X ⟶ Z
g : Y ⟶ Z
inst✝¹ : HasZeroObject C
inst✝ : HasZeroMorphisms C
b : BinaryBicone X Y
h : BinaryBicone.IsBilimit b
⊢ IsPullback b.inr 0 b.fst 0
[PROOFSTEP]
apply flip
[GOAL]
case h
C : Type u₁
inst✝² : Category.{v₁, u₁} C
P X Y Z : C
fst : P ⟶ X
snd : P ⟶ Y
f : X ⟶ Z
g : Y ⟶ Z
inst✝¹ : HasZeroObject C
inst✝ : HasZeroMorphisms C
b : BinaryBicone X Y
h : BinaryBicone.IsBilimit b
⊢ IsPullback 0 b.inr 0 b.fst
[PROOFSTEP]
refine' of_bot _ (by simp) (of_isBilimit h)
[GOAL]
C : Type u₁
inst✝² : Category.{v₁, u₁} C
P X Y Z : C
fst : P ⟶ X
snd : P ⟶ Y
f : X ⟶ Z
g : Y ⟶ Z
inst✝¹ : HasZeroObject C
inst✝ : HasZeroMorphisms C
b : BinaryBicone X Y
h : BinaryBicone.IsBilimit b
⊢ 0 ≫ 0 = b.inr ≫ b.fst
[PROOFSTEP]
simp
[GOAL]
case h
C : Type u₁
inst✝² : Category.{v₁, u₁} C
P X Y Z : C
fst : P ⟶ X
snd : P ⟶ Y
f : X ⟶ Z
g : Y ⟶ Z
inst✝¹ : HasZeroObject C
inst✝ : HasZeroMorphisms C
b : BinaryBicone X Y
h : BinaryBicone.IsBilimit b
⊢ IsPullback 0 (b.inr ≫ b.snd) (0 ≫ 0) 0
[PROOFSTEP]
simp
[GOAL]
C : Type u₁
inst✝² : Category.{v₁, u₁} C
P X Y Z : C
fst : P ⟶ X
snd : P ⟶ Y
f : X ⟶ Z
g : Y ⟶ Z
inst✝¹ : HasZeroObject C
inst✝ : HasZeroMorphisms C
b : BinaryBicone X Y
h : BinaryBicone.IsBilimit b
⊢ IsPullback 0 0 b.inl b.inr
[PROOFSTEP]
refine' IsPullback.of_right _ (by simp) (IsPullback.inl_snd' h).flip
[GOAL]
C : Type u₁
inst✝² : Category.{v₁, u₁} C
P X Y Z : C
fst : P ⟶ X
snd : P ⟶ Y
f : X ⟶ Z
g : Y ⟶ Z
inst✝¹ : HasZeroObject C
inst✝ : HasZeroMorphisms C
b : BinaryBicone X Y
h : BinaryBicone.IsBilimit b
⊢ 0 ≫ b.inl = 0 ≫ b.inr
[PROOFSTEP]
simp
[GOAL]
C : Type u₁
inst✝² : Category.{v₁, u₁} C
P X Y Z : C
fst : P ⟶ X
snd : P ⟶ Y
f : X ⟶ Z
g : Y ⟶ Z
inst✝¹ : HasZeroObject C
inst✝ : HasZeroMorphisms C
b : BinaryBicone X Y
h : BinaryBicone.IsBilimit b
⊢ IsPullback (0 ≫ 0) 0 0 (b.inr ≫ b.snd)
[PROOFSTEP]
simp
[GOAL]
C : Type u₁
inst✝² : Category.{v₁, u₁} C
Z X✝ Y P : C
f : Z ⟶ X✝
g : Z ⟶ Y
inl : X✝ ⟶ P
inr : Y ⟶ P
inst✝¹ : HasZeroObject C
inst✝ : HasZeroMorphisms C
X : C
⊢ 0 ≫ 0 = 𝟙 X ≫ 0
[PROOFSTEP]
simp
[GOAL]
C : Type u₁
inst✝² : Category.{v₁, u₁} C
Z X✝ Y P : C
f : Z ⟶ X✝
g : Z ⟶ Y
inl : X✝ ⟶ P
inr : Y ⟶ P
inst✝¹ : HasZeroObject C
inst✝ : HasZeroMorphisms C
X : C
s : Cocone (span 0 (𝟙 X))
⊢ ∀ (j : WalkingSpan),
    NatTrans.app (PushoutCocone.mk 0 0 (_ : 0 ≫ 0 = 𝟙 X ≫ 0)).ι j ≫ (fun s => 0) s = NatTrans.app s.ι j
[PROOFSTEP]
have c := @PushoutCocone.coequalizer_ext _ _ _ _ _ _ _ s _ 0 (𝟙 _) (by simp) (by simpa using PushoutCocone.condition s)
[GOAL]
C : Type u₁
inst✝² : Category.{v₁, u₁} C
Z X✝ Y P : C
f : Z ⟶ X✝
g : Z ⟶ Y
inl : X✝ ⟶ P
inr : Y ⟶ P
inst✝¹ : HasZeroObject C
inst✝ : HasZeroMorphisms C
X : C
s : Cocone (span 0 (𝟙 X))
⊢ PushoutCocone.inl s ≫ 0 = PushoutCocone.inl s ≫ 𝟙 s.pt
[PROOFSTEP]
simp
[GOAL]
C : Type u₁
inst✝² : Category.{v₁, u₁} C
Z X✝ Y P : C
f : Z ⟶ X✝
g : Z ⟶ Y
inl : X✝ ⟶ P
inr : Y ⟶ P
inst✝¹ : HasZeroObject C
inst✝ : HasZeroMorphisms C
X : C
s : Cocone (span 0 (𝟙 X))
⊢ PushoutCocone.inr s ≫ 0 = PushoutCocone.inr s ≫ 𝟙 s.pt
[PROOFSTEP]
simpa using PushoutCocone.condition s
[GOAL]
C : Type u₁
inst✝² : Category.{v₁, u₁} C
Z X✝ Y P : C
f : Z ⟶ X✝
g : Z ⟶ Y
inl : X✝ ⟶ P
inr : Y ⟶ P
inst✝¹ : HasZeroObject C
inst✝ : HasZeroMorphisms C
X : C
s : Cocone (span 0 (𝟙 X))
c : ∀ (j : WalkingSpan), NatTrans.app s.ι j ≫ 0 = NatTrans.app s.ι j ≫ 𝟙 s.pt
⊢ ∀ (j : WalkingSpan),
    NatTrans.app (PushoutCocone.mk 0 0 (_ : 0 ≫ 0 = 𝟙 X ≫ 0)).ι j ≫ (fun s => 0) s = NatTrans.app s.ι j
[PROOFSTEP]
dsimp at c
[GOAL]
C : Type u₁
inst✝² : Category.{v₁, u₁} C
Z X✝ Y P : C
f : Z ⟶ X✝
g : Z ⟶ Y
inl : X✝ ⟶ P
inr : Y ⟶ P
inst✝¹ : HasZeroObject C
inst✝ : HasZeroMorphisms C
X : C
s : Cocone (span 0 (𝟙 X))
c : ∀ (j : WalkingSpan), NatTrans.app s.ι j ≫ 0 = NatTrans.app s.ι j ≫ 𝟙 s.pt
⊢ ∀ (j : WalkingSpan),
    NatTrans.app (PushoutCocone.mk 0 0 (_ : 0 ≫ 0 = 𝟙 X ≫ 0)).ι j ≫ (fun s => 0) s = NatTrans.app s.ι j
[PROOFSTEP]
simpa using c
[GOAL]
C : Type u₁
inst✝² : Category.{v₁, u₁} C
Z X✝ Y P : C
f : Z ⟶ X✝
g : Z ⟶ Y
inl : X✝ ⟶ P
inr : Y ⟶ P
inst✝¹ : HasZeroObject C
inst✝ : HasZeroMorphisms C
X : C
⊢ CommSq 0 0 (𝟙 X) 0
[PROOFSTEP]
simp
[GOAL]
C : Type u₁
inst✝² : Category.{v₁, u₁} C
Z X✝ Y P : C
f : Z ⟶ X✝
g : Z ⟶ Y
inl : X✝ ⟶ P
inr : Y ⟶ P
inst✝¹ : HasZeroObject C
inst✝ : HasZeroMorphisms C
X : C
⊢ 𝟙 X ≫ ((coprodZeroIso X).symm ≪≫ (pushoutZeroZeroIso X 0).symm).hom = pushout.inl
[PROOFSTEP]
simp
[GOAL]
C : Type u₁
inst✝² : Category.{v₁, u₁} C
Z X✝ Y P : C
f : Z ⟶ X✝
g : Z ⟶ Y
inl : X✝ ⟶ P
inr : Y ⟶ P
inst✝¹ : HasZeroObject C
inst✝ : HasZeroMorphisms C
X : C
⊢ 0 ≫ ((coprodZeroIso X).symm ≪≫ (pushoutZeroZeroIso X 0).symm).hom = pushout.inr
[PROOFSTEP]
simp
[GOAL]
C : Type u₁
inst✝² : Category.{v₁, u₁} C
Z X Y P : C
f : Z ⟶ X
g : Z ⟶ Y
inl : X ⟶ P
inr : Y ⟶ P
inst✝¹ : HasZeroObject C
inst✝ : HasZeroMorphisms C
b : BinaryBicone X Y
h : BinaryBicone.IsBilimit b
⊢ IsPushout 0 0 b.inl b.inr
[PROOFSTEP]
convert IsPushout.of_is_coproduct' h.isColimit HasZeroObject.zeroIsInitial
[GOAL]
C : Type u₁
inst✝² : Category.{v₁, u₁} C
Z X Y P : C
f : Z ⟶ X
g : Z ⟶ Y
inl : X ⟶ P
inr : Y ⟶ P
inst✝¹ : HasZeroObject C
inst✝ : HasZeroMorphisms C
b : BinaryBicone X Y
h : BinaryBicone.IsBilimit b
⊢ IsPushout b.inl 0 b.snd 0
[PROOFSTEP]
apply flip
[GOAL]
case h
C : Type u₁
inst✝² : Category.{v₁, u₁} C
Z X Y P : C
f : Z ⟶ X
g : Z ⟶ Y
inl : X ⟶ P
inr : Y ⟶ P
inst✝¹ : HasZeroObject C
inst✝ : HasZeroMorphisms C
b : BinaryBicone X Y
h : BinaryBicone.IsBilimit b
⊢ IsPushout 0 b.inl 0 b.snd
[PROOFSTEP]
refine' of_right _ (by simp) (of_isBilimit h)
[GOAL]
C : Type u₁
inst✝² : Category.{v₁, u₁} C
Z X Y P : C
f : Z ⟶ X
g : Z ⟶ Y
inl : X ⟶ P
inr : Y ⟶ P
inst✝¹ : HasZeroObject C
inst✝ : HasZeroMorphisms C
b : BinaryBicone X Y
h : BinaryBicone.IsBilimit b
⊢ 0 ≫ 0 = b.inl ≫ b.snd
[PROOFSTEP]
simp
[GOAL]
case h
C : Type u₁
inst✝² : Category.{v₁, u₁} C
Z X Y P : C
f : Z ⟶ X
g : Z ⟶ Y
inl : X ⟶ P
inr : Y ⟶ P
inst✝¹ : HasZeroObject C
inst✝ : HasZeroMorphisms C
b : BinaryBicone X Y
h : BinaryBicone.IsBilimit b
⊢ IsPushout (0 ≫ 0) 0 0 (b.inr ≫ b.snd)
[PROOFSTEP]
simp
[GOAL]
C : Type u₁
inst✝² : Category.{v₁, u₁} C
Z X Y P : C
f : Z ⟶ X
g : Z ⟶ Y
inl : X ⟶ P
inr : Y ⟶ P
inst✝¹ : HasZeroObject C
inst✝ : HasZeroMorphisms C
b : BinaryBicone X Y
h : BinaryBicone.IsBilimit b
⊢ IsPushout b.inr 0 b.fst 0
[PROOFSTEP]
refine' of_bot _ (by simp) (of_isBilimit h)
[GOAL]
C : Type u₁
inst✝² : Category.{v₁, u₁} C
Z X Y P : C
f : Z ⟶ X
g : Z ⟶ Y
inl : X ⟶ P
inr : Y ⟶ P
inst✝¹ : HasZeroObject C
inst✝ : HasZeroMorphisms C
b : BinaryBicone X Y
h : BinaryBicone.IsBilimit b
⊢ b.inr ≫ b.fst = 0 ≫ 0
[PROOFSTEP]
simp
[GOAL]
C : Type u₁
inst✝² : Category.{v₁, u₁} C
Z X Y P : C
f : Z ⟶ X
g : Z ⟶ Y
inl : X ⟶ P
inr : Y ⟶ P
inst✝¹ : HasZeroObject C
inst✝ : HasZeroMorphisms C
b : BinaryBicone X Y
h : BinaryBicone.IsBilimit b
⊢ IsPushout 0 (0 ≫ 0) (b.inl ≫ b.fst) 0
[PROOFSTEP]
simp
[GOAL]
C : Type u₁
inst✝² : Category.{v₁, u₁} C
Z X Y P : C
f : Z ⟶ X
g : Z ⟶ Y
inl : X ⟶ P
inr : Y ⟶ P
inst✝¹ : HasZeroObject C
inst✝ : HasZeroMorphisms C
b : BinaryBicone X Y
h : BinaryBicone.IsBilimit b
⊢ IsPushout b.fst b.snd 0 0
[PROOFSTEP]
refine' IsPushout.of_right _ (by simp) (IsPushout.inl_snd' h)
[GOAL]
C : Type u₁
inst✝² : Category.{v₁, u₁} C
Z X Y P : C
f : Z ⟶ X
g : Z ⟶ Y
inl : X ⟶ P
inr : Y ⟶ P
inst✝¹ : HasZeroObject C
inst✝ : HasZeroMorphisms C
b : BinaryBicone X Y
h : BinaryBicone.IsBilimit b
⊢ b.fst ≫ 0 = b.snd ≫ 0
[PROOFSTEP]
simp
[GOAL]
C : Type u₁
inst✝² : Category.{v₁, u₁} C
Z X Y P : C
f : Z ⟶ X
g : Z ⟶ Y
inl : X ⟶ P
inr : Y ⟶ P
inst✝¹ : HasZeroObject C
inst✝ : HasZeroMorphisms C
b : BinaryBicone X Y
h : BinaryBicone.IsBilimit b
⊢ IsPushout (b.inl ≫ b.fst) 0 0 (0 ≫ 0)
[PROOFSTEP]
simp
[GOAL]
C : Type u₁
inst✝² : Category.{v₁, u₁} C
Z X Y P : C
f : Z ⟶ X
g : Z ⟶ Y
inl : X ⟶ P
inr : Y ⟶ P
inst✝¹ : IsIso f
inst✝ : IsIso inr
sq : CommSq f g inl inr
⊢ IsColimit (CommSq.cocone sq)
[PROOFSTEP]
refine' PushoutCocone.IsColimit.mk _ (fun s => inv inr ≫ s.inr) (fun s => _) (by aesop_cat) (by aesop_cat)
[GOAL]
C : Type u₁
inst✝² : Category.{v₁, u₁} C
Z X Y P : C
f : Z ⟶ X
g : Z ⟶ Y
inl : X ⟶ P
inr : Y ⟶ P
inst✝¹ : IsIso f
inst✝ : IsIso inr
sq : CommSq f g inl inr
⊢ ∀ (s : PushoutCocone f g), inr ≫ (fun s => inv inr ≫ PushoutCocone.inr s) s = PushoutCocone.inr s
[PROOFSTEP]
aesop_cat
[GOAL]
C : Type u₁
inst✝² : Category.{v₁, u₁} C
Z X Y P : C
f : Z ⟶ X
g : Z ⟶ Y
inl : X ⟶ P
inr : Y ⟶ P
inst✝¹ : IsIso f
inst✝ : IsIso inr
sq : CommSq f g inl inr
⊢ ∀ (s : PushoutCocone f g) (m : P ⟶ s.pt),
    inl ≫ m = PushoutCocone.inl s → inr ≫ m = PushoutCocone.inr s → m = (fun s => inv inr ≫ PushoutCocone.inr s) s
[PROOFSTEP]
aesop_cat
[GOAL]
C : Type u₁
inst✝² : Category.{v₁, u₁} C
Z X Y P : C
f : Z ⟶ X
g : Z ⟶ Y
inl : X ⟶ P
inr : Y ⟶ P
inst✝¹ : IsIso f
inst✝ : IsIso inr
sq : CommSq f g inl inr
s : PushoutCocone f g
⊢ inl ≫ (fun s => inv inr ≫ PushoutCocone.inr s) s = PushoutCocone.inl s
[PROOFSTEP]
simp only [← cancel_epi f, s.condition, sq.w_assoc, IsIso.hom_inv_id_assoc]
[GOAL]
C : Type u₁
inst✝ : Category.{v₁, u₁} C
X Y Z : C
f f' : X ⟶ Y
g g' : Y ⟶ Z
H : IsPullback f f g g'
⊢ IsLimit (Fork.ofι f (_ : f ≫ g = f ≫ g'))
[PROOFSTEP]
fapply Fork.IsLimit.mk
[GOAL]
case lift
C : Type u₁
inst✝ : Category.{v₁, u₁} C
X Y Z : C
f f' : X ⟶ Y
g g' : Y ⟶ Z
H : IsPullback f f g g'
⊢ (s : Fork g g') → s.pt ⟶ (Fork.ofι f (_ : f ≫ g = f ≫ g')).pt
[PROOFSTEP]
exact fun s => H.isLimit.lift (PullbackCone.mk s.ι s.ι s.condition)
[GOAL]
case fac
C : Type u₁
inst✝ : Category.{v₁, u₁} C
X Y Z : C
f f' : X ⟶ Y
g g' : Y ⟶ Z
H : IsPullback f f g g'
⊢ ∀ (s : Fork g g'),
    IsLimit.lift (isLimit H) (PullbackCone.mk (Fork.ι s) (Fork.ι s) (_ : Fork.ι s ≫ g = Fork.ι s ≫ g')) ≫
        Fork.ι (Fork.ofι f (_ : f ≫ g = f ≫ g')) =
      Fork.ι s
[PROOFSTEP]
exact fun s => H.isLimit.fac _ WalkingCospan.left
[GOAL]
case uniq
C : Type u₁
inst✝ : Category.{v₁, u₁} C
X Y Z : C
f f' : X ⟶ Y
g g' : Y ⟶ Z
H : IsPullback f f g g'
⊢ ∀ (s : Fork g g') (m : s.pt ⟶ (Fork.ofι f (_ : f ≫ g = f ≫ g')).pt),
    m ≫ Fork.ι (Fork.ofι f (_ : f ≫ g = f ≫ g')) = Fork.ι s →
      m = IsLimit.lift (isLimit H) (PullbackCone.mk (Fork.ι s) (Fork.ι s) (_ : Fork.ι s ≫ g = Fork.ι s ≫ g'))
[PROOFSTEP]
intro s m e
[GOAL]
case uniq
C : Type u₁
inst✝ : Category.{v₁, u₁} C
X Y Z : C
f f' : X ⟶ Y
g g' : Y ⟶ Z
H : IsPullback f f g g'
s : Fork g g'
m : s.pt ⟶ (Fork.ofι f (_ : f ≫ g = f ≫ g')).pt
e : m ≫ Fork.ι (Fork.ofι f (_ : f ≫ g = f ≫ g')) = Fork.ι s
⊢ m = IsLimit.lift (isLimit H) (PullbackCone.mk (Fork.ι s) (Fork.ι s) (_ : Fork.ι s ≫ g = Fork.ι s ≫ g'))
[PROOFSTEP]
apply PullbackCone.IsLimit.hom_ext H.isLimit
[GOAL]
case uniq.h₀
C : Type u₁
inst✝ : Category.{v₁, u₁} C
X Y Z : C
f f' : X ⟶ Y
g g' : Y ⟶ Z
H : IsPullback f f g g'
s : Fork g g'
m : s.pt ⟶ (Fork.ofι f (_ : f ≫ g = f ≫ g')).pt
e : m ≫ Fork.ι (Fork.ofι f (_ : f ≫ g = f ≫ g')) = Fork.ι s
⊢ m ≫ PullbackCone.fst (cone H) =
    IsLimit.lift (isLimit H) (PullbackCone.mk (Fork.ι s) (Fork.ι s) (_ : Fork.ι s ≫ g = Fork.ι s ≫ g')) ≫
      PullbackCone.fst (cone H)
[PROOFSTEP]
refine' e.trans _
[GOAL]
case uniq.h₁
C : Type u₁
inst✝ : Category.{v₁, u₁} C
X Y Z : C
f f' : X ⟶ Y
g g' : Y ⟶ Z
H : IsPullback f f g g'
s : Fork g g'
m : s.pt ⟶ (Fork.ofι f (_ : f ≫ g = f ≫ g')).pt
e : m ≫ Fork.ι (Fork.ofι f (_ : f ≫ g = f ≫ g')) = Fork.ι s
⊢ m ≫ PullbackCone.snd (cone H) =
    IsLimit.lift (isLimit H) (PullbackCone.mk (Fork.ι s) (Fork.ι s) (_ : Fork.ι s ≫ g = Fork.ι s ≫ g')) ≫
      PullbackCone.snd (cone H)
[PROOFSTEP]
refine' e.trans _
[GOAL]
case uniq.h₀
C : Type u₁
inst✝ : Category.{v₁, u₁} C
X Y Z : C
f f' : X ⟶ Y
g g' : Y ⟶ Z
H : IsPullback f f g g'
s : Fork g g'
m : s.pt ⟶ (Fork.ofι f (_ : f ≫ g = f ≫ g')).pt
e : m ≫ Fork.ι (Fork.ofι f (_ : f ≫ g = f ≫ g')) = Fork.ι s
⊢ Fork.ι s =
    IsLimit.lift (isLimit H) (PullbackCone.mk (Fork.ι s) (Fork.ι s) (_ : Fork.ι s ≫ g = Fork.ι s ≫ g')) ≫
      PullbackCone.fst (cone H)
[PROOFSTEP]
symm
[GOAL]
case uniq.h₁
C : Type u₁
inst✝ : Category.{v₁, u₁} C
X Y Z : C
f f' : X ⟶ Y
g g' : Y ⟶ Z
H : IsPullback f f g g'
s : Fork g g'
m : s.pt ⟶ (Fork.ofι f (_ : f ≫ g = f ≫ g')).pt
e : m ≫ Fork.ι (Fork.ofι f (_ : f ≫ g = f ≫ g')) = Fork.ι s
⊢ Fork.ι s =
    IsLimit.lift (isLimit H) (PullbackCone.mk (Fork.ι s) (Fork.ι s) (_ : Fork.ι s ≫ g = Fork.ι s ≫ g')) ≫
      PullbackCone.snd (cone H)
[PROOFSTEP]
symm
[GOAL]
case uniq.h₀
C : Type u₁
inst✝ : Category.{v₁, u₁} C
X Y Z : C
f f' : X ⟶ Y
g g' : Y ⟶ Z
H : IsPullback f f g g'
s : Fork g g'
m : s.pt ⟶ (Fork.ofι f (_ : f ≫ g = f ≫ g')).pt
e : m ≫ Fork.ι (Fork.ofι f (_ : f ≫ g = f ≫ g')) = Fork.ι s
⊢ IsLimit.lift (isLimit H) (PullbackCone.mk (Fork.ι s) (Fork.ι s) (_ : Fork.ι s ≫ g = Fork.ι s ≫ g')) ≫
      PullbackCone.fst (cone H) =
    Fork.ι s
[PROOFSTEP]
exact H.isLimit.fac _ _
[GOAL]
case uniq.h₁
C : Type u₁
inst✝ : Category.{v₁, u₁} C
X Y Z : C
f f' : X ⟶ Y
g g' : Y ⟶ Z
H : IsPullback f f g g'
s : Fork g g'
m : s.pt ⟶ (Fork.ofι f (_ : f ≫ g = f ≫ g')).pt
e : m ≫ Fork.ι (Fork.ofι f (_ : f ≫ g = f ≫ g')) = Fork.ι s
⊢ IsLimit.lift (isLimit H) (PullbackCone.mk (Fork.ι s) (Fork.ι s) (_ : Fork.ι s ≫ g = Fork.ι s ≫ g')) ≫
      PullbackCone.snd (cone H) =
    Fork.ι s
[PROOFSTEP]
exact H.isLimit.fac _ _
[GOAL]
C : Type u₁
inst✝ : Category.{v₁, u₁} C
X Y Z : C
f f' : X ⟶ Y
g g' : Y ⟶ Z
H : IsPushout f f' g g
⊢ IsColimit (Cofork.ofπ g (_ : f ≫ g = f' ≫ g))
[PROOFSTEP]
fapply Cofork.IsColimit.mk
[GOAL]
case desc
C : Type u₁
inst✝ : Category.{v₁, u₁} C
X Y Z : C
f f' : X ⟶ Y
g g' : Y ⟶ Z
H : IsPushout f f' g g
⊢ (s : Cofork f f') → (Cofork.ofπ g (_ : f ≫ g = f' ≫ g)).pt ⟶ s.pt
[PROOFSTEP]
exact fun s => H.isColimit.desc (PushoutCocone.mk s.π s.π s.condition)
[GOAL]
case fac
C : Type u₁
inst✝ : Category.{v₁, u₁} C
X Y Z : C
f f' : X ⟶ Y
g g' : Y ⟶ Z
H : IsPushout f f' g g
⊢ ∀ (s : Cofork f f'),
    Cofork.π (Cofork.ofπ g (_ : f ≫ g = f' ≫ g)) ≫
        IsColimit.desc (isColimit H)
          (PushoutCocone.mk (Cofork.π s) (Cofork.π s) (_ : f ≫ Cofork.π s = f' ≫ Cofork.π s)) =
      Cofork.π s
[PROOFSTEP]
exact fun s => H.isColimit.fac _ WalkingSpan.left
[GOAL]
case uniq
C : Type u₁
inst✝ : Category.{v₁, u₁} C
X Y Z : C
f f' : X ⟶ Y
g g' : Y ⟶ Z
H : IsPushout f f' g g
⊢ ∀ (s : Cofork f f') (m : (Cofork.ofπ g (_ : f ≫ g = f' ≫ g)).pt ⟶ s.pt),
    Cofork.π (Cofork.ofπ g (_ : f ≫ g = f' ≫ g)) ≫ m = Cofork.π s →
      m =
        IsColimit.desc (isColimit H) (PushoutCocone.mk (Cofork.π s) (Cofork.π s) (_ : f ≫ Cofork.π s = f' ≫ Cofork.π s))
[PROOFSTEP]
intro s m e
[GOAL]
case uniq
C : Type u₁
inst✝ : Category.{v₁, u₁} C
X Y Z : C
f f' : X ⟶ Y
g g' : Y ⟶ Z
H : IsPushout f f' g g
s : Cofork f f'
m : (Cofork.ofπ g (_ : f ≫ g = f' ≫ g)).pt ⟶ s.pt
e : Cofork.π (Cofork.ofπ g (_ : f ≫ g = f' ≫ g)) ≫ m = Cofork.π s
⊢ m = IsColimit.desc (isColimit H) (PushoutCocone.mk (Cofork.π s) (Cofork.π s) (_ : f ≫ Cofork.π s = f' ≫ Cofork.π s))
[PROOFSTEP]
apply PushoutCocone.IsColimit.hom_ext H.isColimit
[GOAL]
case uniq.h₀
C : Type u₁
inst✝ : Category.{v₁, u₁} C
X Y Z : C
f f' : X ⟶ Y
g g' : Y ⟶ Z
H : IsPushout f f' g g
s : Cofork f f'
m : (Cofork.ofπ g (_ : f ≫ g = f' ≫ g)).pt ⟶ s.pt
e : Cofork.π (Cofork.ofπ g (_ : f ≫ g = f' ≫ g)) ≫ m = Cofork.π s
⊢ PushoutCocone.inl (cocone H) ≫ m =
    PushoutCocone.inl (cocone H) ≫
      IsColimit.desc (isColimit H) (PushoutCocone.mk (Cofork.π s) (Cofork.π s) (_ : f ≫ Cofork.π s = f' ≫ Cofork.π s))
[PROOFSTEP]
refine' e.trans _
[GOAL]
case uniq.h₁
C : Type u₁
inst✝ : Category.{v₁, u₁} C
X Y Z : C
f f' : X ⟶ Y
g g' : Y ⟶ Z
H : IsPushout f f' g g
s : Cofork f f'
m : (Cofork.ofπ g (_ : f ≫ g = f' ≫ g)).pt ⟶ s.pt
e : Cofork.π (Cofork.ofπ g (_ : f ≫ g = f' ≫ g)) ≫ m = Cofork.π s
⊢ PushoutCocone.inr (cocone H) ≫ m =
    PushoutCocone.inr (cocone H) ≫
      IsColimit.desc (isColimit H) (PushoutCocone.mk (Cofork.π s) (Cofork.π s) (_ : f ≫ Cofork.π s = f' ≫ Cofork.π s))
[PROOFSTEP]
refine' e.trans _
[GOAL]
case uniq.h₀
C : Type u₁
inst✝ : Category.{v₁, u₁} C
X Y Z : C
f f' : X ⟶ Y
g g' : Y ⟶ Z
H : IsPushout f f' g g
s : Cofork f f'
m : (Cofork.ofπ g (_ : f ≫ g = f' ≫ g)).pt ⟶ s.pt
e : Cofork.π (Cofork.ofπ g (_ : f ≫ g = f' ≫ g)) ≫ m = Cofork.π s
⊢ Cofork.π s =
    PushoutCocone.inl (cocone H) ≫
      IsColimit.desc (isColimit H) (PushoutCocone.mk (Cofork.π s) (Cofork.π s) (_ : f ≫ Cofork.π s = f' ≫ Cofork.π s))
[PROOFSTEP]
symm
[GOAL]
case uniq.h₁
C : Type u₁
inst✝ : Category.{v₁, u₁} C
X Y Z : C
f f' : X ⟶ Y
g g' : Y ⟶ Z
H : IsPushout f f' g g
s : Cofork f f'
m : (Cofork.ofπ g (_ : f ≫ g = f' ≫ g)).pt ⟶ s.pt
e : Cofork.π (Cofork.ofπ g (_ : f ≫ g = f' ≫ g)) ≫ m = Cofork.π s
⊢ Cofork.π s =
    PushoutCocone.inr (cocone H) ≫
      IsColimit.desc (isColimit H) (PushoutCocone.mk (Cofork.π s) (Cofork.π s) (_ : f ≫ Cofork.π s = f' ≫ Cofork.π s))
[PROOFSTEP]
symm
[GOAL]
case uniq.h₀
C : Type u₁
inst✝ : Category.{v₁, u₁} C
X Y Z : C
f f' : X ⟶ Y
g g' : Y ⟶ Z
H : IsPushout f f' g g
s : Cofork f f'
m : (Cofork.ofπ g (_ : f ≫ g = f' ≫ g)).pt ⟶ s.pt
e : Cofork.π (Cofork.ofπ g (_ : f ≫ g = f' ≫ g)) ≫ m = Cofork.π s
⊢ PushoutCocone.inl (cocone H) ≫
      IsColimit.desc (isColimit H) (PushoutCocone.mk (Cofork.π s) (Cofork.π s) (_ : f ≫ Cofork.π s = f' ≫ Cofork.π s)) =
    Cofork.π s
[PROOFSTEP]
exact H.isColimit.fac _ _
[GOAL]
case uniq.h₁
C : Type u₁
inst✝ : Category.{v₁, u₁} C
X Y Z : C
f f' : X ⟶ Y
g g' : Y ⟶ Z
H : IsPushout f f' g g
s : Cofork f f'
m : (Cofork.ofπ g (_ : f ≫ g = f' ≫ g)).pt ⟶ s.pt
e : Cofork.π (Cofork.ofπ g (_ : f ≫ g = f' ≫ g)) ≫ m = Cofork.π s
⊢ PushoutCocone.inr (cocone H) ≫
      IsColimit.desc (isColimit H) (PushoutCocone.mk (Cofork.π s) (Cofork.π s) (_ : f ≫ Cofork.π s = f' ≫ Cofork.π s)) =
    Cofork.π s
[PROOFSTEP]
exact H.isColimit.fac _ _
[GOAL]
C : Type u₁
inst✝³ : Category.{v₁, u₁} C
W X Y Z : C
f : W ⟶ X
g : W ⟶ Y
h : X ⟶ Z
i : Y ⟶ Z
inst✝² : HasZeroObject C
inst✝¹ : HasZeroMorphisms C
inst✝ : HasBinaryBiproduct X Y
⊢ BicartesianSq biprod.fst biprod.snd 0 0
[PROOFSTEP]
convert of_is_biproduct₁ (BinaryBiproduct.isBilimit X Y)
[GOAL]
C : Type u₁
inst✝³ : Category.{v₁, u₁} C
W X Y Z : C
f : W ⟶ X
g : W ⟶ Y
h : X ⟶ Z
i : Y ⟶ Z
inst✝² : HasZeroObject C
inst✝¹ : HasZeroMorphisms C
inst✝ : HasBinaryBiproduct X Y
⊢ BicartesianSq 0 0 biprod.inl biprod.inr
[PROOFSTEP]
convert of_is_biproduct₂ (BinaryBiproduct.isBilimit X Y)
[GOAL]
C : Type u₁
inst✝² : Category.{v₁, u₁} C
D : Type u₂
inst✝¹ : Category.{v₂, u₂} D
F : C ⥤ D
W X Y Z : C
f : W ⟶ X
g : W ⟶ Y
h : X ⟶ Z
i : Y ⟶ Z
inst✝ : PreservesLimit (cospan h i) F
s : IsPullback f g h i
⊢ IsPullback (F.map f) (F.map g) (F.map h) (F.map i)
[PROOFSTEP]
refine'
  IsPullback.of_isLimit' (F.map_commSq s.toCommSq)
    (IsLimit.equivOfNatIsoOfIso (cospanCompIso F h i) _ _ (WalkingCospan.ext _ _ _) (isLimitOfPreserves F s.isLimit))
[GOAL]
case refine'_1
C : Type u₁
inst✝² : Category.{v₁, u₁} C
D : Type u₂
inst✝¹ : Category.{v₂, u₂} D
F : C ⥤ D
W X Y Z : C
f : W ⟶ X
g : W ⟶ Y
h : X ⟶ Z
i : Y ⟶ Z
inst✝ : PreservesLimit (cospan h i) F
s : IsPullback f g h i
⊢ ((Cones.postcompose (cospanCompIso F h i).hom).obj (F.mapCone (IsPullback.cone s))).pt ≅
    (CommSq.cone (_ : CommSq (F.map f) (F.map g) (F.map h) (F.map i))).pt
[PROOFSTEP]
rfl
[GOAL]
case refine'_2
C : Type u₁
inst✝² : Category.{v₁, u₁} C
D : Type u₂
inst✝¹ : Category.{v₂, u₂} D
F : C ⥤ D
W X Y Z : C
f : W ⟶ X
g : W ⟶ Y
h : X ⟶ Z
i : Y ⟶ Z
inst✝ : PreservesLimit (cospan h i) F
s : IsPullback f g h i
⊢ NatTrans.app ((Cones.postcompose (cospanCompIso F h i).hom).obj (F.mapCone (IsPullback.cone s))).π
      WalkingCospan.left =
    (Iso.refl ((Cones.postcompose (cospanCompIso F h i).hom).obj (F.mapCone (IsPullback.cone s))).pt).hom ≫
      NatTrans.app (CommSq.cone (_ : CommSq (F.map f) (F.map g) (F.map h) (F.map i))).π WalkingCospan.left
[PROOFSTEP]
simp
[GOAL]
case refine'_3
C : Type u₁
inst✝² : Category.{v₁, u₁} C
D : Type u₂
inst✝¹ : Category.{v₂, u₂} D
F : C ⥤ D
W X Y Z : C
f : W ⟶ X
g : W ⟶ Y
h : X ⟶ Z
i : Y ⟶ Z
inst✝ : PreservesLimit (cospan h i) F
s : IsPullback f g h i
⊢ NatTrans.app ((Cones.postcompose (cospanCompIso F h i).hom).obj (F.mapCone (IsPullback.cone s))).π
      WalkingCospan.right =
    (Iso.refl ((Cones.postcompose (cospanCompIso F h i).hom).obj (F.mapCone (IsPullback.cone s))).pt).hom ≫
      NatTrans.app (CommSq.cone (_ : CommSq (F.map f) (F.map g) (F.map h) (F.map i))).π WalkingCospan.right
[PROOFSTEP]
simp
[GOAL]
C : Type u₁
inst✝² : Category.{v₁, u₁} C
D : Type u₂
inst✝¹ : Category.{v₂, u₂} D
F : C ⥤ D
W X Y Z : C
f : W ⟶ X
g : W ⟶ Y
h : X ⟶ Z
i : Y ⟶ Z
inst✝ : PreservesColimit (span f g) F
s : IsPushout f g h i
⊢ IsPushout (F.map f) (F.map g) (F.map h) (F.map i)
[PROOFSTEP]
refine'
  IsPushout.of_isColimit' (F.map_commSq s.toCommSq)
    (IsColimit.equivOfNatIsoOfIso (spanCompIso F f g) _ _ (WalkingSpan.ext _ _ _) (isColimitOfPreserves F s.isColimit))
[GOAL]
case refine'_1
C : Type u₁
inst✝² : Category.{v₁, u₁} C
D : Type u₂
inst✝¹ : Category.{v₂, u₂} D
F : C ⥤ D
W X Y Z : C
f : W ⟶ X
g : W ⟶ Y
h : X ⟶ Z
i : Y ⟶ Z
inst✝ : PreservesColimit (span f g) F
s : IsPushout f g h i
⊢ ((Cocones.precompose (spanCompIso F f g).inv).obj (F.mapCocone (IsPushout.cocone s))).pt ≅
    (CommSq.cocone (_ : CommSq (F.map f) (F.map g) (F.map h) (F.map i))).pt
[PROOFSTEP]
rfl
[GOAL]
case refine'_2
C : Type u₁
inst✝² : Category.{v₁, u₁} C
D : Type u₂
inst✝¹ : Category.{v₂, u₂} D
F : C ⥤ D
W X Y Z : C
f : W ⟶ X
g : W ⟶ Y
h : X ⟶ Z
i : Y ⟶ Z
inst✝ : PreservesColimit (span f g) F
s : IsPushout f g h i
⊢ NatTrans.app ((Cocones.precompose (spanCompIso F f g).inv).obj (F.mapCocone (IsPushout.cocone s))).ι
        WalkingCospan.left ≫
      (Iso.refl ((Cocones.precompose (spanCompIso F f g).inv).obj (F.mapCocone (IsPushout.cocone s))).pt).hom =
    NatTrans.app (CommSq.cocone (_ : CommSq (F.map f) (F.map g) (F.map h) (F.map i))).ι WalkingCospan.left
[PROOFSTEP]
simp
[GOAL]
case refine'_3
C : Type u₁
inst✝² : Category.{v₁, u₁} C
D : Type u₂
inst✝¹ : Category.{v₂, u₂} D
F : C ⥤ D
W X Y Z : C
f : W ⟶ X
g : W ⟶ Y
h : X ⟶ Z
i : Y ⟶ Z
inst✝ : PreservesColimit (span f g) F
s : IsPushout f g h i
⊢ NatTrans.app ((Cocones.precompose (spanCompIso F f g).inv).obj (F.mapCocone (IsPushout.cocone s))).ι
        WalkingCospan.right ≫
      (Iso.refl ((Cocones.precompose (spanCompIso F f g).inv).obj (F.mapCocone (IsPushout.cocone s))).pt).hom =
    NatTrans.app (CommSq.cocone (_ : CommSq (F.map f) (F.map g) (F.map h) (F.map i))).ι WalkingCospan.right
[PROOFSTEP]
simp
[GOAL]
C : Type u₁
inst✝² : Category.{v₁, u₁} C
D : Type u₂
inst✝¹ : Category.{v₂, u₂} D
F : C ⥤ D
W X Y Z : C
f : W ⟶ X
g : W ⟶ Y
h : X ⟶ Z
i : Y ⟶ Z
inst✝ : ReflectsLimit (cospan h i) F
e : f ≫ h = g ≫ i
H : IsPullback (F.map f) (F.map g) (F.map h) (F.map i)
⊢ IsPullback f g h i
[PROOFSTEP]
refine' ⟨⟨e⟩, ⟨isLimitOfReflects F <| _⟩⟩
[GOAL]
C : Type u₁
inst✝² : Category.{v₁, u₁} C
D : Type u₂
inst✝¹ : Category.{v₂, u₂} D
F : C ⥤ D
W X Y Z : C
f : W ⟶ X
g : W ⟶ Y
h : X ⟶ Z
i : Y ⟶ Z
inst✝ : ReflectsLimit (cospan h i) F
e : f ≫ h = g ≫ i
H : IsPullback (F.map f) (F.map g) (F.map h) (F.map i)
⊢ IsLimit (F.mapCone (PullbackCone.mk f g (_ : f ≫ h = g ≫ i)))
[PROOFSTEP]
refine' (IsLimit.equivOfNatIsoOfIso (cospanCompIso F h i) _ _ (WalkingCospan.ext _ _ _)).symm H.isLimit
[GOAL]
case refine'_1
C : Type u₁
inst✝² : Category.{v₁, u₁} C
D : Type u₂
inst✝¹ : Category.{v₂, u₂} D
F : C ⥤ D
W X Y Z : C
f : W ⟶ X
g : W ⟶ Y
h : X ⟶ Z
i : Y ⟶ Z
inst✝ : ReflectsLimit (cospan h i) F
e : f ≫ h = g ≫ i
H : IsPullback (F.map f) (F.map g) (F.map h) (F.map i)
⊢ ((Cones.postcompose (cospanCompIso F h i).hom).obj (F.mapCone (PullbackCone.mk f g (_ : f ≫ h = g ≫ i)))).pt ≅
    (cone H).pt
case refine'_2
C : Type u₁
inst✝² : Category.{v₁, u₁} C
D : Type u₂
inst✝¹ : Category.{v₂, u₂} D
F : C ⥤ D
W X Y Z : C
f : W ⟶ X
g : W ⟶ Y
h : X ⟶ Z
i : Y ⟶ Z
inst✝ : ReflectsLimit (cospan h i) F
e : f ≫ h = g ≫ i
H : IsPullback (F.map f) (F.map g) (F.map h) (F.map i)
⊢ NatTrans.app
      ((Cones.postcompose (cospanCompIso F h i).hom).obj (F.mapCone (PullbackCone.mk f g (_ : f ≫ h = g ≫ i)))).π
      WalkingCospan.left =
    ?refine'_1.hom ≫ NatTrans.app (cone H).π WalkingCospan.left
case refine'_3
C : Type u₁
inst✝² : Category.{v₁, u₁} C
D : Type u₂
inst✝¹ : Category.{v₂, u₂} D
F : C ⥤ D
W X Y Z : C
f : W ⟶ X
g : W ⟶ Y
h : X ⟶ Z
i : Y ⟶ Z
inst✝ : ReflectsLimit (cospan h i) F
e : f ≫ h = g ≫ i
H : IsPullback (F.map f) (F.map g) (F.map h) (F.map i)
⊢ NatTrans.app
      ((Cones.postcompose (cospanCompIso F h i).hom).obj (F.mapCone (PullbackCone.mk f g (_ : f ≫ h = g ≫ i)))).π
      WalkingCospan.right =
    ?refine'_1.hom ≫ NatTrans.app (cone H).π WalkingCospan.right
[PROOFSTEP]
exacts [Iso.refl _, (Category.comp_id _).trans (Category.id_comp _).symm,
  (Category.comp_id _).trans (Category.id_comp _).symm]
[GOAL]
C : Type u₁
inst✝³ : Category.{v₁, u₁} C
D : Type u₂
inst✝² : Category.{v₂, u₂} D
F : C ⥤ D
W X Y Z : C
f : W ⟶ X
g : W ⟶ Y
h : X ⟶ Z
i : Y ⟶ Z
inst✝¹ : ReflectsLimit (cospan h i) F
inst✝ : Faithful F
H : IsPullback (F.map f) (F.map g) (F.map h) (F.map i)
⊢ F.map (f ≫ h) = F.map (g ≫ i)
[PROOFSTEP]
simpa only [F.map_comp] using H.w
[GOAL]
C : Type u₁
inst✝² : Category.{v₁, u₁} C
D : Type u₂
inst✝¹ : Category.{v₂, u₂} D
F : C ⥤ D
W X Y Z : C
f : W ⟶ X
g : W ⟶ Y
h : X ⟶ Z
i : Y ⟶ Z
inst✝ : ReflectsColimit (span f g) F
e : f ≫ h = g ≫ i
H : IsPushout (F.map f) (F.map g) (F.map h) (F.map i)
⊢ IsPushout f g h i
[PROOFSTEP]
refine' ⟨⟨e⟩, ⟨isColimitOfReflects F <| _⟩⟩
[GOAL]
C : Type u₁
inst✝² : Category.{v₁, u₁} C
D : Type u₂
inst✝¹ : Category.{v₂, u₂} D
F : C ⥤ D
W X Y Z : C
f : W ⟶ X
g : W ⟶ Y
h : X ⟶ Z
i : Y ⟶ Z
inst✝ : ReflectsColimit (span f g) F
e : f ≫ h = g ≫ i
H : IsPushout (F.map f) (F.map g) (F.map h) (F.map i)
⊢ IsColimit (F.mapCocone (PushoutCocone.mk h i (_ : f ≫ h = g ≫ i)))
[PROOFSTEP]
refine' (IsColimit.equivOfNatIsoOfIso (spanCompIso F f g) _ _ (WalkingSpan.ext _ _ _)).symm H.isColimit
[GOAL]
case refine'_1
C : Type u₁
inst✝² : Category.{v₁, u₁} C
D : Type u₂
inst✝¹ : Category.{v₂, u₂} D
F : C ⥤ D
W X Y Z : C
f : W ⟶ X
g : W ⟶ Y
h : X ⟶ Z
i : Y ⟶ Z
inst✝ : ReflectsColimit (span f g) F
e : f ≫ h = g ≫ i
H : IsPushout (F.map f) (F.map g) (F.map h) (F.map i)
⊢ ((Cocones.precompose (spanCompIso F f g).inv).obj (F.mapCocone (PushoutCocone.mk h i (_ : f ≫ h = g ≫ i)))).pt ≅
    (cocone H).pt
case refine'_2
C : Type u₁
inst✝² : Category.{v₁, u₁} C
D : Type u₂
inst✝¹ : Category.{v₂, u₂} D
F : C ⥤ D
W X Y Z : C
f : W ⟶ X
g : W ⟶ Y
h : X ⟶ Z
i : Y ⟶ Z
inst✝ : ReflectsColimit (span f g) F
e : f ≫ h = g ≫ i
H : IsPushout (F.map f) (F.map g) (F.map h) (F.map i)
⊢ NatTrans.app
        ((Cocones.precompose (spanCompIso F f g).inv).obj (F.mapCocone (PushoutCocone.mk h i (_ : f ≫ h = g ≫ i)))).ι
        WalkingCospan.left ≫
      ?refine'_1.hom =
    NatTrans.app (cocone H).ι WalkingCospan.left
case refine'_3
C : Type u₁
inst✝² : Category.{v₁, u₁} C
D : Type u₂
inst✝¹ : Category.{v₂, u₂} D
F : C ⥤ D
W X Y Z : C
f : W ⟶ X
g : W ⟶ Y
h : X ⟶ Z
i : Y ⟶ Z
inst✝ : ReflectsColimit (span f g) F
e : f ≫ h = g ≫ i
H : IsPushout (F.map f) (F.map g) (F.map h) (F.map i)
⊢ NatTrans.app
        ((Cocones.precompose (spanCompIso F f g).inv).obj (F.mapCocone (PushoutCocone.mk h i (_ : f ≫ h = g ≫ i)))).ι
        WalkingCospan.right ≫
      ?refine'_1.hom =
    NatTrans.app (cocone H).ι WalkingCospan.right
[PROOFSTEP]
exacts [Iso.refl _, (Category.comp_id _).trans (Category.id_comp _), (Category.comp_id _).trans (Category.id_comp _)]
[GOAL]
C : Type u₁
inst✝³ : Category.{v₁, u₁} C
D : Type u₂
inst✝² : Category.{v₂, u₂} D
F : C ⥤ D
W X Y Z : C
f : W ⟶ X
g : W ⟶ Y
h : X ⟶ Z
i : Y ⟶ Z
inst✝¹ : ReflectsColimit (span f g) F
inst✝ : Faithful F
H : IsPushout (F.map f) (F.map g) (F.map h) (F.map i)
⊢ F.map (f ≫ h) = F.map (g ≫ i)
[PROOFSTEP]
simpa only [F.map_comp] using H.w