l3lab/ntp-mathlib huggingface dataset:
/-- A stronger version of `Polynomial.exists_degree_le_of_mem_span` under the assumption that the
  set `s : R[X]` is finite. There exists a polynomial `p' ∈ s` whose degree dominates the degree of
  every element of `p ∈ span R s`-/
theorem exists_degree_le_of_mem_span_of_finite {s : Set R[X]} (s_fin : s.Finite) (hs : s.Nonempty) :
    ∃ p' ∈ s, ∀ (p : R[X]), p ∈ Submodule.span R s → degree p ≤ degree p' := by
  rcases Set.Finite.exists_maximal_wrt degree s s_fin hs with ⟨a, has, hmax⟩
  refine ⟨a, has, fun p hp => ?_⟩
  rcases exists_degree_le_of_mem_span hs hp with ⟨p', hp'⟩
  have p'max := hmax p' hp'.left
  by_cases h : degree a ≤ degree p'
  · rw [← p'max h] at hp'; exact hp'.right
  · 

Proof state:
case neg
R : Type u
S : Type u_1
inst✝ : Semiring R
s : Set R[X]
s_fin : Set.Finite s
hs : Set.Nonempty s
a : R[X]
has : a ∈ s
hmax : ∀ a' ∈ s, degree a ≤ degree a' → degree a = degree a'
p : R[X]
hp : p ∈ Submodule.span R s
p' : R[X]
hp' : p' ∈ s ∧ degree p ≤ degree p'
p'max : degree a ≤ degree p' → degree a = degree p'
h : ¬degree a ≤ degree p'
⊢ degree p ≤ degree a

Next tactic:
exact le_trans hp'.right (not_le.mp h).le
/-- The span of every finite set of polynomials is contained in a `degreeLE n` for some `n`. -/
theorem span_le_degreeLE_of_finite {s : Set R[X]} (s_fin : s.Finite) :
    ∃ n : ℕ, Submodule.span R s ≤ degreeLE R n := by
  

Proof state:
R : Type u
S : Type u_1
inst✝ : Semiring R
s : Set R[X]
s_fin : Set.Finite s
⊢ ∃ n, Submodule.span R s ≤ degreeLE R ↑n

Next tactic:
by_cases s_emp : s.Nonempty
/-- The span of every finite set of polynomials is contained in a `degreeLE n` for some `n`. -/
theorem span_le_degreeLE_of_finite {s : Set R[X]} (s_fin : s.Finite) :
    ∃ n : ℕ, Submodule.span R s ≤ degreeLE R n := by
  by_cases s_emp : s.Nonempty
  · 

Proof state:
case pos
R : Type u
S : Type u_1
inst✝ : Semiring R
s : Set R[X]
s_fin : Set.Finite s
s_emp : Set.Nonempty s
⊢ ∃ n, Submodule.span R s ≤ degreeLE R ↑n

Next tactic:
rcases exists_degree_le_of_mem_span_of_finite s_fin s_emp with ⟨p', _, hp'max⟩
/-- The span of every finite set of polynomials is contained in a `degreeLE n` for some `n`. -/
theorem span_le_degreeLE_of_finite {s : Set R[X]} (s_fin : s.Finite) :
    ∃ n : ℕ, Submodule.span R s ≤ degreeLE R n := by
  by_cases s_emp : s.Nonempty
  · rcases exists_degree_le_of_mem_span_of_finite s_fin s_emp with ⟨p', _, hp'max⟩
    

Proof state:
case pos.intro.intro
R : Type u
S : Type u_1
inst✝ : Semiring R
s : Set R[X]
s_fin : Set.Finite s
s_emp : Set.Nonempty s
p' : R[X]
left✝ : p' ∈ s
hp'max : ∀ p ∈ Submodule.span R s, degree p ≤ degree p'
⊢ ∃ n, Submodule.span R s ≤ degreeLE R ↑n

Next tactic:
exact ⟨natDegree p', fun p hp => mem_degreeLE.mpr ((hp'max _ hp).trans degree_le_natDegree)⟩
/-- The span of every finite set of polynomials is contained in a `degreeLE n` for some `n`. -/
theorem span_le_degreeLE_of_finite {s : Set R[X]} (s_fin : s.Finite) :
    ∃ n : ℕ, Submodule.span R s ≤ degreeLE R n := by
  by_cases s_emp : s.Nonempty
  · rcases exists_degree_le_of_mem_span_of_finite s_fin s_emp with ⟨p', _, hp'max⟩
    exact ⟨natDegree p', fun p hp => mem_degreeLE.mpr ((hp'max _ hp).trans degree_le_natDegree)⟩
  · 

