Fermat's Last Theorem in Lean 4

← all definition modules

Definitions/Def_MvPowerSeries_RestrictedEvalV2.lean

definition module

Restricted evaluation of multivariate power series

Fix a commutative ring \mathcal O, an index type \sigma and a natural number p (no primality is assumed; p is used through its image in the relevant ring). A series S \in \mathcal O[[X_s : s \in \sigma]] satisfies Tendsto0 p S when for every N the coefficient \operatorname{coeff}_m S lies in the ideal (p^N) for all but finitely many exponents m, i.e. the condition holds eventually along the cofinite filter on \sigma \to_0 \mathbb N. For such an S, Tendsto0.bad hS N is the resulting finite set of exceptional exponents \{m : \operatorname{coeff}_m S \notin (p^N)\}, increasing in N. A group of lemmas records that this class contains 0, 1, the images of polynomials, X_s and C(c), and is closed under addition, negation, subtraction and \mathcal O-scaling; when \sigma is finite it is equivalently described by total degree (for each N some K with \operatorname{coeff}_m S \in (p^N) whenever \deg m \ge K) and is closed under multiplication, powers, finite products, polynomial expressions (tendsto0_aeval) and substitution of a family of such series with vanishing constant coefficients (tendsto0_subst).

For the target, Cplt p Y abbreviates IsAdicComplete (Ideal.span {(p : Y)}) Y, and Y is a commutative \mathcal O-algebra. With \operatorname{monom} x\, m = \prod_s (x_s)^{m_s} and partial sums \operatorname{psum} x\, T\, S = \sum_{m \in T} \operatorname{algebraMap}(\operatorname{coeff}_m S)\cdot \operatorname{monom} x\,m over finite sets T, the sums over bad N form a Cauchy family for the (p)-adic filtration, so completeness yields an element L with L - \operatorname{psum} x (\mathrm{bad}\,N) S \in (p^N) for all N; evalT p hY x S is such an L for restricted S and 0 otherwise, hence a total function of an arbitrary tuple x \in Y^{\sigma}. It is characterised by the congruences \operatorname{evalT} \equiv \operatorname{psum} x\,T\,S \pmod{(p^N)} for all finite T \supseteq \mathrm{bad}\,N, agrees with MvPolynomial.aeval on polynomials, is additive, \mathcal O-semilinear and (for finite \sigma) multiplicative, sends series with all coefficients in (p^N) into (p^N)Y, and satisfies \operatorname{evalT}(x, \operatorname{subst} a\, S) = \operatorname{evalT}(\operatorname{evalT}(x, a), S). The truncation badPart p hS N is the polynomial \sum_{m \in \mathrm{bad}\,N} c_m X^m used to split a restricted series into a polynomial part and a part with all coefficients divisible by p^N.

Relation to Mathlib

Mathlib's MvPowerSeries.aeval and MvPowerSeries.subst evaluate at topologically nilpotent arguments; the predicate Tendsto0 and the evaluation evalT defined here are the project's own, and impose the growth condition on the coefficients instead, so that the arguments x \in Y^\sigma may be arbitrary. Completeness appears as an explicit hypothesis Cplt p Y, an abbreviation for Mathlib's IsAdicComplete (Ideal.span {(p : Y)}) Y, rather than as an instance.

Where it is used

The evaluation is needed where power series with p-adically growing divisibility of coefficients, such as the integral logarithm f(pX)/p of a formal group, must be evaluated at elements that are not topologically nilpotent.

References

  1. M. Hazewinkel, Formal Groups and Applications, Academic Press, 1978
  2. A. FrΓΆhlich, Formal Groups, Lecture Notes in Mathematics 74, Springer, 1968

References are suggested automatically and have not been individually verified.

English text generated automatically from the Lean source; the Lean statement is authoritative.

Source file: Definitions/Def_MvPowerSeries_RestrictedEvalV2.lean

Declarations

Source

import Mathlib

set_option autoImplicit false

open MvPowerSeries

namespace MvPowerSeries.Restricted

universe u v w

variable {π“ž : Type u} [CommRing π“ž] {Οƒ : Type v}

def Tendsto0 (p : β„•) (S : MvPowerSeries Οƒ π“ž) : Prop :=
  βˆ€ N : β„•, βˆ€αΆ  m in Filter.cofinite, coeff m S ∈ Ideal.span {(p : π“ž) ^ N}

namespace Tendsto0

variable {p : β„•} {S T : MvPowerSeries Οƒ π“ž}

theorem finite_setOf (hS : Tendsto0 p S) (N : β„•) :
    {m : Οƒ β†’β‚€ β„• | coeff m S βˆ‰ Ideal.span {(p : π“ž) ^ N}}.Finite :=
  Filter.eventually_cofinite.1 (hS N)

noncomputable def bad (hS : Tendsto0 p S) (N : β„•) : Finset (Οƒ β†’β‚€ β„•) :=
  (hS.finite_setOf N).toFinset

theorem mem_bad_iff (hS : Tendsto0 p S) (N : β„•) (m : Οƒ β†’β‚€ β„•) :
    m ∈ hS.bad N ↔ coeff m S βˆ‰ Ideal.span {(p : π“ž) ^ N} := by
  simp [bad]

