Theorem: Polynomial.hasseDeriv_mul
File: Mathlib/Data/Polynomial/HasseDeriv.lean

tactic: let D k := (@hasseDeriv R _ k).toAddMonoidHom
state_before: R : Type u_1
inst✝ : Semiring R
k : ℕ
f✝ f g : R[X]
⊢ ↑(hasseDeriv k) (f * g) = ∑ ij in antidiagonal k, ↑(hasseDeriv ij.fst) f * ↑(hasseDeriv ij.snd) g

tactic: let Φ := @AddMonoidHom.mul R[X] _
state_before: R : Type u_1
inst✝ : Semiring R
k : ℕ
f✝ f g : R[X]
D : ℕ → R[X] →+ R[X] := fun k => LinearMap.toAddMonoidHom (hasseDeriv k)
⊢ ↑(hasseDeriv k) (f * g) = ∑ ij in antidiagonal k, ↑(hasseDeriv ij.fst) f * ↑(hasseDeriv ij.snd) g

tactic: show
  (compHom (D k)).comp Φ f g =
    ∑ ij : ℕ × ℕ in antidiagonal k, ((compHom.comp ((compHom Φ) (D ij.1))).flip (D ij.2) f) g
state_before: R : Type u_1
inst✝ : Semiring R
k : ℕ
f✝ f g : R[X]
D : ℕ → R[X] →+ R[X] := fun k => LinearMap.toAddMonoidHom (hasseDeriv k)
Φ : R[X] →+ R[X] →+ R[X] := mul
⊢ ↑(hasseDeriv k) (f * g) = ∑ ij in antidiagonal k, ↑(hasseDeriv ij.fst) f * ↑(hasseDeriv ij.snd) g

tactic: simp only [← finset_sum_apply]
state_before: R : Type u_1
inst✝ : Semiring R
k : ℕ
f✝ f g : R[X]
D : ℕ → R[X] →+ R[X] := fun k => LinearMap.toAddMonoidHom (hasseDeriv k)
Φ : R[X] →+ R[X] →+ R[X] := mul
⊢ ↑(↑(AddMonoidHom.comp (↑compHom (D k)) Φ) f) g =
    ∑ ij in antidiagonal k,
      ↑(↑(↑(AddMonoidHom.flip (AddMonoidHom.comp compHom (↑(↑compHom Φ) (D ij.fst)))) (D ij.snd)) f) g

tactic: congr 2
state_before: R : Type u_1
inst✝ : Semiring R
k : ℕ
f✝ f g : R[X]
D : ℕ → R[X] →+ R[X] := fun k => LinearMap.toAddMonoidHom (hasseDeriv k)
Φ : R[X] →+ R[X] →+ R[X] := mul
⊢ ↑(↑(AddMonoidHom.comp (↑compHom (LinearMap.toAddMonoidHom (hasseDeriv k))) mul) f) g =
    ↑(↑(∑ x in antidiagonal k,
              ↑(AddMonoidHom.flip
                    (AddMonoidHom.comp compHom (↑(↑compHom mul) (LinearMap.toAddMonoidHom (hasseDeriv x.fst)))))
                (LinearMap.toAddMonoidHom (hasseDeriv x.snd)))
          f)
      g

tactic: clear f g
state_before: case e_a.e_a
R : Type u_1
inst✝ : Semiring R
k : ℕ
f✝ f g : R[X]
D : ℕ → R[X] →+ R[X] := fun k => LinearMap.toAddMonoidHom (hasseDeriv k)
Φ : R[X] →+ R[X] →+ R[X] := mul
⊢ AddMonoidHom.comp (↑compHom (LinearMap.toAddMonoidHom (hasseDeriv k))) mul =
    ∑ x in antidiagonal k,
      ↑(AddMonoidHom.flip (AddMonoidHom.comp compHom (↑(↑compHom mul) (LinearMap.toAddMonoidHom (hasseDeriv x.fst)))))
        (LinearMap.toAddMonoidHom (hasseDeriv x.snd))

tactic: ext (m r n s) : 4
state_before: case e_a.e_a
R : Type u_1
inst✝ : Semiring R
k : ℕ
f : R[X]
D : ℕ → R[X] →+ R[X] := fun k => LinearMap.toAddMonoidHom (hasseDeriv k)
Φ : R[X] →+ R[X] →+ R[X] := mul
⊢ AddMonoidHom.comp (↑compHom (LinearMap.toAddMonoidHom (hasseDeriv k))) mul =
    ∑ x in antidiagonal k,
      ↑(AddMonoidHom.flip (AddMonoidHom.comp compHom (↑(↑compHom mul) (LinearMap.toAddMonoidHom (hasseDeriv x.fst)))))
        (LinearMap.toAddMonoidHom (hasseDeriv x.snd))

