l3lab/ntp-mathlib huggingface dataset:
theorem eval_multiset_prod_X_sub_C_derivative [DecidableEq R]
    {S : Multiset R} {r : R} (hr : r ∈ S) :
    eval r (derivative (Multiset.map (fun a => X - C a) S).prod) =
      (Multiset.map (fun a => r - a) (S.erase r)).prod := by
  

Proof state:
R : Type u
S✝ : Type v
T : Type w
ι : Type y
A : Type z
a b : R
n : ℕ
inst✝¹ : CommRing R
inst✝ : DecidableEq R
S : Multiset R
r : R
hr : r ∈ S
⊢ eval r (derivative (Multiset.prod (Multiset.map (fun a => X - C a) S))) =
    Multiset.prod (Multiset.map (fun a => r - a) (Multiset.erase S r))

Next tactic:
nth_rw 1 [← Multiset.cons_erase hr]
theorem eval_multiset_prod_X_sub_C_derivative [DecidableEq R]
    {S : Multiset R} {r : R} (hr : r ∈ S) :
    eval r (derivative (Multiset.map (fun a => X - C a) S).prod) =
      (Multiset.map (fun a => r - a) (S.erase r)).prod := by
  nth_rw 1 [← Multiset.cons_erase hr]
  

Proof state:
R : Type u
S✝ : Type v
T : Type w
ι : Type y
A : Type z
a b : R
n : ℕ
inst✝¹ : CommRing R
inst✝ : DecidableEq R
S : Multiset R
r : R
hr : r ∈ S
⊢ eval r (derivative (Multiset.prod (Multiset.map (fun a => X - C a) (r ::ₘ Multiset.erase S r)))) =
    Multiset.prod (Multiset.map (fun a => r - a) (Multiset.erase S r))

Next tactic:
have := (evalRingHom r).map_multiset_prod (Multiset.map (fun a => X - C a) (S.erase r))
theorem eval_multiset_prod_X_sub_C_derivative [DecidableEq R]
    {S : Multiset R} {r : R} (hr : r ∈ S) :
    eval r (derivative (Multiset.map (fun a => X - C a) S).prod) =
      (Multiset.map (fun a => r - a) (S.erase r)).prod := by
  nth_rw 1 [← Multiset.cons_erase hr]
  have := (evalRingHom r).map_multiset_prod (Multiset.map (fun a => X - C a) (S.erase r))
  

Proof state:
R : Type u
S✝ : Type v
T : Type w
ι : Type y
A : Type z
a b : R
n : ℕ
inst✝¹ : CommRing R
inst✝ : DecidableEq R
S : Multiset R
r : R
hr : r ∈ S
this :
  (evalRingHom r) (Multiset.prod (Multiset.map (fun a => X - C a) (Multiset.erase S r))) =
    Multiset.prod (Multiset.map (⇑(evalRingHom r)) (Multiset.map (fun a => X - C a) (Multiset.erase S r)))
⊢ eval r (derivative (Multiset.prod (Multiset.map (fun a => X - C a) (r ::ₘ Multiset.erase S r)))) =
    Multiset.prod (Multiset.map (fun a => r - a) (Multiset.erase S r))

Next tactic:
simpa using this
theorem derivative_X_sub_C_pow (c : R) (m : ℕ) :
    derivative ((X - C c) ^ m) = C (m : R) * (X - C c) ^ (m - 1) := by
  

Proof state:
R : Type u
S : Type v
T : Type w
ι : Type y
A : Type z
a b : R
n : ℕ
inst✝ : CommRing R
c : R
m : ℕ
⊢ derivative ((X - C c) ^ m) = C ↑m * (X - C c) ^ (m - 1)

Next tactic:
rw [derivative_pow, derivative_X_sub_C, mul_one]
theorem derivative_X_sub_C_sq (c : R) : derivative ((X - C c) ^ 2) = C 2 * (X - C c) := by
  

Proof state:
R : Type u
S : Type v
T : Type w
ι : Type y
A : Type z
a b : R
n : ℕ
inst✝ : CommRing R
c : R
⊢ derivative ((X - C c) ^ 2) = C 2 * (X - C c)

Next tactic:
rw [derivative_sq, derivative_X_sub_C, mul_one]
theorem iterate_derivative_X_sub_pow (n k : ℕ) (c : R) :
    derivative^[k] ((X - C c) ^ n) = n.descFactorial k • (X - C c) ^ (n - k) := by
  

