l3lab/ntp-mathlib huggingface dataset:
/-- The support of a polynomial `f` is a finset in `ℕ`.  The lemma `toLaurent_support f`
shows that the support of `f.toLaurent` is the same finset, but viewed in `ℤ` under the natural
inclusion `ℕ ↪ ℤ`. -/
theorem toLaurent_support (f : R[X]) : f.toLaurent.support = f.support.map Nat.castEmbedding := by
  generalize hd : f.support = s
  revert f
  refine' Finset.induction_on s _ _ <;> clear s
  · simp (config := { contextual := true }) only [Polynomial.support_eq_empty, map_zero,
      Finsupp.support_zero, eq_self_iff_true, imp_true_iff, Finset.map_empty,
      Finsupp.support_eq_empty]
  · intro a s as hf f fs
    have : (erase a f).toLaurent.support = s.map Nat.castEmbedding := by
      refine' hf (f.erase a) _
      simp only [fs, Finset.erase_eq_of_not_mem as, Polynomial.support_erase,
        Finset.erase_insert_eq_erase]
    rw [← monomial_add_erase f a, Finset.map_insert, ← this, map_add, Polynomial.toLaurent_C_mul_T,
      support_add_eq, Finset.insert_eq]
    · congr
      

Proof state:
case refine'_2.e_a
R : Type u_1
inst✝ : Semiring R
a : ℕ
s : Finset ℕ
as : a ∉ s
hf : ∀ (f : R[X]), Polynomial.support f = s → (toLaurent f).support = Finset.map Nat.castEmbedding s
f : R[X]
fs : Polynomial.support f = insert a s
this : (toLaurent (Polynomial.erase a f)).support = Finset.map Nat.castEmbedding s
⊢ (C (coeff f a) * T ↑a).support = {Nat.castEmbedding a}