tactic: simp only [finset_sum_apply, coe_mulLeft, coe_comp, flip_apply, Function.comp_apply,
           hasseDeriv_monomial, LinearMap.toAddMonoidHom_coe, compHom_apply_apply,
           coe_mul, monomial_mul_monomial]
state_before: case e_a.e_a.h.h.h.h
R : Type u_1
inst✝ : Semiring R
k : ℕ
f : R[X]
D : ℕ → R[X] →+ R[X] := fun k => LinearMap.toAddMonoidHom (hasseDeriv k)
Φ : R[X] →+ R[X] →+ R[X] := mul
m : ℕ
r : R
n : ℕ
s : R
⊢ ↑(AddMonoidHom.comp
          (↑(AddMonoidHom.comp (AddMonoidHom.comp (↑compHom (LinearMap.toAddMonoidHom (hasseDeriv k))) mul)
                (LinearMap.toAddMonoidHom (monomial m)))
            r)
          (LinearMap.toAddMonoidHom (monomial n)))
      s =
    ↑(AddMonoidHom.comp
          (↑(AddMonoidHom.comp
                (∑ x in antidiagonal k,
                  ↑(AddMonoidHom.flip
                        (AddMonoidHom.comp compHom (↑(↑compHom mul) (LinearMap.toAddMonoidHom (hasseDeriv x.fst)))))
                    (LinearMap.toAddMonoidHom (hasseDeriv x.snd)))
                (LinearMap.toAddMonoidHom (monomial m)))
            r)
          (LinearMap.toAddMonoidHom (monomial n)))
      s

tactic: rw [Finset.sum_congr rfl aux]
state_before: case e_a.e_a.h.h.h.h
R : Type u_1
inst✝ : Semiring R
k : ℕ
f : R[X]
D : ℕ → R[X] →+ R[X] := fun k => LinearMap.toAddMonoidHom (hasseDeriv k)
Φ : R[X] →+ R[X] →+ R[X] := mul
m : ℕ
r : R
n : ℕ
s : R
aux :
  ∀ (x : ℕ × ℕ),
    x ∈ antidiagonal k →
      ↑(monomial (m - x.fst + (n - x.snd))) (↑(choose m x.fst) * r * (↑(choose n x.snd) * s)) =
        ↑(monomial (m + n - k)) (↑(choose m x.fst) * ↑(choose n x.snd) * (r * s))
⊢ ↑(monomial (m + n - k)) (↑(choose (m + n) k) * (r * s)) =
    ∑ x in antidiagonal k, ↑(monomial (m - x.fst + (n - x.snd))) (↑(choose m x.fst) * r * (↑(choose n x.snd) * s))

tactic: rw [← LinearMap.map_sum, ← Finset.sum_mul]
state_before: case e_a.e_a.h.h.h.h
R : Type u_1
inst✝ : Semiring R
k : ℕ
f : R[X]
D : ℕ → R[X] →+ R[X] := fun k => LinearMap.toAddMonoidHom (hasseDeriv k)
Φ : R[X] →+ R[X] →+ R[X] := mul
m : ℕ
r : R
n : ℕ
s : R
aux :
  ∀ (x : ℕ × ℕ),
    x ∈ antidiagonal k →
      ↑(monomial (m - x.fst + (n - x.snd))) (↑(choose m x.fst) * r * (↑(choose n x.snd) * s)) =
        ↑(monomial (m + n - k)) (↑(choose m x.fst) * ↑(choose n x.snd) * (r * s))
⊢ ↑(monomial (m + n - k)) (↑(choose (m + n) k) * (r * s)) =
    ∑ x in antidiagonal k, ↑(monomial (m + n - k)) (↑(choose m x.fst) * ↑(choose n x.snd) * (r * s))