Proof state:
R : Type u
S : Type v
T : Type w
ι : Type y
A : Type z
a b : R
n✝ : ℕ
inst✝ : CommRing R
n k : ℕ
c : R
⊢ (⇑derivative)^[k] ((X - C c) ^ n) = Nat.descFactorial n k • (X - C c) ^ (n - k)

Next tactic:
rw [sub_eq_add_neg, ← C_neg, iterate_derivative_X_add_pow]
theorem iterate_derivative_X_sub_pow_self (n : ℕ) (c : R) :
    derivative^[n] ((X - C c) ^ n) = n.factorial := by
  

Proof state:
R : Type u
S : Type v
T : Type w
ι : Type y
A : Type z
a b : R
n✝ : ℕ
inst✝ : CommRing R
n : ℕ
c : R
⊢ (⇑derivative)^[n] ((X - C c) ^ n) = ↑(Nat.factorial n)

Next tactic:
rw [iterate_derivative_X_sub_pow, n.sub_self, pow_zero, nsmul_one, n.descFactorial_self]
theorem revAtFun_invol {N i : ℕ} : revAtFun N (revAtFun N i) = i := by
  

Proof state:
R : Type u_1
inst✝ : Semiring R
f : R[X]
N i : ℕ
⊢ revAtFun N (revAtFun N i) = i

Next tactic:
unfold revAtFun
theorem revAtFun_invol {N i : ℕ} : revAtFun N (revAtFun N i) = i := by
  unfold revAtFun
  

Proof state:
R : Type u_1
inst✝ : Semiring R
f : R[X]
N i : ℕ
⊢ (if (if i ≤ N then N - i else i) ≤ N then N - if i ≤ N then N - i else i else if i ≤ N then N - i else i) = i

Next tactic:
split_ifs with h j
theorem revAtFun_invol {N i : ℕ} : revAtFun N (revAtFun N i) = i := by
  unfold revAtFun
  split_ifs with h j
  · 

Proof state:
case pos
R : Type u_1
inst✝ : Semiring R
f : R[X]
N i : ℕ
h : i ≤ N
j : N - i ≤ N
⊢ N - (N - i) = i

Next tactic:
exact tsub_tsub_cancel_of_le h
theorem revAtFun_invol {N i : ℕ} : revAtFun N (revAtFun N i) = i := by
  unfold revAtFun
  split_ifs with h j
  · exact tsub_tsub_cancel_of_le h
  · 

Proof state:
case neg
R : Type u_1
inst✝ : Semiring R
f : R[X]
N i : ℕ
h : i ≤ N
j : ¬N - i ≤ N
⊢ N - i = i

Next tactic:
exfalso
theorem revAtFun_invol {N i : ℕ} : revAtFun N (revAtFun N i) = i := by
  unfold revAtFun
  split_ifs with h j
  · exact tsub_tsub_cancel_of_le h
  · exfalso
    

Proof state:
case neg.h
R : Type u_1
inst✝ : Semiring R
f : R[X]
N i : ℕ
h : i ≤ N
j : ¬N - i ≤ N
⊢ False

Next tactic:
apply j
theorem revAtFun_invol {N i : ℕ} : revAtFun N (revAtFun N i) = i := by
  unfold revAtFun
  split_ifs with h j
  · exact tsub_tsub_cancel_of_le h
  · exfalso
    apply j
    

Proof state:
case neg.h
R : Type u_1
inst✝ : Semiring R
f : R[X]
N i : ℕ
h : i ≤ N
j : ¬N - i ≤ N
⊢ N - i ≤ N

Next tactic:
exact Nat.sub_le N i
theorem revAtFun_invol {N i : ℕ} : revAtFun N (revAtFun N i) = i := by
  unfold revAtFun
  split_ifs with h j
  · exact tsub_tsub_cancel_of_le h
  · exfalso
    apply j
    exact Nat.sub_le N i
  · 

Proof state:
case neg
R : Type u_1
inst✝ : Semiring R
f : R[X]
N i : ℕ
h : ¬i ≤ N
⊢ i = i

Next tactic:
rfl
theorem revAtFun_inj {N : ℕ} : Function.Injective (revAtFun N) := by
  

Proof state:
R : Type u_1
inst✝ : Semiring R
f : R[X]
N : ℕ
⊢ Function.Injective (revAtFun N)

Next tactic:
intro a b hab
theorem revAtFun_inj {N : ℕ} : Function.Injective (revAtFun N) := by
  intro a b hab
  

Proof state:
R : Type u_1
inst✝ : Semiring R
f : R[X]
N a b : ℕ
hab : revAtFun N a = revAtFun N b
⊢ a = b