Next tactic:
exact support_C_mul_T_of_ne_zero (Polynomial.mem_support_iff.mp (by simp [fs])) _
/-- The support of a polynomial `f` is a finset in `ℕ`.  The lemma `toLaurent_support f`
shows that the support of `f.toLaurent` is the same finset, but viewed in `ℤ` under the natural
inclusion `ℕ ↪ ℤ`. -/
theorem toLaurent_support (f : R[X]) : f.toLaurent.support = f.support.map Nat.castEmbedding := by
  generalize hd : f.support = s
  revert f
  refine' Finset.induction_on s _ _ <;> clear s
  · simp (config := { contextual := true }) only [Polynomial.support_eq_empty, map_zero,
      Finsupp.support_zero, eq_self_iff_true, imp_true_iff, Finset.map_empty,
      Finsupp.support_eq_empty]
  · intro a s as hf f fs
    have : (erase a f).toLaurent.support = s.map Nat.castEmbedding := by
      refine' hf (f.erase a) _
      simp only [fs, Finset.erase_eq_of_not_mem as, Polynomial.support_erase,
        Finset.erase_insert_eq_erase]
    rw [← monomial_add_erase f a, Finset.map_insert, ← this, map_add, Polynomial.toLaurent_C_mul_T,
      support_add_eq, Finset.insert_eq]
    · congr
      exact support_C_mul_T_of_ne_zero (Polynomial.mem_support_iff.mp (by 

Proof state:
R : Type u_1
inst✝ : Semiring R
a : ℕ
s : Finset ℕ
as : a ∉ s
hf : ∀ (f : R[X]), Polynomial.support f = s → (toLaurent f).support = Finset.map Nat.castEmbedding s
f : R[X]
fs : Polynomial.support f = insert a s
this : (toLaurent (Polynomial.erase a f)).support = Finset.map Nat.castEmbedding s
⊢ a ∈ Polynomial.support f

Next tactic:
simp [fs]
/-- The support of a polynomial `f` is a finset in `ℕ`.  The lemma `toLaurent_support f`
shows that the support of `f.toLaurent` is the same finset, but viewed in `ℤ` under the natural
inclusion `ℕ ↪ ℤ`. -/
theorem toLaurent_support (f : R[X]) : f.toLaurent.support = f.support.map Nat.castEmbedding := by
  generalize hd : f.support = s
  revert f
  refine' Finset.induction_on s _ _ <;> clear s
  · simp (config := { contextual := true }) only [Polynomial.support_eq_empty, map_zero,
      Finsupp.support_zero, eq_self_iff_true, imp_true_iff, Finset.map_empty,
      Finsupp.support_eq_empty]
  · intro a s as hf f fs
    have : (erase a f).toLaurent.support = s.map Nat.castEmbedding := by
      refine' hf (f.erase a) _
      simp only [fs, Finset.erase_eq_of_not_mem as, Polynomial.support_erase,
        Finset.erase_insert_eq_erase]
    rw [← monomial_add_erase f a, Finset.map_insert, ← this, map_add, Polynomial.toLaurent_C_mul_T,
      support_add_eq, Finset.insert_eq]
    · congr
      exact support_C_mul_T_of_ne_zero (Polynomial.mem_support_iff.mp (by simp [fs])) _
    · 

Proof state:
case refine'_2
R : Type u_1
inst✝ : Semiring R
a : ℕ
s : Finset ℕ
as : a ∉ s
hf : ∀ (f : R[X]), Polynomial.support f = s → (toLaurent f).support = Finset.map Nat.castEmbedding s
f : R[X]
fs : Polynomial.support f = insert a s
this : (toLaurent (Polynomial.erase a f)).support = Finset.map Nat.castEmbedding s
⊢ Disjoint (C (coeff f a) * T ↑a).support (toLaurent (Polynomial.erase a f)).support

Next tactic:
rw [this]
/-- The support of a polynomial `f` is a finset in `ℕ`.  The lemma `toLaurent_support f`
shows that the support of `f.toLaurent` is the same finset, but viewed in `ℤ` under the natural
inclusion `ℕ ↪ ℤ`. -/
theorem toLaurent_support (f : R[X]) : f.toLaurent.support = f.support.map Nat.castEmbedding := by
  generalize hd : f.support = s
  revert f
  refine' Finset.induction_on s _ _ <;> clear s
  · simp (config := { contextual := true }) only [Polynomial.support_eq_empty, map_zero,
      Finsupp.support_zero, eq_self_iff_true, imp_true_iff, Finset.map_empty,
      Finsupp.support_eq_empty]
  · intro a s as hf f fs
    have : (erase a f).toLaurent.support = s.map Nat.castEmbedding := by
      refine' hf (f.erase a) _
      simp only [fs, Finset.erase_eq_of_not_mem as, Polynomial.support_erase,
        Finset.erase_insert_eq_erase]
    rw [← monomial_add_erase f a, Finset.map_insert, ← this, map_add, Polynomial.toLaurent_C_mul_T,
      support_add_eq, Finset.insert_eq]
    · congr
      exact support_C_mul_T_of_ne_zero (Polynomial.mem_support_iff.mp (by simp [fs])) _
    · rw [this]
      

Proof state:
case refine'_2
R : Type u_1
inst✝ : Semiring R
a : ℕ
s : Finset ℕ
as : a ∉ s
hf : ∀ (f : R[X]), Polynomial.support f = s → (toLaurent f).support = Finset.map Nat.castEmbedding s
f : R[X]
fs : Polynomial.support f = insert a s
this : (toLaurent (Polynomial.erase a f)).support = Finset.map Nat.castEmbedding s
⊢ Disjoint (C (coeff f a) * T ↑a).support (Finset.map Nat.castEmbedding s)

Next tactic:
exact Disjoint.mono_left (support_C_mul_T _ _) (by simpa)
/-- The support of a polynomial `f` is a finset in `ℕ`.  The lemma `toLaurent_support f`
shows that the support of `f.toLaurent` is the same finset, but viewed in `ℤ` under the natural
inclusion `ℕ ↪ ℤ`. -/
theorem toLaurent_support (f : R[X]) : f.toLaurent.support = f.support.map Nat.castEmbedding := by
  generalize hd : f.support = s
  revert f
  refine' Finset.induction_on s _ _ <;> clear s
  · simp (config := { contextual := true }) only [Polynomial.support_eq_empty, map_zero,
      Finsupp.support_zero, eq_self_iff_true, imp_true_iff, Finset.map_empty,
      Finsupp.support_eq_empty]
  · intro a s as hf f fs
    have : (erase a f).toLaurent.support = s.map Nat.castEmbedding := by
      refine' hf (f.erase a) _
      simp only [fs, Finset.erase_eq_of_not_mem as, Polynomial.support_erase,
        Finset.erase_insert_eq_erase]
    rw [← monomial_add_erase f a, Finset.map_insert, ← this, map_add, Polynomial.toLaurent_C_mul_T,
      support_add_eq, Finset.insert_eq]
    · congr
      exact support_C_mul_T_of_ne_zero (Polynomial.mem_support_iff.mp (by simp [fs])) _
    · rw [this]
      exact Disjoint.mono_left (support_C_mul_T _ _) (by 

Proof state:
R : Type u_1
inst✝ : Semiring R
a : ℕ
s : Finset ℕ
as : a ∉ s
hf : ∀ (f : R[X]), Polynomial.support f = s → (toLaurent f).support = Finset.map Nat.castEmbedding s
f : R[X]
fs : Polynomial.support f = insert a s
this : (toLaurent (Polynomial.erase a f)).support = Finset.map Nat.castEmbedding s
⊢ Disjoint {↑a} (Finset.map Nat.castEmbedding s)

Next tactic:
simpa
@[simp]
theorem degree_eq_bot_iff {f : R[T;T⁻¹]} : f.degree = ⊥ ↔ f = 0 := by
  

Proof state:
R : Type u_1
inst✝ : Semiring R
f : R[T;T⁻¹]
⊢ degree f = ⊥ ↔ f = 0

Next tactic:
refine' ⟨fun h => _, fun h => by rw [h, degree_zero]⟩
@[simp]
theorem degree_eq_bot_iff {f : R[T;T⁻¹]} : f.degree = ⊥ ↔ f = 0 := by
  refine' ⟨fun h => _, fun h => by 

Proof state:
R : Type u_1
inst✝ : Semiring R
f : R[T;T⁻¹]
h : f = 0
⊢ degree f = ⊥

Next tactic:
rw [h, degree_zero]
@[simp]
theorem degree_eq_bot_iff {f : R[T;T⁻¹]} : f.degree = ⊥ ↔ f = 0 := by
  refine' ⟨fun h => _, fun h => by rw [h, degree_zero]⟩
  

Proof state:
R : Type u_1
inst✝ : Semiring R
f : R[T;T⁻¹]
h : degree f = ⊥
⊢ f = 0

Next tactic:
rw [degree, Finset.max_eq_sup_withBot] at h
@[simp]
theorem degree_eq_bot_iff {f : R[T;T⁻¹]} : f.degree = ⊥ ↔ f = 0 := by
  refine' ⟨fun h => _, fun h => by rw [h, degree_zero]⟩
  rw [degree, Finset.max_eq_sup_withBot] at h
  

Proof state:
R : Type u_1
inst✝ : Semiring R
f : R[T;T⁻¹]
h : Finset.sup f.support WithBot.some = ⊥
⊢ f = 0

Next tactic:
ext n
@[simp]
theorem degree_eq_bot_iff {f : R[T;T⁻¹]} : f.degree = ⊥ ↔ f = 0 := by
  refine' ⟨fun h => _, fun h => by rw [h, degree_zero]⟩
  rw [degree, Finset.max_eq_sup_withBot] at h
  ext n
  

Proof state:
case h
R : Type u_1
inst✝ : Semiring R
f : R[T;T⁻¹]
h : Finset.sup f.support WithBot.some = ⊥
n : ℤ
⊢ f n = 0 n

Next tactic:
refine' not_not.mp fun f0 => _
@[simp]
theorem degree_eq_bot_iff {f : R[T;T⁻¹]} : f.degree = ⊥ ↔ f = 0 := by
  refine' ⟨fun h => _, fun h => by rw [h, degree_zero]⟩
  rw [degree, Finset.max_eq_sup_withBot] at h
  ext n
  refine' not_not.mp fun f0 => _
  

Proof state:
case h
R : Type u_1
inst✝ : Semiring R
f : R[T;T⁻¹]
h : Finset.sup f.support WithBot.some = ⊥
n : ℤ
f0 : ¬f n = 0 n
⊢ False

Next tactic:
simp_rw [Finset.sup_eq_bot_iff, Finsupp.mem_support_iff, Ne.def, WithBot.coe_ne_bot] at h
@[simp]
theorem degree_eq_bot_iff {f : R[T;T⁻¹]} : f.degree = ⊥ ↔ f = 0 := by
  refine' ⟨fun h => _, fun h => by rw [h, degree_zero]⟩
  rw [degree, Finset.max_eq_sup_withBot] at h
  ext n
  refine' not_not.mp fun f0 => _
  simp_rw [Finset.sup_eq_bot_iff, Finsupp.mem_support_iff, Ne.def, WithBot.coe_ne_bot] at h
  

Proof state:
case h
R : Type u_1
inst✝ : Semiring R
f : R[T;T⁻¹]
n : ℤ
f0 : ¬f n = 0 n
h : ∀ (s : ℤ), ¬f s = 0 → False
⊢ False

Next tactic:
exact h n f0
@[simp]
theorem degree_C_mul_T (n : ℤ) (a : R) (a0 : a ≠ 0) : degree (C a * T n) = n := by
  

Proof state:
R : Type u_1
inst✝ : Semiring R
n : ℤ
a : R
a0 : a ≠ 0
⊢ degree (C a * T n) = ↑n

Next tactic:
rw [degree]
@[simp]
theorem degree_C_mul_T (n : ℤ) (a : R) (a0 : a ≠ 0) : degree (C a * T n) = n := by
  rw [degree]
  -- Porting note: was `convert Finset.max_singleton`
  

Proof state:
R : Type u_1
inst✝ : Semiring R
n : ℤ
a : R
a0 : a ≠ 0
⊢ Finset.max (C a * T n).support = ↑n

Next tactic:
have : Finsupp.support (C a * T n) = {n} := by
    refine' support_eq_singleton.mpr _
    rw [← single_eq_C_mul_T]
    simp only [single_eq_same, a0, Ne.def, not_false_iff, eq_self_iff_true, and_self_iff]
@[simp]
theorem degree_C_mul_T (n : ℤ) (a : R) (a0 : a ≠ 0) : degree (C a * T n) = n := by
  rw [degree]
  -- Porting note: was `convert Finset.max_singleton`
  have : Finsupp.support (C a * T n) = {n} := by
    

Proof state:
R : Type u_1
inst✝ : Semiring R
n : ℤ
a : R
a0 : a ≠ 0
⊢ (C a * T n).support = {n}

Next tactic:
refine' support_eq_singleton.mpr _
@[simp]
theorem degree_C_mul_T (n : ℤ) (a : R) (a0 : a ≠ 0) : degree (C a * T n) = n := by
  rw [degree]
  -- Porting note: was `convert Finset.max_singleton`
  have : Finsupp.support (C a * T n) = {n} := by
    refine' support_eq_singleton.mpr _
    

Proof state:
R : Type u_1
inst✝ : Semiring R
n : ℤ
a : R
a0 : a ≠ 0
⊢ (C a * T n) n ≠ 0 ∧ C a * T n = fun₀ | n => (C a * T n) n

Next tactic:
rw [← single_eq_C_mul_T]
@[simp]
theorem degree_C_mul_T (n : ℤ) (a : R) (a0 : a ≠ 0) : degree (C a * T n) = n := by
  rw [degree]
  -- Porting note: was `convert Finset.max_singleton`
  have : Finsupp.support (C a * T n) = {n} := by
    refine' support_eq_singleton.mpr _
    rw [← single_eq_C_mul_T]
    

Proof state:
R : Type u_1
inst✝ : Semiring R
n : ℤ
a : R
a0 : a ≠ 0
⊢ (fun₀ | n => a) n ≠ 0 ∧ (fun₀ | n => a) = fun₀ | n => (fun₀ | n => a) n

Next tactic:
simp only [single_eq_same, a0, Ne.def, not_false_iff, eq_self_iff_true, and_self_iff]
@[simp]
theorem degree_C_mul_T (n : ℤ) (a : R) (a0 : a ≠ 0) : degree (C a * T n) = n := by
  rw [degree]
  -- Porting note: was `convert Finset.max_singleton`
  have : Finsupp.support (C a * T n) = {n} := by
    refine' support_eq_singleton.mpr _
    rw [← single_eq_C_mul_T]
    simp only [single_eq_same, a0, Ne.def, not_false_iff, eq_self_iff_true, and_self_iff]
  

Proof state:
R : Type u_1
inst✝ : Semiring R
n : ℤ
a : R
a0 : a ≠ 0
this : (C a * T n).support = {n}
⊢ Finset.max (C a * T n).support = ↑n

Next tactic:
rw [this]
@[simp]
theorem degree_C_mul_T (n : ℤ) (a : R) (a0 : a ≠ 0) : degree (C a * T n) = n := by
  rw [degree]
  -- Porting note: was `convert Finset.max_singleton`
  have : Finsupp.support (C a * T n) = {n} := by
    refine' support_eq_singleton.mpr _
    rw [← single_eq_C_mul_T]
    simp only [single_eq_same, a0, Ne.def, not_false_iff, eq_self_iff_true, and_self_iff]
  rw [this]
  

Proof state:
R : Type u_1
inst✝ : Semiring R
n : ℤ
a : R
a0 : a ≠ 0
this : (C a * T n).support = {n}
⊢ Finset.max {n} = ↑n

Next tactic:
exact Finset.max_singleton
theorem degree_C_mul_T_ite [DecidableEq R] (n : ℤ) (a : R) :
    degree (C a * T n) = if a = 0 then ⊥ else ↑n := by
  

Proof state:
R : Type u_1
inst✝¹ : Semiring R
inst✝ : DecidableEq R
n : ℤ
a : R
⊢ degree (C a * T n) = if a = 0 then ⊥ else ↑n

Next tactic:
split_ifs with h
theorem degree_C_mul_T_ite [DecidableEq R] (n : ℤ) (a : R) :
    degree (C a * T n) = if a = 0 then ⊥ else ↑n := by
  split_ifs with h <;>
    

Proof state:
case pos
R : Type u_1
inst✝¹ : Semiring R
inst✝ : DecidableEq R
n : ℤ
a : R
h : a = 0
⊢ degree (C a * T n) = ⊥

Next tactic:
simp only [h, map_zero, zero_mul, degree_zero, degree_C_mul_T, Ne.def,
      not_false_iff]
theorem degree_C_mul_T_ite [DecidableEq R] (n : ℤ) (a : R) :
    degree (C a * T n) = if a = 0 then ⊥ else ↑n := by
  split_ifs with h <;>
    

Proof state:
case neg
R : Type u_1
inst✝¹ : Semiring R
inst✝ : DecidableEq R
n : ℤ
a : R
h : ¬a = 0
⊢ degree (C a * T n) = ↑n

Next tactic:
simp only [h, map_zero, zero_mul, degree_zero, degree_C_mul_T, Ne.def,
      not_false_iff]
@[simp]
theorem degree_T [Nontrivial R] (n : ℤ) : (T n : R[T;T⁻¹]).degree = n := by
  

Proof state:
R : Type u_1
inst✝¹ : Semiring R
inst✝ : Nontrivial R
n : ℤ
⊢ degree (T n) = ↑n

Next tactic:
rw [← one_mul (T n), ← map_one C]
@[simp]
theorem degree_T [Nontrivial R] (n : ℤ) : (T n : R[T;T⁻¹]).degree = n := by
  rw [← one_mul (T n), ← map_one C]
  

Proof state:
R : Type u_1
inst✝¹ : Semiring R
inst✝ : Nontrivial R
n : ℤ
⊢ degree (C 1 * T n) = ↑n

Next tactic:
exact degree_C_mul_T n 1 (one_ne_zero : (1 : R) ≠ 0)
theorem degree_C {a : R} (a0 : a ≠ 0) : (C a).degree = 0 := by
  

Proof state:
R : Type u_1
inst✝ : Semiring R
a : R
a0 : a ≠ 0
⊢ degree (C a) = 0

Next tactic:
rw [← mul_one (C a), ← T_zero]
theorem degree_C {a : R} (a0 : a ≠ 0) : (C a).degree = 0 := by
  rw [← mul_one (C a), ← T_zero]
  

Proof state:
R : Type u_1
inst✝ : Semiring R
a : R
a0 : a ≠ 0
⊢ degree (C a * T 0) = 0

Next tactic:
exact degree_C_mul_T 0 a a0
theorem degree_C_ite [DecidableEq R] (a : R) : (C a).degree = if a = 0 then ⊥ else 0 := by
  

Proof state:
R : Type u_1
inst✝¹ : Semiring R
inst✝ : DecidableEq R
a : R
⊢ degree (C a) = if a = 0 then ⊥ else 0

Next tactic:
split_ifs with h
theorem degree_C_ite [DecidableEq R] (a : R) : (C a).degree = if a = 0 then ⊥ else 0 := by
  split_ifs with h <;> 

Proof state:
case pos
R : Type u_1
inst✝¹ : Semiring R
inst✝ : DecidableEq R
a : R
h : a = 0
⊢ degree (C a) = ⊥

Next tactic:
simp only [h, map_zero, degree_zero, degree_C, Ne.def, not_false_iff]
theorem degree_C_ite [DecidableEq R] (a : R) : (C a).degree = if a = 0 then ⊥ else 0 := by
  split_ifs with h <;> 

Proof state:
case neg
R : Type u_1
inst✝¹ : Semiring R
inst✝ : DecidableEq R
a : R
h : ¬a = 0
⊢ degree (C a) = 0

Next tactic:
simp only [h, map_zero, degree_zero, degree_C, Ne.def, not_false_iff]
theorem degree_C_mul_T_le (n : ℤ) (a : R) : degree (C a * T n) ≤ n := by
  

Proof state:
R : Type u_1
inst✝ : Semiring R
n : ℤ
a : R
⊢ degree (C a * T n) ≤ ↑n

Next tactic:
by_cases a0 : a = 0
theorem degree_C_mul_T_le (n : ℤ) (a : R) : degree (C a * T n) ≤ n := by
  by_cases a0 : a = 0
  · 

Proof state:
case pos
R : Type u_1
inst✝ : Semiring R
n : ℤ
a : R
a0 : a = 0
⊢ degree (C a * T n) ≤ ↑n

Next tactic:
simp only [a0, map_zero, zero_mul, degree_zero, bot_le]
theorem degree_C_mul_T_le (n : ℤ) (a : R) : degree (C a * T n) ≤ n := by
  by_cases a0 : a = 0
  · simp only [a0, map_zero, zero_mul, degree_zero, bot_le]
  · 

Proof state:
case neg
R : Type u_1
inst✝ : Semiring R
n : ℤ
a : R
a0 : ¬a = 0
⊢ degree (C a * T n) ≤ ↑n

Next tactic:
exact (degree_C_mul_T n a a0).le
theorem degree_T_le (n : ℤ) : (T n : R[T;T⁻¹]).degree ≤ n :=
  (le_of_eq (by 

Proof state:
R : Type u_1
inst✝ : Semiring R
n : ℤ
⊢ degree (T n) = degree (C 1 * T n)

Next tactic:
rw [map_one, one_mul]
theorem degree_C_le (a : R) : (C a).degree ≤ 0 :=
  (le_of_eq (by 

Proof state:
R : Type u_1
inst✝ : Semiring R
a : R
⊢ degree (C a) = degree (C a * T 0)

Next tactic:
rw [T_zero, mul_one]
instance (R : Type*) [Semiring R] : IsScalarTower R[X] R[X] R[T;T⁻¹] where
  smul_assoc x y z := by 

Proof state:
R✝ : Type u_1
inst✝¹ : Semiring R✝
R : Type u_2
inst✝ : Semiring R
x y : R[X]
z : R[T;T⁻¹]
⊢ (x • y) • z = x • y • z

Next tactic:
dsimp
instance (R : Type*) [Semiring R] : IsScalarTower R[X] R[X] R[T;T⁻¹] where
  smul_assoc x y z := by dsimp; 

Proof state:
R✝ : Type u_1
inst✝¹ : Semiring R✝
R : Type u_2
inst✝ : Semiring R
x y : R[X]
z : R[T;T⁻¹]
⊢ (x * y) • z = x • y • z

Next tactic:
simp_rw [MulAction.mul_smul]
instance algebraPolynomial (R : Type*) [CommSemiring R] : Algebra R[X] R[T;T⁻¹] :=
  { Polynomial.toLaurent with
    commutes' := fun f l => by 

Proof state:
R✝ : Type u_1
inst✝¹ : CommSemiring R✝
R : Type u_2
inst✝ : CommSemiring R
src✝ : R[X] →+* R[T;T⁻¹] := toLaurent
f : R[X]
l : R[T;T⁻¹]
⊢ { toMonoidHom := ↑src✝, map_zero' := (_ : OneHom.toFun (↑↑src✝) 0 = 0),
          map_add' :=
            (_ : ∀ (x y : R[X]), OneHom.toFun (↑↑src✝) (x + y) = OneHom.toFun (↑↑src✝) x + OneHom.toFun (↑↑src✝) y) }
        f *
      l =
    l *
      { toMonoidHom := ↑src✝, map_zero' := (_ : OneHom.toFun (↑↑src✝) 0 = 0),
          map_add' :=
            (_ : ∀ (x y : R[X]), OneHom.toFun (↑↑src✝) (x + y) = OneHom.toFun (↑↑src✝) x + OneHom.toFun (↑↑src✝) y) }
        f

Next tactic:
simp [mul_comm]
theorem isLocalization : IsLocalization (Submonoid.closure ({X} : Set R[X])) R[T;T⁻¹] :=
  { map_units' := fun t => by
      

Proof state:
R : Type u_1
inst✝ : CommSemiring R
t : ↥(Submonoid.closure {X})
⊢ IsUnit ((algebraMap R[X] R[T;T⁻¹]) ↑t)

Next tactic:
cases' t with t ht
theorem isLocalization : IsLocalization (Submonoid.closure ({X} : Set R[X])) R[T;T⁻¹] :=
  { map_units' := fun t => by
      cases' t with t ht
      

Proof state:
case mk
R : Type u_1
inst✝ : CommSemiring R
t : R[X]
ht : t ∈ Submonoid.closure {X}
⊢ IsUnit ((algebraMap R[X] R[T;T⁻¹]) ↑{ val := t, property := ht })

Next tactic:
rcases Submonoid.mem_closure_singleton.mp ht with ⟨n, rfl⟩
theorem isLocalization : IsLocalization (Submonoid.closure ({X} : Set R[X])) R[T;T⁻¹] :=
  { map_units' := fun t => by
      cases' t with t ht
      rcases Submonoid.mem_closure_singleton.mp ht with ⟨n, rfl⟩
      

Proof state:
case mk.intro
R : Type u_1
inst✝ : CommSemiring R
n : ℕ
ht : X ^ n ∈ Submonoid.closure {X}
⊢ IsUnit ((algebraMap R[X] R[T;T⁻¹]) ↑{ val := X ^ n, property := ht })

Next tactic:
simp only [isUnit_T n, algebraMap_eq_toLaurent, Polynomial.toLaurent_X_pow]
theorem isLocalization : IsLocalization (Submonoid.closure ({X} : Set R[X])) R[T;T⁻¹] :=
  { map_units' := fun t => by
      cases' t with t ht
      rcases Submonoid.mem_closure_singleton.mp ht with ⟨n, rfl⟩
      simp only [isUnit_T n, algebraMap_eq_toLaurent, Polynomial.toLaurent_X_pow]
    surj' := fun f => by
      

Proof state:
R : Type u_1
inst✝ : CommSemiring R
f : R[T;T⁻¹]
⊢ ∃ x, f * (algebraMap R[X] R[T;T⁻¹]) ↑x.2 = (algebraMap R[X] R[T;T⁻¹]) x.1

Next tactic:
induction' f using LaurentPolynomial.induction_on_mul_T with f n
theorem isLocalization : IsLocalization (Submonoid.closure ({X} : Set R[X])) R[T;T⁻¹] :=
  { map_units' := fun t => by
      cases' t with t ht
      rcases Submonoid.mem_closure_singleton.mp ht with ⟨n, rfl⟩
      simp only [isUnit_T n, algebraMap_eq_toLaurent, Polynomial.toLaurent_X_pow]
    surj' := fun f => by
      induction' f using LaurentPolynomial.induction_on_mul_T with f n
      

Proof state:
case Qf
R : Type u_1
inst✝ : CommSemiring R
f : R[X]
n : ℕ
⊢ ∃ x, toLaurent f * T (-↑n) * (algebraMap R[X] R[T;T⁻¹]) ↑x.2 = (algebraMap R[X] R[T;T⁻¹]) x.1

Next tactic:
have := (Submonoid.closure ({X} : Set R[X])).pow_mem Submonoid.mem_closure_singleton_self n
theorem isLocalization : IsLocalization (Submonoid.closure ({X} : Set R[X])) R[T;T⁻¹] :=
  { map_units' := fun t => by
      cases' t with t ht
      rcases Submonoid.mem_closure_singleton.mp ht with ⟨n, rfl⟩
      simp only [isUnit_T n, algebraMap_eq_toLaurent, Polynomial.toLaurent_X_pow]
    surj' := fun f => by
      induction' f using LaurentPolynomial.induction_on_mul_T with f n
      have := (Submonoid.closure ({X} : Set R[X])).pow_mem Submonoid.mem_closure_singleton_self n
      

Proof state:
case Qf
R : Type u_1
inst✝ : CommSemiring R
f : R[X]
n : ℕ
this : X ^ n ∈ Submonoid.closure {X}
⊢ ∃ x, toLaurent f * T (-↑n) * (algebraMap R[X] R[T;T⁻¹]) ↑x.2 = (algebraMap R[X] R[T;T⁻¹]) x.1

Next tactic:
refine' ⟨(f, ⟨_, this⟩), _⟩
theorem isLocalization : IsLocalization (Submonoid.closure ({X} : Set R[X])) R[T;T⁻¹] :=
  { map_units' := fun t => by
      cases' t with t ht
      rcases Submonoid.mem_closure_singleton.mp ht with ⟨n, rfl⟩
      simp only [isUnit_T n, algebraMap_eq_toLaurent, Polynomial.toLaurent_X_pow]
    surj' := fun f => by
      induction' f using LaurentPolynomial.induction_on_mul_T with f n
      have := (Submonoid.closure ({X} : Set R[X])).pow_mem Submonoid.mem_closure_singleton_self n
      refine' ⟨(f, ⟨_, this⟩), _⟩
      

Proof state:
case Qf
R : Type u_1
inst✝ : CommSemiring R
f : R[X]
n : ℕ
this : X ^ n ∈ Submonoid.closure {X}
⊢ toLaurent f * T (-↑n) * (algebraMap R[X] R[T;T⁻¹]) ↑(f, { val := X ^ n, property := this }).2 =
    (algebraMap R[X] R[T;T⁻¹]) (f, { val := X ^ n, property := this }).1

Next tactic:
simp only [algebraMap_eq_toLaurent, Polynomial.toLaurent_X_pow, mul_T_assoc,
        add_left_neg, T_zero, mul_one]
theorem isLocalization : IsLocalization (Submonoid.closure ({X} : Set R[X])) R[T;T⁻¹] :=
  { map_units' := fun t => by
      cases' t with t ht
      rcases Submonoid.mem_closure_singleton.mp ht with ⟨n, rfl⟩
      simp only [isUnit_T n, algebraMap_eq_toLaurent, Polynomial.toLaurent_X_pow]
    surj' := fun f => by
      induction' f using LaurentPolynomial.induction_on_mul_T with f n
      have := (Submonoid.closure ({X} : Set R[X])).pow_mem Submonoid.mem_closure_singleton_self n
      refine' ⟨(f, ⟨_, this⟩), _⟩
      simp only [algebraMap_eq_toLaurent, Polynomial.toLaurent_X_pow, mul_T_assoc,
        add_left_neg, T_zero, mul_one]
    exists_of_eq := fun {f g} => by
      

Proof state:
R : Type u_1
inst✝ : CommSemiring R
f g : R[X]
⊢ (algebraMap R[X] R[T;T⁻¹]) f = (algebraMap R[X] R[T;T⁻¹]) g → ∃ c, ↑c * f = ↑c * g

Next tactic:
rw [algebraMap_eq_toLaurent, algebraMap_eq_toLaurent, Polynomial.toLaurent_inj]
theorem isLocalization : IsLocalization (Submonoid.closure ({X} : Set R[X])) R[T;T⁻¹] :=
  { map_units' := fun t => by
      cases' t with t ht
      rcases Submonoid.mem_closure_singleton.mp ht with ⟨n, rfl⟩
      simp only [isUnit_T n, algebraMap_eq_toLaurent, Polynomial.toLaurent_X_pow]
    surj' := fun f => by
      induction' f using LaurentPolynomial.induction_on_mul_T with f n
      have := (Submonoid.closure ({X} : Set R[X])).pow_mem Submonoid.mem_closure_singleton_self n
      refine' ⟨(f, ⟨_, this⟩), _⟩
      simp only [algebraMap_eq_toLaurent, Polynomial.toLaurent_X_pow, mul_T_assoc,
        add_left_neg, T_zero, mul_one]
    exists_of_eq := fun {f g} => by
      rw [algebraMap_eq_toLaurent, algebraMap_eq_toLaurent, Polynomial.toLaurent_inj]
      

Proof state:
R : Type u_1
inst✝ : CommSemiring R
f g : R[X]
⊢ f = g → ∃ c, ↑c * f = ↑c * g

Next tactic:
rintro rfl