Skip to content

Commit 482cd79

Browse files
committed
chore: move algebraic properties of Finsupp.single to Algebra.Group.Finsupp (#28073)
They do not belong under `Data` as they are not about a datatype.
1 parent cd49593 commit 482cd79

File tree

6 files changed

+242
-246
lines changed

6 files changed

+242
-246
lines changed

Mathlib/Algebra/Group/Finsupp.lean

Lines changed: 236 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -4,22 +4,31 @@ Released under Apache 2.0 license as described in the file LICENSE.
44
Authors: Johannes Hölzl, Kim Morrison
55
-/
66
import Mathlib.Algebra.Group.Equiv.Defs
7-
import Mathlib.Algebra.Group.InjSurj
8-
import Mathlib.Algebra.Group.Pi.Basic
9-
import Mathlib.Data.Finsupp.Defs
7+
import Mathlib.Data.Finset.Max
8+
import Mathlib.Data.Finsupp.Single
109
import Mathlib.Tactic.FastInstance
1110

1211
/-!
1312
# Additive monoid structure on `ι →₀ M`
1413
-/
1514

15+
assert_not_exists MonoidWithZero
16+
1617
open Finset
1718

1819
noncomputable section
1920

20-
variable {ι F M N G H : Type*}
21+
variable {ι F M N O G H : Type*}
2122

2223
namespace Finsupp
24+
section Zero
25+
variable [Zero M] [Zero N]
26+
27+
lemma apply_single [FunLike F M N] [ZeroHomClass F M N] (e : F) (i : ι) (m : M) (b : ι) :
28+
e (single i m b) = single i (e m) b := apply_single' e (map_zero e) i m b
29+
30+
end Zero
31+
2332
section AddZeroClass
2433
variable [AddZeroClass M] [AddZeroClass N] {f : M → N} {g₁ g₂ : ι →₀ M}
2534

@@ -105,6 +114,171 @@ def embDomain.addMonoidHom (f : ι ↪ F) : (ι →₀ M) →+ F →₀ M where
105114
lemma embDomain_add (f : ι ↪ F) (v w : ι →₀ M) :
106115
embDomain f (v + w) = embDomain f v + embDomain f w := (embDomain.addMonoidHom f).map_add v w
107116

117+
@[simp]
118+
lemma single_add (a : ι) (b₁ b₂ : M) : single a (b₁ + b₂) = single a b₁ + single a b₂ :=
119+
(zipWith_single_single _ _ _ _ _).symm
120+
121+
lemma single_add_apply (a : ι) (m₁ m₂ : M) (b : ι) :
122+
single a (m₁ + m₂) b = single a m₁ b + single a m₂ b := by simp
123+
124+
lemma support_single_add {a : ι} {b : M} {f : ι →₀ M} (ha : a ∉ f.support) (hb : b ≠ 0) :
125+
support (single a b + f) = cons a f.support ha := by
126+
classical
127+
have H := support_single_ne_zero a hb
128+
rw [support_add_eq, H, cons_eq_insert, insert_eq]
129+
rwa [H, disjoint_singleton_left]
130+
131+
lemma support_add_single {a : ι} {b : M} {f : ι →₀ M} (ha : a ∉ f.support) (hb : b ≠ 0) :
132+
support (f + single a b) = cons a f.support ha := by
133+
classical
134+
have H := support_single_ne_zero a hb
135+
rw [support_add_eq, H, union_comm, cons_eq_insert, insert_eq]
136+
rwa [H, disjoint_singleton_right]
137+
138+
lemma _root_.AddEquiv.finsuppUnique_symm {M : Type*} [AddZeroClass M] (d : M) :
139+
AddEquiv.finsuppUnique.symm d = single () d := by
140+
rw [Finsupp.unique_single (AddEquiv.finsuppUnique.symm d), Finsupp.unique_single_eq_iff]
141+
simp [AddEquiv.finsuppUnique]
142+
143+
/-- `Finsupp.single` as an `AddMonoidHom`.
144+
145+
See `Finsupp.lsingle` in `Mathlib/LinearAlgebra/Finsupp/Defs.lean` for the stronger version as a
146+
linear map. -/
147+
@[simps]
148+
def singleAddHom (a : ι) : M →+ ι →₀ M where
149+
toFun := single a
150+
map_zero' := single_zero a
151+
map_add' := single_add a
152+
153+
lemma update_eq_single_add_erase (f : ι →₀ M) (a : ι) (b : M) :
154+
f.update a b = single a b + f.erase a := by
155+
classical
156+
ext j
157+
rcases eq_or_ne a j with (rfl | h)
158+
· simp
159+
· simp [h, erase_ne, h.symm]
160+
161+
lemma update_eq_erase_add_single (f : ι →₀ M) (a : ι) (b : M) :
162+
f.update a b = f.erase a + single a b := by
163+
classical
164+
ext j
165+
rcases eq_or_ne a j with (rfl | h)
166+
· simp
167+
· simp [h, erase_ne, h.symm]
168+
169+
lemma single_add_erase (a : ι) (f : ι →₀ M) : single a (f a) + f.erase a = f := by
170+
rw [← update_eq_single_add_erase, update_self]
171+
172+
lemma erase_add_single (a : ι) (f : ι →₀ M) : f.erase a + single a (f a) = f := by
173+
rw [← update_eq_erase_add_single, update_self]
174+
175+
@[simp]
176+
lemma erase_add (a : ι) (f f' : ι →₀ M) : erase a (f + f') = erase a f + erase a f' := by
177+
ext s; by_cases hs : s = a
178+
· rw [hs, add_apply, erase_same, erase_same, erase_same, add_zero]
179+
rw [add_apply, erase_ne hs, erase_ne hs, erase_ne hs, add_apply]
180+
181+
/-- `Finsupp.erase` as an `AddMonoidHom`. -/
182+
@[simps]
183+
def eraseAddHom (a : ι) : (ι →₀ M) →+ ι →₀ M where
184+
toFun := erase a
185+
map_zero' := erase_zero a
186+
map_add' := erase_add a
187+
188+
@[elab_as_elim]
189+
protected lemma induction {motive : (ι →₀ M) → Prop} (f : ι →₀ M) (zero : motive 0)
190+
(single_add : ∀ (a b) (f : ι →₀ M),
191+
a ∉ f.support → b ≠ 0 → motive f → motive (single a b + f)) : motive f :=
192+
suffices ∀ (s) (f : ι →₀ M), f.support = s → motive f from this _ _ rfl
193+
fun s =>
194+
Finset.cons_induction_on s (fun f hf => by rwa [support_eq_empty.1 hf]) fun a s has ih f hf => by
195+
suffices motive (single a (f a) + f.erase a) by rwa [single_add_erase] at this
196+
classical
197+
apply single_add
198+
· rw [support_erase, mem_erase]
199+
exact fun H => H.1 rfl
200+
· rw [← mem_support_iff, hf]
201+
exact mem_cons_self _ _
202+
· apply ih _ _
203+
rw [support_erase, hf, Finset.erase_cons]
204+
205+
@[elab_as_elim]
206+
lemma induction₂ {motive : (ι →₀ M) → Prop} (f : ι →₀ M) (zero : motive 0)
207+
(add_single : ∀ (a b) (f : ι →₀ M),
208+
a ∉ f.support → b ≠ 0 → motive f → motive (f + single a b)) : motive f :=
209+
suffices ∀ (s) (f : ι →₀ M), f.support = s → motive f from this _ _ rfl
210+
fun s =>
211+
Finset.cons_induction_on s (fun f hf => by rwa [support_eq_empty.1 hf]) fun a s has ih f hf => by
212+
suffices motive (f.erase a + single a (f a)) by rwa [erase_add_single] at this
213+
classical
214+
apply add_single
215+
· rw [support_erase, mem_erase]
216+
exact fun H => H.1 rfl
217+
· rw [← mem_support_iff, hf]
218+
exact mem_cons_self _ _
219+
· apply ih _ _
220+
rw [support_erase, hf, Finset.erase_cons]
221+
222+
@[elab_as_elim]
223+
lemma induction_linear {motive : (ι →₀ M) → Prop} (f : ι →₀ M) (zero : motive 0)
224+
(add : ∀ f g : ι →₀ M, motive f → motive g → motive (f + g))
225+
(single : ∀ a b, motive (single a b)) : motive f :=
226+
induction₂ f zero fun _a _b _f _ _ w => add _ _ w (single _ _)
227+
228+
section LinearOrder
229+
230+
variable [LinearOrder ι] {p : (ι →₀ M) → Prop}
231+
232+
/-- A finitely supported function can be built by adding up `single a b` for increasing `a`.
233+
234+
The lemma `induction_on_max₂` swaps the argument order in the sum. -/
235+
lemma induction_on_max (f : ι →₀ M) (h0 : p 0)
236+
(ha : ∀ (a b) (f : ι →₀ M), (∀ c ∈ f.support, c < a) → b ≠ 0 → p f → p (single a b + f)) :
237+
p f := by
238+
suffices ∀ (s) (f : ι →₀ M), f.support = s → p f from this _ _ rfl
239+
refine fun s => s.induction_on_max (fun f h => ?_) (fun a s hm hf f hs => ?_)
240+
· rwa [support_eq_empty.1 h]
241+
· have hs' : (erase a f).support = s := by
242+
rw [support_erase, hs, erase_insert (fun ha => (hm a ha).false)]
243+
rw [← single_add_erase a f]
244+
refine ha _ _ _ (fun c hc => hm _ <| hs'.symm ▸ hc) ?_ (hf _ hs')
245+
rw [← mem_support_iff, hs]
246+
exact mem_insert_self a s
247+
248+
/-- A finitely supported function can be built by adding up `single a b` for decreasing `a`.
249+
250+
The lemma `induction_on_min₂` swaps the argument order in the sum. -/
251+
lemma induction_on_min (f : ι →₀ M) (h0 : p 0)
252+
(ha : ∀ (a b) (f : ι →₀ M), (∀ c ∈ f.support, a < c) → b ≠ 0 → p f → p (single a b + f)) :
253+
p f :=
254+
induction_on_max (ι := ιᵒᵈ) f h0 ha
255+
256+
/-- A finitely supported function can be built by adding up `single a b` for increasing `a`.
257+
258+
The lemma `induction_on_max` swaps the argument order in the sum. -/
259+
lemma induction_on_max₂ (f : ι →₀ M) (h0 : p 0)
260+
(ha : ∀ (a b) (f : ι →₀ M), (∀ c ∈ f.support, c < a) → b ≠ 0 → p f → p (f + single a b)) :
261+
p f := by
262+
suffices ∀ (s) (f : ι →₀ M), f.support = s → p f from this _ _ rfl
263+
refine fun s => s.induction_on_max (fun f h => ?_) (fun a s hm hf f hs => ?_)
264+
· rwa [support_eq_empty.1 h]
265+
· have hs' : (erase a f).support = s := by
266+
rw [support_erase, hs, erase_insert (fun ha => (hm a ha).false)]
267+
rw [← erase_add_single a f]
268+
refine ha _ _ _ (fun c hc => hm _ <| hs'.symm ▸ hc) ?_ (hf _ hs')
269+
rw [← mem_support_iff, hs]
270+
exact mem_insert_self a s
271+
272+
/-- A finitely supported function can be built by adding up `single a b` for decreasing `a`.
273+
274+
The lemma `induction_on_min` swaps the argument order in the sum. -/
275+
lemma induction_on_min₂ (f : ι →₀ M) (h0 : p 0)
276+
(ha : ∀ (a b) (f : ι →₀ M), (∀ c ∈ f.support, a < c) → b ≠ 0 → p f → p (f + single a b)) :
277+
p f :=
278+
induction_on_max₂ (ι := ιᵒᵈ) f h0 ha
279+
280+
end LinearOrder
281+
108282
end AddZeroClass
109283

110284
section AddMonoid
@@ -119,10 +293,22 @@ instance instAddMonoid : AddMonoid (ι →₀ M) :=
119293

120294
end AddMonoid
121295

122-
instance instAddCommMonoid [AddCommMonoid M] : AddCommMonoid (ι →₀ M) :=
296+
section AddCommMonoid
297+
variable [AddCommMonoid M]
298+
299+
instance instAddCommMonoid : AddCommMonoid (ι →₀ M) :=
123300
fast_instance% DFunLike.coe_injective.addCommMonoid
124301
DFunLike.coe coe_zero coe_add (fun _ _ => rfl)
125302

303+
lemma single_add_single_eq_single_add_single {k l m n : ι} {u v : M} (hu : u ≠ 0) (hv : v ≠ 0) :
304+
single k u + single l v = single m u + single n v ↔
305+
(k = m ∧ l = n) ∨ (u = v ∧ k = n ∧ l = m) ∨ (u + v = 0 ∧ k = l ∧ m = n) := by
306+
classical
307+
simp_rw [DFunLike.ext_iff, coe_add, single_eq_pi_single, ← funext_iff]
308+
exact Pi.single_add_single_eq_single_add_single hu hv
309+
310+
end AddCommMonoid
311+
126312
instance instNeg [NegZeroClass G] : Neg (ι →₀ G) where neg := mapRange Neg.neg neg_zero
127313

128314
@[simp, norm_cast] lemma coe_neg [NegZeroClass G] (g : ι →₀ G) : ⇑(-g) = -g := rfl
@@ -134,11 +320,6 @@ lemma mapRange_neg [NegZeroClass G] [NegZeroClass H] {f : G → H} {hf : f 0 = 0
134320
(hf' : ∀ x, f (-x) = -f x) (v : ι →₀ G) : mapRange f hf (-v) = -mapRange f hf v :=
135321
ext fun _ => by simp only [hf', neg_apply, mapRange_apply]
136322

137-
lemma mapRange_neg' [AddGroup G] [SubtractionMonoid H] [FunLike F G H] [AddMonoidHomClass F G H]
138-
{f : F} (v : ι →₀ G) :
139-
mapRange f (map_zero f) (-v) = -mapRange f (map_zero f) v :=
140-
mapRange_neg (map_neg f) v
141-
142323
instance instSub [SubNegZeroMonoid G] : Sub (ι →₀ G) :=
143324
⟨zipWith Sub.sub (sub_zero _)⟩
144325

@@ -151,35 +332,70 @@ lemma mapRange_sub [SubNegZeroMonoid G] [SubNegZeroMonoid H] {f : G → H} {hf :
151332
mapRange f hf (v₁ - v₂) = mapRange f hf v₁ - mapRange f hf v₂ :=
152333
ext fun _ => by simp only [hf', sub_apply, mapRange_apply]
153334

154-
lemma mapRange_sub' [AddGroup G] [SubtractionMonoid H] [FunLike F G H] [AddMonoidHomClass F G H]
335+
section AddGroup
336+
variable [AddGroup G] {p : ι → Prop} {v v' : ι →₀ G}
337+
338+
lemma mapRange_neg' [SubtractionMonoid H] [FunLike F G H] [AddMonoidHomClass F G H]
339+
{f : F} (v : ι →₀ G) :
340+
mapRange f (map_zero f) (-v) = -mapRange f (map_zero f) v :=
341+
mapRange_neg (map_neg f) v
342+
343+
lemma mapRange_sub' [SubtractionMonoid H] [FunLike F G H] [AddMonoidHomClass F G H]
155344
{f : F} (v₁ v₂ : ι →₀ G) :
156345
mapRange f (map_zero f) (v₁ - v₂) = mapRange f (map_zero f) v₁ - mapRange f (map_zero f) v₂ :=
157346
mapRange_sub (map_sub f) v₁ v₂
158347

159348
/-- Note the general `SMul` instance for `Finsupp` doesn't apply as `ℤ` is not distributive
160349
unless `F i`'s addition is commutative. -/
161-
instance instIntSMul [AddGroup G] : SMul ℤ (ι →₀ G) :=
350+
instance instIntSMul : SMul ℤ (ι →₀ G) :=
162351
fun n v => v.mapRange (n • ·) (zsmul_zero _)⟩
163352

164-
instance instAddGroup [AddGroup G] : AddGroup (ι →₀ G) :=
353+
instance instAddGroup : AddGroup (ι →₀ G) :=
165354
fast_instance% DFunLike.coe_injective.addGroup DFunLike.coe coe_zero coe_add coe_neg coe_sub
166355
(fun _ _ => rfl) fun _ _ => rfl
167356

168-
instance instAddCommGroup [AddCommGroup G] : AddCommGroup (ι →₀ G) :=
169-
fast_instance% DFunLike.coe_injective.addCommGroup DFunLike.coe coe_zero coe_add coe_neg coe_sub
170-
(fun _ _ => rfl) fun _ _ => rfl
171-
172357
@[simp]
173-
lemma support_neg [AddGroup G] (f : ι →₀ G) : support (-f) = support f :=
358+
lemma support_neg (f : ι →₀ G) : support (-f) = support f :=
174359
Finset.Subset.antisymm support_mapRange
175360
(calc
176361
support f = support (- -f) := congr_arg support (neg_neg _).symm
177362
_ ⊆ support (-f) := support_mapRange
178363
)
179364

180-
lemma support_sub [DecidableEq ι] [AddGroup G] {f g : ι →₀ G} :
181-
support (f - g) ⊆ support f ∪ support g := by
365+
lemma support_sub [DecidableEq ι] {f g : ι →₀ G} : support (f - g) ⊆ support f ∪ support g := by
182366
rw [sub_eq_add_neg, ← support_neg g]
183367
exact support_add
184368

369+
lemma erase_eq_sub_single (f : ι →₀ G) (a : ι) : f.erase a = f - single a (f a) := by
370+
ext a'
371+
rcases eq_or_ne a a' with (rfl | h)
372+
· simp
373+
· simp [erase_ne h.symm, single_eq_of_ne h]
374+
375+
lemma update_eq_sub_add_single (f : ι →₀ G) (a : ι) (b : G) :
376+
f.update a b = f - single a (f a) + single a b := by
377+
rw [update_eq_erase_add_single, erase_eq_sub_single]
378+
379+
@[simp]
380+
lemma single_neg (a : ι) (b : G) : single a (-b) = -single a b :=
381+
(singleAddHom a : G →+ _).map_neg b
382+
383+
@[simp]
384+
lemma single_sub (a : ι) (b₁ b₂ : G) : single a (b₁ - b₂) = single a b₁ - single a b₂ :=
385+
(singleAddHom a : G →+ _).map_sub b₁ b₂
386+
387+
@[simp]
388+
lemma erase_neg (a : ι) (f : ι →₀ G) : erase a (-f) = -erase a f :=
389+
(eraseAddHom a : (_ →₀ G) →+ _).map_neg f
390+
391+
@[simp]
392+
lemma erase_sub (a : ι) (f₁ f₂ : ι →₀ G) : erase a (f₁ - f₂) = erase a f₁ - erase a f₂ :=
393+
(eraseAddHom a : (_ →₀ G) →+ _).map_sub f₁ f₂
394+
395+
end AddGroup
396+
397+
instance instAddCommGroup [AddCommGroup G] : AddCommGroup (ι →₀ G) :=
398+
fast_instance% DFunLike.coe_injective.addCommGroup DFunLike.coe coe_zero coe_add coe_neg coe_sub
399+
(fun _ _ => rfl) fun _ _ => rfl
400+
185401
end Finsupp

Mathlib/Data/Finsupp/Ext.lean

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,9 @@ Copyright (c) 2017 Johannes Hölzl. All rights reserved.
33
Released under Apache 2.0 license as described in the file LICENSE.
44
Authors: Johannes Hölzl, Kim Morrison
55
-/
6+
import Mathlib.Algebra.Group.Finsupp
67
import Mathlib.Algebra.Group.Submonoid.Basic
78
import Mathlib.Algebra.Group.TypeTags.Hom
8-
import Mathlib.Data.Finsupp.Single
99

1010
/-!
1111
# Extensionality for maps on `Finsupp`

Mathlib/Data/Finsupp/Pointwise.lean

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,10 @@ Copyright (c) 2020 Kim Morrison. All rights reserved.
33
Released under Apache 2.0 license as described in the file LICENSE.
44
Authors: Kim Morrison
55
-/
6+
import Mathlib.Algebra.Group.Finsupp
67
import Mathlib.Algebra.Module.Defs
78
import Mathlib.Algebra.Ring.InjSurj
89
import Mathlib.Algebra.Ring.Pi
9-
import Mathlib.Data.Finsupp.Single
1010

1111
/-!
1212
# The pointwise product on `Finsupp`.

Mathlib/Data/Finsupp/SMulWithZero.lean

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@ Released under Apache 2.0 license as described in the file LICENSE.
44
Authors: Johannes Hölzl, Kim Morrison
55
-/
66
import Mathlib.Algebra.Group.Action.Pi
7+
import Mathlib.Algebra.Group.Finsupp
78
import Mathlib.Algebra.GroupWithZero.Action.Defs
8-
import Mathlib.Data.Finsupp.Single
99

1010
/-!
1111
# Scalar multiplication on `Finsupp`

0 commit comments

Comments
 (0)