Proof state:
case neg
R : Type u
S : Type u_1
inst✝ : Semiring R
s : Set R[X]
s_fin : Set.Finite s
s_emp : ¬Set.Nonempty s
⊢ ∃ n, Submodule.span R s ≤ degreeLE R ↑n

Next tactic:
rw [Set.not_nonempty_iff_eq_empty] at s_emp
/-- The span of every finite set of polynomials is contained in a `degreeLE n` for some `n`. -/
theorem span_le_degreeLE_of_finite {s : Set R[X]} (s_fin : s.Finite) :
    ∃ n : ℕ, Submodule.span R s ≤ degreeLE R n := by
  by_cases s_emp : s.Nonempty
  · rcases exists_degree_le_of_mem_span_of_finite s_fin s_emp with ⟨p', _, hp'max⟩
    exact ⟨natDegree p', fun p hp => mem_degreeLE.mpr ((hp'max _ hp).trans degree_le_natDegree)⟩
  · rw [Set.not_nonempty_iff_eq_empty] at s_emp
    

Proof state:
case neg
R : Type u
S : Type u_1
inst✝ : Semiring R
s : Set R[X]
s_fin : Set.Finite s
s_emp : s = ∅
⊢ ∃ n, Submodule.span R s ≤ degreeLE R ↑n

Next tactic:
rw [s_emp, Submodule.span_empty]
/-- The span of every finite set of polynomials is contained in a `degreeLE n` for some `n`. -/
theorem span_le_degreeLE_of_finite {s : Set R[X]} (s_fin : s.Finite) :
    ∃ n : ℕ, Submodule.span R s ≤ degreeLE R n := by
  by_cases s_emp : s.Nonempty
  · rcases exists_degree_le_of_mem_span_of_finite s_fin s_emp with ⟨p', _, hp'max⟩
    exact ⟨natDegree p', fun p hp => mem_degreeLE.mpr ((hp'max _ hp).trans degree_le_natDegree)⟩
  · rw [Set.not_nonempty_iff_eq_empty] at s_emp
    rw [s_emp, Submodule.span_empty]
    

Proof state:
case neg
R : Type u
S : Type u_1
inst✝ : Semiring R
s : Set R[X]
s_fin : Set.Finite s
s_emp : s = ∅
⊢ ∃ n, ⊥ ≤ degreeLE R ↑n

Next tactic:
exact ⟨0, bot_le⟩
/-- The span of every finite set of polynomials is contained in a `degreeLT n` for some `n`. -/
theorem span_of_finite_le_degreeLT {s : Set R[X]} (s_fin : s.Finite) :
    ∃ n : ℕ, Submodule.span R s ≤ degreeLT R n := by
  

Proof state:
R : Type u
S : Type u_1
inst✝ : Semiring R
s : Set R[X]
s_fin : Set.Finite s
⊢ ∃ n, Submodule.span R s ≤ degreeLT R n

Next tactic:
rcases span_le_degreeLE_of_finite s_fin with ⟨n, _⟩
/-- The span of every finite set of polynomials is contained in a `degreeLT n` for some `n`. -/
theorem span_of_finite_le_degreeLT {s : Set R[X]} (s_fin : s.Finite) :
    ∃ n : ℕ, Submodule.span R s ≤ degreeLT R n := by
  rcases span_le_degreeLE_of_finite s_fin with ⟨n, _⟩
  

Proof state:
case intro
R : Type u
S : Type u_1
inst✝ : Semiring R
s : Set R[X]
s_fin : Set.Finite s
n : ℕ
h✝ : Submodule.span R s ≤ degreeLE R ↑n
⊢ ∃ n, Submodule.span R s ≤ degreeLT R n

Next tactic:
exact ⟨n + 1, by rwa [degreeLT_succ_eq_degreeLE]⟩
/-- The span of every finite set of polynomials is contained in a `degreeLT n` for some `n`. -/
theorem span_of_finite_le_degreeLT {s : Set R[X]} (s_fin : s.Finite) :
    ∃ n : ℕ, Submodule.span R s ≤ degreeLT R n := by
  rcases span_le_degreeLE_of_finite s_fin with ⟨n, _⟩
  exact ⟨n + 1, by 