tactic: congr
state_before: case e_a.e_a.h.h.h.h
R : Type u_1
inst✝ : Semiring R
k : ℕ
f : R[X]
D : ℕ → R[X] →+ R[X] := fun k => LinearMap.toAddMonoidHom (hasseDeriv k)
Φ : R[X] →+ R[X] →+ R[X] := mul
m : ℕ
r : R
n : ℕ
s : R
aux :
  ∀ (x : ℕ × ℕ),
    x ∈ antidiagonal k →
      ↑(monomial (m - x.fst + (n - x.snd))) (↑(choose m x.fst) * r * (↑(choose n x.snd) * s)) =
        ↑(monomial (m + n - k)) (↑(choose m x.fst) * ↑(choose n x.snd) * (r * s))
⊢ ↑(monomial (m + n - k)) (↑(choose (m + n) k) * (r * s)) =
    ↑(monomial (m + n - k)) ((∑ x in antidiagonal k, ↑(choose m x.fst) * ↑(choose n x.snd)) * (r * s))

tactic: rw_mod_cast [←Nat.add_choose_eq]
state_before: case e_a.e_a.h.h.h.h.h.e_6.h.e_a
R : Type u_1
inst✝ : Semiring R
k : ℕ
f : R[X]
D : ℕ → R[X] →+ R[X] := fun k => LinearMap.toAddMonoidHom (hasseDeriv k)
Φ : R[X] →+ R[X] →+ R[X] := mul
m : ℕ
r : R
n : ℕ
s : R
aux :
  ∀ (x : ℕ × ℕ),
    x ∈ antidiagonal k →
      ↑(monomial (m - x.fst + (n - x.snd))) (↑(choose m x.fst) * r * (↑(choose n x.snd) * s)) =
        ↑(monomial (m + n - k)) (↑(choose m x.fst) * ↑(choose n x.snd) * (r * s))
⊢ ↑(choose (m + n) k) = ∑ x in antidiagonal k, ↑(choose m x.fst) * ↑(choose n x.snd)

tactic: intro x hx
state_before: R : Type u_1
inst✝ : Semiring R
k : ℕ
f : R[X]
D : ℕ → R[X] →+ R[X] := fun k => LinearMap.toAddMonoidHom (hasseDeriv k)
Φ : R[X] →+ R[X] →+ R[X] := mul
m : ℕ
r : R
n : ℕ
s : R
⊢ ∀ (x : ℕ × ℕ),
    x ∈ antidiagonal k →
      ↑(monomial (m - x.fst + (n - x.snd))) (↑(choose m x.fst) * r * (↑(choose n x.snd) * s)) =
        ↑(monomial (m + n - k)) (↑(choose m x.fst) * ↑(choose n x.snd) * (r * s))

tactic: rw [Finset.Nat.mem_antidiagonal] at hx
state_before: R : Type u_1
inst✝ : Semiring R
k : ℕ
f : R[X]
D : ℕ → R[X] →+ R[X] := fun k => LinearMap.toAddMonoidHom (hasseDeriv k)
Φ : R[X] →+ R[X] →+ R[X] := mul
m : ℕ
r : R
n : ℕ
s : R
x : ℕ × ℕ
hx : x ∈ antidiagonal k
⊢ ↑(monomial (m - x.fst + (n - x.snd))) (↑(choose m x.fst) * r * (↑(choose n x.snd) * s)) =
    ↑(monomial (m + n - k)) (↑(choose m x.fst) * ↑(choose n x.snd) * (r * s))

tactic: subst hx
state_before: R : Type u_1
inst✝ : Semiring R
k : ℕ
f : R[X]
D : ℕ → R[X] →+ R[X] := fun k => LinearMap.toAddMonoidHom (hasseDeriv k)
Φ : R[X] →+ R[X] →+ R[X] := mul
m : ℕ
r : R
n : ℕ
s : R
x : ℕ × ℕ
hx : x.fst + x.snd = k
⊢ ↑(monomial (m - x.fst + (n - x.snd))) (↑(choose m x.fst) * r * (↑(choose n x.snd) * s)) =
    ↑(monomial (m + n - k)) (↑(choose m x.fst) * ↑(choose n x.snd) * (r * s))

tactic: by_cases hm : m < x.1
state_before: R : Type u_1
inst✝ : Semiring R
f : R[X]
D : ℕ → R[X] →+ R[X] := fun k => LinearMap.toAddMonoidHom (hasseDeriv k)
Φ : R[X] →+ R[X] →+ R[X] := mul
m : ℕ
r : R
n : ℕ
s : R
x : ℕ × ℕ
⊢ ↑(monomial (m - x.fst + (n - x.snd))) (↑(choose m x.fst) * r * (↑(choose n x.snd) * s)) =
    ↑(monomial (m + n - (x.fst + x.snd))) (↑(choose m x.fst) * ↑(choose n x.snd) * (r * s))

