|
| 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