Proof state:
R : Type u
S : Type u_1
inst✝ : Semiring R
s : Set R[X]
s_fin : Set.Finite s
n : ℕ
h✝ : Submodule.span R s ≤ degreeLE R ↑n
⊢ Submodule.span R s ≤ degreeLT R (n + 1)

Next tactic:
rwa [degreeLT_succ_eq_degreeLE]
/-- If `R` is a nontrivial ring, the polynomials `R[X]` are not finite as an `R`-module. When `R` is
a field, this is equivalent to `R[X]` being an infinite-dimensional vector space over `R`.  -/
theorem not_finite [Nontrivial R] : ¬ Module.Finite R R[X] := by
  

Proof state:
R : Type u
S : Type u_1
inst✝¹ : Semiring R
inst✝ : Nontrivial R
⊢ ¬Module.Finite R R[X]

Next tactic:
rw [Module.finite_def, Submodule.fg_def]
/-- If `R` is a nontrivial ring, the polynomials `R[X]` are not finite as an `R`-module. When `R` is
a field, this is equivalent to `R[X]` being an infinite-dimensional vector space over `R`.  -/
theorem not_finite [Nontrivial R] : ¬ Module.Finite R R[X] := by
  rw [Module.finite_def, Submodule.fg_def]
  

Proof state:
R : Type u
S : Type u_1
inst✝¹ : Semiring R
inst✝ : Nontrivial R
⊢ ¬∃ S, Set.Finite S ∧ Submodule.span R S = ⊤

Next tactic:
push_neg
/-- If `R` is a nontrivial ring, the polynomials `R[X]` are not finite as an `R`-module. When `R` is
a field, this is equivalent to `R[X]` being an infinite-dimensional vector space over `R`.  -/
theorem not_finite [Nontrivial R] : ¬ Module.Finite R R[X] := by
  rw [Module.finite_def, Submodule.fg_def]
  push_neg
  

Proof state:
R : Type u
S : Type u_1
inst✝¹ : Semiring R
inst✝ : Nontrivial R
⊢ ∀ (S : Set R[X]), Set.Finite S → Submodule.span R S ≠ ⊤

Next tactic:
intro s hs contra
/-- If `R` is a nontrivial ring, the polynomials `R[X]` are not finite as an `R`-module. When `R` is
a field, this is equivalent to `R[X]` being an infinite-dimensional vector space over `R`.  -/
theorem not_finite [Nontrivial R] : ¬ Module.Finite R R[X] := by
  rw [Module.finite_def, Submodule.fg_def]
  push_neg
  intro s hs contra
  

Proof state:
R : Type u
S : Type u_1
inst✝¹ : Semiring R
inst✝ : Nontrivial R
s : Set R[X]
hs : Set.Finite s
contra : Submodule.span R s = ⊤
⊢ False

Next tactic:
rcases span_le_degreeLE_of_finite hs with ⟨n,hn⟩
/-- If `R` is a nontrivial ring, the polynomials `R[X]` are not finite as an `R`-module. When `R` is
a field, this is equivalent to `R[X]` being an infinite-dimensional vector space over `R`.  -/
theorem not_finite [Nontrivial R] : ¬ Module.Finite R R[X] := by
  rw [Module.finite_def, Submodule.fg_def]
  push_neg
  intro s hs contra
  rcases span_le_degreeLE_of_finite hs with ⟨n,hn⟩
  

Proof state:
case intro
R : Type u
S : Type u_1
inst✝¹ : Semiring R
inst✝ : Nontrivial R
s : Set R[X]
hs : Set.Finite s
contra : Submodule.span R s = ⊤
n : ℕ
hn : Submodule.span R s ≤ degreeLE R ↑n
⊢ False

Next tactic:
have : ((X : R[X]) ^ (n + 1)) ∈ Polynomial.degreeLE R ↑n := by
    rw [contra] at hn
    exact hn Submodule.mem_top
/-- If `R` is a nontrivial ring, the polynomials `R[X]` are not finite as an `R`-module. When `R` is
a field, this is equivalent to `R[X]` being an infinite-dimensional vector space over `R`.  -/
theorem not_finite [Nontrivial R] : ¬ Module.Finite R R[X] := by
  rw [Module.finite_def, Submodule.fg_def]
  push_neg
  intro s hs contra
  rcases span_le_degreeLE_of_finite hs with ⟨n,hn⟩
  have : ((X : R[X]) ^ (n + 1)) ∈ Polynomial.degreeLE R ↑n := by
    