Next tactic:
rw [← @revAtFun_invol N a, hab, revAtFun_invol]
lemma revAt_eq_self_of_lt {N i : ℕ} (h : N < i) : revAt N i = i := by 

Proof state:
R : Type u_1
inst✝ : Semiring R
f : R[X]
N i : ℕ
h : N < i
⊢ (revAt N) i = i

Next tactic:
simp [revAt, Nat.not_le.mpr h]
theorem revAt_add {N O n o : ℕ} (hn : n ≤ N) (ho : o ≤ O) :
    revAt (N + O) (n + o) = revAt N n + revAt O o := by
  

Proof state:
R : Type u_1
inst✝ : Semiring R
f : R[X]
N O n o : ℕ
hn : n ≤ N
ho : o ≤ O
⊢ (revAt (N + O)) (n + o) = (revAt N) n + (revAt O) o

Next tactic:
rcases Nat.le.dest hn with ⟨n', rfl⟩
theorem revAt_add {N O n o : ℕ} (hn : n ≤ N) (ho : o ≤ O) :
    revAt (N + O) (n + o) = revAt N n + revAt O o := by
  rcases Nat.le.dest hn with ⟨n', rfl⟩
  

Proof state:
case intro
R : Type u_1
inst✝ : Semiring R
f : R[X]
O n o : ℕ
ho : o ≤ O
n' : ℕ
hn : n ≤ n + n'
⊢ (revAt (n + n' + O)) (n + o) = (revAt (n + n')) n + (revAt O) o

Next tactic:
rcases Nat.le.dest ho with ⟨o', rfl⟩
theorem revAt_add {N O n o : ℕ} (hn : n ≤ N) (ho : o ≤ O) :
    revAt (N + O) (n + o) = revAt N n + revAt O o := by
  rcases Nat.le.dest hn with ⟨n', rfl⟩
  rcases Nat.le.dest ho with ⟨o', rfl⟩
  

Proof state:
case intro.intro
R : Type u_1
inst✝ : Semiring R
f : R[X]
n o n' : ℕ
hn : n ≤ n + n'
o' : ℕ
ho : o ≤ o + o'
⊢ (revAt (n + n' + (o + o'))) (n + o) = (revAt (n + n')) n + (revAt (o + o')) o

Next tactic:
repeat' rw [revAt_le (le_add_right rfl.le)]
theorem revAt_add {N O n o : ℕ} (hn : n ≤ N) (ho : o ≤ O) :
    revAt (N + O) (n + o) = revAt N n + revAt O o := by
  rcases Nat.le.dest hn with ⟨n', rfl⟩
  rcases Nat.le.dest ho with ⟨o', rfl⟩
  repeat' 

Proof state:
case intro.intro
R : Type u_1
inst✝ : Semiring R
f : R[X]
n o n' : ℕ
hn : n ≤ n + n'
o' : ℕ
ho : o ≤ o + o'
⊢ (revAt (n + n' + (o + o'))) (n + o) = (revAt (n + n')) n + (revAt (o + o')) o

Next tactic:
rw [revAt_le (le_add_right rfl.le)]
theorem revAt_add {N O n o : ℕ} (hn : n ≤ N) (ho : o ≤ O) :
    revAt (N + O) (n + o) = revAt N n + revAt O o := by
  rcases Nat.le.dest hn with ⟨n', rfl⟩
  rcases Nat.le.dest ho with ⟨o', rfl⟩
  repeat' 

Proof state:
case intro.intro
R : Type u_1
inst✝ : Semiring R
f : R[X]
n o n' : ℕ
hn : n ≤ n + n'
o' : ℕ
ho : o ≤ o + o'
⊢ (revAt (n + n' + (o + o'))) (n + o) = n + n' - n + (revAt (o + o')) o

Next tactic:
rw [revAt_le (le_add_right rfl.le)]
theorem revAt_add {N O n o : ℕ} (hn : n ≤ N) (ho : o ≤ O) :
    revAt (N + O) (n + o) = revAt N n + revAt O o := by
  rcases Nat.le.dest hn with ⟨n', rfl⟩
  rcases Nat.le.dest ho with ⟨o', rfl⟩
  repeat' 

Proof state:
case intro.intro
R : Type u_1
inst✝ : Semiring R
f : R[X]
n o n' : ℕ
hn : n ≤ n + n'
o' : ℕ
ho : o ≤ o + o'
⊢ (revAt (n + n' + (o + o'))) (n + o) = n + n' - n + (o + o' - o)