theorem coeff_mem_of_not_mem_bad (hS : Tendsto0 p S) {N : β„•} {m : Οƒ β†’β‚€ β„•} (hm : m βˆ‰ hS.bad N) :
    coeff m S ∈ Ideal.span {(p : π“ž) ^ N} := by
  by_contra h
  exact hm ((hS.mem_bad_iff N m).2 h)

theorem span_pow_le_span_pow {R : Type*} [CommRing R] (a : R) {M N : β„•} (h : M ≀ N) :
    Ideal.span {a ^ N} ≀ Ideal.span {a ^ M} :=
  Ideal.span_singleton_le_span_singleton.2 (pow_dvd_pow a h)

theorem bad_mono (hS : Tendsto0 p S) {M N : β„•} (h : M ≀ N) : hS.bad M βŠ† hS.bad N := by
  intro m hm
  rw [mem_bad_iff] at hm ⊒
  exact fun h' => hm (span_pow_le_span_pow (p : π“ž) h h')

theorem of_forall_eventually_eq_zero {S : MvPowerSeries Οƒ π“ž}
    (h : βˆ€αΆ  m in Filter.cofinite, coeff m S = 0) : Tendsto0 p S := by
  intro N
  filter_upwards [h] with m hm
  rw [hm]
  exact Ideal.zero_mem _

theorem zero : Tendsto0 p (0 : MvPowerSeries Οƒ π“ž) :=
  of_forall_eventually_eq_zero (Filter.Eventually.of_forall fun m => by simp)

theorem coe (P : MvPolynomial Οƒ π“ž) : Tendsto0 p (P : MvPowerSeries Οƒ π“ž) := by
  apply of_forall_eventually_eq_zero
  rw [Filter.eventually_cofinite]
  refine (P.support.finite_toSet).subset ?_
  intro m hm
  by_contra h'
  apply hm
  rw [MvPolynomial.coeff_coe]
  exact MvPolynomial.notMem_support_iff.1 h'

theorem one : Tendsto0 p (1 : MvPowerSeries Οƒ π“ž) := by
  have h := coe (p := p) (Οƒ := Οƒ) (π“ž := π“ž) 1
  rwa [MvPolynomial.coe_one] at h

theorem add (hS : Tendsto0 p S) (hT : Tendsto0 p T) : Tendsto0 p (S + T) := by
  intro N
  filter_upwards [hS N, hT N] with m hmS hmT
  rw [map_add]
  exact Ideal.add_mem _ hmS hmT

theorem neg (hS : Tendsto0 p S) : Tendsto0 p (-S) := by
  intro N
  filter_upwards [hS N] with m hm
  rw [map_neg]
  exact (Ideal.neg_mem_iff _).2 hm

theorem sub (hS : Tendsto0 p S) (hT : Tendsto0 p T) : Tendsto0 p (S - T) := by
  rw [sub_eq_add_neg]; exact hS.add hT.neg

theorem smul (hS : Tendsto0 p S) (c : π“ž) : Tendsto0 p (c β€’ S) := by
  intro N
  filter_upwards [hS N] with m hm
  rw [map_smul, smul_eq_mul]
  exact Ideal.mul_mem_left _ c hm

theorem exists_degree [Finite Οƒ] (hS : Tendsto0 p S) (N : β„•) :
    βˆƒ K : β„•, βˆ€ m : Οƒ β†’β‚€ β„•, K ≀ m.degree β†’ coeff m S ∈ Ideal.span {(p : π“ž) ^ N} := by
  classical
  refine ⟨(hS.bad N).sup (fun m => m.degree) + 1, fun m hm => ?_⟩
  apply hS.coeff_mem_of_not_mem_bad
  intro hbad
  have := Finset.le_sup (f := fun m : Οƒ β†’β‚€ β„• => m.degree) hbad
  omega

