-
Notifications
You must be signed in to change notification settings - Fork 232
Expand file tree
/
Copy pathSection_4_2.lean
More file actions
384 lines (299 loc) · 13.8 KB
/
Section_4_2.lean
File metadata and controls
384 lines (299 loc) · 13.8 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
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
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
import Mathlib.Tactic
import Mathlib.Algebra.Group.MinimalAxioms
set_option doc.verso.suggestions false
/-!
# Analysis I, Section 4.2
This file is a translation of Section 4.2 of Analysis I to Lean 4.
All numbering refers to the original text.
I have attempted to make the translation as faithful a paraphrasing as possible of the original
text. When there is a choice between a more idiomatic Lean solution and a more faithful
translation, I have generally chosen the latter. In particular, there will be places where the
Lean code could be "golfed" to be more elegant and idiomatic, but I have consciously avoided
doing so.
Main constructions and results of this section:
- Definition of the "Section 4.2" rationals, `Section_4_2.Rat`, as formal quotients `a // b` of
integers `a b:ℤ`, up to equivalence. (This is a quotient of a scaffolding type
`Section_4_2.PreRat`, which consists of formal quotients without any equivalence imposed.)
- Field operations and order on these rationals, as well as an embedding of {lean}`ℕ` and {lean}`ℤ`.
- Equivalence with the Mathlib rationals {name}`_root_.Rat` (or {lean}`ℚ`), which we will use going forward.
Note: here (and in the sequel) we use Mathlib's natural numbers {lean}`ℕ` and integers {lean}`ℤ` rather than
the Chapter 2 natural numbers and Section 4.1 integers.
## Tips from past users
Users of the companion who have completed the exercises in this section are welcome to send their tips for future users in this section as PRs.
- (Add tip here)
-/
namespace Section_4_2
structure PreRat where
numerator : ℤ
denominator : ℤ
nonzero : denominator ≠ 0
/-- Exercise 4.2.1 -/
instance PreRat.instSetoid : Setoid PreRat where
r a b := a.numerator * b.denominator = b.numerator * a.denominator
iseqv := {
refl := by sorry
symm := by sorry
trans := by sorry
}
@[simp]
theorem PreRat.eq (a b c d:ℤ) (hb: b ≠ 0) (hd: d ≠ 0) :
(⟨ a,b,hb ⟩: PreRat) ≈ ⟨ c,d,hd ⟩ ↔ a * d = c * b := by rfl
abbrev Rat := Quotient PreRat.instSetoid
/-- We give division a "junk" value of 0//1 if the denominator is zero -/
abbrev Rat.formalDiv (a b:ℤ) : Rat :=
Quotient.mk PreRat.instSetoid (if h:b ≠ 0 then ⟨ a,b,h ⟩ else ⟨ 0, 1, by decide ⟩)
infix:100 " // " => Rat.formalDiv
/-- Definition 4.2.1 (Rationals) -/
theorem Rat.eq (a c:ℤ) {b d:ℤ} (hb: b ≠ 0) (hd: d ≠ 0): a // b = c // d ↔ a * d = c * b := by
simp [formalDiv, hb, hd, Quotient.eq, PreRat.instSetoid]
/-- Definition 4.2.1 (Rationals) -/
theorem Rat.eq_diff (n:Rat) : ∃ a b, b ≠ 0 ∧ n = a // b := by
apply Quotient.ind _ n; intro ⟨ a, b, h ⟩
refine ⟨ a, b, h, ?_ ⟩
simp [formalDiv, h]
/--
Decidability of equality. Hint: modify the proof of {lean}`DecidableEq Int` from the previous
section. However, because formal division handles the case of zero denominator separately, it
may be more convenient to avoid that operation and work directly with the {name}`Quotient` API.
-/
instance Rat.decidableEq : DecidableEq Rat := by
sorry
/-- Lemma 4.2.3 (Addition well-defined) -/
instance Rat.add_inst : Add Rat where
add := Quotient.lift₂ (fun ⟨ a, b, h1 ⟩ ⟨ c, d, h2 ⟩ ↦ (a*d+b*c) // (b*d)) (by
intro ⟨ a, b, h1 ⟩ ⟨ c, d, h2 ⟩ ⟨ a', b', h1' ⟩ ⟨ c', d', h2' ⟩ h3 h4
simp_all [Quotient.eq]
linear_combination d * d' * h3 + b * b' * h4
)
/-- Definition 4.2.2 (Addition of rationals) -/
theorem Rat.add_eq (a c:ℤ) {b d:ℤ} (hb: b ≠ 0) (hd: d ≠ 0) :
(a // b) + (c // d) = (a*d + b*c) // (b*d) := by
convert Quotient.lift₂_mk _ _ _ _ <;> simp [hb, hd]
/-- Lemma 4.2.3 (Multiplication well-defined) -/
instance Rat.mul_inst : Mul Rat where
mul := Quotient.lift₂ (fun ⟨ a, b, h1 ⟩ ⟨ c, d, h2 ⟩ ↦ (a*c) // (b*d)) (by sorry)
/-- Definition 4.2.2 (Multiplication of rationals) -/
theorem Rat.mul_eq (a c:ℤ) {b d:ℤ} (hb: b ≠ 0) (hd: d ≠ 0) :
(a // b) * (c // d) = (a*c) // (b*d) := by
convert Quotient.lift₂_mk _ _ _ _ <;> simp [hb, hd]
/-- Lemma 4.2.3 (Negation well-defined) -/
instance Rat.neg_inst : Neg Rat where
neg := Quotient.lift (fun ⟨ a, b, h1 ⟩ ↦ (-a) // b) (by sorry)
/-- Definition 4.2.2 (Negation of rationals) -/
theorem Rat.neg_eq (a:ℤ) {b:ℤ} (hb: b ≠ 0) : - (a // b) = (-a) // b := by
convert Quotient.lift_mk _ _ _ <;> simp [hb]
/-- Embedding the integers in the rationals -/
instance Rat.instIntCast : IntCast Rat where
intCast a := a // 1
instance Rat.instNatCast : NatCast Rat where
natCast n := (n:ℤ) // 1
instance Rat.instOfNat {n:ℕ} : OfNat Rat n where
ofNat := (n:ℤ) // 1
theorem Rat.coe_Int_eq (a:ℤ) : (a:Rat) = a // 1 := rfl
theorem Rat.coe_Nat_eq (n:ℕ) : (n:Rat) = n // 1 := rfl
theorem Rat.of_Nat_eq (n:ℕ) : (ofNat(n):Rat) = (ofNat(n):Nat) // 1 := rfl
/-- natCast distributes over successor -/
theorem Rat.natCast_succ (n: ℕ) : ((n + 1: ℕ): Rat) = (n: Rat) + 1 := by sorry
/-- intCast distributes over addition -/
lemma Rat.intCast_add (a b:ℤ) : (a:Rat) + (b:Rat) = (a+b:ℤ) := by sorry
/-- intCast distributes over multiplication -/
lemma Rat.intCast_mul (a b:ℤ) : (a:Rat) * (b:Rat) = (a*b:ℤ) := by sorry
/-- intCast commutes with negation -/
lemma Rat.intCast_neg (a:ℤ) : - (a:Rat) = (-a:ℤ) := rfl
theorem Rat.coe_Int_inj : Function.Injective (fun n:ℤ ↦ (n:Rat)) := by sorry
/--
Whereas the book leaves the inverse of 0 undefined, it is more convenient in Lean to assign a
"junk" value to this inverse; we arbitrarily choose this junk value to be 0.
-/
instance Rat.instInv : Inv Rat where
inv := Quotient.lift (fun ⟨ a, b, h1 ⟩ ↦ b // a) (by
sorry -- hint: split into the `a=0` and `a≠0` cases
)
lemma Rat.inv_eq (a:ℤ) {b:ℤ} (hb: b ≠ 0) : (a // b)⁻¹ = b // a := by
convert Quotient.lift_mk _ _ _ <;> simp [hb]
@[simp]
theorem Rat.inv_zero : (0:Rat)⁻¹ = 0 := rfl
/-- Proposition 4.2.4 (laws of algebra) / Exercise 4.2.3 -/
instance Rat.addGroup_inst : AddGroup Rat :=
AddGroup.ofLeftAxioms (by
-- this proof is written to follow the structure of the original text.
intro x y z
obtain ⟨ a, b, hb, rfl ⟩ := eq_diff x
obtain ⟨ c, d, hd, rfl ⟩ := eq_diff y
obtain ⟨ e, f, hf, rfl ⟩ := eq_diff z
have hbd : b*d ≠ 0 := Int.mul_ne_zero hb hd -- can also use `observe hbd : b*d ≠ 0` here
have hdf : d*f ≠ 0 := Int.mul_ne_zero hd hf -- can also use `observe hdf : d*f ≠ 0` here
have hbdf : b*d*f ≠ 0 := Int.mul_ne_zero hbd hf -- can also use `observe hbdf : b*d*f ≠ 0` here
rw [add_eq _ _ hb hd, add_eq _ _ hbd hf, add_eq _ _ hd hf,
add_eq _ _ hb hdf, ←mul_assoc b, eq _ _ hbdf hbdf]
ring
)
(by sorry) (by sorry)
/-- Proposition 4.2.4 (laws of algebra) / Exercise 4.2.3 -/
instance Rat.instAddCommGroup : AddCommGroup Rat where
add_comm := by sorry
/-- Proposition 4.2.4 (laws of algebra) / Exercise 4.2.3 -/
instance Rat.instCommMonoid : CommMonoid Rat where
mul_comm := by sorry
mul_assoc := by sorry
one_mul := by sorry
mul_one := by sorry
/-- Proposition 4.2.4 (laws of algebra) / Exercise 4.2.3 -/
instance Rat.instCommRing : CommRing Rat where
left_distrib := by sorry
right_distrib := by sorry
zero_mul := by sorry
mul_zero := by sorry
mul_assoc := by sorry
-- Usually CommRing will generate a natCast instance and a proof for this.
-- However, we are using a custom natCast for which `natCast_succ` cannot
-- be proven automatically by `rfl`. Luckily we have proven it already.
natCast_succ := natCast_succ
instance Rat.instRatCast : RatCast Rat where
ratCast q := q.num // q.den
theorem Rat.ratCast_inj : Function.Injective (fun n:ℚ ↦ (n:Rat)) := by sorry
theorem Rat.coe_Rat_eq (a:ℤ) {b:ℤ} (hb: b ≠ 0) : (a/b:ℚ) = a // b := by
set q := (a/b:ℚ)
set num :ℤ := q.num
set den :ℤ := (q.den:ℤ)
have hden : den ≠ 0 := by simp [den, q.den_nz]
change num // den = a // b
rw [eq _ _ hden hb]
qify
have hq : num / den = q := Rat.num_div_den q
rwa [div_eq_div_iff] at hq <;> simp [hden, hb]
/-- Default definition of division -/
instance Rat.instDivInvMonoid : DivInvMonoid Rat where
theorem Rat.div_eq (q r:Rat) : q/r = q * r⁻¹ := by rfl
/-- Proposition 4.2.4 (laws of algebra) / Exercise 4.2.3 -/
instance Rat.instField : Field Rat where
exists_pair_ne := by sorry
mul_inv_cancel := by sorry
inv_zero := rfl
ratCast_def := by
intro q
set num := q.num
set den := q.den
have hden : (den:ℤ) ≠ 0 := by simp [den, q.den_nz]
rw [← Rat.num_div_den q]
convert coe_Rat_eq _ hden
rw [coe_Int_eq, coe_Nat_eq, div_eq, inv_eq, mul_eq, eq] <;> simp [num, den, q.den_nz]
qsmul := _
nnqsmul := _
example : (3//4) / (5//6) = 9 // 10 := by sorry
/-- Definition of subtraction -/
theorem Rat.sub_eq (a b:Rat) : a - b = a + (-b) := by rfl
def Rat.coe_int_hom : ℤ →+* Rat where
toFun n := (n:Rat)
map_zero' := rfl
map_one' := rfl
map_add' := by sorry
map_mul' := by sorry
/-- Definition 4.2.6 (positivity) -/
def Rat.isPos (q:Rat) : Prop := ∃ a b:ℤ, a > 0 ∧ b > 0 ∧ q = a/b
/-- Definition 4.2.6 (negativity) -/
def Rat.isNeg (q:Rat) : Prop := ∃ r:Rat, r.isPos ∧ q = -r
/-- Lemma 4.2.7 (trichotomy of rationals) / Exercise 4.2.4 -/
theorem Rat.trichotomous (x:Rat) : x = 0 ∨ x.isPos ∨ x.isNeg := by sorry
/-- Lemma 4.2.7 (trichotomy of rationals) / Exercise 4.2.4 -/
theorem Rat.not_zero_and_pos (x:Rat) : ¬(x = 0 ∧ x.isPos) := by sorry
/-- Lemma 4.2.7 (trichotomy of rationals) / Exercise 4.2.4 -/
theorem Rat.not_zero_and_neg (x:Rat) : ¬(x = 0 ∧ x.isNeg) := by sorry
/-- Lemma 4.2.7 (trichotomy of rationals) / Exercise 4.2.4 -/
theorem Rat.not_pos_and_neg (x:Rat) : ¬(x.isPos ∧ x.isNeg) := by sorry
/-- Definition 4.2.8 (Ordering of the rationals) -/
instance Rat.instLT : LT Rat where
lt x y := (x-y).isNeg
/-- Definition 4.2.8 (Ordering of the rationals) -/
instance Rat.instLE : LE Rat where
le x y := (x < y) ∨ (x = y)
theorem Rat.lt_iff (x y:Rat) : x < y ↔ (x-y).isNeg := by rfl
theorem Rat.le_iff (x y:Rat) : x ≤ y ↔ (x < y) ∨ (x = y) := by rfl
theorem Rat.gt_iff (x y:Rat) : x > y ↔ (x-y).isPos := by sorry
theorem Rat.ge_iff (x y:Rat) : x ≥ y ↔ (x > y) ∨ (x = y) := by sorry
/-- Proposition 4.2.9(a) (order trichotomy) / Exercise 4.2.5 -/
theorem Rat.trichotomous' (x y:Rat) : x > y ∨ x < y ∨ x = y := by sorry
/-- Proposition 4.2.9(a) (order trichotomy) / Exercise 4.2.5 -/
theorem Rat.not_gt_and_lt (x y:Rat) : ¬ (x > y ∧ x < y):= by sorry
/-- Proposition 4.2.9(a) (order trichotomy) / Exercise 4.2.5 -/
theorem Rat.not_gt_and_eq (x y:Rat) : ¬ (x > y ∧ x = y):= by sorry
/-- Proposition 4.2.9(a) (order trichotomy) / Exercise 4.2.5 -/
theorem Rat.not_lt_and_eq (x y:Rat) : ¬ (x < y ∧ x = y):= by sorry
/-- Proposition 4.2.9(b) (order is anti-symmetric) / Exercise 4.2.5 -/
theorem Rat.antisymm (x y:Rat) : x < y ↔ y > x := by sorry
/-- Proposition 4.2.9(c) (order is transitive) / Exercise 4.2.5 -/
theorem Rat.lt_trans {x y z:Rat} (hxy: x < y) (hyz: y < z) : x < z := by sorry
/-- Proposition 4.2.9(d) (addition preserves order) / Exercise 4.2.5 -/
theorem Rat.add_lt_add_right {x y:Rat} (z:Rat) (hxy: x < y) : x + z < y + z := by sorry
/-- Proposition 4.2.9(e) (positive multiplication preserves order) / Exercise 4.2.5 -/
theorem Rat.mul_lt_mul_right {x y z:Rat} (hxy: x < y) (hz: z.isPos) : x * z < y * z := by sorry
/-- (Not from textbook) Establish the decidability of this order. -/
instance Rat.decidableRel : DecidableRel (· ≤ · : Rat → Rat → Prop) := by
intro n m
have : ∀ (n:PreRat) (m: PreRat),
Decidable (Quotient.mk PreRat.instSetoid n ≤ Quotient.mk PreRat.instSetoid m) := by
intro ⟨ a,b,hb ⟩ ⟨ c,d,hd ⟩
-- at this point, the goal is morally `Decidable(a//b ≤ c//d)`, but there are technical
-- issues due to the junk value of formal division when the denominator vanishes.
-- It may be more convenient to avoid formal division and work directly with `Quotient.mk`.
cases (0:ℤ).decLe (b*d) with
| isTrue hbd =>
cases (a * d).decLe (b * c) with
| isTrue h =>
apply isTrue
sorry
| isFalse h =>
apply isFalse
sorry
| isFalse hbd =>
cases (b * c).decLe (a * d) with
| isTrue h =>
apply isTrue
sorry
| isFalse h =>
apply isFalse
sorry
exact Quotient.recOnSubsingleton₂ n m this
/-- (Not from textbook) Rat has the structure of a linear ordering. -/
instance Rat.instLinearOrder : LinearOrder Rat where
le_refl := sorry
le_trans := sorry
lt_iff_le_not_ge := sorry
le_antisymm := sorry
le_total := sorry
toDecidableLE := decidableRel
/-- (Not from textbook) Rat has the structure of a strict ordered ring. -/
instance Rat.instIsStrictOrderedRing : IsStrictOrderedRing Rat where
add_le_add_left := by sorry
add_le_add_right := by sorry
mul_lt_mul_of_pos_left := by sorry
mul_lt_mul_of_pos_right := by sorry
le_of_add_le_add_left := by sorry
zero_le_one := by sorry
/-- Exercise 4.2.6 -/
theorem Rat.mul_lt_mul_right_of_neg (x y z:Rat) (hxy: x < y) (hz: z.isNeg) : x * z > y * z := by
sorry
/--
Not in textbook: create an equivalence between Rat and ℚ. This requires some familiarity with
the API for Mathlib's version of the rationals.
-/
abbrev Rat.equivRat : Rat ≃ ℚ where
toFun := Quotient.lift (fun ⟨ a, b, h ⟩ ↦ a / b) (by
sorry)
invFun := fun n: ℚ ↦ (n:Rat)
left_inv n := sorry
right_inv n := sorry
/-- Not in textbook: equivalence preserves order -/
abbrev Rat.equivRat_order : Rat ≃o ℚ where
toEquiv := equivRat
map_rel_iff' := by sorry
/-- Not in textbook: equivalence preserves ring operations -/
abbrev Rat.equivRat_ring : Rat ≃+* ℚ where
toEquiv := equivRat
map_add' := by sorry
map_mul' := by sorry
/--
(Not from textbook) The textbook rationals are isomorphic (as a field) to the Mathlib rationals.
-/
def Rat.equivRat_ring_symm : ℚ ≃+* Rat := Rat.equivRat_ring.symm
end Section_4_2