Next tactic:
rw [revAt_le (le_add_right rfl.le)]
theorem revAt_add {N O n o : ℕ} (hn : n ≤ N) (ho : o ≤ O) :
    revAt (N + O) (n + o) = revAt N n + revAt O o := by
  rcases Nat.le.dest hn with ⟨n', rfl⟩
  rcases Nat.le.dest ho with ⟨o', rfl⟩
  repeat' rw [revAt_le (le_add_right rfl.le)]
  

Proof state:
case intro.intro
R : Type u_1
inst✝ : Semiring R
f : R[X]
n o n' : ℕ
hn : n ≤ n + n'
o' : ℕ
ho : o ≤ o + o'
⊢ (revAt (n + n' + (o + o'))) (n + o) = n + n' - n + (o + o' - o)

Next tactic:
rw [add_assoc, add_left_comm n' o, ← add_assoc, revAt_le (le_add_right rfl.le)]
theorem revAt_add {N O n o : ℕ} (hn : n ≤ N) (ho : o ≤ O) :
    revAt (N + O) (n + o) = revAt N n + revAt O o := by
  rcases Nat.le.dest hn with ⟨n', rfl⟩
  rcases Nat.le.dest ho with ⟨o', rfl⟩
  repeat' rw [revAt_le (le_add_right rfl.le)]
  rw [add_assoc, add_left_comm n' o, ← add_assoc, revAt_le (le_add_right rfl.le)]
  

Proof state:
case intro.intro
R : Type u_1
inst✝ : Semiring R
f : R[X]
n o n' : ℕ
hn : n ≤ n + n'
o' : ℕ
ho : o ≤ o + o'
⊢ n + o + (n' + o') - (n + o) = n + n' - n + (o + o' - o)

Next tactic:
repeat' rw [add_tsub_cancel_left]
theorem revAt_add {N O n o : ℕ} (hn : n ≤ N) (ho : o ≤ O) :
    revAt (N + O) (n + o) = revAt N n + revAt O o := by
  rcases Nat.le.dest hn with ⟨n', rfl⟩
  rcases Nat.le.dest ho with ⟨o', rfl⟩
  repeat' rw [revAt_le (le_add_right rfl.le)]
  rw [add_assoc, add_left_comm n' o, ← add_assoc, revAt_le (le_add_right rfl.le)]
  repeat' 

Proof state:
case intro.intro
R : Type u_1
inst✝ : Semiring R
f : R[X]
n o n' : ℕ
hn : n ≤ n + n'
o' : ℕ
ho : o ≤ o + o'
⊢ n + o + (n' + o') - (n + o) = n + n' - n + (o + o' - o)

Next tactic:
rw [add_tsub_cancel_left]
theorem revAt_add {N O n o : ℕ} (hn : n ≤ N) (ho : o ≤ O) :
    revAt (N + O) (n + o) = revAt N n + revAt O o := by
  rcases Nat.le.dest hn with ⟨n', rfl⟩
  rcases Nat.le.dest ho with ⟨o', rfl⟩
  repeat' rw [revAt_le (le_add_right rfl.le)]
  rw [add_assoc, add_left_comm n' o, ← add_assoc, revAt_le (le_add_right rfl.le)]
  repeat' 

Proof state:
case intro.intro
R : Type u_1
inst✝ : Semiring R
f : R[X]
n o n' : ℕ
hn : n ≤ n + n'
o' : ℕ
ho : o ≤ o + o'
⊢ n' + o' = n + n' - n + (o + o' - o)

Next tactic:
rw [add_tsub_cancel_left]
theorem revAt_add {N O n o : ℕ} (hn : n ≤ N) (ho : o ≤ O) :
    revAt (N + O) (n + o) = revAt N n + revAt O o := by
  rcases Nat.le.dest hn with ⟨n', rfl⟩
  rcases Nat.le.dest ho with ⟨o', rfl⟩
  repeat' rw [revAt_le (le_add_right rfl.le)]
  rw [add_assoc, add_left_comm n' o, ← add_assoc, revAt_le (le_add_right rfl.le)]
  repeat' 

Proof state:
case intro.intro
R : Type u_1
inst✝ : Semiring R
f : R[X]
n o n' : ℕ
hn : n ≤ n + n'
o' : ℕ
ho : o ≤ o + o'
⊢ n' + o' = n' + (o + o' - o)

Next tactic:
rw [add_tsub_cancel_left]
theorem revAt_zero (N : ℕ) : revAt N 0 = N := by 

Proof state:
R : Type u_1
inst✝ : Semiring R
f : R[X]
N : ℕ
⊢ (revAt N) 0 = N

Next tactic:
simp
theorem reflect_support (N : ℕ) (f : R[X]) :
    (reflect N f).support = Finset.image (revAt N) f.support := by
  

Proof state:
R : Type u_1
inst✝ : Semiring R
f✝ : R[X]
N : ℕ
f : R[X]
⊢ support (reflect N f) = image (⇑(revAt N)) (support f)

Next tactic:
rcases f with ⟨⟩
theorem reflect_support (N : ℕ) (f : R[X]) :
    (reflect N f).support = Finset.image (revAt N) f.support := by
  rcases f with ⟨⟩
  

Proof state:
case ofFinsupp
R : Type u_1
inst✝ : Semiring R
f : R[X]
N : ℕ
toFinsupp✝ : AddMonoidAlgebra R ℕ
⊢ support (reflect N { toFinsupp := toFinsupp✝ }) = image (⇑(revAt N)) (support { toFinsupp := toFinsupp✝ })

Next tactic:
ext1
theorem reflect_support (N : ℕ) (f : R[X]) :
    (reflect N f).support = Finset.image (revAt N) f.support := by
  rcases f with ⟨⟩
  ext1
  

Proof state:
case ofFinsupp.a
R : Type u_1
inst✝ : Semiring R
f : R[X]
N : ℕ
toFinsupp✝ : AddMonoidAlgebra R ℕ
a✝ : ℕ
⊢ a✝ ∈ support (reflect N { toFinsupp := toFinsupp✝ }) ↔ a✝ ∈ image (⇑(revAt N)) (support { toFinsupp := toFinsupp✝ })

Next tactic:
simp only [reflect, support_ofFinsupp, support_embDomain, Finset.mem_map, Finset.mem_image]
@[simp]
theorem coeff_reflect (N : ℕ) (f : R[X]) (i : ℕ) : coeff (reflect N f) i = f.coeff (revAt N i) := by
  

Proof state:
R : Type u_1
inst✝ : Semiring R
f✝ : R[X]
N : ℕ
f : R[X]
i : ℕ
⊢ coeff (reflect N f) i = coeff f ((revAt N) i)

Next tactic:
rcases f with ⟨f⟩
@[simp]
theorem coeff_reflect (N : ℕ) (f : R[X]) (i : ℕ) : coeff (reflect N f) i = f.coeff (revAt N i) := by
  rcases f with ⟨f⟩
  

Proof state:
case ofFinsupp
R : Type u_1
inst✝ : Semiring R
f✝ : R[X]
N i : ℕ
f : AddMonoidAlgebra R ℕ
⊢ coeff (reflect N { toFinsupp := f }) i = coeff { toFinsupp := f } ((revAt N) i)

Next tactic:
simp only [reflect, coeff]
@[simp]
theorem coeff_reflect (N : ℕ) (f : R[X]) (i : ℕ) : coeff (reflect N f) i = f.coeff (revAt N i) := by
  rcases f with ⟨f⟩
  simp only [reflect, coeff]
  

Proof state:
case ofFinsupp
R : Type u_1
inst✝ : Semiring R
f✝ : R[X]
N i : ℕ
f : AddMonoidAlgebra R ℕ
⊢ (embDomain (revAt N) f) i = f ((revAt N) i)

Next tactic:
calc
    Finsupp.embDomain (revAt N) f i = Finsupp.embDomain (revAt N) f (revAt N (revAt N i)) := by
      rw [revAt_invol]
    _ = f (revAt N i) := Finsupp.embDomain_apply _ _ _
@[simp]
theorem coeff_reflect (N : ℕ) (f : R[X]) (i : ℕ) : coeff (reflect N f) i = f.coeff (revAt N i) := by
  rcases f with ⟨f⟩
  simp only [reflect, coeff]
  calc
    Finsupp.embDomain (revAt N) f i = Finsupp.embDomain (revAt N) f (revAt N (revAt N i)) := by
      

Proof state:
R : Type u_1
inst✝ : Semiring R
f✝ : R[X]
N i : ℕ
f : AddMonoidAlgebra R ℕ
⊢ (embDomain (revAt N) f) i = (embDomain (revAt N) f) ((revAt N) ((revAt N) i))

Next tactic:
rw [revAt_invol]
@[simp]
theorem reflect_eq_zero_iff {N : ℕ} {f : R[X]} : reflect N (f : R[X]) = 0 ↔ f = 0 := by
  

Proof state:
R : Type u_1
inst✝ : Semiring R
f✝ : R[X]
N : ℕ
f : R[X]
⊢ reflect N f = 0 ↔ f = 0

Next tactic:
rw [ofFinsupp_eq_zero, reflect, embDomain_eq_zero, ofFinsupp_eq_zero]
@[simp]
theorem reflect_add (f g : R[X]) (N : ℕ) : reflect N (f + g) = reflect N f + reflect N g := by
  

Proof state:
R : Type u_1
inst✝ : Semiring R
f✝ f g : R[X]
N : ℕ
⊢ reflect N (f + g) = reflect N f + reflect N g

Next tactic:
ext
@[simp]
theorem reflect_add (f g : R[X]) (N : ℕ) : reflect N (f + g) = reflect N f + reflect N g := by
  ext
  

Proof state:
case a
R : Type u_1
inst✝ : Semiring R
f✝ f g : R[X]
N n✝ : ℕ
⊢ coeff (reflect N (f + g)) n✝ = coeff (reflect N f + reflect N g) n✝

Next tactic:
simp only [coeff_add, coeff_reflect]
@[simp]
theorem reflect_C_mul (f : R[X]) (r : R) (N : ℕ) : reflect N (C r * f) = C r * reflect N f := by
  

Proof state:
R : Type u_1
inst✝ : Semiring R
f✝ f : R[X]
r : R
N : ℕ
⊢ reflect N (C r * f) = C r * reflect N f

Next tactic:
ext
@[simp]
theorem reflect_C_mul (f : R[X]) (r : R) (N : ℕ) : reflect N (C r * f) = C r * reflect N f := by
  ext
  

Proof state:
case a
R : Type u_1
inst✝ : Semiring R
f✝ f : R[X]
r : R
N n✝ : ℕ
⊢ coeff (reflect N (C r * f)) n✝ = coeff (C r * reflect N f) n✝

Next tactic:
simp only [coeff_reflect, coeff_C_mul]
theorem reflect_C_mul_X_pow (N n : ℕ) {c : R} : reflect N (C c * X ^ n) = C c * X ^ revAt N n := by
  

Proof state:
R : Type u_1
inst✝ : Semiring R
f : R[X]
N n : ℕ
c : R
⊢ reflect N (C c * X ^ n) = C c * X ^ (revAt N) n

Next tactic:
ext
theorem reflect_C_mul_X_pow (N n : ℕ) {c : R} : reflect N (C c * X ^ n) = C c * X ^ revAt N n := by
  ext
  

Proof state:
case a
R : Type u_1
inst✝ : Semiring R
f : R[X]
N n : ℕ
c : R
n✝ : ℕ
⊢ coeff (reflect N (C c * X ^ n)) n✝ = coeff (C c * X ^ (revAt N) n) n✝

Next tactic:
rw [reflect_C_mul, coeff_C_mul, coeff_C_mul, coeff_X_pow, coeff_reflect]
theorem reflect_C_mul_X_pow (N n : ℕ) {c : R} : reflect N (C c * X ^ n) = C c * X ^ revAt N n := by
  ext
  rw [reflect_C_mul, coeff_C_mul, coeff_C_mul, coeff_X_pow, coeff_reflect]
  

Proof state:
case a
R : Type u_1
inst✝ : Semiring R
f : R[X]
N n : ℕ
c : R
n✝ : ℕ
⊢ c * coeff (X ^ n) ((revAt N) n✝) = c * if n✝ = (revAt N) n then 1 else 0

Next tactic:
split_ifs with h
theorem reflect_C_mul_X_pow (N n : ℕ) {c : R} : reflect N (C c * X ^ n) = C c * X ^ revAt N n := by
  ext
  rw [reflect_C_mul, coeff_C_mul, coeff_C_mul, coeff_X_pow, coeff_reflect]
  split_ifs with h
  · 

Proof state:
case pos
R : Type u_1
inst✝ : Semiring R
f : R[X]
N n : ℕ
c : R
n✝ : ℕ
h : n✝ = (revAt N) n
⊢ c * coeff (X ^ n) ((revAt N) n✝) = c * 1

Next tactic:
rw [h, revAt_invol, coeff_X_pow_self]
theorem reflect_C_mul_X_pow (N n : ℕ) {c : R} : reflect N (C c * X ^ n) = C c * X ^ revAt N n := by
  ext
  rw [reflect_C_mul, coeff_C_mul, coeff_C_mul, coeff_X_pow, coeff_reflect]
  split_ifs with h
  · rw [h, revAt_invol, coeff_X_pow_self]
  · 

Proof state:
case neg
R : Type u_1
inst✝ : Semiring R
f : R[X]
N n : ℕ
c : R
n✝ : ℕ
h : ¬n✝ = (revAt N) n
⊢ c * coeff (X ^ n) ((revAt N) n✝) = c * 0

Next tactic:
rw [not_mem_support_iff.mp]
theorem reflect_C_mul_X_pow (N n : ℕ) {c : R} : reflect N (C c * X ^ n) = C c * X ^ revAt N n := by
  ext
  rw [reflect_C_mul, coeff_C_mul, coeff_C_mul, coeff_X_pow, coeff_reflect]
  split_ifs with h
  · rw [h, revAt_invol, coeff_X_pow_self]
  · rw [not_mem_support_iff.mp]
    

Proof state:
case neg
R : Type u_1
inst✝ : Semiring R
f : R[X]
N n : ℕ
c : R
n✝ : ℕ
h : ¬n✝ = (revAt N) n
⊢ (revAt N) n✝ ∉ support (X ^ n)

Next tactic:
intro a
theorem reflect_C_mul_X_pow (N n : ℕ) {c : R} : reflect N (C c * X ^ n) = C c * X ^ revAt N n := by
  ext
  rw [reflect_C_mul, coeff_C_mul, coeff_C_mul, coeff_X_pow, coeff_reflect]
  split_ifs with h
  · rw [h, revAt_invol, coeff_X_pow_self]
  · rw [not_mem_support_iff.mp]
    intro a
    

Proof state:
case neg
R : Type u_1
inst✝ : Semiring R
f : R[X]
N n : ℕ
c : R
n✝ : ℕ
h : ¬n✝ = (revAt N) n
a : (revAt N) n✝ ∈ support (X ^ n)
⊢ False

Next tactic:
rw [← one_mul (X ^ n), ← C_1] at a
theorem reflect_C_mul_X_pow (N n : ℕ) {c : R} : reflect N (C c * X ^ n) = C c * X ^ revAt N n := by
  ext
  rw [reflect_C_mul, coeff_C_mul, coeff_C_mul, coeff_X_pow, coeff_reflect]
  split_ifs with h
  · rw [h, revAt_invol, coeff_X_pow_self]
  · rw [not_mem_support_iff.mp]
    intro a
    rw [← one_mul (X ^ n), ← C_1] at a
    

Proof state:
case neg
R : Type u_1
inst✝ : Semiring R
f : R[X]
N n : ℕ
c : R
n✝ : ℕ
h : ¬n✝ = (revAt N) n
a : (revAt N) n✝ ∈ support (C 1 * X ^ n)
⊢ False

Next tactic:
apply h
theorem reflect_C_mul_X_pow (N n : ℕ) {c : R} : reflect N (C c * X ^ n) = C c * X ^ revAt N n := by
  ext
  rw [reflect_C_mul, coeff_C_mul, coeff_C_mul, coeff_X_pow, coeff_reflect]
  split_ifs with h
  · rw [h, revAt_invol, coeff_X_pow_self]
  · rw [not_mem_support_iff.mp]
    intro a
    rw [← one_mul (X ^ n), ← C_1] at a
    apply h
    

Proof state:
case neg
R : Type u_1
inst✝ : Semiring R
f : R[X]
N n : ℕ
c : R
n✝ : ℕ
h : ¬n✝ = (revAt N) n
a : (revAt N) n✝ ∈ support (C 1 * X ^ n)
⊢ n✝ = (revAt N) n

Next tactic:
rw [← mem_support_C_mul_X_pow a, revAt_invol]
@[simp]
theorem reflect_C (r : R) (N : ℕ) : reflect N (C r) = C r * X ^ N := by
  

Proof state:
R : Type u_1
inst✝ : Semiring R
f : R[X]
r : R
N : ℕ
⊢ reflect N (C r) = C r * X ^ N

Next tactic:
conv_lhs => rw [← mul_one (C r), ← pow_zero X, reflect_C_mul_X_pow, revAt_zero]
@[simp]
theorem reflect_C (r : R) (N : ℕ) : reflect N (C r) = C r * X ^ N := by
  conv_lhs => 

Proof state:
R : Type u_1
inst✝ : Semiring R
f : R[X]
r : R
N : ℕ
| reflect N (C r)

Next tactic:
rw [← mul_one (C r), ← pow_zero X, reflect_C_mul_X_pow, revAt_zero]
@[simp]
theorem reflect_monomial (N n : ℕ) : reflect N ((X : R[X]) ^ n) = X ^ revAt N n := by
  

Proof state:
R : Type u_1
inst✝ : Semiring R
f : R[X]
N n : ℕ
⊢ reflect N (X ^ n) = X ^ (revAt N) n

Next tactic:
rw [← one_mul (X ^ n), ← one_mul (X ^ revAt N n), ← C_1, reflect_C_mul_X_pow]
@[simp] lemma reflect_one_X : reflect 1 (X : R[X]) = 1 := by
  

Proof state:
R : Type u_1
inst✝ : Semiring R
f : R[X]
⊢ reflect 1 X = 1

Next tactic:
simpa using reflect_monomial 1 1 (R := R)
theorem reflect_mul_induction (cf cg : ℕ) :
    ∀ N O : ℕ,
      ∀ f g : R[X],
        f.support.card ≤ cf.succ →
          g.support.card ≤ cg.succ →
            f.natDegree ≤ N →
              g.natDegree ≤ O → reflect (N + O) (f * g) = reflect N f * reflect O g := by
  

Proof state:
R : Type u_1
inst✝ : Semiring R
f : R[X]
cf cg : ℕ
⊢ ∀ (N O : ℕ) (f g : R[X]),
    card (support f) ≤ Nat.succ cf →
      card (support g) ≤ Nat.succ cg →
        natDegree f ≤ N → natDegree g ≤ O → reflect (N + O) (f * g) = reflect N f * reflect O g

Next tactic:
induction' cf with cf hcf
theorem reflect_mul_induction (cf cg : ℕ) :
    ∀ N O : ℕ,
      ∀ f g : R[X],
        f.support.card ≤ cf.succ →
          g.support.card ≤ cg.succ →
            f.natDegree ≤ N →
              g.natDegree ≤ O → reflect (N + O) (f * g) = reflect N f * reflect O g := by
  induction' cf with cf hcf
  --first induction (left): base case
  · 

Proof state:
case zero
R : Type u_1
inst✝ : Semiring R
f : R[X]
cg : ℕ
⊢ ∀ (N O : ℕ) (f g : R[X]),
    card (support f) ≤ Nat.succ Nat.zero →
      card (support g) ≤ Nat.succ cg →
        natDegree f ≤ N → natDegree g ≤ O → reflect (N + O) (f * g) = reflect N f * reflect O g

Next tactic:
induction' cg with cg hcg
theorem reflect_mul_induction (cf cg : ℕ) :
    ∀ N O : ℕ,
      ∀ f g : R[X],
        f.support.card ≤ cf.succ →
          g.support.card ≤ cg.succ →
            f.natDegree ≤ N →
              g.natDegree ≤ O → reflect (N + O) (f * g) = reflect N f * reflect O g := by
  induction' cf with cf hcf
  --first induction (left): base case
  · induction' cg with cg hcg
    -- second induction (right): base case
    · 

Proof state:
case zero.zero
R : Type u_1
inst✝ : Semiring R
f : R[X]
⊢ ∀ (N O : ℕ) (f g : R[X]),
    card (support f) ≤ Nat.succ Nat.zero →
      card (support g) ≤ Nat.succ Nat.zero →
        natDegree f ≤ N → natDegree g ≤ O → reflect (N + O) (f * g) = reflect N f * reflect O g

Next tactic:
intro N O f g Cf Cg Nf Og
theorem reflect_mul_induction (cf cg : ℕ) :
    ∀ N O : ℕ,
      ∀ f g : R[X],
        f.support.card ≤ cf.succ →
          g.support.card ≤ cg.succ →
            f.natDegree ≤ N →
              g.natDegree ≤ O → reflect (N + O) (f * g) = reflect N f * reflect O g := by
  induction' cf with cf hcf
  --first induction (left): base case
  · induction' cg with cg hcg
    -- second induction (right): base case
    · intro N O f g Cf Cg Nf Og
      

Proof state:
case zero.zero
R : Type u_1
inst✝ : Semiring R
f✝ : R[X]
N O : ℕ
f g : R[X]
Cf : card (support f) ≤ Nat.succ Nat.zero
Cg : card (support g) ≤ Nat.succ Nat.zero
Nf : natDegree f ≤ N
Og : natDegree g ≤ O
⊢ reflect (N + O) (f * g) = reflect N f * reflect O g

Next tactic:
rw [← C_mul_X_pow_eq_self Cf, ← C_mul_X_pow_eq_self Cg]