Proof state:
R : Type u
S : Type u_1
inst✝¹ : Semiring R
inst✝ : Nontrivial R
s : Set R[X]
hs : Set.Finite s
contra : Submodule.span R s = ⊤
n : ℕ
hn : Submodule.span R s ≤ degreeLE R ↑n
⊢ X ^ (n + 1) ∈ degreeLE R ↑n

Next tactic:
rw [contra] at hn
/-- If `R` is a nontrivial ring, the polynomials `R[X]` are not finite as an `R`-module. When `R` is
a field, this is equivalent to `R[X]` being an infinite-dimensional vector space over `R`.  -/
theorem not_finite [Nontrivial R] : ¬ Module.Finite R R[X] := by
  rw [Module.finite_def, Submodule.fg_def]
  push_neg
  intro s hs contra
  rcases span_le_degreeLE_of_finite hs with ⟨n,hn⟩
  have : ((X : R[X]) ^ (n + 1)) ∈ Polynomial.degreeLE R ↑n := by
    rw [contra] at hn
    

Proof state:
R : Type u
S : Type u_1
inst✝¹ : Semiring R
inst✝ : Nontrivial R
s : Set R[X]
hs : Set.Finite s
contra : Submodule.span R s = ⊤
n : ℕ
hn : ⊤ ≤ degreeLE R ↑n
⊢ X ^ (n + 1) ∈ degreeLE R ↑n

Next tactic:
exact hn Submodule.mem_top
/-- If `R` is a nontrivial ring, the polynomials `R[X]` are not finite as an `R`-module. When `R` is
a field, this is equivalent to `R[X]` being an infinite-dimensional vector space over `R`.  -/
theorem not_finite [Nontrivial R] : ¬ Module.Finite R R[X] := by
  rw [Module.finite_def, Submodule.fg_def]
  push_neg
  intro s hs contra
  rcases span_le_degreeLE_of_finite hs with ⟨n,hn⟩
  have : ((X : R[X]) ^ (n + 1)) ∈ Polynomial.degreeLE R ↑n := by
    rw [contra] at hn
    exact hn Submodule.mem_top
  

Proof state:
case intro
R : Type u
S : Type u_1
inst✝¹ : Semiring R
inst✝ : Nontrivial R
s : Set R[X]
hs : Set.Finite s
contra : Submodule.span R s = ⊤
n : ℕ
hn : Submodule.span R s ≤ degreeLE R ↑n
this : X ^ (n + 1) ∈ degreeLE R ↑n
⊢ False

Next tactic:
rw [mem_degreeLE, degree_X_pow, Nat.cast_le, add_le_iff_nonpos_right, nonpos_iff_eq_zero] at this
/-- If `R` is a nontrivial ring, the polynomials `R[X]` are not finite as an `R`-module. When `R` is
a field, this is equivalent to `R[X]` being an infinite-dimensional vector space over `R`.  -/
theorem not_finite [Nontrivial R] : ¬ Module.Finite R R[X] := by
  rw [Module.finite_def, Submodule.fg_def]
  push_neg
  intro s hs contra
  rcases span_le_degreeLE_of_finite hs with ⟨n,hn⟩
  have : ((X : R[X]) ^ (n + 1)) ∈ Polynomial.degreeLE R ↑n := by
    rw [contra] at hn
    exact hn Submodule.mem_top
  rw [mem_degreeLE, degree_X_pow, Nat.cast_le, add_le_iff_nonpos_right, nonpos_iff_eq_zero] at this
  

Proof state:
case intro
R : Type u
S : Type u_1
inst✝¹ : Semiring R
inst✝ : Nontrivial R
s : Set R[X]
hs : Set.Finite s
contra : Submodule.span R s = ⊤
n : ℕ
hn : Submodule.span R s ≤ degreeLE R ↑n
this : 1 = 0
⊢ False

Next tactic:
exact one_ne_zero this
theorem mem_frange_iff {p : R[X]} {c : R} : c ∈ p.frange ↔ ∃ n ∈ p.support, c = p.coeff n := by
  

Proof state:
R : Type u
S : Type u_1
inst✝ : Semiring R
p : R[X]
c : R
⊢ c ∈ frange p ↔ ∃ n ∈ support p, c = coeff p n

Next tactic:
simp [frange, eq_comm, (Finset.mem_image)]
theorem frange_one : frange (1 : R[X]) ⊆ {1} := by
  