tactic: by_cases hn : n < x.2
state_before: case neg
R : Type u_1
inst✝ : Semiring R
f : R[X]
D : ℕ → R[X] →+ R[X] := fun k => LinearMap.toAddMonoidHom (hasseDeriv k)
Φ : R[X] →+ R[X] →+ R[X] := mul
m : ℕ
r : R
n : ℕ
s : R
x : ℕ × ℕ
hm : ¬m < x.fst
⊢ ↑(monomial (m - x.fst + (n - x.snd))) (↑(choose m x.fst) * r * (↑(choose n x.snd) * s)) =
    ↑(monomial (m + n - (x.fst + x.snd))) (↑(choose m x.fst) * ↑(choose n x.snd) * (r * s))

tactic: push_neg at hm hn
state_before: case neg
R : Type u_1
inst✝ : Semiring R
f : R[X]
D : ℕ → R[X] →+ R[X] := fun k => LinearMap.toAddMonoidHom (hasseDeriv k)
Φ : R[X] →+ R[X] →+ R[X] := mul
m : ℕ
r : R
n : ℕ
s : R
x : ℕ × ℕ
hm : ¬m < x.fst
hn : ¬n < x.snd
⊢ ↑(monomial (m - x.fst + (n - x.snd))) (↑(choose m x.fst) * r * (↑(choose n x.snd) * s)) =
    ↑(monomial (m + n - (x.fst + x.snd))) (↑(choose m x.fst) * ↑(choose n x.snd) * (r * s))

tactic: rw [tsub_add_eq_add_tsub hm, ← add_tsub_assoc_of_le hn, ← tsub_add_eq_tsub_tsub,
  add_comm x.2 x.1, mul_assoc, ← mul_assoc r, ← (Nat.cast_commute _ r).eq, mul_assoc, mul_assoc]
state_before: case neg
R : Type u_1
inst✝ : Semiring R
f : R[X]
D : ℕ → R[X] →+ R[X] := fun k => LinearMap.toAddMonoidHom (hasseDeriv k)
Φ : R[X] →+ R[X] →+ R[X] := mul
m : ℕ
r : R
n : ℕ
s : R
x : ℕ × ℕ
hm : x.fst ≤ m
hn : x.snd ≤ n
⊢ ↑(monomial (m - x.fst + (n - x.snd))) (↑(choose m x.fst) * r * (↑(choose n x.snd) * s)) =
    ↑(monomial (m + n - (x.fst + x.snd))) (↑(choose m x.fst) * ↑(choose n x.snd) * (r * s))

tactic: simp only [Nat.choose_eq_zero_of_lt hm, Nat.cast_zero, MulZeroClass.zero_mul,
           monomial_zero_right]
state_before: case pos
R : Type u_1
inst✝ : Semiring R
f : R[X]
D : ℕ → R[X] →+ R[X] := fun k => LinearMap.toAddMonoidHom (hasseDeriv k)
Φ : R[X] →+ R[X] →+ R[X] := mul
m : ℕ
r : R
n : ℕ
s : R
x : ℕ × ℕ
hm : m < x.fst
⊢ ↑(monomial (m - x.fst + (n - x.snd))) (↑(choose m x.fst) * r * (↑(choose n x.snd) * s)) =
    ↑(monomial (m + n - (x.fst + x.snd))) (↑(choose m x.fst) * ↑(choose n x.snd) * (r * s))

tactic: simp only [Nat.choose_eq_zero_of_lt hn, Nat.cast_zero, MulZeroClass.zero_mul,
           MulZeroClass.mul_zero, monomial_zero_right]
state_before: case pos
R : Type u_1
inst✝ : Semiring R
f : R[X]
D : ℕ → R[X] →+ R[X] := fun k => LinearMap.toAddMonoidHom (hasseDeriv k)
Φ : R[X] →+ R[X] →+ R[X] := mul
m : ℕ
r : R
n : ℕ
s : R
x : ℕ × ℕ
hm : ¬m < x.fst
hn : n < x.snd
⊢ ↑(monomial (m - x.fst + (n - x.snd))) (↑(choose m x.fst) * r * (↑(choose n x.snd) * s)) =
    ↑(monomial (m + n - (x.fst + x.snd))) (↑(choose m x.fst) * ↑(choose n x.snd) * (r * s))