Theorem: Polynomial.natDegree_hasseDeriv_le
File: Mathlib/Algebra/Polynomial/HasseDeriv.lean

tactic: rw [hasseDeriv_apply, sum_def]
state_before: R : Type u_1
inst✝ : Semiring R
k : ℕ
f p : R[X]
n : ℕ
⊢ ((hasseDeriv n) p).natDegree ≤ p.natDegree - n
state_after: R : Type u_1
inst✝ : Semiring R
k : ℕ
f p : R[X]
n : ℕ
⊢ (∑ n_1 ∈ p.support, (monomial (n_1 - n)) (↑(n_1.choose n) * p.coeff n_1)).natDegree ≤ p.natDegree - n

tactic: refine (natDegree_sum_le _ _).trans ?_
state_before: R : Type u_1
inst✝ : Semiring R
k : ℕ
f p : R[X]
n : ℕ
⊢ (∑ n_1 ∈ p.support, (monomial (n_1 - n)) (↑(n_1.choose n) * p.coeff n_1)).natDegree ≤ p.natDegree - n
state_after: R : Type u_1
inst✝ : Semiring R
k : ℕ
f p : R[X]
n : ℕ
⊢ Finset.fold max 0 (natDegree ∘ fun n_1 => (monomial (n_1 - n)) (↑(n_1.choose n) * p.coeff n_1)) p.support ≤
    p.natDegree - n

tactic: simp_rw [Function.comp, natDegree_monomial]
state_before: R : Type u_1
inst✝ : Semiring R
k : ℕ
f p : R[X]
n : ℕ
⊢ Finset.fold max 0 (natDegree ∘ fun n_1 => (monomial (n_1 - n)) (↑(n_1.choose n) * p.coeff n_1)) p.support ≤
    p.natDegree - n
state_after: R : Type u_1
inst✝ : Semiring R
k : ℕ
f p : R[X]
n : ℕ
⊢ Finset.fold max 0 (fun x => if ↑(x.choose n) * p.coeff x = 0 then 0 else x - n) p.support ≤ p.natDegree - n

tactic: rw [Finset.fold_ite, Finset.fold_const]
state_before: R : Type u_1
inst✝ : Semiring R
k : ℕ
f p : R[X]
n : ℕ
⊢ Finset.fold max 0 (fun x => if ↑(x.choose n) * p.coeff x = 0 then 0 else x - n) p.support ≤ p.natDegree - n
state_after: R : Type u_1
inst✝ : Semiring R
k : ℕ
f p : R[X]
n : ℕ
⊢ max (if Finset.filter (fun x => ↑(x.choose n) * p.coeff x = 0) p.support = ∅ then 0 else max 0 0)
      (Finset.fold max 0 (fun x => x - n) (Finset.filter (fun i => ¬↑(i.choose n) * p.coeff i = 0) p.support)) ≤
    p.natDegree - n

case h
R : Type u_1
inst✝ : Semiring R
k : ℕ
f p : R[X]
n : ℕ
⊢ max 0 (max 0 0) = max 0 0

tactic: simp only [ite_self, max_eq_right, zero_le', Finset.fold_max_le, true_and_iff, and_imp,
  tsub_le_iff_right, mem_support_iff, Ne, Finset.mem_filter]
state_before: R : Type u_1
inst✝ : Semiring R
k : ℕ
f p : R[X]
n : ℕ
⊢ max (if Finset.filter (fun x => ↑(x.choose n) * p.coeff x = 0) p.support = ∅ then 0 else max 0 0)
      (Finset.fold max 0 (fun x => x - n) (Finset.filter (fun i => ¬↑(i.choose n) * p.coeff i = 0) p.support)) ≤
    p.natDegree - n
state_after: R : Type u_1
inst✝ : Semiring R
k : ℕ
f p : R[X]
n : ℕ
⊢ ∀ (x : ℕ), ¬p.coeff x = 0 → ¬↑(x.choose n) * p.coeff x = 0 → x ≤ p.natDegree - n + n

tactic: intro x hx hx'
state_before: R : Type u_1
inst✝ : Semiring R
k : ℕ
f p : R[X]
n : ℕ
⊢ ∀ (x : ℕ), ¬p.coeff x = 0 → ¬↑(x.choose n) * p.coeff x = 0 → x ≤ p.natDegree - n + n
state_after: R : Type u_1
inst✝ : Semiring R
k : ℕ
f p : R[X]
n x : ℕ
hx : ¬p.coeff x = 0
hx' : ¬↑(x.choose n) * p.coeff x = 0
⊢ x ≤ p.natDegree - n + n

tactic: have hxp : x ≤ p.natDegree := le_natDegree_of_ne_zero hx
state_before: R : Type u_1
inst✝ : Semiring R
k : ℕ
f p : R[X]
n x : ℕ
hx : ¬p.coeff x = 0
hx' : ¬↑(x.choose n) * p.coeff x = 0
⊢ x ≤ p.natDegree - n + n
state_after: R : Type u_1
inst✝ : Semiring R
k : ℕ
f p : R[X]
n x : ℕ
hx : ¬p.coeff x = 0
hx' : ¬↑(x.choose n) * p.coeff x = 0
hxp : x ≤ p.natDegree
⊢ x ≤ p.natDegree - n + n

tactic: have hxn : n ≤ x := by
  contrapose! hx'
  simp [Nat.choose_eq_zero_of_lt hx']
state_before: R : Type u_1
inst✝ : Semiring R
k : ℕ
f p : R[X]
n x : ℕ
hx : ¬p.coeff x = 0
hx' : ¬↑(x.choose n) * p.coeff x = 0
hxp : x ≤ p.natDegree
⊢ x ≤ p.natDegree - n + n
state_after: R : Type u_1
inst✝ : Semiring R
k : ℕ
f p : R[X]
n x : ℕ
hx : ¬p.coeff x = 0
hx' : ¬↑(x.choose n) * p.coeff x = 0
hxp : x ≤ p.natDegree
hxn : n ≤ x
⊢ x ≤ p.natDegree - n + n

tactic: rwa [tsub_add_cancel_of_le (hxn.trans hxp)]
state_before: R : Type u_1
inst✝ : Semiring R
k : ℕ
f p : R[X]
n x : ℕ
hx : ¬p.coeff x = 0
hx' : ¬↑(x.choose n) * p.coeff x = 0
hxp : x ≤ p.natDegree
hxn : n ≤ x
⊢ x ≤ p.natDegree - n + n
state_after: no goals

tactic: contrapose! hx'
state_before: R : Type u_1
inst✝ : Semiring R
k : ℕ
f p : R[X]
n x : ℕ
hx : ¬p.coeff x = 0
hx' : ¬↑(x.choose n) * p.coeff x = 0
hxp : x ≤ p.natDegree
⊢ n ≤ x
state_after: R : Type u_1
inst✝ : Semiring R
k : ℕ
f p : R[X]
n x : ℕ
hx : ¬p.coeff x = 0
hxp : x ≤ p.natDegree
hx' : x < n
⊢ ↑(x.choose n) * p.coeff x = 0

tactic: simp [Nat.choose_eq_zero_of_lt hx']
state_before: R : Type u_1
inst✝ : Semiring R
k : ℕ
f p : R[X]
n x : ℕ
hx : ¬p.coeff x = 0
hxp : x ≤ p.natDegree
hx' : x < n
⊢ ↑(x.choose n) * p.coeff x = 0
state_after: no goals

tactic: simp
state_before: case h
R : Type u_1
inst✝ : Semiring R
k : ℕ
f p : R[X]
n : ℕ
⊢ max 0 (max 0 0) = max 0 0
state_after: no goals