Proof state:
R : Type u
S : Type u_1
inst✝ : Semiring R
⊢ frange 1 ⊆ {1}

Next tactic:
classical
  simp only [frange]
  rw [Finset.image_subset_iff]
  simp only [mem_support_iff, ne_eq, mem_singleton, ← C_1, coeff_C]
  intro n hn
  simp only [exists_prop, ite_eq_right_iff, not_forall] at hn
  simp [hn]
theorem frange_one : frange (1 : R[X]) ⊆ {1} := by
  classical
  

Proof state:
R : Type u
S : Type u_1
inst✝ : Semiring R
⊢ frange 1 ⊆ {1}

Next tactic:
simp only [frange]
theorem frange_one : frange (1 : R[X]) ⊆ {1} := by
  classical
  simp only [frange]
  

Proof state:
R : Type u
S : Type u_1
inst✝ : Semiring R
⊢ image (fun n => coeff 1 n) (support 1) ⊆ {1}

Next tactic:
rw [Finset.image_subset_iff]
theorem frange_one : frange (1 : R[X]) ⊆ {1} := by
  classical
  simp only [frange]
  rw [Finset.image_subset_iff]
  

Proof state:
R : Type u
S : Type u_1
inst✝ : Semiring R
⊢ ∀ x ∈ support 1, coeff 1 x ∈ {1}

Next tactic:
simp only [mem_support_iff, ne_eq, mem_singleton, ← C_1, coeff_C]
theorem frange_one : frange (1 : R[X]) ⊆ {1} := by
  classical
  simp only [frange]
  rw [Finset.image_subset_iff]
  simp only [mem_support_iff, ne_eq, mem_singleton, ← C_1, coeff_C]
  

Proof state:
R : Type u
S : Type u_1
inst✝ : Semiring R
⊢ ∀ (x : ℕ), ¬(if x = 0 then 1 else 0) = 0 → (if x = 0 then 1 else 0) = 1

Next tactic:
intro n hn
theorem frange_one : frange (1 : R[X]) ⊆ {1} := by
  classical
  simp only [frange]
  rw [Finset.image_subset_iff]
  simp only [mem_support_iff, ne_eq, mem_singleton, ← C_1, coeff_C]
  intro n hn
  

Proof state:
R : Type u
S : Type u_1
inst✝ : Semiring R
n : ℕ
hn : ¬(if n = 0 then 1 else 0) = 0
⊢ (if n = 0 then 1 else 0) = 1

Next tactic:
simp only [exists_prop, ite_eq_right_iff, not_forall] at hn
theorem frange_one : frange (1 : R[X]) ⊆ {1} := by
  classical
  simp only [frange]
  rw [Finset.image_subset_iff]
  simp only [mem_support_iff, ne_eq, mem_singleton, ← C_1, coeff_C]
  intro n hn
  simp only [exists_prop, ite_eq_right_iff, not_forall] at hn
  

Proof state:
R : Type u
S : Type u_1
inst✝ : Semiring R
n : ℕ
hn : n = 0 ∧ ¬1 = 0
⊢ (if n = 0 then 1 else 0) = 1

Next tactic:
simp [hn]
theorem coeff_mem_frange (p : R[X]) (n : ℕ) (h : p.coeff n ≠ 0) : p.coeff n ∈ p.frange := by
  

Proof state:
R : Type u
S : Type u_1
inst✝ : Semiring R
p : R[X]
n : ℕ
h : coeff p n ≠ 0
⊢ coeff p n ∈ frange p

Next tactic:
classical
  simp only [frange, exists_prop, mem_support_iff, (Finset.mem_image), Ne.def]
  exact ⟨n, h, rfl⟩
theorem coeff_mem_frange (p : R[X]) (n : ℕ) (h : p.coeff n ≠ 0) : p.coeff n ∈ p.frange := by
  classical
  

Proof state:
R : Type u
S : Type u_1
inst✝ : Semiring R
p : R[X]
n : ℕ
h : coeff p n ≠ 0
⊢ coeff p n ∈ frange p

Next tactic:
simp only [frange, exists_prop, mem_support_iff, (Finset.mem_image), Ne.def]
theorem coeff_mem_frange (p : R[X]) (n : ℕ) (h : p.coeff n ≠ 0) : p.coeff n ∈ p.frange := by
  classical
  simp only [frange, exists_prop, mem_support_iff, (Finset.mem_image), Ne.def]
  

