Skip to content

Commit 044efe5

Browse files
feat(RingTheory/MvPowerSeries): partial derivatives of MvPowerSeries (#39626)
Previously, we had formal derivatives for `PowerSeries` and `Polynomial` and formal partial derivatives for `MvPolynomial`, but no formal partial derivatives for `MvPowerSeries`. This PR adds them. Furthermore, `PowerSeries.derivative` is refactored to be defined in terms of `MvPowerSeries.pderiv`, which reduces code duplication (In particular, there is no need to define the bare function `PowerSeries.derivativeFun` anymore). Most proofs are direct generalizations from the univariate case. I only had to add a few missing API lemmas, which I am PR'ing separately below: - [x] depends on: #39623 - [x] depends on: #39624 - [x] depends on: #39625
1 parent 74f793c commit 044efe5

4 files changed

Lines changed: 326 additions & 132 deletions

File tree

Mathlib.lean

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6830,6 +6830,7 @@ public import Mathlib.RingTheory.MvPolynomial.Symmetric.NewtonIdentities
68306830
public import Mathlib.RingTheory.MvPolynomial.Tower
68316831
public import Mathlib.RingTheory.MvPolynomial.WeightedHomogeneous
68326832
public import Mathlib.RingTheory.MvPowerSeries.Basic
6833+
public import Mathlib.RingTheory.MvPowerSeries.Derivative
68336834
public import Mathlib.RingTheory.MvPowerSeries.Equiv
68346835
public import Mathlib.RingTheory.MvPowerSeries.Evaluation
68356836
public import Mathlib.RingTheory.MvPowerSeries.Expand
Lines changed: 209 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,209 @@
1+
/-
2+
Copyright (c) 2026 Justus Springer. All rights reserved.
3+
Released under Apache 2.0 license as described in the file LICENSE.
4+
Authors: Justus Springer
5+
-/
6+
module
7+
8+
public import Mathlib.Algebra.MvPolynomial.PDeriv
9+
public import Mathlib.RingTheory.MvPowerSeries.Inverse
10+
public import Mathlib.RingTheory.MvPowerSeries.Trunc
11+
12+
/-!
13+
# Formal partial derivatives of multivariate power series
14+
15+
This file defines `MvPowerSeries.pderiv R i`, the formal partial derivative of a multivariate
16+
power series with respect to variable `i`, as a
17+
`Derivation R (MvPowerSeries σ R) (MvPowerSeries σ R)`.
18+
19+
See also `PowerSeries.derivative` for the univariate setting.
20+
21+
## Main definitions
22+
23+
- `MvPowerSeries.pderiv R i`: the formal partial derivative with respect to `i`, as a derivation.
24+
25+
## Main results
26+
27+
- `MvPowerSeries.coeff_pderiv`: coefficient formula
28+
`coeff n (pderiv R i f) = coeff (n + single i 1) f * (n i + 1)`.
29+
- `MvPowerSeries.pderiv_coe`: compatibility with `MvPolynomial.pderiv`.
30+
- `MvPowerSeries.trunc_pderiv`: truncation commutes with partial differentiation.
31+
- `MvPowerSeries.pderiv.ext`: a power series is determined by its constant term and its partial
32+
derivatives.
33+
- `MvPowerSeries.pderiv_pow`: power rule.
34+
- `MvPowerSeries.pderiv_inv`, `MvPowerSeries.pderiv_inv'`: derivative of an inverse.
35+
36+
-/
37+
38+
@[expose] public section
39+
40+
namespace MvPowerSeries
41+
42+
open MvPolynomial Finsupp
43+
44+
variable {σ R : Type*}
45+
46+
section Semiring
47+
48+
variable [Semiring R]
49+
50+
/-- The underlying function of the formal partial derivative with respect to variable `i`.
51+
This is packaged as a derivation in `MvPowerSeries.pderiv`. -/
52+
noncomputable def pderivFun (i : σ) (f : MvPowerSeries σ R) : MvPowerSeries σ R :=
53+
fun d ↦ coeff (d + single i 1) f * (d i + 1)
54+
55+
theorem coeff_pderivFun {i : σ} (f : MvPowerSeries σ R) (d : σ →₀ ℕ) :
56+
coeff d (f.pderivFun i) = coeff (d + single i 1) f * (d i + 1) := by
57+
rfl
58+
59+
theorem pderivFun_add {i : σ} (f g : MvPowerSeries σ R) :
60+
pderivFun i (f + g) = pderivFun i f + pderivFun i g := by
61+
ext
62+
rw [coeff_pderivFun, map_add, map_add, coeff_pderivFun, coeff_pderivFun, add_mul]
63+
64+
theorem pderivFun_C {i : σ} (r : R) : pderivFun i (C r) = 0 := by
65+
ext n
66+
rw [coeff_pderivFun, coeff_add_single_C, zero_mul, (coeff n).map_zero]
67+
68+
theorem pderivFun_one {i : σ} : pderivFun i (1 : MvPowerSeries σ R) = 0 := by
69+
rw [← map_one C, pderivFun_C (1 : R)]
70+
71+
end Semiring
72+
73+
section CommSemiring
74+
75+
variable [CommSemiring R]
76+
77+
private theorem pderivFun_coe {i : σ} (f : MvPolynomial σ R) :
78+
(f : MvPowerSeries σ R).pderivFun i = f.pderiv i := by
79+
ext
80+
rw [coeff_pderivFun, coeff_coe, coeff_coe, coeff_pderiv]
81+
82+
private theorem trunc_pderivFun [DecidableEq σ] {i : σ} (f : MvPowerSeries σ R) (n : σ →₀ ℕ) :
83+
trunc R n (pderivFun i f) = pderiv i (trunc R (n + single i 1) f) := by
84+
ext
85+
rw [coeff_trunc]
86+
split_ifs with h
87+
· rw [coeff_pderivFun, coeff_pderiv, coeff_trunc, if_pos (add_lt_add_left h _)]
88+
· rw [coeff_pderiv, coeff_trunc, if_neg ((add_lt_add_iff_right _).not.mpr h), zero_mul]
89+
90+
-- A special case of `pderivFun_mul`, used in its proof.
91+
private theorem pderivFun_coe_mul_coe {i : σ} (f g : MvPolynomial σ R) :
92+
pderivFun i (f * g : MvPowerSeries σ R) = f * pderiv i g + g * pderiv i f := by
93+
rw [← coe_mul, pderivFun_coe, pderiv_mul, add_comm, mul_comm _ g, ← coe_mul, ← coe_mul,
94+
MvPolynomial.coe_add]
95+
96+
private theorem pderivFun_mul {i : σ} (f g : MvPowerSeries σ R) :
97+
pderivFun i (f * g) = f • g.pderivFun i + g • f.pderivFun i := by
98+
classical
99+
ext n
100+
have h₁ : n < n + single i 1 := lt_def.mpr ⟨self_le_add_right _ _, i, by simp⟩
101+
have h₂ : n + single i 1 < n + single i 1 + single i 1 :=
102+
lt_def.mpr ⟨self_le_add_right _ _, i, by simp⟩
103+
have h₃ : n < n + single i 1 + single i 1 := lt_trans h₁ h₂
104+
rw [coeff_pderivFun, map_add, ← coeff_trunc_mul_trunc_eq_coeff_mul _ _ _ h₂, smul_eq_mul,
105+
smul_eq_mul, ← coeff_trunc_mul_trunc_eq_coeff_mul₂ _ _ g (f.pderivFun i) h₃ h₁,
106+
← coeff_trunc_mul_trunc_eq_coeff_mul₂ _ _ f (g.pderivFun i) h₃ h₁, trunc_pderivFun,
107+
trunc_pderivFun, ← coeff_coe, ← coeff_coe, ← coeff_coe, ← map_add, coe_mul, coe_mul, coe_mul,
108+
← pderivFun_coe_mul_coe, coeff_pderivFun]
109+
110+
private theorem pderivFun_smul {i : σ} (r : R) (f : MvPowerSeries σ R) :
111+
pderivFun i (r • f) = r • pderivFun i f := by
112+
rw [smul_eq_C_mul, smul_eq_C_mul, pderivFun_mul, pderivFun_C, smul_zero, add_zero, smul_eq_mul]
113+
114+
variable (R) in
115+
/-- The formal partial derivative of a multivariate formal power series with respect to
116+
variable `i`, as an `R`-derivation on `MvPowerSeries σ R`. -/
117+
@[no_expose]
118+
noncomputable def pderiv (i : σ) : Derivation R (MvPowerSeries σ R) (MvPowerSeries σ R) where
119+
toFun := pderivFun i
120+
map_add' := pderivFun_add
121+
map_smul' := pderivFun_smul
122+
map_one_eq_zero' := pderivFun_one
123+
leibniz' := pderivFun_mul
124+
125+
@[simp] theorem pderiv_C {i : σ} {r : R} : pderiv R i (C r) = 0 := pderivFun_C r
126+
127+
theorem pderiv_one {i : σ} : pderiv R i 1 = 0 := pderiv_C
128+
129+
theorem coeff_pderiv {i : σ} (f : MvPowerSeries σ R) (n : σ →₀ ℕ) :
130+
coeff n (pderiv R i f) = coeff (n + single i 1) f * (n i + 1) :=
131+
coeff_pderivFun f n
132+
133+
theorem pderiv_coe {i : σ} (f : MvPolynomial σ R) :
134+
pderiv R i f = MvPolynomial.pderiv i f := pderivFun_coe f
135+
136+
@[simp]
137+
theorem pderiv_X_self {i : σ} : pderiv R i (X i) = 1 := by
138+
classical
139+
ext n
140+
simp only [coeff_pderiv, coeff_X, boole_mul, add_eq_right, coeff_one]
141+
split_ifs <;> simp_all
142+
143+
@[simp]
144+
theorem pderiv_X_of_ne {i j : σ} (h : j ≠ i) : pderiv R i (X j) = 0 := by
145+
classical
146+
ext n
147+
simpa only [coeff_pderiv, coeff_X, boole_mul, coeff_zero] using
148+
if_neg (ne_iff.mpr ⟨i, by grind [Finsupp.add_apply]⟩)
149+
150+
theorem pderiv_X [DecidableEq σ] (i j : σ) :
151+
pderiv R i (X j) = Pi.single (M := fun _ => MvPowerSeries σ R) i 1 j := by
152+
by_cases h : i = j
153+
· subst h; simp only [pderiv_X_self, Pi.single_eq_same]
154+
· grind [pderiv_X_of_ne]
155+
156+
theorem trunc_pderiv [DecidableEq σ] {i : σ} (f : MvPowerSeries σ R) (n : σ →₀ ℕ) :
157+
trunc R n (pderiv R i f) = MvPolynomial.pderiv i (trunc R (n + single i 1) f) :=
158+
trunc_pderivFun ..
159+
160+
/-- The partial derivative of `g^n` equals `n * g^(n-1) * g'`. -/
161+
theorem pderiv_pow {i : σ} (g : MvPowerSeries σ R) (n : ℕ) :
162+
pderiv R i (g ^ n) = n * g ^ (n - 1) * pderiv R i g := by
163+
rw [Derivation.leibniz_pow, smul_eq_mul, nsmul_eq_mul, mul_assoc]
164+
165+
end CommSemiring
166+
167+
/-- If `f` and `g` have the same constant term and all partial derivatives, then they are equal.
168+
169+
The `CommRing` assumption is needed because the proof uses `smul_right_inj`, which requires
170+
cancellation of addition in `R`; `IsAddTorsionFree` alone does not suffice. -/
171+
theorem pderiv.ext [CommRing R] [IsAddTorsionFree R] {f g : MvPowerSeries σ R}
172+
(hD : ∀ i, pderiv R i f = pderiv R i g) (hc : constantCoeff f = constantCoeff g) : f = g := by
173+
ext n
174+
by_cases h : n = 0
175+
· rw [h, coeff_zero_eq_constantCoeff, hc]
176+
obtain ⟨i, hi : n i ≠ 0⟩ := ne_iff.mp h
177+
have : single i 1 ≤ n := fun j ↦ by
178+
by_cases hj : j = i <;> grind [single_eq_same, single_eq_of_ne]
179+
have e := congr(coeff (n - single i 1) $(hD i))
180+
rwa [coeff_pderiv, coeff_pderiv, tsub_add_cancel_of_le this, coe_tsub, Pi.sub_apply,
181+
single_eq_same, Nat.cast_sub (Nat.one_le_iff_ne_zero.mpr hi), Nat.cast_one, sub_add_cancel,
182+
mul_comm, ← nsmul_eq_mul, mul_comm, ← nsmul_eq_mul, smul_right_inj hi] at e
183+
184+
@[simp]
185+
theorem pderiv_inv {i : σ} [CommRing R] (f : (MvPowerSeries σ R)ˣ) :
186+
pderiv R i ↑f⁻¹ = -(↑f⁻¹ : MvPowerSeries σ R) ^ 2 * pderiv R i f :=
187+
(pderiv R i).leibniz_of_mul_eq_one f.inv_mul
188+
189+
@[simp]
190+
theorem pderiv_invOf {i : σ} [CommRing R] (f : MvPowerSeries σ R) [Invertible f] :
191+
pderiv R i ⅟f = -⅟f ^ 2 * pderiv R i f :=
192+
(pderiv R i).leibniz_invOf f
193+
194+
/-
195+
The following theorem is stated only in the case that `R` is a field. This is because
196+
there is currently no instance of `Inv (MvPowerSeries σ R)` for more general base rings `R`.
197+
-/
198+
199+
@[simp]
200+
theorem pderiv_inv' {i : σ} [Field R] (f : MvPowerSeries σ R) :
201+
pderiv R i f⁻¹ = -f⁻¹ ^ 2 * pderiv R i f := by
202+
by_cases h : constantCoeff f = 0
203+
· suffices f⁻¹ = 0 by
204+
rw [this, pow_two, zero_mul, neg_zero, zero_mul, map_zero]
205+
rwa [MvPowerSeries.inv_eq_zero]
206+
apply Derivation.leibniz_of_mul_eq_one
207+
exact MvPowerSeries.inv_mul_cancel (h := h)
208+
209+
end MvPowerSeries

0 commit comments

Comments
 (0)