theorem of_degree [Finite Οƒ] {S : MvPowerSeries Οƒ π“ž}
    (h : βˆ€ N : β„•, βˆƒ K : β„•, βˆ€ m : Οƒ β†’β‚€ β„•, K ≀ m.degree β†’ coeff m S ∈ Ideal.span {(p : π“ž) ^ N}) :
    Tendsto0 p S := by
  classical
  intro N
  obtain ⟨K, hK⟩ := h N
  rw [Filter.eventually_cofinite]
  refine Set.Finite.subset (Finsupp.finite_of_degree_le (Οƒ := Οƒ) (n := K)) ?_
  intro m hm
  by_contra h'
  simp only [Set.mem_setOf_eq, not_le] at h'
  exact hm (hK m h'.le)

theorem mul [Finite Οƒ] (hS : Tendsto0 p S) (hT : Tendsto0 p T) : Tendsto0 p (S * T) := by
  classical
  apply of_degree
  intro N
  obtain ⟨K, hK⟩ := hS.exists_degree N
  obtain ⟨K', hK'⟩ := hT.exists_degree N
  refine ⟨K + K', fun e he => ?_⟩
  rw [coeff_mul]
  refine Ideal.sum_mem _ fun x hx => ?_
  rw [Finset.HasAntidiagonal.mem_antidiagonal] at hx
  have hdeg : x.1.degree + x.2.degree = e.degree := by rw [← map_add, hx]
  by_cases h1 : K ≀ x.1.degree
  Β· exact Ideal.mul_mem_right _ _ (hK _ h1)
  Β· have h2 : K' ≀ x.2.degree := by omega
    exact Ideal.mul_mem_left _ _ (hK' _ h2)

theorem pow [Finite Οƒ] (hS : Tendsto0 p S) : βˆ€ n : β„•, Tendsto0 p (S ^ n)
  | 0 => by rw [pow_zero]; exact one
  | n + 1 => by rw [pow_succ]; exact (pow hS n).mul hS

theorem prod [Finite Οƒ] {ΞΉ : Type*} (s : Finset ΞΉ) (f : ΞΉ β†’ MvPowerSeries Οƒ π“ž)
    (hf : βˆ€ i ∈ s, Tendsto0 p (f i)) : Tendsto0 p (∏ i ∈ s, f i) := by
  classical
  induction s using Finset.induction_on with
  | empty => rw [Finset.prod_empty]; exact one
  | insert a s ha ih =>
    rw [Finset.prod_insert ha]
    exact (hf a (Finset.mem_insert_self a s)).mul (ih fun i hi => hf i (Finset.mem_insert_of_mem hi))

end Tendsto0

theorem tendsto0_X (p : β„•) (s : Οƒ) : Tendsto0 p (X s : MvPowerSeries Οƒ π“ž) := by
  have h := Tendsto0.coe (p := p) (MvPolynomial.X s : MvPolynomial Οƒ π“ž)
  rwa [MvPolynomial.coe_X] at h

theorem tendsto0_C (p : β„•) (c : π“ž) : Tendsto0 p (C c : MvPowerSeries Οƒ π“ž) := by
  have h := Tendsto0.coe (p := p) (MvPolynomial.C c : MvPolynomial Οƒ π“ž)
  rwa [MvPolynomial.coe_C] at h

theorem tendsto0_of_forall_coeff_mem_pow_degree [Finite Οƒ] (p : β„•) {S : MvPowerSeries Οƒ π“ž}
    (h : βˆ€ m, coeff m S ∈ Ideal.span {(p : π“ž) ^ m.degree}) : Tendsto0 p S :=
  Tendsto0.of_degree fun N => ⟨N, fun m hm => Tendsto0.span_pow_le_span_pow (p : π“ž) hm (h m)⟩

section Eval

variable (p : β„•) {Y : Type w} [CommRing Y] [Algebra π“ž Y]

abbrev Cplt (Y : Type w) [CommRing Y] : Prop := IsAdicComplete (Ideal.span {(p : Y)}) Y

def monom (x : Οƒ β†’ Y) (m : Οƒ β†’β‚€ β„•) : Y := m.prod fun s e => x s ^ e

theorem monom_zero (x : Οƒ β†’ Y) : monom x 0 = 1 := by simp [monom]

theorem monom_add (x : Οƒ β†’ Y) (m m' : Οƒ β†’β‚€ β„•) : monom x (m + m') = monom x m * monom x m' := by
  classical
  simp only [monom]
  rw [Finsupp.prod_add_index']
  Β· intro s; exact pow_zero _
  Β· intro s a b; exact pow_add _ _ _

noncomputable def psum (x : Οƒ β†’ Y) (T : Finset (Οƒ β†’β‚€ β„•)) (S : MvPowerSeries Οƒ π“ž) : Y :=
  βˆ‘ m ∈ T, algebraMap π“ž Y (coeff m S) * monom x m

theorem algebraMap_mem_span_pow {N : β„•} {c : π“ž} (hc : c ∈ Ideal.span {(p : π“ž) ^ N}) :
    algebraMap π“ž Y c ∈ Ideal.span {(p : Y) ^ N} := by
  rw [Ideal.mem_span_singleton] at hc ⊒
  obtain ⟨d, rfl⟩ := hc
  refine ⟨algebraMap π“ž Y d, ?_⟩
  rw [map_mul, map_pow, map_natCast]

theorem psum_sub_psum_mem {S : MvPowerSeries Οƒ π“ž} (hS : Tendsto0 p S) (x : Οƒ β†’ Y) {N : β„•}
    {T T' : Finset (Οƒ β†’β‚€ β„•)} (hT : hS.bad N βŠ† T) (hT' : hS.bad N βŠ† T') :
    psum x T S - psum x T' S ∈ Ideal.span {(p : Y) ^ N} := by
  classical
  have key : βˆ€ (A B : Finset (Οƒ β†’β‚€ β„•)), hS.bad N βŠ† B β†’
      psum x A S - psum x (A ∩ B) S ∈ Ideal.span {(p : Y) ^ N} := by
    intro A B hB
    rw [psum, psum, ← Finset.sum_sdiff (Finset.inter_subset_left (s₁ := A) (sβ‚‚ := B)), add_sub_cancel_right]
    refine Ideal.sum_mem _ fun m hm => ?_
    rw [Finset.mem_sdiff, Finset.mem_inter, not_and] at hm
    have hmB : m βˆ‰ hS.bad N := fun h => hm.2 hm.1 (hB h)
    exact Ideal.mul_mem_right _ _ (algebraMap_mem_span_pow p (hS.coeff_mem_of_not_mem_bad hmB))
  have h1 := key T T' hT'
  have h2 := key T' T hT
  rw [Finset.inter_comm] at h2
  have := Ideal.sub_mem _ h1 h2
  rwa [sub_sub_sub_cancel_right] at this

theorem smodEq_iff_sub_mem (N : β„•) (a b : Y) :
    a ≑ b [SMOD (Ideal.span {(p : Y)}) ^ N β€’ (⊀ : Submodule Y Y)] ↔ a - b ∈ Ideal.span {(p : Y) ^ N} := by
  rw [SModEq.sub_mem, Ideal.span_singleton_pow, smul_eq_mul, Ideal.mul_top]

theorem eq_of_forall_sub_mem (hY : Cplt p Y) {a b : Y}
    (h : βˆ€ N : β„•, a - b ∈ Ideal.span {(p : Y) ^ N}) : a = b := by
  rw [← sub_eq_zero]
  refine IsHausdorff.haus hY.toIsHausdorff (a - b) fun N => ?_
  rw [smodEq_iff_sub_mem, sub_zero]
  exact h N

theorem exists_limit (hY : Cplt p Y) {S : MvPowerSeries Οƒ π“ž}
    (hS : Tendsto0 p S) (x : Οƒ β†’ Y) :
    βˆƒ L : Y, βˆ€ N : β„•, L - psum x (hS.bad N) S ∈ Ideal.span {(p : Y) ^ N} := by
  have hprec := IsPrecomplete.prec hY.toIsPrecomplete (f := fun N => psum x (hS.bad N) S) ?_
  · obtain ⟨L, hL⟩ := hprec
    refine ⟨L, fun N => ?_⟩
    have h := (smodEq_iff_sub_mem p N _ _).1 (hL N)
    rw [← Ideal.neg_mem_iff, neg_sub] at h
    exact h
  Β· intro M N hMN
    rw [smodEq_iff_sub_mem]
    exact psum_sub_psum_mem p hS x subset_rfl (hS.bad_mono hMN)

open Classical in

noncomputable def evalT (hY : Cplt p Y) (x : Οƒ β†’ Y) (S : MvPowerSeries Οƒ π“ž) : Y :=
  if hS : Tendsto0 p S then Classical.choose (exists_limit p hY hS x) else 0

variable (hY : Cplt p Y)
include hY

theorem evalT_sub_psum_bad_mem {S : MvPowerSeries Οƒ π“ž} (hS : Tendsto0 p S) (x : Οƒ β†’ Y) (N : β„•) :
    evalT p hY x S - psum x (hS.bad N) S ∈ Ideal.span {(p : Y) ^ N} := by
  rw [evalT, dif_pos hS]
  exact Classical.choose_spec (exists_limit p hY hS x) N

theorem evalT_sub_psum_mem {S : MvPowerSeries Οƒ π“ž} (hS : Tendsto0 p S) (x : Οƒ β†’ Y) {N : β„•}
    {T : Finset (Οƒ β†’β‚€ β„•)} (hT : hS.bad N βŠ† T) :
    evalT p hY x S - psum x T S ∈ Ideal.span {(p : Y) ^ N} := by
  have h1 := evalT_sub_psum_bad_mem p hY hS x N
  have h2 := psum_sub_psum_mem p hS x subset_rfl hT
  have := Ideal.add_mem _ h1 h2
  rwa [sub_add_sub_cancel] at this

theorem evalT_mem_of_forall_coeff_mem {S : MvPowerSeries Οƒ π“ž} (hS : Tendsto0 p S) (x : Οƒ β†’ Y) {N : β„•}
    (h : βˆ€ m, coeff m S ∈ Ideal.span {(p : π“ž) ^ N}) : evalT p hY x S ∈ Ideal.span {(p : Y) ^ N} := by
  have hbad : hS.bad N = βˆ… := by
    ext m
    simp only [Finset.notMem_empty, iff_false]
    rw [hS.mem_bad_iff]
    exact fun hm => hm (h m)
  have := evalT_sub_psum_bad_mem p hY hS x N
  rwa [hbad, psum, Finset.sum_empty, sub_zero] at this

theorem evalT_congr_of_forall_sub_mem {S : MvPowerSeries Οƒ π“ž} (hS : Tendsto0 p S) (x : Οƒ β†’ Y) {a : Y}
    (h : βˆ€ N : β„•, βˆƒ T : Finset (Οƒ β†’β‚€ β„•), hS.bad N βŠ† T ∧ a - psum x T S ∈ Ideal.span {(p : Y) ^ N}) :
    evalT p hY x S = a := by
  refine eq_of_forall_sub_mem p hY fun N => ?_
  obtain ⟨T, hT, ha⟩ := h N
  have := Ideal.sub_mem _ (evalT_sub_psum_mem p hY hS x hT) ha
  rwa [sub_sub_sub_cancel_right] at this

theorem evalT_coe (x : Οƒ β†’ Y) (P : MvPolynomial Οƒ π“ž) :
    evalT p hY x (P : MvPowerSeries Οƒ π“ž) = MvPolynomial.aeval x P := by
  classical
  apply evalT_congr_of_forall_sub_mem p hY (Tendsto0.coe P) x
  intro N
  refine ⟨(Tendsto0.coe (p := p) P).bad N βˆͺ P.support, Finset.subset_union_left, ?_⟩
  have : psum x ((Tendsto0.coe (p := p) P).bad N βˆͺ P.support) (P : MvPowerSeries Οƒ π“ž) =
      MvPolynomial.aeval x P := by
    rw [psum, MvPolynomial.aeval_def, MvPolynomial.evalβ‚‚_eq, ← Finset.sum_subset Finset.subset_union_right]
    Β· refine Finset.sum_congr rfl fun m _ => ?_
      rw [MvPolynomial.coeff_coe, monom, Finsupp.prod]
    Β· intro m _ hm
      rw [MvPolynomial.coeff_coe, MvPolynomial.notMem_support_iff.1 hm, map_zero, zero_mul]
  rw [this, sub_self]
  exact Ideal.zero_mem _

theorem evalT_add {S T : MvPowerSeries Οƒ π“ž} (hS : Tendsto0 p S) (hT : Tendsto0 p T) (x : Οƒ β†’ Y) :
    evalT p hY x (S + T) = evalT p hY x S + evalT p hY x T := by
  classical
  apply evalT_congr_of_forall_sub_mem p hY (hS.add hT) x
  intro N
  refine ⟨(hS.add hT).bad N βˆͺ (hS.bad N βˆͺ hT.bad N), Finset.subset_union_left, ?_⟩
  set U := (hS.add hT).bad N βˆͺ (hS.bad N βˆͺ hT.bad N)
  have hU : psum x U (S + T) = psum x U S + psum x U T := by
    simp only [psum, map_add, add_mul, Finset.sum_add_distrib]
  rw [hU, add_sub_add_comm]
  exact Ideal.add_mem _
    (evalT_sub_psum_mem p hY hS x (Finset.subset_union_left.trans Finset.subset_union_right))
    (evalT_sub_psum_mem p hY hT x (Finset.subset_union_right.trans Finset.subset_union_right))

theorem evalT_smul {S : MvPowerSeries Οƒ π“ž} (hS : Tendsto0 p S) (c : π“ž) (x : Οƒ β†’ Y) :
    evalT p hY x (c β€’ S) = algebraMap π“ž Y c * evalT p hY x S := by
  classical
  apply evalT_congr_of_forall_sub_mem p hY (hS.smul c) x
  intro N
  refine ⟨(hS.smul c).bad N βˆͺ hS.bad N, Finset.subset_union_left, ?_⟩
  have hU : psum x ((hS.smul c).bad N βˆͺ hS.bad N) (c β€’ S) =
      algebraMap π“ž Y c * psum x ((hS.smul c).bad N βˆͺ hS.bad N) S := by
    simp only [psum, map_smul, smul_eq_mul, map_mul, Finset.mul_sum, mul_assoc]
  rw [hU, ← mul_sub]
  exact Ideal.mul_mem_left _ _ (evalT_sub_psum_mem p hY hS x Finset.subset_union_right)

theorem evalT_neg {S : MvPowerSeries Οƒ π“ž} (hS : Tendsto0 p S) (x : Οƒ β†’ Y) :
    evalT p hY x (-S) = -evalT p hY x S := by
  have h := evalT_smul p hY hS (-1 : π“ž) x
  rwa [neg_one_smul, map_neg, map_one, neg_one_mul] at h

theorem evalT_sub {S T : MvPowerSeries Οƒ π“ž} (hS : Tendsto0 p S) (hT : Tendsto0 p T) (x : Οƒ β†’ Y) :
    evalT p hY x (S - T) = evalT p hY x S - evalT p hY x T := by
  rw [sub_eq_add_neg, evalT_add p hY hS hT.neg, evalT_neg p hY hT, sub_eq_add_neg]

theorem evalT_zero (x : Οƒ β†’ Y) : evalT p hY x (0 : MvPowerSeries Οƒ π“ž) = 0 := by
  have h := evalT_coe p hY x (0 : MvPolynomial Οƒ π“ž)
  rwa [MvPolynomial.coe_zero, map_zero] at h

theorem evalT_one (x : Οƒ β†’ Y) : evalT p hY x (1 : MvPowerSeries Οƒ π“ž) = 1 := by
  have h := evalT_coe p hY x (1 : MvPolynomial Οƒ π“ž)
  rwa [MvPolynomial.coe_one, map_one] at h

theorem evalT_C (x : Οƒ β†’ Y) (c : π“ž) : evalT p hY x (C c : MvPowerSeries Οƒ π“ž) = algebraMap π“ž Y c := by
  have h := evalT_coe p hY x (MvPolynomial.C c : MvPolynomial Οƒ π“ž)
  rwa [MvPolynomial.coe_C, MvPolynomial.aeval_C] at h

theorem evalT_X (x : Οƒ β†’ Y) (s : Οƒ) : evalT p hY x (X s : MvPowerSeries Οƒ π“ž) = x s := by
  have h := evalT_coe p hY x (MvPolynomial.X s : MvPolynomial Οƒ π“ž)
  rwa [MvPolynomial.coe_X, MvPolynomial.aeval_X] at h

noncomputable def badPart {S : MvPowerSeries Οƒ π“ž} (hS : Tendsto0 p S) (N : β„•) : MvPolynomial Οƒ π“ž :=
  βˆ‘ m ∈ hS.bad N, MvPolynomial.monomial m (coeff m S)

omit hY in
theorem coeff_badPart [DecidableEq Οƒ] {S : MvPowerSeries Οƒ π“ž} (hS : Tendsto0 p S) (N : β„•) (m : Οƒ β†’β‚€ β„•) :
    MvPolynomial.coeff m (badPart p hS N) = if m ∈ hS.bad N then coeff m S else 0 := by
  classical
  rw [badPart, MvPolynomial.coeff_sum]
  simp only [MvPolynomial.coeff_monomial]
  rw [Finset.sum_ite_eq']

omit hY in

theorem coeff_sub_badPart_mem {S : MvPowerSeries Οƒ π“ž} (hS : Tendsto0 p S) (N : β„•) (m : Οƒ β†’β‚€ β„•) :
    coeff m (S - (badPart p hS N : MvPowerSeries Οƒ π“ž)) ∈ Ideal.span {(p : π“ž) ^ N} := by
  classical
  rw [map_sub, MvPolynomial.coeff_coe, coeff_badPart]
  split_ifs with h
  Β· rw [sub_self]; exact Ideal.zero_mem _
  Β· rw [sub_zero]; exact hS.coeff_mem_of_not_mem_bad h

omit hY in
theorem coeff_mul_mem_of_forall_left {I : Ideal π“ž} {S : MvPowerSeries Οƒ π“ž} (h : βˆ€ m, coeff m S ∈ I)
    (T : MvPowerSeries Οƒ π“ž) (e : Οƒ β†’β‚€ β„•) : coeff e (S * T) ∈ I := by
  classical
  rw [coeff_mul]
  exact Ideal.sum_mem _ fun x _ => Ideal.mul_mem_right _ _ (h x.1)

omit hY in
theorem coeff_mul_mem_of_forall_right {I : Ideal π“ž} (S : MvPowerSeries Οƒ π“ž) {T : MvPowerSeries Οƒ π“ž}
    (h : βˆ€ m, coeff m T ∈ I) (e : Οƒ β†’β‚€ β„•) : coeff e (S * T) ∈ I := by
  rw [mul_comm]; exact coeff_mul_mem_of_forall_left h S e

theorem evalT_sub_aeval_badPart_mem {S : MvPowerSeries Οƒ π“ž} (hS : Tendsto0 p S) (x : Οƒ β†’ Y) (N : β„•) :
    evalT p hY x S - MvPolynomial.aeval x (badPart p hS N) ∈ Ideal.span {(p : Y) ^ N} := by
  classical
  have hdec : S = (badPart p hS N : MvPowerSeries Οƒ π“ž) + (S - (badPart p hS N : MvPowerSeries Οƒ π“ž)) := by
    ring
  have h1 : evalT p hY x S = evalT p hY x (badPart p hS N : MvPowerSeries Οƒ π“ž) +
      evalT p hY x (S - (badPart p hS N : MvPowerSeries Οƒ π“ž)) := by
    conv_lhs => rw [hdec]
    exact evalT_add p hY (Tendsto0.coe _) (hS.sub (Tendsto0.coe _)) x
  rw [h1, evalT_coe, add_sub_cancel_left]
  exact evalT_mem_of_forall_coeff_mem p hY (hS.sub (Tendsto0.coe _)) x (coeff_sub_badPart_mem p hS N)

theorem evalT_mul [Finite Οƒ] {S T : MvPowerSeries Οƒ π“ž} (hS : Tendsto0 p S) (hT : Tendsto0 p T)
    (x : Οƒ β†’ Y) : evalT p hY x (S * T) = evalT p hY x S * evalT p hY x T := by
  classical
  refine eq_of_forall_sub_mem p hY fun N => ?_
  set PS := badPart p hS N
  set PT := badPart p hT N
  set S' := S - (PS : MvPowerSeries Οƒ π“ž)
  set T' := T - (PT : MvPowerSeries Οƒ π“ž)
  have hS' : Tendsto0 p S' := hS.sub (Tendsto0.coe _)
  have hT' : Tendsto0 p T' := hT.sub (Tendsto0.coe _)
  have hcS' : βˆ€ m, coeff m S' ∈ Ideal.span {(p : π“ž) ^ N} := coeff_sub_badPart_mem p hS N
  have hcT' : βˆ€ m, coeff m T' ∈ Ideal.span {(p : π“ž) ^ N} := coeff_sub_badPart_mem p hT N
  have hdec : S * T = ((PS * PT : MvPolynomial Οƒ π“ž) : MvPowerSeries Οƒ π“ž) +
      ((PS : MvPowerSeries Οƒ π“ž) * T' + S' * T) := by
    simp only [S', T', MvPolynomial.coe_mul]; ring
  have hR : Tendsto0 p ((PS : MvPowerSeries Οƒ π“ž) * T' + S' * T) :=
    ((Tendsto0.coe _).mul hT').add (hS'.mul hT)
  have hcR : βˆ€ m, coeff m ((PS : MvPowerSeries Οƒ π“ž) * T' + S' * T) ∈ Ideal.span {(p : π“ž) ^ N} := by
    intro m
    rw [map_add]
    exact Ideal.add_mem _ (coeff_mul_mem_of_forall_right _ hcT' m) (coeff_mul_mem_of_forall_left hcS' _ m)
  have h1 : evalT p hY x (S * T) = MvPolynomial.aeval x PS * MvPolynomial.aeval x PT +
      evalT p hY x ((PS : MvPowerSeries Οƒ π“ž) * T' + S' * T) := by
    rw [hdec, evalT_add p hY (Tendsto0.coe _) hR, evalT_coe, map_mul]
  have h2 := evalT_mem_of_forall_coeff_mem p hY hR x hcR
  have h3 := evalT_sub_aeval_badPart_mem p hY hS x N
  have h4 := evalT_sub_aeval_badPart_mem p hY hT x N

  have h5 : evalT p hY x S * evalT p hY x T - MvPolynomial.aeval x PS * MvPolynomial.aeval x PT ∈
      Ideal.span {(p : Y) ^ N} := by
    have : evalT p hY x S * evalT p hY x T - MvPolynomial.aeval x PS * MvPolynomial.aeval x PT =
        (evalT p hY x S - MvPolynomial.aeval x PS) * evalT p hY x T +
          MvPolynomial.aeval x PS * (evalT p hY x T - MvPolynomial.aeval x PT) := by ring
    rw [this]
    exact Ideal.add_mem _ (Ideal.mul_mem_right _ _ h3) (Ideal.mul_mem_left _ _ h4)
  rw [h1]
  have : MvPolynomial.aeval x PS * MvPolynomial.aeval x PT +
      evalT p hY x ((PS : MvPowerSeries Οƒ π“ž) * T' + S' * T) - evalT p hY x S * evalT p hY x T =
      evalT p hY x ((PS : MvPowerSeries Οƒ π“ž) * T' + S' * T) -
        (evalT p hY x S * evalT p hY x T - MvPolynomial.aeval x PS * MvPolynomial.aeval x PT) := by ring
  rw [this]
  exact Ideal.sub_mem _ h2 h5

theorem evalT_pow [Finite Οƒ] {S : MvPowerSeries Οƒ π“ž} (hS : Tendsto0 p S) (x : Οƒ β†’ Y) :
    βˆ€ n : β„•, evalT p hY x (S ^ n) = evalT p hY x S ^ n
  | 0 => by rw [pow_zero, pow_zero, evalT_one]
  | n + 1 => by rw [pow_succ, pow_succ, evalT_mul p hY (hS.pow n) hS, evalT_pow hS x n]

omit hY in
theorem tendsto0_aeval [Finite Οƒ] {Ο„ : Type*} (a : Ο„ β†’ MvPowerSeries Οƒ π“ž) (ha : βˆ€ i, Tendsto0 p (a i))
    (P : MvPolynomial Ο„ π“ž) : Tendsto0 p (MvPolynomial.aeval a P) := by
  classical
  induction P using MvPolynomial.induction_on with
  | C c =>
    rw [MvPolynomial.aeval_C, Algebra.algebraMap_eq_smul_one]
    exact Tendsto0.one.smul c
  | add P Q hP hQ => rw [map_add]; exact hP.add hQ
  | mul_X P i hP => rw [map_mul, MvPolynomial.aeval_X]; exact hP.mul (ha i)

theorem evalT_aeval [Finite Οƒ] {Ο„ : Type*} (a : Ο„ β†’ MvPowerSeries Οƒ π“ž) (ha : βˆ€ i, Tendsto0 p (a i))
    (x : Οƒ β†’ Y) (P : MvPolynomial Ο„ π“ž) :
    evalT p hY x (MvPolynomial.aeval a P) = MvPolynomial.aeval (fun i => evalT p hY x (a i)) P := by
  classical
  induction P using MvPolynomial.induction_on with
  | C c =>
    rw [MvPolynomial.aeval_C, MvPolynomial.aeval_C, Algebra.algebraMap_eq_smul_one,
      evalT_smul p hY Tendsto0.one, evalT_one, mul_one]
  | add P Q hP hQ =>
    rw [map_add, map_add, evalT_add p hY (tendsto0_aeval p a ha P) (tendsto0_aeval p a ha Q), hP, hQ]
  | mul_X P i hP =>
    rw [map_mul, MvPolynomial.aeval_X, map_mul, MvPolynomial.aeval_X,
      evalT_mul p hY (tendsto0_aeval p a ha P) (ha i), hP]

omit hY in

theorem tendsto0_subst [Finite Οƒ] {Ο„ : Type*} [Finite Ο„] {a : Ο„ β†’ MvPowerSeries Οƒ π“ž}
    (ha0 : βˆ€ i, constantCoeff (a i) = 0) (ha : βˆ€ i, Tendsto0 p (a i))
    {S : MvPowerSeries Ο„ π“ž} (hS : Tendsto0 p S) : Tendsto0 p (subst a S) := by
  classical
  have has : HasSubst a := hasSubst_of_constantCoeff_zero ha0
  intro N

  have hmon : βˆ€ d : Ο„ β†’β‚€ β„•, Tendsto0 p (d.prod fun s e => a s ^ e) := by
    intro d
    exact Tendsto0.prod _ _ fun s _ => (ha s).pow _
  rw [Filter.eventually_cofinite]
  refine Set.Finite.subset ((hS.bad N).finite_toSet.biUnion fun d _ => (hmon d).finite_setOf N) ?_
  intro e he
  simp only [Set.mem_setOf_eq] at he
  by_contra hcon
  apply he
  rw [coeff_subst has S e, finsum_eq_sum _ (coeff_subst_finite has S e)]
  refine Ideal.sum_mem _ fun d hd => ?_
  by_cases hbad : d ∈ hS.bad N
  Β· have : coeff e (d.prod fun s e => a s ^ e) ∈ Ideal.span {(p : π“ž) ^ N} := by
      by_contra h'
      exact hcon (Set.mem_biUnion (Finset.mem_coe.2 hbad) h')
    rw [smul_eq_mul]
    exact Ideal.mul_mem_left _ _ this
  Β· rw [smul_eq_mul]
    exact Ideal.mul_mem_right _ _ (hS.coeff_mem_of_not_mem_bad hbad)

omit hY in
theorem coeff_subst_mem_of_forall {Ο„ : Type*} {a : Ο„ β†’ MvPowerSeries Οƒ π“ž} (has : HasSubst a)
    {I : Ideal π“ž} {S : MvPowerSeries Ο„ π“ž} (h : βˆ€ d, coeff d S ∈ I) (e : Οƒ β†’β‚€ β„•) :
    coeff e (subst a S) ∈ I := by
  classical
  rw [coeff_subst has S e, finsum_eq_sum _ (coeff_subst_finite has S e)]
  refine Ideal.sum_mem _ fun d _ => ?_
  rw [smul_eq_mul]
  exact Ideal.mul_mem_right _ _ (h d)

theorem evalT_subst [Finite Οƒ] {Ο„ : Type*} [Finite Ο„] {a : Ο„ β†’ MvPowerSeries Οƒ π“ž}
    (ha0 : βˆ€ i, constantCoeff (a i) = 0) (ha : βˆ€ i, Tendsto0 p (a i))
    {S : MvPowerSeries Ο„ π“ž} (hS : Tendsto0 p S) (x : Οƒ β†’ Y) :
    evalT p hY x (subst a S) = evalT p hY (fun i => evalT p hY x (a i)) S := by
  classical
  have has : HasSubst a := hasSubst_of_constantCoeff_zero ha0
  refine eq_of_forall_sub_mem p hY fun N => ?_
  set P := badPart p hS N
  set S' := S - (P : MvPowerSeries Ο„ π“ž)
  have hS' : Tendsto0 p S' := hS.sub (Tendsto0.coe _)
  have hdec : S = (P : MvPowerSeries Ο„ π“ž) + S' := by simp only [S']; ring
  have hsub : subst a S = MvPolynomial.aeval a P + subst a S' := by
    conv_lhs => rw [hdec]
    rw [subst_add has, subst_coe]
  have hS'sub : Tendsto0 p (subst a S') := tendsto0_subst p ha0 ha hS'
  have h1 : evalT p hY x (subst a S) = MvPolynomial.aeval (fun i => evalT p hY x (a i)) P +
      evalT p hY x (subst a S') := by
    rw [hsub, evalT_add p hY (tendsto0_aeval p a ha P) hS'sub, evalT_aeval p hY a ha]
  have h2 : evalT p hY x (subst a S') ∈ Ideal.span {(p : Y) ^ N} :=
    evalT_mem_of_forall_coeff_mem p hY hS'sub x
      (coeff_subst_mem_of_forall has (coeff_sub_badPart_mem p hS N))
  have h3 := evalT_sub_aeval_badPart_mem p hY hS (fun i => evalT p hY x (a i)) N
  rw [h1]
  have : MvPolynomial.aeval (fun i => evalT p hY x (a i)) P + evalT p hY x (subst a S') -
      evalT p hY (fun i => evalT p hY x (a i)) S =
      evalT p hY x (subst a S') - (evalT p hY (fun i => evalT p hY x (a i)) S -
        MvPolynomial.aeval (fun i => evalT p hY x (a i)) P) := by ring
  rw [this]
  exact Ideal.sub_mem _ h2 h3

end Eval

end MvPowerSeries.Restricted

Statements phrased using this module (0)

No statement module imports it directly (it is used through other definition modules or by proofs).