Proof state:
R : Type u
S : Type u_1
inst✝ : Semiring R
p : R[X]
n : ℕ
h : coeff p n ≠ 0
⊢ ∃ a, ¬coeff p a = 0 ∧ coeff p a = coeff p n

Next tactic:
exact ⟨n, h, rfl⟩
theorem geom_sum_X_comp_X_add_one_eq_sum (n : ℕ) :
    (∑ i in range n, (X : R[X]) ^ i).comp (X + 1) =
      (Finset.range n).sum fun i : ℕ => (n.choose (i + 1) : R[X]) * X ^ i := by
  

Proof state:
R : Type u
S : Type u_1
inst✝ : Semiring R
n : ℕ
⊢ comp (∑ i in range n, X ^ i) (X + 1) = ∑ i in range n, ↑(Nat.choose n (i + 1)) * X ^ i

Next tactic:
ext i
theorem geom_sum_X_comp_X_add_one_eq_sum (n : ℕ) :
    (∑ i in range n, (X : R[X]) ^ i).comp (X + 1) =
      (Finset.range n).sum fun i : ℕ => (n.choose (i + 1) : R[X]) * X ^ i := by
  ext i
  

Proof state:
case a
R : Type u
S : Type u_1
inst✝ : Semiring R
n i : ℕ
⊢ coeff (comp (∑ i in range n, X ^ i) (X + 1)) i = coeff (∑ i in range n, ↑(Nat.choose n (i + 1)) * X ^ i) i

Next tactic:
trans (n.choose (i + 1) : R)
theorem geom_sum_X_comp_X_add_one_eq_sum (n : ℕ) :
    (∑ i in range n, (X : R[X]) ^ i).comp (X + 1) =
      (Finset.range n).sum fun i : ℕ => (n.choose (i + 1) : R[X]) * X ^ i := by
  ext i
  trans (n.choose (i + 1) : R); 

Proof state:
R : Type u
S : Type u_1
inst✝ : Semiring R
n i : ℕ
⊢ coeff (comp (∑ i in range n, X ^ i) (X + 1)) i = ↑(Nat.choose n (i + 1))
R : Type u
S : Type u_1
inst✝ : Semiring R
n i : ℕ
⊢ ↑(Nat.choose n (i + 1)) = coeff (∑ i in range n, ↑(Nat.choose n (i + 1)) * X ^ i) i

Next tactic:
swap
theorem geom_sum_X_comp_X_add_one_eq_sum (n : ℕ) :
    (∑ i in range n, (X : R[X]) ^ i).comp (X + 1) =
      (Finset.range n).sum fun i : ℕ => (n.choose (i + 1) : R[X]) * X ^ i := by
  ext i
  trans (n.choose (i + 1) : R); swap
  · 

Proof state:
R : Type u
S : Type u_1
inst✝ : Semiring R
n i : ℕ
⊢ ↑(Nat.choose n (i + 1)) = coeff (∑ i in range n, ↑(Nat.choose n (i + 1)) * X ^ i) i

Next tactic:
simp only [finset_sum_coeff, ← C_eq_nat_cast, coeff_C_mul_X_pow]
theorem geom_sum_X_comp_X_add_one_eq_sum (n : ℕ) :
    (∑ i in range n, (X : R[X]) ^ i).comp (X + 1) =
      (Finset.range n).sum fun i : ℕ => (n.choose (i + 1) : R[X]) * X ^ i := by
  ext i
  trans (n.choose (i + 1) : R); swap
  · simp only [finset_sum_coeff, ← C_eq_nat_cast, coeff_C_mul_X_pow]
    

Proof state:
R : Type u
S : Type u_1
inst✝ : Semiring R
n i : ℕ
⊢ ↑(Nat.choose n (i + 1)) = ∑ x in range n, if i = x then ↑(Nat.choose n (x + 1)) else 0

Next tactic:
rw [Finset.sum_eq_single i, if_pos rfl]
theorem geom_sum_X_comp_X_add_one_eq_sum (n : ℕ) :
    (∑ i in range n, (X : R[X]) ^ i).comp (X + 1) =
      (Finset.range n).sum fun i : ℕ => (n.choose (i + 1) : R[X]) * X ^ i := by
  ext i
  trans (n.choose (i + 1) : R); swap
  · simp only [finset_sum_coeff, ← C_eq_nat_cast, coeff_C_mul_X_pow]
    rw [Finset.sum_eq_single i, if_pos rfl]
    · 

