Skip to content
This repository was archived by the owner on Jul 24, 2024. It is now read-only.

Commit a07d750

Browse files
refactor(algebra): Redefine a ≡ b [PMOD p] (#18958)
as `∃ n : ℤ, b - a = n • p` instead of `∀ n : ℤ, b - n • p ∉ set.Ioo a (a + p)`. Since this new definition doesn't require an order on `α`, we move it to a new file `algebra.modeq`. Expand the API. Co-authored-by: Eric Wieser <wieser.eric@gmail.com>
1 parent 0b20dff commit a07d750

File tree

6 files changed

+276
-68
lines changed

6 files changed

+276
-68
lines changed

src/algebra/group/basic.lean

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -451,6 +451,9 @@ by rw [div_eq_mul_inv, mul_right_inv a]
451451
lemma mul_div_cancel'' (a b : G) : a * b / b = a :=
452452
by rw [div_eq_mul_inv, mul_inv_cancel_right a b]
453453

454+
@[simp, to_additive sub_add_cancel'']
455+
lemma div_mul_cancel''' (a b : G) : a / (b * a) = b⁻¹ := by rw [←inv_div, mul_div_cancel'']
456+
454457
@[simp, to_additive]
455458
lemma mul_div_mul_right_eq_div (a b c : G) : (a * c) / (b * c) = a / b :=
456459
by rw [div_mul_eq_div_div_swap]; simp only [mul_left_inj, eq_self_iff_true, mul_div_cancel'']

src/algebra/group_power/lemmas.lean

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -423,6 +423,11 @@ by { dsimp [bit1], rw [add_mul, bit0_mul, one_mul], }
423423
lemma mul_bit1 [non_assoc_ring R] {n r : R} : r * bit1 n = (2 : ℤ) • (r * n) + r :=
424424
by { dsimp [bit1], rw [mul_add, mul_bit0, mul_one], }
425425

426+
/-- Note this holds in marginally more generality than `int.cast_mul` -/
427+
lemma int.cast_mul_eq_zsmul_cast [add_comm_group_with_one α] : ∀ m n, ((m * n : ℤ) : α) = m • n :=
428+
λ m, int.induction_on' m 0 (by simp) (λ k _ ih n, by simp [add_mul, add_zsmul, ih])
429+
(λ k _ ih n, by simp [sub_mul, sub_zsmul, ih, ←sub_eq_add_neg])
430+
426431
@[simp] theorem zsmul_eq_mul [ring R] (a : R) : ∀ (n : ℤ), n • a = n * a
427432
| (n : ℕ) := by rw [coe_nat_zsmul, nsmul_eq_mul, int.cast_coe_nat]
428433
| -[1+ n] := by simp [nat.cast_succ, neg_add_rev, int.cast_neg_succ_of_nat, add_mul]

src/algebra/hom/units.lean

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -278,7 +278,9 @@ h.eq_div_iff.2
278278
@[to_additive] protected lemma div_eq_one_iff_eq (h : is_unit b) : a / b = 1 ↔ a = b :=
279279
⟨eq_of_div_eq_one, λ hab, hab.symm ▸ h.div_self⟩
280280

281-
@[to_additive] protected lemma div_mul_left (h : is_unit b) : b / (a * b) = 1 / a :=
281+
/-- The `group` version of this lemma is `div_mul_cancel'''` -/
282+
@[to_additive "The `add_group` version of this lemma is `sub_add_cancel''`"]
283+
protected lemma div_mul_left (h : is_unit b) : b / (a * b) = 1 / a :=
282284
by rw [div_eq_mul_inv, mul_inv_rev, h.mul_inv_cancel_left, one_div]
283285

284286
@[to_additive] protected lemma mul_div_mul_right (h : is_unit c) (a b : α) :

src/algebra/modeq.lean

Lines changed: 219 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,219 @@
1+
/-
2+
Copyright (c) 2023 Yaël Dillies. All rights reserved.
3+
Released under Apache 2.0 license as described in the file LICENSE.
4+
Authors: Yaël Dillies
5+
-/
6+
import data.int.modeq
7+
import group_theory.quotient_group
8+
9+
/-!
10+
# Equality modulo an element
11+
12+
This file defines equality modulo an element in a commutative group.
13+
14+
## Main definitions
15+
16+
* `a ≡ b [PMOD p]`: `a` and `b` are congruent modulo a`p`.
17+
18+
## See also
19+
20+
`smodeq` is a generalisation to arbitrary submodules.
21+
22+
## TODO
23+
24+
Delete `int.modeq` in favour of `add_comm_group.modeq`. Generalise `smodeq` to `add_subgroup` and
25+
redefine `add_comm_group.modeq` using it. Once this is done, we can rename `add_comm_group.modeq`
26+
to `add_subgroup.modeq` and multiplicativise it. Longer term, we could generalise to submonoids and
27+
also unify with `nat.modeq`.
28+
-/
29+
30+
namespace add_comm_group
31+
variables {α : Type*}
32+
33+
section add_comm_group
34+
variables [add_comm_group α] {p a a₁ a₂ b b₁ b₂ c : α} {n : ℕ} {z : ℤ}
35+
36+
/-- `a ≡ b [PMOD p]` means that `b` is congruent to `a` modulo `p`.
37+
38+
Equivalently (as shown in `algebra.order.to_interval_mod`), `b` does not lie in the open interval
39+
`(a, a + p)` modulo `p`, or `to_Ico_mod hp a` disagrees with `to_Ioc_mod hp a` at `b`, or
40+
`to_Ico_div hp a` disagrees with `to_Ioc_div hp a` at `b`. -/
41+
def modeq (p a b : α) : Prop := ∃ z : ℤ, b - a = z • p
42+
43+
notation a ` ≡ `:50 b ` [PMOD `:50 p `]`:0 := modeq p a b
44+
45+
@[refl, simp] lemma modeq_refl (a : α) : a ≡ a [PMOD p] := ⟨0, by simp⟩
46+
47+
lemma modeq_rfl : a ≡ a [PMOD p] := modeq_refl _
48+
49+
lemma modeq_comm : a ≡ b [PMOD p] ↔ b ≡ a [PMOD p] :=
50+
(equiv.neg _).exists_congr_left.trans $ by simp [modeq, ←neg_eq_iff_eq_neg]
51+
52+
alias modeq_comm ↔ modeq.symm _
53+
54+
attribute [symm] modeq.symm
55+
56+
@[trans] lemma modeq.trans : a ≡ b [PMOD p] → b ≡ c [PMOD p] → a ≡ c [PMOD p] :=
57+
λ ⟨m, hm⟩ ⟨n, hn⟩, ⟨m + n, by simp [add_smul, ←hm, ←hn]⟩
58+
59+
instance : is_refl _ (modeq p) := ⟨modeq_refl⟩
60+
61+
@[simp] lemma neg_modeq_neg : -a ≡ -b [PMOD p] ↔ a ≡ b [PMOD p] :=
62+
modeq_comm.trans $ by simp [modeq]
63+
64+
alias neg_modeq_neg ↔ modeq.of_neg modeq.neg
65+
66+
@[simp] lemma modeq_neg : a ≡ b [PMOD -p] ↔ a ≡ b [PMOD p] :=
67+
modeq_comm.trans $ by simp [modeq, ←neg_eq_iff_eq_neg]
68+
69+
alias modeq_neg ↔ modeq.of_neg' modeq.neg'
70+
71+
lemma modeq_sub (a b : α) : a ≡ b [PMOD b - a] := ⟨1, (one_smul _ _).symm⟩
72+
73+
@[simp] lemma modeq_zero : a ≡ b [PMOD 0] ↔ a = b := by simp [modeq, sub_eq_zero, eq_comm]
74+
75+
@[simp] lemma self_modeq_zero : p ≡ 0 [PMOD p] := ⟨-1, by simp⟩
76+
77+
@[simp] lemma zsmul_modeq_zero (z : ℤ) : z • p ≡ 0 [PMOD p] := ⟨-z, by simp⟩
78+
lemma add_zsmul_modeq (z : ℤ) : a + z • p ≡ a [PMOD p] := ⟨-z, by simp⟩
79+
lemma zsmul_add_modeq (z : ℤ) : z • p + a ≡ a [PMOD p] := ⟨-z, by simp⟩
80+
lemma add_nsmul_modeq (n : ℕ) : a + n • p ≡ a [PMOD p] := ⟨-n, by simp⟩
81+
lemma nsmul_add_modeq (n : ℕ) : n • p + a ≡ a [PMOD p] := ⟨-n, by simp⟩
82+
83+
namespace modeq
84+
85+
protected lemma add_zsmul (z : ℤ) : a ≡ b [PMOD p] → a + z • p ≡ b [PMOD p] :=
86+
(add_zsmul_modeq _).trans
87+
protected lemma zsmul_add (z : ℤ) : a ≡ b [PMOD p] → z • p + a ≡ b [PMOD p] :=
88+
(zsmul_add_modeq _).trans
89+
protected lemma add_nsmul (n : ℕ) : a ≡ b [PMOD p] → a + n • p ≡ b [PMOD p] :=
90+
(add_nsmul_modeq _).trans
91+
protected lemma nsmul_add (n : ℕ) : a ≡ b [PMOD p] → n • p + a ≡ b [PMOD p] :=
92+
(nsmul_add_modeq _).trans
93+
94+
protected lemma of_zsmul : a ≡ b [PMOD (z • p)] → a ≡ b [PMOD p] :=
95+
λ ⟨m, hm⟩, ⟨m * z, by rwa [mul_smul]⟩
96+
97+
protected lemma of_nsmul : a ≡ b [PMOD (n • p)] → a ≡ b [PMOD p] :=
98+
λ ⟨m, hm⟩, ⟨m * n, by rwa [mul_smul, coe_nat_zsmul]⟩
99+
100+
protected lemma zsmul : a ≡ b [PMOD p] → z • a ≡ z • b [PMOD (z • p)] :=
101+
Exists.imp $ λ m hm, by rw [←smul_sub, hm, smul_comm]
102+
103+
protected lemma nsmul : a ≡ b [PMOD p] → n • a ≡ n • b [PMOD (n • p)] :=
104+
Exists.imp $ λ m hm, by rw [←smul_sub, hm, smul_comm]
105+
106+
end modeq
107+
108+
@[simp] lemma zsmul_modeq_zsmul [no_zero_smul_divisors ℤ α] (hn : z ≠ 0) :
109+
z • a ≡ z • b [PMOD (z • p)] ↔ a ≡ b [PMOD p] :=
110+
exists_congr $ λ m, by rw [←smul_sub, smul_comm, smul_right_inj hn]; apply_instance
111+
112+
@[simp] lemma nsmul_modeq_nsmul [no_zero_smul_divisors ℕ α] (hn : n ≠ 0) :
113+
n • a ≡ n • b [PMOD (n • p)] ↔ a ≡ b [PMOD p] :=
114+
exists_congr $ λ m, by rw [←smul_sub, smul_comm, smul_right_inj hn]; apply_instance
115+
116+
alias zsmul_modeq_zsmul ↔ modeq.zsmul_cancel _
117+
alias nsmul_modeq_nsmul ↔ modeq.nsmul_cancel _
118+
119+
namespace modeq
120+
121+
@[simp] protected lemma add_iff_left :
122+
a₁ ≡ b₁ [PMOD p] → (a₁ + a₂ ≡ b₁ + b₂ [PMOD p] ↔ a₂ ≡ b₂ [PMOD p]) :=
123+
λ ⟨m, hm⟩, (equiv.add_left m).symm.exists_congr_left.trans $
124+
by simpa [add_sub_add_comm, hm, add_smul]
125+
126+
@[simp] protected lemma add_iff_right :
127+
a₂ ≡ b₂ [PMOD p] → (a₁ + a₂ ≡ b₁ + b₂ [PMOD p] ↔ a₁ ≡ b₁ [PMOD p]) :=
128+
λ ⟨m, hm⟩, (equiv.add_right m).symm.exists_congr_left.trans $
129+
by simpa [add_sub_add_comm, hm, add_smul]
130+
131+
@[simp] protected lemma sub_iff_left :
132+
a₁ ≡ b₁ [PMOD p] → (a₁ - a₂ ≡ b₁ - b₂ [PMOD p] ↔ a₂ ≡ b₂ [PMOD p]) :=
133+
λ ⟨m, hm⟩, (equiv.sub_left m).symm.exists_congr_left.trans $
134+
by simpa [sub_sub_sub_comm, hm, sub_smul]
135+
136+
@[simp] protected lemma sub_iff_right :
137+
a₂ ≡ b₂ [PMOD p] → (a₁ - a₂ ≡ b₁ - b₂ [PMOD p] ↔ a₁ ≡ b₁ [PMOD p]) :=
138+
λ ⟨m, hm⟩, (equiv.sub_right m).symm.exists_congr_left.trans $
139+
by simpa [sub_sub_sub_comm, hm, sub_smul]
140+
141+
alias modeq.add_iff_left ↔ add_left_cancel add
142+
alias modeq.add_iff_right ↔ add_right_cancel _
143+
alias modeq.sub_iff_left ↔ sub_left_cancel sub
144+
alias modeq.sub_iff_right ↔ sub_right_cancel _
145+
146+
attribute [protected] add_left_cancel add_right_cancel add sub_left_cancel sub_right_cancel sub
147+
148+
protected lemma add_left (c : α) (h : a ≡ b [PMOD p]) : c + a ≡ c + b [PMOD p] := modeq_rfl.add h
149+
protected lemma sub_left (c : α) (h : a ≡ b [PMOD p]) : c - a ≡ c - b [PMOD p] := modeq_rfl.sub h
150+
protected lemma add_right (c : α) (h : a ≡ b [PMOD p]) : a + c ≡ b + c [PMOD p] := h.add modeq_rfl
151+
protected lemma sub_right (c : α) (h : a ≡ b [PMOD p]) : a - c ≡ b - c [PMOD p] := h.sub modeq_rfl
152+
153+
protected lemma add_left_cancel' (c : α) : c + a ≡ c + b [PMOD p] → a ≡ b [PMOD p] :=
154+
modeq_rfl.add_left_cancel
155+
156+
protected lemma add_right_cancel' (c : α) : a + c ≡ b + c [PMOD p] → a ≡ b [PMOD p] :=
157+
modeq_rfl.add_right_cancel
158+
159+
protected lemma sub_left_cancel' (c : α) : c - a ≡ c - b [PMOD p] → a ≡ b [PMOD p] :=
160+
modeq_rfl.sub_left_cancel
161+
162+
protected lemma sub_right_cancel' (c : α) : a - c ≡ b - c [PMOD p] → a ≡ b [PMOD p] :=
163+
modeq_rfl.sub_right_cancel
164+
165+
end modeq
166+
167+
lemma modeq_sub_iff_add_modeq' : a ≡ b - c [PMOD p] ↔ c + a ≡ b [PMOD p] := by simp [modeq, sub_sub]
168+
lemma modeq_sub_iff_add_modeq : a ≡ b - c [PMOD p] ↔ a + c ≡ b [PMOD p] :=
169+
modeq_sub_iff_add_modeq'.trans $ by rw add_comm
170+
lemma sub_modeq_iff_modeq_add' : a - b ≡ c [PMOD p] ↔ a ≡ b + c [PMOD p] :=
171+
modeq_comm.trans $ modeq_sub_iff_add_modeq'.trans modeq_comm
172+
lemma sub_modeq_iff_modeq_add : a - b ≡ c [PMOD p] ↔ a ≡ c + b [PMOD p] :=
173+
modeq_comm.trans $ modeq_sub_iff_add_modeq.trans modeq_comm
174+
175+
@[simp] lemma sub_modeq_zero : a - b ≡ 0 [PMOD p] ↔ a ≡ b [PMOD p] :=
176+
by simp [sub_modeq_iff_modeq_add]
177+
178+
@[simp] lemma add_modeq_left : a + b ≡ a [PMOD p] ↔ b ≡ 0 [PMOD p] :=
179+
by simp [←modeq_sub_iff_add_modeq']
180+
181+
@[simp] lemma add_modeq_right : a + b ≡ b [PMOD p] ↔ a ≡ 0 [PMOD p] :=
182+
by simp [←modeq_sub_iff_add_modeq]
183+
184+
lemma modeq_iff_eq_add_zsmul : a ≡ b [PMOD p] ↔ ∃ z : ℤ, b = a + z • p :=
185+
by simp_rw [modeq, sub_eq_iff_eq_add']
186+
187+
lemma not_modeq_iff_ne_add_zsmul : ¬a ≡ b [PMOD p] ↔ ∀ z : ℤ, b ≠ a + z • p :=
188+
by rw [modeq_iff_eq_add_zsmul, not_exists]
189+
190+
lemma modeq_iff_eq_mod_zmultiples : a ≡ b [PMOD p] ↔ (b : α ⧸ add_subgroup.zmultiples p) = a :=
191+
by simp_rw [modeq_iff_eq_add_zsmul, quotient_add_group.eq_iff_sub_mem,
192+
add_subgroup.mem_zmultiples_iff, eq_sub_iff_add_eq', eq_comm]
193+
194+
lemma not_modeq_iff_ne_mod_zmultiples :
195+
¬a ≡ b [PMOD p] ↔ (b : α ⧸ add_subgroup.zmultiples p) ≠ a :=
196+
modeq_iff_eq_mod_zmultiples.not
197+
198+
end add_comm_group
199+
200+
@[simp] lemma modeq_iff_int_modeq {a b z : ℤ} : a ≡ b [PMOD z] ↔ a ≡ b [ZMOD z] :=
201+
by simp [modeq, dvd_iff_exists_eq_mul_left, int.modeq_iff_dvd]
202+
203+
section add_comm_group_with_one
204+
variables [add_comm_group_with_one α] [char_zero α]
205+
206+
@[simp, norm_cast]
207+
lemma int_cast_modeq_int_cast {a b z : ℤ} : a ≡ b [PMOD (z : α)] ↔ a ≡ b [PMOD z] :=
208+
by simp_rw [modeq, ←int.cast_mul_eq_zsmul_cast]; norm_cast
209+
210+
@[simp, norm_cast]
211+
lemma nat_cast_modeq_nat_cast {a b n : ℕ} : a ≡ b [PMOD (n : α)] ↔ a ≡ b [MOD n] :=
212+
by simp_rw [←int.coe_nat_modeq_iff, ←modeq_iff_int_modeq, ←@int_cast_modeq_int_cast α,
213+
int.cast_coe_nat]
214+
215+
alias int_cast_modeq_int_cast ↔ modeq.of_int_cast modeq.int_cast
216+
alias nat_cast_modeq_nat_cast ↔ _root_.nat.modeq.of_nat_cast modeq.nat_cast
217+
218+
end add_comm_group_with_one
219+
end add_comm_group

0 commit comments

Comments
 (0)