-
Notifications
You must be signed in to change notification settings - Fork 1.5k
Expand file tree
/
Copy pathDefs.lean
More file actions
212 lines (150 loc) · 6.46 KB
/
Copy pathDefs.lean
File metadata and controls
212 lines (150 loc) · 6.46 KB
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
/-
Copyright (c) 2019 Neil Strickland. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Neil Strickland, Yury Kudryashov
-/
module
public import Mathlib.Algebra.Group.Semiconj.Defs
/-!
# Commuting pairs of elements in monoids
We define the predicate `Commute a b := a * b = b * a` and provide some operations on terms
`(h : Commute a b)`. E.g., if `a`, `b`, and c are elements of a semiring, and that
`hb : Commute a b` and `hc : Commute a c`. Then `hb.pow_left 5` proves `Commute (a ^ 5) b` and
`(hb.pow_right 2).add_right (hb.mul_right hc)` proves `Commute a (b ^ 2 + b * c)`.
Lean does not immediately recognise these terms as equations, so for rewriting we need syntax like
`rw [(hb.pow_left 5).eq]` rather than just `rw [hb.pow_left 5]`.
This file defines only a few operations (`mul_left`, `inv_right`, etc). Other operations
(`pow_right`, field inverse etc) are in the files that define corresponding notions.
## Implementation details
Most of the proofs come from the properties of `SemiconjBy`.
-/
@[expose] public section
assert_not_exists MonoidWithZero DenselyOrdered
variable {G M S : Type*}
/-- Two elements commute if `a * b = b * a`. -/
@[to_additive /-- Two elements additively commute if `a + b = b + a` -/]
def Commute [Mul S] (a b : S) : Prop :=
SemiconjBy a b b
/--
Two elements `a` and `b` commute if `a * b = b * a`.
-/
@[to_additive]
theorem commute_iff_eq [Mul S] (a b : S) : Commute a b ↔ a * b = b * a := Iff.rfl
namespace Commute
section Mul
variable [Mul S]
/-- Equality behind `Commute a b`; useful for rewriting. -/
@[to_additive (attr := grind →) /-- Equality behind `AddCommute a b`; useful for rewriting. -/]
protected theorem eq {a b : S} (h : Commute a b) : a * b = b * a :=
h
/-- Any element commutes with itself. -/
@[to_additive (attr := refl, simp) /-- Any element commutes with itself. -/]
protected theorem refl (a : S) : Commute a a :=
Eq.refl (a * a)
/-- If `a` commutes with `b`, then `b` commutes with `a`. -/
@[to_additive (attr := symm) /-- If `a` commutes with `b`, then `b` commutes with `a`. -/]
protected theorem symm {a b : S} (h : Commute a b) : Commute b a :=
Eq.symm h
@[to_additive]
protected theorem semiconjBy {a b : S} (h : Commute a b) : SemiconjBy a b b :=
h
@[to_additive (attr := grind =)]
protected theorem symm_iff {a b : S} : Commute a b ↔ Commute b a :=
⟨Commute.symm, Commute.symm⟩
@[to_additive]
instance : @Std.Refl S Commute :=
⟨Commute.refl⟩
@[to_additive]
instance : @Std.Symm S Commute where
symm _ _ := .symm
-- This instance is useful for `Finset.noncommProd`
@[to_additive]
instance on_refl {f : G → S} : Std.Refl fun a b => Commute (f a) (f b) :=
⟨fun _ => Commute.refl _⟩
end Mul
section Semigroup
variable [Semigroup S] {a b c : S}
/-- If `a` commutes with both `b` and `c`, then it commutes with their product. -/
@[to_additive (attr := simp)
/-- If `a` commutes with both `b` and `c`, then it commutes with their sum. -/]
theorem mul_right (hab : Commute a b) (hac : Commute a c) : Commute a (b * c) :=
SemiconjBy.mul_right hab hac
/-- If both `a` and `b` commute with `c`, then their product commutes with `c`. -/
@[to_additive (attr := simp)
/-- If both `a` and `b` commute with `c`, then their product commutes with `c`. -/]
theorem mul_left (hac : Commute a c) (hbc : Commute b c) : Commute (a * b) c :=
SemiconjBy.mul_left hac hbc
@[to_additive]
protected theorem right_comm (h : Commute b c) (a : S) : a * b * c = a * c * b := by
simp only [mul_assoc, h.eq]
@[to_additive]
protected theorem left_comm (h : Commute a b) (c) : a * (b * c) = b * (a * c) := by
simp only [← mul_assoc, h.eq]
@[to_additive]
protected theorem mul_mul_mul_comm (hbc : Commute b c) (a d : S) :
a * b * (c * d) = a * c * (b * d) := by simp only [hbc.left_comm, mul_assoc]
end Semigroup
@[to_additive]
protected theorem all [CommMagma S] (a b : S) : Commute a b :=
mul_comm a b
section MulOneClass
variable [MulOneClass M]
@[to_additive (attr := simp)]
theorem one_right (a : M) : Commute a 1 :=
SemiconjBy.one_right a
@[to_additive (attr := simp)]
theorem one_left (a : M) : Commute 1 a :=
SemiconjBy.one_left a
end MulOneClass
section Monoid
variable [Monoid M] {a b : M}
@[to_additive (attr := simp)]
theorem pow_right (h : Commute a b) (n : ℕ) : Commute a (b ^ n) :=
SemiconjBy.pow_right h n
@[to_additive (attr := simp)]
theorem pow_left (h : Commute a b) (n : ℕ) : Commute (a ^ n) b :=
(h.symm.pow_right n).symm
-- todo: should nat power be called `nsmul` here?
@[to_additive]
theorem pow_pow (h : Commute a b) (m n : ℕ) : Commute (a ^ m) (b ^ n) := by
simp [h]
@[to_additive]
theorem self_pow (a : M) (n : ℕ) : Commute a (a ^ n) :=
(Commute.refl a).pow_right n
@[to_additive]
theorem pow_self (a : M) (n : ℕ) : Commute (a ^ n) a :=
(Commute.refl a).pow_left n
@[to_additive]
theorem pow_pow_self (a : M) (m n : ℕ) : Commute (a ^ m) (a ^ n) :=
(Commute.refl a).pow_pow m n
@[to_additive] lemma mul_pow (h : Commute a b) : ∀ n, (a * b) ^ n = a ^ n * b ^ n
| 0 => by rw [pow_zero, pow_zero, pow_zero, one_mul]
| n + 1 => by simp only [pow_succ', h.mul_pow n, ← mul_assoc, (h.pow_left n).right_comm]
end Monoid
section DivisionMonoid
variable [DivisionMonoid G] {a b : G}
@[to_additive]
protected theorem mul_inv (hab : Commute a b) : (a * b)⁻¹ = a⁻¹ * b⁻¹ := by rw [hab.eq, mul_inv_rev]
@[to_additive]
protected theorem inv (hab : Commute a b) : (a * b)⁻¹ = a⁻¹ * b⁻¹ := by rw [hab.eq, mul_inv_rev]
@[to_additive AddCommute.zsmul_add]
protected lemma mul_zpow (h : Commute a b) : ∀ n : ℤ, (a * b) ^ n = a ^ n * b ^ n
| (n : ℕ) => by simp [zpow_natCast, h.mul_pow n]
| .negSucc n => by simp [h.mul_pow, (h.pow_pow _ _).eq, mul_inv_rev]
end DivisionMonoid
section Group
variable [Group G] {a b : G}
@[to_additive]
protected theorem mul_inv_cancel (h : Commute a b) : a * b * a⁻¹ = b := by
rw [h.eq, mul_inv_cancel_right]
@[to_additive]
theorem mul_inv_cancel_assoc (h : Commute a b) : a * (b * a⁻¹) = b := by
rw [← mul_assoc, h.mul_inv_cancel]
end Group
end Commute
@[to_additive] protected lemma IsLeftRegular.commute_mul_left_iff [Semigroup S] {a b : S}
(reg : IsLeftRegular a) : Commute (a * b) a ↔ Commute a b := by
simp [commute_iff_eq, mul_assoc, reg.eq_iff, eq_comm]
@[to_additive] protected lemma IsRightRegular.commute_mul_right_iff [Semigroup S] {a b : S}
(reg : IsRightRegular a) : Commute (b * a) a ↔ Commute a b := by
simp [commute_iff_eq, ← mul_assoc, reg.eq_iff, eq_comm]