Proof state:
case h₀
R : Type u
S : Type u_1
inst✝ : Semiring R
n i : ℕ
⊢ ∀ b ∈ range n, b ≠ i → (if i = b then ↑(Nat.choose n (b + 1)) else 0) = 0

Next tactic:
simp (config := { contextual := true }) only [@eq_comm _ i, if_false, eq_self_iff_true,
        imp_true_iff]
theorem geom_sum_X_comp_X_add_one_eq_sum (n : ℕ) :
    (∑ i in range n, (X : R[X]) ^ i).comp (X + 1) =
      (Finset.range n).sum fun i : ℕ => (n.choose (i + 1) : R[X]) * X ^ i := by
  ext i
  trans (n.choose (i + 1) : R); swap
  · simp only [finset_sum_coeff, ← C_eq_nat_cast, coeff_C_mul_X_pow]
    rw [Finset.sum_eq_single i, if_pos rfl]
    · simp (config := { contextual := true }) only [@eq_comm _ i, if_false, eq_self_iff_true,
        imp_true_iff]
    · 

Proof state:
case h₁
R : Type u
S : Type u_1
inst✝ : Semiring R
n i : ℕ
⊢ i ∉ range n → (if i = i then ↑(Nat.choose n (i + 1)) else 0) = 0

Next tactic:
simp (config := { contextual := true }) only [Nat.lt_add_one_iff, Nat.choose_eq_zero_of_lt,
        Nat.cast_zero, Finset.mem_range, not_lt, eq_self_iff_true, if_true, imp_true_iff]
theorem geom_sum_X_comp_X_add_one_eq_sum (n : ℕ) :
    (∑ i in range n, (X : R[X]) ^ i).comp (X + 1) =
      (Finset.range n).sum fun i : ℕ => (n.choose (i + 1) : R[X]) * X ^ i := by
  ext i
  trans (n.choose (i + 1) : R); swap
  · simp only [finset_sum_coeff, ← C_eq_nat_cast, coeff_C_mul_X_pow]
    rw [Finset.sum_eq_single i, if_pos rfl]
    · simp (config := { contextual := true }) only [@eq_comm _ i, if_false, eq_self_iff_true,
        imp_true_iff]
    · simp (config := { contextual := true }) only [Nat.lt_add_one_iff, Nat.choose_eq_zero_of_lt,
        Nat.cast_zero, Finset.mem_range, not_lt, eq_self_iff_true, if_true, imp_true_iff]
  

Proof state:
R : Type u
S : Type u_1
inst✝ : Semiring R
n i : ℕ
⊢ coeff (comp (∑ i in range n, X ^ i) (X + 1)) i = ↑(Nat.choose n (i + 1))

Next tactic:
induction' n with n ih generalizing i
theorem geom_sum_X_comp_X_add_one_eq_sum (n : ℕ) :
    (∑ i in range n, (X : R[X]) ^ i).comp (X + 1) =
      (Finset.range n).sum fun i : ℕ => (n.choose (i + 1) : R[X]) * X ^ i := by
  ext i
  trans (n.choose (i + 1) : R); swap
  · simp only [finset_sum_coeff, ← C_eq_nat_cast, coeff_C_mul_X_pow]
    rw [Finset.sum_eq_single i, if_pos rfl]
    · simp (config := { contextual := true }) only [@eq_comm _ i, if_false, eq_self_iff_true,
        imp_true_iff]
    · simp (config := { contextual := true }) only [Nat.lt_add_one_iff, Nat.choose_eq_zero_of_lt,
        Nat.cast_zero, Finset.mem_range, not_lt, eq_self_iff_true, if_true, imp_true_iff]
  induction' n with n ih generalizing i
  · 

Proof state:
case zero
R : Type u
S : Type u_1
inst✝ : Semiring R
i : ℕ
⊢ coeff (comp (∑ i in range Nat.zero, X ^ i) (X + 1)) i = ↑(Nat.choose Nat.zero (i + 1))

