@@ -4,22 +4,31 @@ Released under Apache 2.0 license as described in the file LICENSE.
4
4
Authors: Johannes Hölzl, Kim Morrison
5
5
-/
6
6
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
10
9
import Mathlib.Tactic.FastInstance
11
10
12
11
/-!
13
12
# Additive monoid structure on `ι →₀ M`
14
13
-/
15
14
15
+ assert_not_exists MonoidWithZero
16
+
16
17
open Finset
17
18
18
19
noncomputable section
19
20
20
- variable {ι F M N G H : Type *}
21
+ variable {ι F M N O G H : Type *}
21
22
22
23
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
+
23
32
section AddZeroClass
24
33
variable [AddZeroClass M] [AddZeroClass N] {f : M → N} {g₁ g₂ : ι →₀ M}
25
34
@@ -105,6 +114,171 @@ def embDomain.addMonoidHom (f : ι ↪ F) : (ι →₀ M) →+ F →₀ M where
105
114
lemma embDomain_add (f : ι ↪ F) (v w : ι →₀ M) :
106
115
embDomain f (v + w) = embDomain f v + embDomain f w := (embDomain.addMonoidHom f).map_add v w
107
116
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
+
108
282
end AddZeroClass
109
283
110
284
section AddMonoid
@@ -119,10 +293,22 @@ instance instAddMonoid : AddMonoid (ι →₀ M) :=
119
293
120
294
end AddMonoid
121
295
122
- instance instAddCommMonoid [AddCommMonoid M] : AddCommMonoid (ι →₀ M) :=
296
+ section AddCommMonoid
297
+ variable [AddCommMonoid M]
298
+
299
+ instance instAddCommMonoid : AddCommMonoid (ι →₀ M) :=
123
300
fast_instance% DFunLike.coe_injective.addCommMonoid
124
301
DFunLike.coe coe_zero coe_add (fun _ _ => rfl)
125
302
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
+
126
312
instance instNeg [NegZeroClass G] : Neg (ι →₀ G) where neg := mapRange Neg.neg neg_zero
127
313
128
314
@[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
134
320
(hf' : ∀ x, f (-x) = -f x) (v : ι →₀ G) : mapRange f hf (-v) = -mapRange f hf v :=
135
321
ext fun _ => by simp only [hf', neg_apply, mapRange_apply]
136
322
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
-
142
323
instance instSub [SubNegZeroMonoid G] : Sub (ι →₀ G) :=
143
324
⟨zipWith Sub.sub (sub_zero _)⟩
144
325
@@ -151,35 +332,70 @@ lemma mapRange_sub [SubNegZeroMonoid G] [SubNegZeroMonoid H] {f : G → H} {hf :
151
332
mapRange f hf (v₁ - v₂) = mapRange f hf v₁ - mapRange f hf v₂ :=
152
333
ext fun _ => by simp only [hf', sub_apply, mapRange_apply]
153
334
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]
155
344
{f : F} (v₁ v₂ : ι →₀ G) :
156
345
mapRange f (map_zero f) (v₁ - v₂) = mapRange f (map_zero f) v₁ - mapRange f (map_zero f) v₂ :=
157
346
mapRange_sub (map_sub f) v₁ v₂
158
347
159
348
/-- Note the general `SMul` instance for `Finsupp` doesn't apply as `ℤ` is not distributive
160
349
unless `F i`'s addition is commutative. -/
161
- instance instIntSMul [AddGroup G] : SMul ℤ (ι →₀ G) :=
350
+ instance instIntSMul : SMul ℤ (ι →₀ G) :=
162
351
⟨fun n v => v.mapRange (n • ·) (zsmul_zero _)⟩
163
352
164
- instance instAddGroup [AddGroup G] : AddGroup (ι →₀ G) :=
353
+ instance instAddGroup : AddGroup (ι →₀ G) :=
165
354
fast_instance% DFunLike.coe_injective.addGroup DFunLike.coe coe_zero coe_add coe_neg coe_sub
166
355
(fun _ _ => rfl) fun _ _ => rfl
167
356
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
-
172
357
@[simp]
173
- lemma support_neg [AddGroup G] (f : ι →₀ G) : support (-f) = support f :=
358
+ lemma support_neg (f : ι →₀ G) : support (-f) = support f :=
174
359
Finset.Subset.antisymm support_mapRange
175
360
(calc
176
361
support f = support (- -f) := congr_arg support (neg_neg _).symm
177
362
_ ⊆ support (-f) := support_mapRange
178
363
)
179
364
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
182
366
rw [sub_eq_add_neg, ← support_neg g]
183
367
exact support_add
184
368
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
+
185
401
end Finsupp
0 commit comments