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

Commit 20b4143

Browse files
committed
feat(algebra): add normalization and GCD domain; setup for int
1 parent 5df7cac commit 20b4143

File tree

2 files changed

+414
-66
lines changed

2 files changed

+414
-66
lines changed

algebra/gcd_domain.lean

Lines changed: 311 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,311 @@
1+
/-
2+
Copyright (c) 2018 Johannes Hölzl. All rights reserved.
3+
Released under Apache 2.0 license as described in the file LICENSE.
4+
Authors: Johannes Hölzl, Jens Wagemaker
5+
6+
GCD domain and integral domains with normalization functions
7+
8+
TODO: abstract the domains to to semi domains (i.e. domains on semirings) to include ℕ and ℕ[X] etc.
9+
-/
10+
import algebra.ring
11+
12+
variables {α : Type*}
13+
14+
set_option old_structure_cmd true
15+
16+
/-- Normalization domain: multiplying with `norm_unit` gives a normal form for associated elements. -/
17+
class normalization_domain (α : Type*) extends integral_domain α :=
18+
(norm_unit : α → units α)
19+
(norm_unit_zero : norm_unit 0 = 1)
20+
(norm_unit_mul : ∀a b, a ≠ 0 → b ≠ 0 → norm_unit (a * b) = norm_unit a * norm_unit b)
21+
(norm_unit_coe_units : ∀(u : units α), norm_unit u = u⁻¹)
22+
23+
export normalization_domain (norm_unit norm_unit_zero norm_unit_mul norm_unit_coe_units)
24+
25+
attribute [simp] norm_unit_coe_units norm_unit_zero norm_unit_mul
26+
27+
section normalization_domain
28+
variable [normalization_domain α]
29+
30+
@[simp] theorem norm_unit_one : norm_unit (1:α) = 1 :=
31+
norm_unit_coe_units 1
32+
33+
theorem norm_unit_mul_norm_unit (a : α) : norm_unit (a * norm_unit a) = 1 :=
34+
classical.by_cases (assume : a = 0, by simp [this]) $
35+
assume h, by rw [norm_unit_mul _ _ h (units.ne_zero _), norm_unit_coe_units, mul_inv_eq_one]
36+
37+
theorem associated_of_dvd_of_dvd : ∀{a b : α}, a ∣ b → b ∣ a → ∃u:units α, a * u = b
38+
| a b ⟨c, rfl⟩ ⟨d, hd⟩ :=
39+
classical.by_cases (assume : c = 0, ⟨1, by simp * at *⟩) $ assume hc : c ≠ 0,
40+
classical.by_cases (assume : a = 0, ⟨1, by simp * at *⟩) $ assume ha : a ≠ 0,
41+
have a * 1 = a * (c * d), by simpa [mul_assoc] using hd,
42+
have 1 = c * d, from eq_of_mul_eq_mul_left ha this,
43+
⟨units.mk_of_mul_eq_one c d this.symm, rfl⟩
44+
45+
theorem mul_norm_unit_eq_mul_norm_unit {a b : α}
46+
(hab : a ∣ b) (hba : b ∣ a) : a * norm_unit a = b * norm_unit b :=
47+
begin
48+
rcases associated_of_dvd_of_dvd hab hba with ⟨u, rfl⟩,
49+
refine classical.by_cases (assume : a = 0, by simp [this] at *) (assume ha : a ≠ 0, _),
50+
suffices : a * ↑(norm_unit a) = a * ↑u * ↑(norm_unit a) * ↑u⁻¹, by simpa [ha, mul_assoc],
51+
calc a * ↑(norm_unit a) = a * ↑(norm_unit a) * ↑ u * ↑u⁻¹: by simp
52+
... = a * ↑u * ↑(norm_unit a) * ↑u⁻¹ : by ac_refl
53+
end
54+
55+
theorem dvd_antisymm_of_norm {a b : α}
56+
(ha : norm_unit a = 1) (hb : norm_unit b = 1) (hab : a ∣ b) (hba : b ∣ a) :
57+
a = b :=
58+
have a * norm_unit a = b * norm_unit b, from mul_norm_unit_eq_mul_norm_unit hab hba,
59+
by simpa [ha, hb]
60+
61+
end normalization_domain
62+
63+
/-- GCD domain: an integral domain with normalization and `gcd` (greatest common divisor) and
64+
`lcm` (least common multiple) operations. In this setting `gcd` and `lcm` form a bounded lattice on
65+
the associated elements where `gcd` is the infimum, `lcm` is the supremum, `1` is bottom, and
66+
`0` is top. The type class focuses on `gcd` and we derive the correpsonding `lcm` facts from `gcd`.
67+
-/
68+
class gcd_domain (α : Type*) extends normalization_domain α :=
69+
(gcd : α → α → α)
70+
(lcm : α → α → α)
71+
(gcd_dvd_left : ∀a b, gcd a b ∣ a)
72+
(gcd_dvd_right : ∀a b, gcd a b ∣ b)
73+
(dvd_gcd : ∀{a b c}, a ∣ c → a ∣ b → a ∣ gcd c b)
74+
(norm_unit_gcd : ∀a b, norm_unit (gcd a b) = 1)
75+
(gcd_mul_lcm : ∀a b, gcd a b * lcm a b = a * b * norm_unit (a * b))
76+
(lcm_zero_left : ∀a, lcm 0 a = 0)
77+
(lcm_zero_right : ∀a, lcm a 0 = 0)
78+
79+
export gcd_domain (gcd lcm gcd_dvd_left gcd_dvd_right dvd_gcd lcm_zero_left lcm_zero_right)
80+
81+
attribute [simp] lcm_zero_left lcm_zero_right
82+
83+
section gcd_domain
84+
variables [gcd_domain α]
85+
86+
@[simp] theorem norm_unit_gcd : ∀a b:α, norm_unit (gcd a b) = 1 :=
87+
gcd_domain.norm_unit_gcd
88+
89+
@[simp] theorem gcd_mul_lcm : ∀a b:α, gcd a b * lcm a b = a * b * norm_unit (a * b) :=
90+
gcd_domain.gcd_mul_lcm
91+
92+
section gcd
93+
94+
theorem dvd_gcd_iff (a b c : α) : a ∣ gcd b c ↔ (a ∣ b ∧ a ∣ c) :=
95+
iff.intro
96+
(assume h, ⟨dvd_trans h (gcd_dvd_left _ _), dvd_trans h (gcd_dvd_right _ _)⟩)
97+
(assume ⟨hab, hac⟩, dvd_gcd hab hac)
98+
99+
theorem gcd_comm (a b : α) : gcd a b = gcd b a :=
100+
dvd_antisymm_of_norm (norm_unit_gcd _ _) (norm_unit_gcd _ _)
101+
(dvd_gcd (gcd_dvd_right _ _) (gcd_dvd_left _ _))
102+
(dvd_gcd (gcd_dvd_right _ _) (gcd_dvd_left _ _))
103+
104+
theorem gcd_assoc (m n k : α) : gcd (gcd m n) k = gcd m (gcd n k) :=
105+
dvd_antisymm_of_norm (norm_unit_gcd _ _) (norm_unit_gcd _ _)
106+
(dvd_gcd
107+
(dvd.trans (gcd_dvd_left (gcd m n) k) (gcd_dvd_left m n))
108+
(dvd_gcd (dvd.trans (gcd_dvd_left (gcd m n) k) (gcd_dvd_right m n)) (gcd_dvd_right (gcd m n) k)))
109+
(dvd_gcd
110+
(dvd_gcd (gcd_dvd_left m (gcd n k)) (dvd.trans (gcd_dvd_right m (gcd n k)) (gcd_dvd_left n k)))
111+
(dvd.trans (gcd_dvd_right m (gcd n k)) (gcd_dvd_right n k)))
112+
113+
instance : is_commutative α gcd := ⟨gcd_comm⟩
114+
instance : is_associative α gcd := ⟨gcd_assoc⟩
115+
116+
theorem gcd_eq_mul_norm_unit {a b c : α} (habc : gcd a b ∣ c) (hcab : c ∣ gcd a b) :
117+
gcd a b = c * norm_unit c :=
118+
suffices gcd a b * norm_unit (gcd a b) = c * norm_unit c, by simpa,
119+
mul_norm_unit_eq_mul_norm_unit habc hcab
120+
121+
@[simp] theorem gcd_zero_left (a : α) : gcd 0 a = a * norm_unit a :=
122+
gcd_eq_mul_norm_unit (gcd_dvd_right 0 a) (dvd_gcd (dvd_zero _) (dvd_refl a))
123+
124+
@[simp] theorem gcd_zero_right (a : α) : gcd a 0 = a * norm_unit a :=
125+
gcd_eq_mul_norm_unit (gcd_dvd_left a 0) (dvd_gcd (dvd_refl a) (dvd_zero _))
126+
127+
@[simp] theorem gcd_eq_zero_iff (a b : α) : gcd a b = 0 ↔ a = 0 ∧ b = 0 :=
128+
iff.intro
129+
(assume h, let ⟨ca, ha⟩ := gcd_dvd_left a b, ⟨cb, hb⟩ := gcd_dvd_right a b in
130+
by simp [h] at ha hb; exact ⟨ha, hb⟩)
131+
(assume ⟨ha, hb⟩, by simp [ha, hb])
132+
133+
@[simp] theorem gcd_one_left (a : α) : gcd 1 a = 1 :=
134+
dvd_antisymm_of_norm (norm_unit_gcd _ _) norm_unit_one (gcd_dvd_left _ _)
135+
(dvd_gcd (dvd_refl 1) (one_dvd _))
136+
137+
@[simp] theorem gcd_one_right (a : α) : gcd a 1 = 1 :=
138+
dvd_antisymm_of_norm (norm_unit_gcd _ _) norm_unit_one (gcd_dvd_right _ _)
139+
(dvd_gcd (one_dvd _) (dvd_refl 1))
140+
141+
theorem gcd_dvd_gcd {a b c d: α} (hab : a ∣ b) (hcd : c ∣ d) : gcd a c ∣ gcd b d :=
142+
dvd_gcd (dvd.trans (gcd_dvd_left _ _) hab) (dvd.trans (gcd_dvd_right _ _) hcd)
143+
144+
@[simp] theorem gcd_same (a : α) : gcd a a = a * norm_unit a :=
145+
gcd_eq_mul_norm_unit (gcd_dvd_left _ _) (dvd_gcd (dvd_refl a) (dvd_refl a))
146+
147+
@[simp] theorem gcd_mul_left (a b c : α) : gcd (a * b) (a * c) = (a * norm_unit a) * gcd b c :=
148+
classical.by_cases (assume h : a = 0, by simp [h]) $ assume ha : a ≠ 0,
149+
classical.by_cases (assume h : gcd b c = 0, by simp * at *) $ assume hbc : gcd b c ≠ 0,
150+
suffices gcd (a * b) (a * c) = a * gcd b c * norm_unit (a * gcd b c),
151+
by simpa [mul_comm, mul_assoc, mul_left_comm, norm_unit_mul a _ ha hbc],
152+
let ⟨d, eq⟩ := dvd_gcd (dvd_mul_right a b) (dvd_mul_right a c) in
153+
gcd_eq_mul_norm_unit
154+
(eq.symm ▸ mul_dvd_mul_left a $ show d ∣ gcd b c, from
155+
dvd_gcd
156+
((mul_dvd_mul_iff_left ha).1 $ eq ▸ gcd_dvd_left _ _)
157+
((mul_dvd_mul_iff_left ha).1 $ eq ▸ gcd_dvd_right _ _))
158+
(dvd_gcd
159+
(mul_dvd_mul_left a $ gcd_dvd_left _ _)
160+
(mul_dvd_mul_left a $ gcd_dvd_right _ _))
161+
162+
@[simp] theorem gcd_mul_right (a b c : α) : gcd (b * a) (c * a) = gcd b c * (a * norm_unit a) :=
163+
by simpa [mul_comm] using gcd_mul_left a b c
164+
165+
theorem gcd_eq_left_iff (a b : α) (h : norm_unit a = 1) : gcd a b = a ↔ a ∣ b :=
166+
iff.intro (assume eq, eq ▸ gcd_dvd_right _ _) $
167+
assume hab, dvd_antisymm_of_norm (norm_unit_gcd _ _) h (gcd_dvd_left _ _) (dvd_gcd (dvd_refl a) hab)
168+
169+
theorem gcd_eq_right_iff (a b : α) (h : norm_unit b = 1) : gcd a b = b ↔ b ∣ a :=
170+
by simpa [gcd_comm a b] using gcd_eq_left_iff b a h
171+
172+
theorem gcd_dvd_gcd_mul_left (m n k : α) : gcd m n ∣ gcd (k * m) n :=
173+
gcd_dvd_gcd (dvd_mul_left _ _) (dvd_refl _)
174+
175+
theorem gcd_dvd_gcd_mul_right (m n k : α) : gcd m n ∣ gcd (m * k) n :=
176+
gcd_dvd_gcd (dvd_mul_right _ _) (dvd_refl _)
177+
178+
theorem gcd_dvd_gcd_mul_left_right (m n k : α) : gcd m n ∣ gcd m (k * n) :=
179+
gcd_dvd_gcd (dvd_refl _) (dvd_mul_left _ _)
180+
181+
theorem gcd_dvd_gcd_mul_right_right (m n k : α) : gcd m n ∣ gcd m (n * k) :=
182+
gcd_dvd_gcd (dvd_refl _) (dvd_mul_right _ _)
183+
184+
end gcd
185+
186+
section lcm
187+
188+
lemma lcm_dvd_iff (a b c : α) : lcm a b ∣ c ↔ a ∣ c ∧ b ∣ c :=
189+
classical.by_cases
190+
(assume : a = 0 ∨ b = 0, by cases this with h h; simp [h, iff_def] {contextual := tt})
191+
(assume this : ¬ (a = 0 ∨ b = 0),
192+
have a ≠ 0 ∧ b ≠ 0, by simpa [not_or_distrib] using this,
193+
have h : gcd a b ≠ 0, by simp [gcd_eq_zero_iff, this],
194+
by rw [← mul_dvd_mul_iff_left h, gcd_mul_lcm, units.coe_mul_dvd,
195+
← units.dvd_coe_mul _ _ (norm_unit c), mul_assoc, mul_comm (gcd a b),
196+
← gcd_mul_left, dvd_gcd_iff, mul_comm c a, mul_dvd_mul_iff_left this.1,
197+
mul_dvd_mul_iff_right this.2, and_comm])
198+
199+
lemma dvd_lcm_left (a b : α) : a ∣ lcm a b :=
200+
have a ∣ lcm a b ∧ b ∣ lcm a b, from (lcm_dvd_iff _ _ _).1 (dvd_refl _),
201+
this.1
202+
203+
lemma dvd_lcm_right (a b : α) : b ∣ lcm a b :=
204+
have a ∣ lcm a b ∧ b ∣ lcm a b, from (lcm_dvd_iff _ _ _).1 (dvd_refl _),
205+
this.2
206+
207+
lemma lcm_dvd {a b c : α} (hab : a ∣ b) (hcb : c ∣ b) : lcm a c ∣ b :=
208+
(lcm_dvd_iff _ _ _).2 ⟨hab, hcb⟩
209+
210+
@[simp] theorem lcm_eq_zero_iff (a b : α) : lcm a b = 0 ↔ a = 0 ∨ b = 0 :=
211+
iff.intro
212+
(assume h : lcm a b = 0,
213+
have a * b * norm_unit (a * b) = 0,
214+
by rw [← gcd_mul_lcm _ _, h, mul_zero],
215+
by simpa [mul_eq_zero])
216+
(by simp [or_imp_distrib] {contextual := tt})
217+
218+
@[simp] lemma norm_unit_lcm (a b : α) : norm_unit (lcm a b) = 1 :=
219+
classical.by_cases (assume : lcm a b = 0, by simp [this]) $
220+
assume h_lcm : lcm a b ≠ 0,
221+
have gcd a b ≠ 0, by simp [*, not_or_distrib] at *,
222+
have norm_unit (gcd a b * lcm a b) = 1,
223+
by rw [gcd_mul_lcm, norm_unit_mul_norm_unit],
224+
by simp [norm_unit_mul, *, -gcd_mul_lcm] at *
225+
226+
theorem lcm_comm (a b : α) : lcm a b = lcm b a :=
227+
dvd_antisymm_of_norm (norm_unit_lcm _ _) (norm_unit_lcm _ _)
228+
(lcm_dvd (dvd_lcm_right _ _) (dvd_lcm_left _ _))
229+
(lcm_dvd (dvd_lcm_right _ _) (dvd_lcm_left _ _))
230+
231+
theorem lcm_assoc (m n k : α) : lcm (lcm m n) k = lcm m (lcm n k) :=
232+
dvd_antisymm_of_norm (norm_unit_lcm _ _) (norm_unit_lcm _ _)
233+
(lcm_dvd
234+
(lcm_dvd (dvd_lcm_left _ _) (dvd.trans (dvd_lcm_left _ _) (dvd_lcm_right _ _)))
235+
(dvd.trans (dvd_lcm_right _ _) (dvd_lcm_right _ _)))
236+
(lcm_dvd
237+
(dvd.trans (dvd_lcm_left _ _) (dvd_lcm_left _ _))
238+
(lcm_dvd (dvd.trans (dvd_lcm_right _ _) (dvd_lcm_left _ _)) (dvd_lcm_right _ _)))
239+
240+
instance : is_commutative α lcm := ⟨lcm_comm⟩
241+
instance : is_associative α lcm := ⟨lcm_assoc⟩
242+
243+
lemma lcm_eq_mul_norm_unit {a b c : α} (habc : lcm a b ∣ c) (hcab : c ∣ lcm a b) :
244+
lcm a b = c * norm_unit c :=
245+
dvd_antisymm_of_norm (norm_unit_lcm _ _) (norm_unit_mul_norm_unit _)
246+
((units.dvd_coe_mul _ _ _).2 $ habc)
247+
((units.coe_mul_dvd _ _ _).2 $ hcab)
248+
249+
theorem lcm_dvd_lcm {a b c d : α} (hab : a ∣ b) (hcd : c ∣ d) : lcm a c ∣ lcm b d :=
250+
lcm_dvd (dvd.trans hab (dvd_lcm_left _ _)) (dvd.trans hcd (dvd_lcm_right _ _))
251+
252+
@[simp] theorem lcm_units_coe_left (u : units α) (a : α) : lcm ↑u a = a * norm_unit a :=
253+
lcm_eq_mul_norm_unit (lcm_dvd (units.coe_dvd _ _) (dvd_refl _)) (dvd_lcm_right _ _)
254+
255+
@[simp] theorem lcm_units_coe_right (a : α) (u : units α) : lcm a ↑u = a * norm_unit a :=
256+
by rw [lcm_comm a, lcm_units_coe_left]
257+
258+
@[simp] theorem lcm_one_left (a : α) : lcm 1 a = a * norm_unit a :=
259+
lcm_units_coe_left 1 a
260+
261+
@[simp] theorem lcm_one_right (a : α) : lcm a 1 = a * norm_unit a :=
262+
lcm_units_coe_right a 1
263+
264+
@[simp] theorem lcm_same (a : α) : lcm a a = a * norm_unit a :=
265+
lcm_eq_mul_norm_unit (lcm_dvd (dvd_refl _) (dvd_refl _)) (dvd_lcm_left _ _)
266+
267+
@[simp] theorem lcm_eq_one_iff (a b : α) : lcm a b = 1 ↔ a ∣ 1 ∧ b ∣ 1 :=
268+
iff.intro
269+
(assume eq, eq ▸ ⟨dvd_lcm_left _ _, dvd_lcm_right _ _⟩)
270+
(assume ⟨⟨c, hc⟩, ⟨d, hd⟩⟩,
271+
show lcm (units.mk_of_mul_eq_one a c hc.symm : α) (units.mk_of_mul_eq_one b d hd.symm) = 1,
272+
by simp)
273+
274+
@[simp] theorem lcm_mul_left (a b c : α) : lcm (a * b) (a * c) = (a * norm_unit a) * lcm b c :=
275+
classical.by_cases (assume : a = 0, by simp * at *) $ assume ha : a ≠ 0,
276+
classical.by_cases (assume : lcm b c = 0, by simp [*, mul_eq_zero] at *) $ assume hbc : lcm b c ≠ 0,
277+
suffices lcm (a * b) (a * c) = a * lcm b c * norm_unit (a * lcm b c),
278+
by simpa [ha, hbc, norm_unit_mul, mul_assoc, mul_comm, mul_left_comm],
279+
have a ∣ lcm (a * b) (a * c), from dvd.trans (dvd_mul_right _ _) (dvd_lcm_left _ _),
280+
let ⟨d, eq⟩ := this in
281+
lcm_eq_mul_norm_unit
282+
(lcm_dvd (mul_dvd_mul_left a (dvd_lcm_left _ _)) (mul_dvd_mul_left a (dvd_lcm_right _ _)))
283+
(eq.symm ▸ (mul_dvd_mul_left a $ lcm_dvd
284+
((mul_dvd_mul_iff_left ha).1 $ eq ▸ dvd_lcm_left _ _)
285+
((mul_dvd_mul_iff_left ha).1 $ eq ▸ dvd_lcm_right _ _)))
286+
287+
@[simp] theorem lcm_mul_right (a b c : α) : lcm (b * a) (c * a) = lcm b c * (a * norm_unit a) :=
288+
by simpa [mul_comm] using lcm_mul_left a b c
289+
290+
theorem lcm_eq_left_iff (a b : α) (h : norm_unit a = 1) : lcm a b = a ↔ b ∣ a :=
291+
iff.intro (assume eq, eq ▸ dvd_lcm_right _ _) $
292+
assume hab, dvd_antisymm_of_norm (norm_unit_lcm _ _) h (lcm_dvd (dvd_refl a) hab) (dvd_lcm_left _ _)
293+
294+
theorem lcm_eq_right_iff (a b : α) (h : norm_unit b = 1) : lcm a b = b ↔ a ∣ b :=
295+
by simpa [lcm_comm b a] using lcm_eq_left_iff b a h
296+
297+
theorem lcm_dvd_lcm_mul_left (m n k : α) : lcm m n ∣ lcm (k * m) n :=
298+
lcm_dvd_lcm (dvd_mul_left _ _) (dvd_refl _)
299+
300+
theorem lcm_dvd_lcm_mul_right (m n k : α) : lcm m n ∣ lcm (m * k) n :=
301+
lcm_dvd_lcm (dvd_mul_right _ _) (dvd_refl _)
302+
303+
theorem lcm_dvd_lcm_mul_left_right (m n k : α) : lcm m n ∣ lcm m (k * n) :=
304+
lcm_dvd_lcm (dvd_refl _) (dvd_mul_left _ _)
305+
306+
theorem lcm_dvd_lcm_mul_right_right (m n k : α) : lcm m n ∣ lcm m (n * k) :=
307+
lcm_dvd_lcm (dvd_refl _) (dvd_mul_right _ _)
308+
309+
end lcm
310+
311+
end gcd_domain

0 commit comments

Comments
 (0)