-
Notifications
You must be signed in to change notification settings - Fork 259
/
Basic.lean
321 lines (237 loc) · 13.7 KB
/
Basic.lean
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
/-
Copyright (c) 2022 Yaël Dillies. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Yaël Dillies
-/
import Mathlib.Logic.Basic
import Mathlib.Tactic.Positivity.Basic
/-!
# Algebraic order homomorphism classes
This file defines hom classes for common properties at the intersection of order theory and algebra.
## Typeclasses
Basic typeclasses
* `NonnegHomClass`: Homs are nonnegative: `∀ f a, 0 ≤ f a`
* `SubadditiveHomClass`: Homs are subadditive: `∀ f a b, f (a + b) ≤ f a + f b`
* `SubmultiplicativeHomClass`: Homs are submultiplicative: `∀ f a b, f (a * b) ≤ f a * f b`
* `MulLEAddHomClass`: `∀ f a b, f (a * b) ≤ f a + f b`
* `NonarchimedeanHomClass`: `∀ a b, f (a + b) ≤ max (f a) (f b)`
Group norms
* `AddGroupSeminormClass`: Homs are nonnegative, subadditive, even and preserve zero.
* `GroupSeminormClass`: Homs are nonnegative, respect `f (a * b) ≤ f a + f b`, `f a⁻¹ = f a` and
preserve zero.
* `AddGroupNormClass`: Homs are seminorms such that `f x = 0 → x = 0` for all `x`.
* `GroupNormClass`: Homs are seminorms such that `f x = 0 → x = 1` for all `x`.
Ring norms
* `RingSeminormClass`: Homs are submultiplicative group norms.
* `RingNormClass`: Homs are ring seminorms that are also additive group norms.
* `MulRingSeminormClass`: Homs are ring seminorms that are multiplicative.
* `MulRingNormClass`: Homs are ring norms that are multiplicative.
## Notes
Typeclasses for seminorms are defined here while types of seminorms are defined in
`Analysis.Normed.Group.Seminorm` and `Analysis.Normed.Ring.Seminorm` because absolute values are
multiplicative ring norms but outside of this use we only consider real-valued seminorms.
## TODO
Finitary versions of the current lemmas.
-/
library_note "out-param inheritance"/--
Diamond inheritance cannot depend on `outParam`s in the following circumstances:
* there are three classes `Top`, `Middle`, `Bottom`
* all of these classes have a parameter `(α : outParam _)`
* all of these classes have an instance parameter `[Root α]` that depends on this `outParam`
* the `Root` class has two child classes: `Left` and `Right`, these are siblings in the hierarchy
* the instance `Bottom.toMiddle` takes a `[Left α]` parameter
* the instance `Middle.toTop` takes a `[Right α]` parameter
* there is a `Leaf` class that inherits from both `Left` and `Right`.
In that case, given instances `Bottom α` and `Leaf α`, Lean cannot synthesize a `Top α` instance,
even though the hypotheses of the instances `Bottom.toMiddle` and `Middle.toTop` are satisfied.
There are two workarounds:
* You could replace the bundled inheritance implemented by the instance `Middle.toTop` with
unbundled inheritance implemented by adding a `[Top α]` parameter to the `Middle` class. This is
the preferred option since it is also more compatible with Lean 4, at the cost of being more work
to implement and more verbose to use.
* You could weaken the `Bottom.toMiddle` instance by making it depend on a subclass of
`Middle.toTop`'s parameter, in this example replacing `[Left α]` with `[Leaf α]`.
-/
open Function
variable {ι F α β γ δ : Type*}
/-! ### Basics -/
/-- `NonnegHomClass F α β` states that `F` is a type of nonnegative morphisms. -/
class NonnegHomClass (F α β : Type*) [Zero β] [LE β] [FunLike F α β] : Prop where
/-- the image of any element is non negative. -/
apply_nonneg (f : F) : ∀ a, 0 ≤ f a
/-- `SubadditiveHomClass F α β` states that `F` is a type of subadditive morphisms. -/
class SubadditiveHomClass (F α β : Type*) [Add α] [Add β] [LE β] [FunLike F α β] : Prop where
/-- the image of a sum is less or equal than the sum of the images. -/
map_add_le_add (f : F) : ∀ a b, f (a + b) ≤ f a + f b
/-- `SubmultiplicativeHomClass F α β` states that `F` is a type of submultiplicative morphisms. -/
@[to_additive SubadditiveHomClass]
class SubmultiplicativeHomClass (F α β : Type*) [Mul α] [Mul β] [LE β] [FunLike F α β] : Prop where
/-- the image of a product is less or equal than the product of the images. -/
map_mul_le_mul (f : F) : ∀ a b, f (a * b) ≤ f a * f b
/-- `MulLEAddHomClass F α β` states that `F` is a type of subadditive morphisms. -/
@[to_additive SubadditiveHomClass]
class MulLEAddHomClass (F α β : Type*) [Mul α] [Add β] [LE β] [FunLike F α β] : Prop where
/-- the image of a product is less or equal than the sum of the images. -/
map_mul_le_add (f : F) : ∀ a b, f (a * b) ≤ f a + f b
/-- `NonarchimedeanHomClass F α β` states that `F` is a type of non-archimedean morphisms. -/
class NonarchimedeanHomClass (F α β : Type*) [Add α] [LinearOrder β] [FunLike F α β] : Prop where
/-- the image of a sum is less or equal than the maximum of the images. -/
map_add_le_max (f : F) : ∀ a b, f (a + b) ≤ max (f a) (f b)
export NonnegHomClass (apply_nonneg)
export SubadditiveHomClass (map_add_le_add)
export SubmultiplicativeHomClass (map_mul_le_mul)
export MulLEAddHomClass (map_mul_le_add)
export NonarchimedeanHomClass (map_add_le_max)
attribute [simp] apply_nonneg
variable [FunLike F α β]
@[to_additive]
theorem le_map_mul_map_div [Group α] [CommSemigroup β] [LE β] [SubmultiplicativeHomClass F α β]
(f : F) (a b : α) : f a ≤ f b * f (a / b) := by
simpa only [mul_comm, div_mul_cancel] using map_mul_le_mul f (a / b) b
@[to_additive existing]
theorem le_map_add_map_div [Group α] [AddCommSemigroup β] [LE β] [MulLEAddHomClass F α β] (f : F)
(a b : α) : f a ≤ f b + f (a / b) := by
simpa only [add_comm, div_mul_cancel] using map_mul_le_add f (a / b) b
-- Porting note (#11215): TODO: `to_additive` clashes
@[to_additive]
theorem le_map_div_mul_map_div [Group α] [CommSemigroup β] [LE β] [SubmultiplicativeHomClass F α β]
(f : F) (a b c : α) : f (a / c) ≤ f (a / b) * f (b / c) := by
simpa only [div_mul_div_cancel'] using map_mul_le_mul f (a / b) (b / c)
@[to_additive existing]
theorem le_map_div_add_map_div [Group α] [AddCommSemigroup β] [LE β] [MulLEAddHomClass F α β]
(f : F) (a b c : α) : f (a / c) ≤ f (a / b) + f (b / c) := by
simpa only [div_mul_div_cancel'] using map_mul_le_add f (a / b) (b / c)
-- Porting note (#11215): TODO: `to_additive` clashes
namespace Mathlib.Meta.Positivity
open Lean Meta Qq Function
/-- Extension for the `positivity` tactic: nonnegative maps take nonnegative values. -/
@[positivity DFunLike.coe _ _]
def evalMap : PositivityExt where eval {_ β} _ _ e := do
let .app (.app _ f) a ← whnfR e
| throwError "not ↑f · where f is of NonnegHomClass"
let pa ← mkAppOptM ``apply_nonneg #[none, none, β, none, none, none, none, f, a]
pure (.nonnegative pa)
end Mathlib.Meta.Positivity
/-! ### Group (semi)norms -/
/-- `AddGroupSeminormClass F α` states that `F` is a type of `β`-valued seminorms on the additive
group `α`.
You should extend this class when you extend `AddGroupSeminorm`. -/
class AddGroupSeminormClass (F α β : Type*) [AddGroup α] [OrderedAddCommMonoid β] [FunLike F α β]
extends SubadditiveHomClass F α β : Prop where
/-- The image of zero is zero. -/
map_zero (f : F) : f 0 = 0
/-- The map is invariant under negation of its argument. -/
map_neg_eq_map (f : F) (a : α) : f (-a) = f a
/-- `GroupSeminormClass F α` states that `F` is a type of `β`-valued seminorms on the group `α`.
You should extend this class when you extend `GroupSeminorm`. -/
@[to_additive]
class GroupSeminormClass (F α β : Type*) [Group α] [OrderedAddCommMonoid β] [FunLike F α β]
extends MulLEAddHomClass F α β : Prop where
/-- The image of one is zero. -/
map_one_eq_zero (f : F) : f 1 = 0
/-- The map is invariant under inversion of its argument. -/
map_inv_eq_map (f : F) (a : α) : f a⁻¹ = f a
/-- `AddGroupNormClass F α` states that `F` is a type of `β`-valued norms on the additive group
`α`.
You should extend this class when you extend `AddGroupNorm`. -/
class AddGroupNormClass (F α β : Type*) [AddGroup α] [OrderedAddCommMonoid β] [FunLike F α β]
extends AddGroupSeminormClass F α β : Prop where
/-- The argument is zero if its image under the map is zero. -/
eq_zero_of_map_eq_zero (f : F) {a : α} : f a = 0 → a = 0
/-- `GroupNormClass F α` states that `F` is a type of `β`-valued norms on the group `α`.
You should extend this class when you extend `GroupNorm`. -/
@[to_additive]
class GroupNormClass (F α β : Type*) [Group α] [OrderedAddCommMonoid β] [FunLike F α β]
extends GroupSeminormClass F α β : Prop where
/-- The argument is one if its image under the map is zero. -/
eq_one_of_map_eq_zero (f : F) {a : α} : f a = 0 → a = 1
export AddGroupSeminormClass (map_neg_eq_map)
export GroupSeminormClass (map_one_eq_zero map_inv_eq_map)
export AddGroupNormClass (eq_zero_of_map_eq_zero)
export GroupNormClass (eq_one_of_map_eq_zero)
attribute [simp] map_one_eq_zero -- Porting note: `to_additive` translation already exists
attribute [simp] map_neg_eq_map
attribute [simp] map_inv_eq_map -- Porting note: `to_additive` translation already exists
attribute [to_additive] GroupSeminormClass.toMulLEAddHomClass
-- See note [lower instance priority]
instance (priority := 100) AddGroupSeminormClass.toZeroHomClass [AddGroup α]
[OrderedAddCommMonoid β] [AddGroupSeminormClass F α β] : ZeroHomClass F α β :=
{ ‹AddGroupSeminormClass F α β› with }
section GroupSeminormClass
variable [Group α] [OrderedAddCommMonoid β] [GroupSeminormClass F α β] (f : F) (x y : α)
@[to_additive]
theorem map_div_le_add : f (x / y) ≤ f x + f y := by
rw [div_eq_mul_inv, ← map_inv_eq_map f y]
exact map_mul_le_add _ _ _
@[to_additive]
theorem map_div_rev : f (x / y) = f (y / x) := by rw [← inv_div, map_inv_eq_map]
@[to_additive]
theorem le_map_add_map_div' : f x ≤ f y + f (y / x) := by
simpa only [add_comm, map_div_rev, div_mul_cancel] using map_mul_le_add f (x / y) y
end GroupSeminormClass
example [OrderedAddCommGroup β] : OrderedAddCommMonoid β :=
inferInstance
@[to_additive]
theorem abs_sub_map_le_div [Group α] [LinearOrderedAddCommGroup β] [GroupSeminormClass F α β]
(f : F) (x y : α) : |f x - f y| ≤ f (x / y) := by
rw [abs_sub_le_iff, sub_le_iff_le_add', sub_le_iff_le_add']
exact ⟨le_map_add_map_div _ _ _, le_map_add_map_div' _ _ _⟩
-- See note [lower instance priority]
@[to_additive]
instance (priority := 100) GroupSeminormClass.toNonnegHomClass [Group α]
[LinearOrderedAddCommMonoid β] [GroupSeminormClass F α β] : NonnegHomClass F α β :=
{ ‹GroupSeminormClass F α β› with
apply_nonneg := fun f a =>
(nsmul_nonneg_iff two_ne_zero).1 <| by
rw [two_nsmul, ← map_one_eq_zero f, ← div_self' a]
exact map_div_le_add _ _ _ }
section GroupNormClass
variable [Group α] [OrderedAddCommMonoid β] [GroupNormClass F α β] (f : F) {x : α}
@[to_additive (attr := simp)]
theorem map_eq_zero_iff_eq_one : f x = 0 ↔ x = 1 :=
⟨eq_one_of_map_eq_zero _, by
rintro rfl
exact map_one_eq_zero _⟩
@[to_additive]
theorem map_ne_zero_iff_ne_one : f x ≠ 0 ↔ x ≠ 1 :=
(map_eq_zero_iff_eq_one _).not
end GroupNormClass
@[to_additive]
theorem map_pos_of_ne_one [Group α] [LinearOrderedAddCommMonoid β] [GroupNormClass F α β] (f : F)
{x : α} (hx : x ≠ 1) : 0 < f x :=
(apply_nonneg _ _).lt_of_ne <| ((map_ne_zero_iff_ne_one _).2 hx).symm
/-! ### Ring (semi)norms -/
/-- `RingSeminormClass F α` states that `F` is a type of `β`-valued seminorms on the ring `α`.
You should extend this class when you extend `RingSeminorm`. -/
class RingSeminormClass (F α β : Type*) [NonUnitalNonAssocRing α] [OrderedSemiring β]
[FunLike F α β] extends AddGroupSeminormClass F α β, SubmultiplicativeHomClass F α β : Prop
/-- `RingNormClass F α` states that `F` is a type of `β`-valued norms on the ring `α`.
You should extend this class when you extend `RingNorm`. -/
class RingNormClass (F α β : Type*) [NonUnitalNonAssocRing α] [OrderedSemiring β] [FunLike F α β]
extends RingSeminormClass F α β, AddGroupNormClass F α β : Prop
/-- `MulRingSeminormClass F α` states that `F` is a type of `β`-valued multiplicative seminorms
on the ring `α`.
You should extend this class when you extend `MulRingSeminorm`. -/
class MulRingSeminormClass (F α β : Type*) [NonAssocRing α] [OrderedSemiring β] [FunLike F α β]
extends AddGroupSeminormClass F α β, MonoidWithZeroHomClass F α β : Prop
-- Lower the priority of these instances since they require synthesizing an order structure.
attribute [instance 50]
MulRingSeminormClass.toMonoidHomClass MulRingSeminormClass.toMonoidWithZeroHomClass
/-- `MulRingNormClass F α` states that `F` is a type of `β`-valued multiplicative norms on the
ring `α`.
You should extend this class when you extend `MulRingNorm`. -/
class MulRingNormClass (F α β : Type*) [NonAssocRing α] [OrderedSemiring β] [FunLike F α β]
extends MulRingSeminormClass F α β, AddGroupNormClass F α β : Prop
-- See note [out-param inheritance]
-- See note [lower instance priority]
instance (priority := 100) RingSeminormClass.toNonnegHomClass [NonUnitalNonAssocRing α]
[LinearOrderedSemiring β] [RingSeminormClass F α β] : NonnegHomClass F α β :=
AddGroupSeminormClass.toNonnegHomClass
-- See note [lower instance priority]
instance (priority := 100) MulRingSeminormClass.toRingSeminormClass [NonAssocRing α]
[OrderedSemiring β] [MulRingSeminormClass F α β] : RingSeminormClass F α β :=
{ ‹MulRingSeminormClass F α β› with map_mul_le_mul := fun f a b => (map_mul _ _ _).le }
-- See note [lower instance priority]
instance (priority := 100) MulRingNormClass.toRingNormClass [NonAssocRing α]
[OrderedSemiring β] [MulRingNormClass F α β] : RingNormClass F α β :=
{ ‹MulRingNormClass F α β›, MulRingSeminormClass.toRingSeminormClass with }