Next tactic:
dsimp
theorem geom_sum_X_comp_X_add_one_eq_sum (n : ℕ) :
    (∑ i in range n, (X : R[X]) ^ i).comp (X + 1) =
      (Finset.range n).sum fun i : ℕ => (n.choose (i + 1) : R[X]) * X ^ i := by
  ext i
  trans (n.choose (i + 1) : R); swap
  · simp only [finset_sum_coeff, ← C_eq_nat_cast, coeff_C_mul_X_pow]
    rw [Finset.sum_eq_single i, if_pos rfl]
    · simp (config := { contextual := true }) only [@eq_comm _ i, if_false, eq_self_iff_true,
        imp_true_iff]
    · simp (config := { contextual := true }) only [Nat.lt_add_one_iff, Nat.choose_eq_zero_of_lt,
        Nat.cast_zero, Finset.mem_range, not_lt, eq_self_iff_true, if_true, imp_true_iff]
  induction' n with n ih generalizing i
  · dsimp; 

Proof state:
case zero
R : Type u
S : Type u_1
inst✝ : Semiring R
i : ℕ
⊢ coeff (comp 0 (X + 1)) i = ↑0

Next tactic:
simp only [zero_comp, coeff_zero, Nat.cast_zero]
theorem geom_sum_X_comp_X_add_one_eq_sum (n : ℕ) :
    (∑ i in range n, (X : R[X]) ^ i).comp (X + 1) =
      (Finset.range n).sum fun i : ℕ => (n.choose (i + 1) : R[X]) * X ^ i := by
  ext i
  trans (n.choose (i + 1) : R); swap
  · simp only [finset_sum_coeff, ← C_eq_nat_cast, coeff_C_mul_X_pow]
    rw [Finset.sum_eq_single i, if_pos rfl]
    · simp (config := { contextual := true }) only [@eq_comm _ i, if_false, eq_self_iff_true,
        imp_true_iff]
    · simp (config := { contextual := true }) only [Nat.lt_add_one_iff, Nat.choose_eq_zero_of_lt,
        Nat.cast_zero, Finset.mem_range, not_lt, eq_self_iff_true, if_true, imp_true_iff]
  induction' n with n ih generalizing i
  · dsimp; simp only [zero_comp, coeff_zero, Nat.cast_zero]
  · 

Proof state:
case succ
R : Type u
S : Type u_1
inst✝ : Semiring R
n : ℕ
ih : ∀ (i : ℕ), coeff (comp (∑ i in range n, X ^ i) (X + 1)) i = ↑(Nat.choose n (i + 1))
i : ℕ
⊢ coeff (comp (∑ i in range (Nat.succ n), X ^ i) (X + 1)) i = ↑(Nat.choose (Nat.succ n) (i + 1))

Next tactic:
simp only [geom_sum_succ', ih, add_comp, X_pow_comp, coeff_add, Nat.choose_succ_succ,
    Nat.cast_add, coeff_X_add_one_pow]
theorem Monic.geom_sum {P : R[X]} (hP : P.Monic) (hdeg : 0 < P.natDegree) {n : ℕ} (hn : n ≠ 0) :
    (∑ i in range n, P ^ i).Monic := by
  

Proof state:
R : Type u
S : Type u_1
inst✝ : Semiring R
P : R[X]
hP : Monic P
hdeg : 0 < natDegree P
n : ℕ
hn : n ≠ 0
⊢ Monic (∑ i in range n, P ^ i)

Next tactic:
nontriviality R
theorem Monic.geom_sum {P : R[X]} (hP : P.Monic) (hdeg : 0 < P.natDegree) {n : ℕ} (hn : n ≠ 0) :
    (∑ i in range n, P ^ i).Monic := by
  nontriviality R
  

Proof state:
R : Type u
S : Type u_1
inst✝ : Semiring R
P : R[X]
hP : Monic P
hdeg : 0 < natDegree P
n : ℕ
hn : n ≠ 0
✝ : Nontrivial R
⊢ Monic (∑ i in range n, P ^ i)

Next tactic:
obtain ⟨n, rfl⟩ := Nat.exists_eq_succ_of_ne_zero hn
theorem Monic.geom_sum {P : R[X]} (hP : P.Monic) (hdeg : 0 < P.natDegree) {n : ℕ} (hn : n ≠ 0) :
    (∑ i in range n, P ^ i).Monic := by
  nontriviality R
  obtain ⟨n, rfl⟩ := Nat.exists_eq_succ_of_ne_zero hn
  

Proof state:
case intro
R : Type u
S : Type u_1
inst✝ : Semiring R
P : R[X]
hP : Monic P
hdeg : 0 < natDegree P
✝ : Nontrivial R
n : ℕ
hn : Nat.succ n ≠ 0
⊢ Monic (∑ i in range (Nat.succ n), P ^ i)

Next tactic:
rw [geom_sum_succ']