2015-04-18 18:00:09 +00:00
|
|
|
|
/-
|
|
|
|
|
Copyright (c) 2014 Jeremy Avigad. All rights reserved.
|
|
|
|
|
Released under Apache 2.0 license as described in the file LICENSE.
|
|
|
|
|
Author: Jeremy Avigad
|
|
|
|
|
|
|
|
|
|
The rational numbers as a field generated by the integers, defined as the usual quotient.
|
|
|
|
|
-/
|
|
|
|
|
import data.int algebra.field
|
|
|
|
|
open int quot eq.ops
|
|
|
|
|
|
|
|
|
|
record prerat : Type :=
|
|
|
|
|
(num : ℤ) (denom : ℤ) (denom_pos : denom > 0)
|
|
|
|
|
|
|
|
|
|
/-
|
|
|
|
|
prerat: the representations of the rationals as integers num, denom, with denom > 0.
|
|
|
|
|
note: names are not protected, because it is not expected that users will open prerat.
|
|
|
|
|
-/
|
|
|
|
|
|
|
|
|
|
namespace prerat
|
|
|
|
|
|
|
|
|
|
/- the equivalence relation -/
|
|
|
|
|
|
|
|
|
|
definition equiv (a b : prerat) : Prop := num a * denom b = num b * denom a
|
|
|
|
|
|
2015-04-27 17:24:18 +00:00
|
|
|
|
infix `≡` := equiv
|
2015-04-18 18:00:09 +00:00
|
|
|
|
|
2015-05-02 22:15:35 +00:00
|
|
|
|
theorem equiv.refl [refl] (a : prerat) : a ≡ a := rfl
|
2015-04-18 18:00:09 +00:00
|
|
|
|
|
2015-05-02 22:15:35 +00:00
|
|
|
|
theorem equiv.symm [symm] {a b : prerat} (H : a ≡ b) : b ≡ a := !eq.symm H
|
2015-04-18 18:00:09 +00:00
|
|
|
|
|
|
|
|
|
theorem num_eq_zero_of_equiv {a b : prerat} (H : a ≡ b) (na_zero : num a = 0) : num b = 0 :=
|
2015-07-21 16:10:56 +00:00
|
|
|
|
have num a * denom b = 0, from !zero_mul ▸ na_zero ▸ rfl,
|
|
|
|
|
have num b * denom a = 0, from H ▸ this,
|
|
|
|
|
show num b = 0, from or_resolve_left (eq_zero_or_eq_zero_of_mul_eq_zero this) (ne_of_gt (denom_pos a))
|
2015-04-18 18:00:09 +00:00
|
|
|
|
|
|
|
|
|
theorem num_pos_of_equiv {a b : prerat} (H : a ≡ b) (na_pos : num a > 0) : num b > 0 :=
|
2015-07-21 16:10:56 +00:00
|
|
|
|
have num a * denom b > 0, from mul_pos na_pos (denom_pos b),
|
|
|
|
|
have num b * denom a > 0, from H ▸ this,
|
|
|
|
|
show num b > 0, from pos_of_mul_pos_right this (le_of_lt (denom_pos a))
|
2015-04-18 18:00:09 +00:00
|
|
|
|
|
|
|
|
|
theorem num_neg_of_equiv {a b : prerat} (H : a ≡ b) (na_neg : num a < 0) : num b < 0 :=
|
2015-07-21 16:10:56 +00:00
|
|
|
|
have num a * denom b < 0, from mul_neg_of_neg_of_pos na_neg (denom_pos b),
|
|
|
|
|
have -(-num b * denom a) < 0, from !neg_mul_eq_neg_mul⁻¹ ▸ !neg_neg⁻¹ ▸ H ▸ this,
|
|
|
|
|
have -num b > 0, from pos_of_mul_pos_right (pos_of_neg_neg this) (le_of_lt (denom_pos a)),
|
|
|
|
|
neg_of_neg_pos this
|
2015-04-18 18:00:09 +00:00
|
|
|
|
|
|
|
|
|
theorem equiv_of_num_eq_zero {a b : prerat} (H1 : num a = 0) (H2 : num b = 0) : a ≡ b :=
|
|
|
|
|
by rewrite [↑equiv, H1, H2, *zero_mul]
|
|
|
|
|
|
2015-05-02 22:15:35 +00:00
|
|
|
|
theorem equiv.trans [trans] {a b c : prerat} (H1 : a ≡ b) (H2 : b ≡ c) : a ≡ c :=
|
2015-04-18 18:00:09 +00:00
|
|
|
|
decidable.by_cases
|
2015-07-21 16:10:56 +00:00
|
|
|
|
(suppose num b = 0,
|
|
|
|
|
have num a = 0, from num_eq_zero_of_equiv (equiv.symm H1) `num b = 0`,
|
|
|
|
|
have num c = 0, from num_eq_zero_of_equiv H2 `num b = 0`,
|
|
|
|
|
equiv_of_num_eq_zero `num a = 0` `num c = 0`)
|
|
|
|
|
(suppose num b ≠ 0,
|
|
|
|
|
have H3 : num b * denom b ≠ 0, from mul_ne_zero this (ne_of_gt (denom_pos b)),
|
2015-04-18 18:00:09 +00:00
|
|
|
|
have H4 : (num b * denom b) * (num a * denom c) = (num b * denom b) * (num c * denom a),
|
|
|
|
|
from calc
|
|
|
|
|
(num b * denom b) * (num a * denom c) = (num a * denom b) * (num b * denom c) :
|
|
|
|
|
by rewrite [*mul.assoc, *mul.left_comm (num a), *mul.left_comm (num b)]
|
|
|
|
|
... = (num b * denom a) * (num b * denom c) : {H1}
|
|
|
|
|
... = (num b * denom a) * (num c * denom b) : {H2}
|
|
|
|
|
... = (num b * denom b) * (num c * denom a) :
|
|
|
|
|
by rewrite [*mul.assoc, *mul.left_comm (denom a),
|
|
|
|
|
*mul.left_comm (denom b), mul.comm (denom a)],
|
2015-06-01 01:39:59 +00:00
|
|
|
|
eq_of_mul_eq_mul_left H3 H4)
|
2015-04-18 18:00:09 +00:00
|
|
|
|
|
|
|
|
|
theorem equiv.is_equivalence : equivalence equiv :=
|
|
|
|
|
mk_equivalence equiv equiv.refl @equiv.symm @equiv.trans
|
|
|
|
|
|
|
|
|
|
definition setoid : setoid prerat :=
|
|
|
|
|
setoid.mk equiv equiv.is_equivalence
|
|
|
|
|
|
|
|
|
|
/- field operations -/
|
|
|
|
|
|
|
|
|
|
definition of_int (i : int) : prerat := prerat.mk i 1 !of_nat_succ_pos
|
|
|
|
|
|
|
|
|
|
definition zero : prerat := of_int 0
|
|
|
|
|
|
|
|
|
|
definition one : prerat := of_int 1
|
|
|
|
|
|
|
|
|
|
private theorem mul_denom_pos (a b : prerat) : denom a * denom b > 0 :=
|
|
|
|
|
mul_pos (denom_pos a) (denom_pos b)
|
|
|
|
|
|
|
|
|
|
definition add (a b : prerat) : prerat :=
|
|
|
|
|
prerat.mk (num a * denom b + num b * denom a) (denom a * denom b) (mul_denom_pos a b)
|
|
|
|
|
|
|
|
|
|
definition mul (a b : prerat) : prerat :=
|
|
|
|
|
prerat.mk (num a * num b) (denom a * denom b) (mul_denom_pos a b)
|
|
|
|
|
|
|
|
|
|
definition neg (a : prerat) : prerat :=
|
|
|
|
|
prerat.mk (- num a) (denom a) (denom_pos a)
|
|
|
|
|
|
2015-07-24 15:56:18 +00:00
|
|
|
|
definition smul (a : ℤ) (b : prerat) (H : a > 0) : prerat :=
|
|
|
|
|
prerat.mk (a * num b) (a * denom b) (mul_pos H (denom_pos b))
|
|
|
|
|
|
2015-05-23 02:21:08 +00:00
|
|
|
|
theorem of_int_add (a b : ℤ) : of_int (#int a + b) ≡ add (of_int a) (of_int b) :=
|
|
|
|
|
by esimp [equiv, num, denom, one, add, of_int]; rewrite [*int.mul_one]
|
|
|
|
|
|
|
|
|
|
theorem of_int_mul (a b : ℤ) : of_int (#int a * b) ≡ mul (of_int a) (of_int b) :=
|
|
|
|
|
!equiv.refl
|
|
|
|
|
|
|
|
|
|
theorem of_int_neg (a : ℤ) : of_int (#int -a) ≡ neg (of_int a) :=
|
|
|
|
|
!equiv.refl
|
|
|
|
|
|
2015-06-10 02:46:30 +00:00
|
|
|
|
theorem of_int.inj {a b : ℤ} : of_int a ≡ of_int b → a = b :=
|
|
|
|
|
by rewrite [↑of_int, ↑equiv, *mul_one]; intros; assumption
|
|
|
|
|
|
2015-04-18 18:00:09 +00:00
|
|
|
|
definition inv : prerat → prerat
|
2015-06-29 05:16:58 +00:00
|
|
|
|
| inv (prerat.mk nat.zero d dp) := zero
|
2015-04-18 18:00:09 +00:00
|
|
|
|
| inv (prerat.mk (nat.succ n) d dp) := prerat.mk d (nat.succ n) !of_nat_succ_pos
|
2015-06-29 05:16:58 +00:00
|
|
|
|
| inv (prerat.mk -[1+n] d dp) := prerat.mk (-d) (nat.succ n) !of_nat_succ_pos
|
2015-04-18 18:00:09 +00:00
|
|
|
|
|
|
|
|
|
theorem equiv_zero_of_num_eq_zero {a : prerat} (H : num a = 0) : a ≡ zero :=
|
|
|
|
|
by rewrite [↑equiv, H, ↑zero, ↑num, ↑of_int, *zero_mul]
|
|
|
|
|
|
|
|
|
|
theorem num_eq_zero_of_equiv_zero {a : prerat} : a ≡ zero → num a = 0 :=
|
|
|
|
|
by rewrite [↑equiv, ↑zero, ↑of_int, mul_one, zero_mul]; intro H; exact H
|
|
|
|
|
|
|
|
|
|
theorem inv_zero {d : int} (dp : d > 0) : inv (mk nat.zero d dp) = zero :=
|
2015-05-07 16:09:07 +00:00
|
|
|
|
begin rewrite [↑inv, ▸*] end
|
2015-04-18 18:00:09 +00:00
|
|
|
|
|
|
|
|
|
theorem inv_zero' : inv zero = zero := inv_zero (of_nat_succ_pos nat.zero)
|
|
|
|
|
|
|
|
|
|
theorem inv_of_pos {n d : int} (np : n > 0) (dp : d > 0) : inv (mk n d dp) ≡ mk d n np :=
|
|
|
|
|
obtain (n' : nat) (Hn' : n = of_nat n'), from exists_eq_of_nat (le_of_lt np),
|
2015-07-21 16:10:56 +00:00
|
|
|
|
have (#nat n' > nat.zero), from lt_of_of_nat_lt_of_nat (Hn' ▸ np),
|
|
|
|
|
obtain (k : nat) (Hk : n' = nat.succ k), from nat.exists_eq_succ_of_lt this,
|
|
|
|
|
have d * n = d * nat.succ k, by rewrite [Hn', Hk],
|
|
|
|
|
Hn'⁻¹ ▸ (Hk⁻¹ ▸ this)
|
2015-04-18 18:00:09 +00:00
|
|
|
|
|
|
|
|
|
theorem inv_neg {n d : int} (np : n > 0) (dp : d > 0) : inv (mk (-n) d dp) ≡ mk (-d) n np :=
|
|
|
|
|
obtain (n' : nat) (Hn' : n = of_nat n'), from exists_eq_of_nat (le_of_lt np),
|
2015-07-21 16:10:56 +00:00
|
|
|
|
have (#nat n' > nat.zero), from lt_of_of_nat_lt_of_nat (Hn' ▸ np),
|
|
|
|
|
obtain (k : nat) (Hk : n' = nat.succ k), from nat.exists_eq_succ_of_lt this,
|
|
|
|
|
have -d * n = -d * nat.succ k, by rewrite [Hn', Hk],
|
|
|
|
|
have H3 : inv (mk -[1+k] d dp) ≡ mk (-d) n np, from this,
|
2015-06-29 05:16:58 +00:00
|
|
|
|
have H4 : -[1+k] = -n, from calc
|
|
|
|
|
-[1+k] = -(nat.succ k) : rfl
|
2015-04-18 18:00:09 +00:00
|
|
|
|
... = -n : by rewrite [Hk⁻¹, Hn'],
|
|
|
|
|
H4 ▸ H3
|
|
|
|
|
|
|
|
|
|
theorem inv_of_neg {n d : int} (nn : n < 0) (dp : d > 0) :
|
|
|
|
|
inv (mk n d dp) ≡ mk (-d) (-n) (neg_pos_of_neg nn) :=
|
2015-07-21 16:10:56 +00:00
|
|
|
|
have inv (mk (-(-n)) d dp) ≡ mk (-d) (-n) (neg_pos_of_neg nn),
|
2015-04-18 18:00:09 +00:00
|
|
|
|
from inv_neg (neg_pos_of_neg nn) dp,
|
2015-07-21 16:10:56 +00:00
|
|
|
|
!neg_neg ▸ this
|
2015-04-18 18:00:09 +00:00
|
|
|
|
|
|
|
|
|
/- operations respect equiv -/
|
|
|
|
|
|
|
|
|
|
theorem add_equiv_add {a1 b1 a2 b2 : prerat} (eqv1 : a1 ≡ a2) (eqv2 : b1 ≡ b2) :
|
|
|
|
|
add a1 b1 ≡ add a2 b2 :=
|
|
|
|
|
calc
|
|
|
|
|
(num a1 * denom b1 + num b1 * denom a1) * (denom a2 * denom b2)
|
|
|
|
|
= num a1 * denom a2 * denom b1 * denom b2 + num b1 * denom b2 * denom a1 * denom a2 :
|
|
|
|
|
by rewrite [mul.right_distrib, *mul.assoc, mul.left_comm (denom b1),
|
|
|
|
|
mul.comm (denom b2), *mul.assoc]
|
|
|
|
|
... = num a2 * denom a1 * denom b1 * denom b2 + num b2 * denom b1 * denom a1 * denom a2 :
|
|
|
|
|
by rewrite [↑equiv at *, eqv1, eqv2]
|
|
|
|
|
... = (num a2 * denom b2 + num b2 * denom a2) * (denom a1 * denom b1) :
|
|
|
|
|
by rewrite [mul.right_distrib, *mul.assoc, *mul.left_comm (denom b2),
|
|
|
|
|
*mul.comm (denom b1), *mul.assoc, mul.left_comm (denom a2)]
|
|
|
|
|
|
|
|
|
|
theorem mul_equiv_mul {a1 b1 a2 b2 : prerat} (eqv1 : a1 ≡ a2) (eqv2 : b1 ≡ b2) :
|
|
|
|
|
mul a1 b1 ≡ mul a2 b2 :=
|
|
|
|
|
calc
|
|
|
|
|
(num a1 * num b1) * (denom a2 * denom b2)
|
|
|
|
|
= (num a1 * denom a2) * (num b1 * denom b2) : by rewrite [*mul.assoc, mul.left_comm (num b1)]
|
|
|
|
|
... = (num a2 * denom a1) * (num b2 * denom b1) : by rewrite [↑equiv at *, eqv1, eqv2]
|
|
|
|
|
... = (num a2 * num b2) * (denom a1 * denom b1) : by rewrite [*mul.assoc, mul.left_comm (num b2)]
|
|
|
|
|
|
|
|
|
|
theorem neg_equiv_neg {a b : prerat} (eqv : a ≡ b) : neg a ≡ neg b :=
|
|
|
|
|
calc
|
|
|
|
|
-num a * denom b = -(num a * denom b) : neg_mul_eq_neg_mul
|
|
|
|
|
... = -(num b * denom a) : {eqv}
|
|
|
|
|
... = -num b * denom a : neg_mul_eq_neg_mul
|
|
|
|
|
|
|
|
|
|
theorem inv_equiv_inv : ∀{a b : prerat}, a ≡ b → inv a ≡ inv b
|
|
|
|
|
| (mk an ad adp) (mk bn bd bdp) :=
|
|
|
|
|
assume H,
|
|
|
|
|
lt.by_cases
|
|
|
|
|
(assume an_neg : an < 0,
|
|
|
|
|
have bn_neg : bn < 0, from num_neg_of_equiv H an_neg,
|
|
|
|
|
calc
|
|
|
|
|
inv (mk an ad adp) ≡ mk (-ad) (-an) (neg_pos_of_neg an_neg) : inv_of_neg an_neg adp
|
|
|
|
|
... ≡ mk (-bd) (-bn) (neg_pos_of_neg bn_neg) :
|
|
|
|
|
by rewrite [↑equiv at *, ▸*, *neg_mul_neg, mul.comm ad, mul.comm bd, H]
|
2015-05-27 19:07:39 +00:00
|
|
|
|
... ≡ inv (mk bn bd bdp) : (inv_of_neg bn_neg bdp)⁻¹)
|
2015-04-18 18:00:09 +00:00
|
|
|
|
(assume an_zero : an = 0,
|
|
|
|
|
have bn_zero : bn = 0, from num_eq_zero_of_equiv H an_zero,
|
|
|
|
|
eq.subst (calc
|
|
|
|
|
inv (mk an ad adp) = inv (mk 0 ad adp) : {an_zero}
|
|
|
|
|
... = zero : inv_zero
|
|
|
|
|
... = inv (mk 0 bd bdp) : inv_zero
|
|
|
|
|
... = inv (mk bn bd bdp) : bn_zero) !equiv.refl)
|
|
|
|
|
(assume an_pos : an > 0,
|
|
|
|
|
have bn_pos : bn > 0, from num_pos_of_equiv H an_pos,
|
|
|
|
|
calc
|
|
|
|
|
inv (mk an ad adp) ≡ mk ad an an_pos : inv_of_pos an_pos adp
|
|
|
|
|
... ≡ mk bd bn bn_pos :
|
|
|
|
|
by rewrite [↑equiv at *, ▸*, mul.comm ad, mul.comm bd, H]
|
2015-05-27 19:07:39 +00:00
|
|
|
|
... ≡ inv (mk bn bd bdp) : (inv_of_pos bn_pos bdp)⁻¹)
|
2015-04-18 18:00:09 +00:00
|
|
|
|
|
2015-07-24 15:56:18 +00:00
|
|
|
|
theorem smul_equiv {a : ℤ} {b : prerat} (H : a > 0) : smul a b H ≡ b :=
|
|
|
|
|
by esimp[equiv, smul]; rewrite[mul.assoc, mul.left_comm]
|
|
|
|
|
|
2015-04-18 18:00:09 +00:00
|
|
|
|
/- properties -/
|
|
|
|
|
|
|
|
|
|
theorem add.comm (a b : prerat) : add a b ≡ add b a :=
|
|
|
|
|
by rewrite [↑add, ↑equiv, ▸*, add.comm, mul.comm (denom a)]
|
|
|
|
|
|
|
|
|
|
theorem add.assoc (a b c : prerat) : add (add a b) c ≡ add a (add b c) :=
|
|
|
|
|
by rewrite [↑add, ↑equiv, ▸*, *(mul.comm (num c)), *(λy, mul.comm y (denom a)), *mul.left_distrib,
|
|
|
|
|
*mul.right_distrib, *mul.assoc, *add.assoc]
|
|
|
|
|
|
|
|
|
|
theorem add_zero (a : prerat) : add a zero ≡ a :=
|
|
|
|
|
by rewrite [↑add, ↑equiv, ↑zero, ↑of_int, ▸*, *mul_one, zero_mul, add_zero]
|
|
|
|
|
|
|
|
|
|
theorem add.left_inv (a : prerat) : add (neg a) a ≡ zero :=
|
|
|
|
|
by rewrite [↑add, ↑equiv, ↑neg, ↑zero, ↑of_int, ▸*, -neg_mul_eq_neg_mul, add.left_inv, *zero_mul]
|
|
|
|
|
|
|
|
|
|
theorem mul.comm (a b : prerat) : mul a b ≡ mul b a :=
|
|
|
|
|
by rewrite [↑mul, ↑equiv, mul.comm (num a), mul.comm (denom a)]
|
|
|
|
|
|
|
|
|
|
theorem mul.assoc (a b c : prerat) : mul (mul a b) c ≡ mul a (mul b c) :=
|
|
|
|
|
by rewrite [↑mul, ↑equiv, *mul.assoc]
|
|
|
|
|
|
|
|
|
|
theorem mul_one (a : prerat) : mul a one ≡ a :=
|
|
|
|
|
by rewrite [↑mul, ↑one, ↑of_int, ↑equiv, ▸*, *mul_one]
|
|
|
|
|
|
|
|
|
|
theorem mul.left_distrib (a b c : prerat) : mul a (add b c) ≡ add (mul a b) (mul a c) :=
|
2015-07-24 15:56:18 +00:00
|
|
|
|
have H : smul (denom a) (mul a (add b c)) (denom_pos a) =
|
|
|
|
|
add (mul a b) (mul a c), from begin
|
|
|
|
|
rewrite[↑smul, ↑mul, ↑add],
|
|
|
|
|
congruence,
|
|
|
|
|
rewrite[*mul.left_distrib, *mul.right_distrib, -*int.mul.assoc],
|
|
|
|
|
have T : ∀ {x y z w : ℤ}, x*y*z*w=y*z*x*w, from
|
|
|
|
|
λx y z w, (!int.mul.assoc ⬝ !int.mul.comm) ▸ rfl,
|
|
|
|
|
exact !congr_arg2 T T,
|
|
|
|
|
exact !mul.left_comm ▸ !int.mul.assoc⁻¹
|
|
|
|
|
end,
|
|
|
|
|
equiv.symm (H ▸ smul_equiv (denom_pos a))
|
2015-04-18 18:00:09 +00:00
|
|
|
|
|
|
|
|
|
theorem mul_inv_cancel : ∀{a : prerat}, ¬ a ≡ zero → mul a (inv a) ≡ one
|
|
|
|
|
| (mk an ad adp) :=
|
|
|
|
|
assume H,
|
|
|
|
|
let a := mk an ad adp in
|
|
|
|
|
lt.by_cases
|
|
|
|
|
(assume an_neg : an < 0,
|
|
|
|
|
let ia := mk (-ad) (-an) (neg_pos_of_neg an_neg) in
|
|
|
|
|
calc
|
|
|
|
|
mul a (inv a) ≡ mul a ia : mul_equiv_mul !equiv.refl (inv_of_neg an_neg adp)
|
|
|
|
|
... ≡ one : begin
|
|
|
|
|
esimp [equiv, num, denom, one, mul, of_int],
|
|
|
|
|
rewrite [*int.mul_one, *int.one_mul, int.mul.comm,
|
|
|
|
|
neg_mul_comm]
|
|
|
|
|
end)
|
|
|
|
|
(assume an_zero : an = 0, absurd (equiv_zero_of_num_eq_zero an_zero) H)
|
|
|
|
|
(assume an_pos : an > 0,
|
|
|
|
|
let ia := mk ad an an_pos in
|
|
|
|
|
calc
|
|
|
|
|
mul a (inv a) ≡ mul a ia : mul_equiv_mul !equiv.refl (inv_of_pos an_pos adp)
|
|
|
|
|
... ≡ one : begin
|
|
|
|
|
esimp [equiv, num, denom, one, mul, of_int],
|
|
|
|
|
rewrite [*int.mul_one, *int.one_mul, int.mul.comm]
|
|
|
|
|
end)
|
|
|
|
|
|
|
|
|
|
theorem zero_not_equiv_one : ¬ zero ≡ one :=
|
|
|
|
|
begin
|
|
|
|
|
esimp [equiv, zero, one, of_int],
|
|
|
|
|
rewrite [zero_mul, int.mul_one],
|
|
|
|
|
exact zero_ne_one
|
|
|
|
|
end
|
|
|
|
|
|
2015-06-10 02:46:30 +00:00
|
|
|
|
theorem mul_denom_equiv (a : prerat) : mul a (of_int (denom a)) ≡ of_int (num a) :=
|
|
|
|
|
by esimp [mul, of_int, equiv]; rewrite [*int.mul_one]
|
|
|
|
|
|
|
|
|
|
/- Reducing a fraction to lowest terms. Needed to choose a canonical representative of rat, and
|
|
|
|
|
define numerator and denominator. -/
|
|
|
|
|
|
|
|
|
|
definition reduce : prerat → prerat
|
|
|
|
|
| (mk an ad adpos) :=
|
|
|
|
|
have pos : ad div gcd an ad > 0, from div_pos_of_pos_of_dvd adpos !gcd_nonneg !gcd_dvd_right,
|
|
|
|
|
if an = 0 then prerat.zero
|
|
|
|
|
else mk (an div gcd an ad) (ad div gcd an ad) pos
|
|
|
|
|
|
|
|
|
|
protected theorem eq {a b : prerat} (Hn : num a = num b) (Hd : denom a = denom b) : a = b :=
|
|
|
|
|
begin
|
|
|
|
|
cases a with [an, ad, adpos],
|
|
|
|
|
cases b with [bn, bd, bdpos],
|
|
|
|
|
generalize adpos, generalize bdpos,
|
|
|
|
|
esimp at *,
|
|
|
|
|
rewrite [Hn, Hd],
|
|
|
|
|
intros, apply rfl
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
theorem reduce_equiv : ∀ a : prerat, reduce a ≡ a
|
|
|
|
|
| (mk an ad adpos) :=
|
|
|
|
|
decidable.by_cases
|
|
|
|
|
(assume anz : an = 0,
|
|
|
|
|
by krewrite [↑reduce, if_pos anz, ↑equiv, anz, *zero_mul])
|
|
|
|
|
(assume annz : an ≠ 0,
|
|
|
|
|
by rewrite [↑reduce, if_neg annz, ↑equiv, int.mul.comm, -!mul_div_assoc !gcd_dvd_left,
|
|
|
|
|
-!mul_div_assoc !gcd_dvd_right, int.mul.comm])
|
|
|
|
|
|
|
|
|
|
theorem reduce_eq_reduce : ∀{a b : prerat}, a ≡ b → reduce a = reduce b
|
|
|
|
|
| (mk an ad adpos) (mk bn bd bdpos) :=
|
|
|
|
|
assume H : an * bd = bn * ad,
|
|
|
|
|
decidable.by_cases
|
|
|
|
|
(assume anz : an = 0,
|
|
|
|
|
have H' : bn * ad = 0, by rewrite [-H, anz, zero_mul],
|
2015-06-29 05:16:58 +00:00
|
|
|
|
assert bnz : bn = 0,
|
|
|
|
|
from or_resolve_left (eq_zero_or_eq_zero_of_mul_eq_zero H') (ne_of_gt adpos),
|
2015-06-10 02:46:30 +00:00
|
|
|
|
by rewrite [↑reduce, if_pos anz, if_pos bnz])
|
|
|
|
|
(assume annz : an ≠ 0,
|
|
|
|
|
assert bnnz : bn ≠ 0, from
|
|
|
|
|
assume bnz,
|
|
|
|
|
have H' : an * bd = 0, by rewrite [H, bnz, zero_mul],
|
2015-06-29 05:16:58 +00:00
|
|
|
|
have anz : an = 0,
|
|
|
|
|
from or_resolve_left (eq_zero_or_eq_zero_of_mul_eq_zero H') (ne_of_gt bdpos),
|
2015-06-10 02:46:30 +00:00
|
|
|
|
show false, from annz anz,
|
|
|
|
|
begin
|
|
|
|
|
rewrite [↑reduce, if_neg annz, if_neg bnnz],
|
|
|
|
|
apply prerat.eq,
|
|
|
|
|
{apply div_gcd_eq_div_gcd H adpos bdpos},
|
|
|
|
|
{esimp, rewrite [gcd.comm, gcd.comm bn],
|
|
|
|
|
apply div_gcd_eq_div_gcd_of_nonneg,
|
|
|
|
|
rewrite [int.mul.comm, -H, int.mul.comm],
|
|
|
|
|
apply annz,
|
|
|
|
|
apply bnnz,
|
|
|
|
|
apply le_of_lt adpos,
|
|
|
|
|
apply le_of_lt bdpos},
|
|
|
|
|
end)
|
|
|
|
|
|
2015-04-18 18:00:09 +00:00
|
|
|
|
end prerat
|
|
|
|
|
|
|
|
|
|
/-
|
|
|
|
|
the rationals
|
|
|
|
|
-/
|
|
|
|
|
|
|
|
|
|
definition rat : Type.{1} := quot prerat.setoid
|
|
|
|
|
notation `ℚ` := rat
|
|
|
|
|
|
|
|
|
|
local attribute prerat.setoid [instance]
|
|
|
|
|
|
|
|
|
|
namespace rat
|
|
|
|
|
|
|
|
|
|
/- operations -/
|
|
|
|
|
|
|
|
|
|
definition of_int [coercion] (i : ℤ) : ℚ := ⟦prerat.of_int i⟧
|
|
|
|
|
definition of_nat [coercion] (n : ℕ) : ℚ := ⟦prerat.of_int n⟧
|
|
|
|
|
definition of_num [coercion] [reducible] (n : num) : ℚ := of_int (int.of_num n)
|
|
|
|
|
|
|
|
|
|
definition add : ℚ → ℚ → ℚ :=
|
|
|
|
|
quot.lift₂
|
2015-06-10 02:46:30 +00:00
|
|
|
|
(λ a b : prerat, ⟦prerat.add a b⟧)
|
2015-04-18 18:00:09 +00:00
|
|
|
|
(take a1 a2 b1 b2, assume H1 H2, quot.sound (prerat.add_equiv_add H1 H2))
|
|
|
|
|
|
|
|
|
|
definition mul : ℚ → ℚ → ℚ :=
|
|
|
|
|
quot.lift₂
|
2015-06-10 02:46:30 +00:00
|
|
|
|
(λ a b : prerat, ⟦prerat.mul a b⟧)
|
2015-04-18 18:00:09 +00:00
|
|
|
|
(take a1 a2 b1 b2, assume H1 H2, quot.sound (prerat.mul_equiv_mul H1 H2))
|
|
|
|
|
|
|
|
|
|
definition neg : ℚ → ℚ :=
|
|
|
|
|
quot.lift
|
2015-06-10 02:46:30 +00:00
|
|
|
|
(λ a : prerat, ⟦prerat.neg a⟧)
|
2015-04-18 18:00:09 +00:00
|
|
|
|
(take a1 a2, assume H, quot.sound (prerat.neg_equiv_neg H))
|
|
|
|
|
|
|
|
|
|
definition inv : ℚ → ℚ :=
|
|
|
|
|
quot.lift
|
2015-06-10 02:46:30 +00:00
|
|
|
|
(λ a : prerat, ⟦prerat.inv a⟧)
|
2015-04-18 18:00:09 +00:00
|
|
|
|
(take a1 a2, assume H, quot.sound (prerat.inv_equiv_inv H))
|
|
|
|
|
|
2015-06-10 02:46:30 +00:00
|
|
|
|
definition reduce : ℚ → prerat :=
|
|
|
|
|
quot.lift
|
|
|
|
|
(λ a : prerat, prerat.reduce a)
|
|
|
|
|
@prerat.reduce_eq_reduce
|
|
|
|
|
|
|
|
|
|
definition num (a : ℚ) : ℤ := prerat.num (reduce a)
|
|
|
|
|
definition denom (a : ℚ) : ℤ := prerat.denom (reduce a)
|
2015-04-18 18:00:09 +00:00
|
|
|
|
|
2015-06-10 02:46:30 +00:00
|
|
|
|
theorem denom_pos (a : ℚ): denom a > 0 :=
|
|
|
|
|
prerat.denom_pos (reduce a)
|
2015-04-18 18:00:09 +00:00
|
|
|
|
|
2015-07-01 00:34:35 +00:00
|
|
|
|
protected definition prio := num.pred int.prio
|
|
|
|
|
|
|
|
|
|
infix [priority rat.prio] + := rat.add
|
|
|
|
|
infix [priority rat.prio] * := rat.mul
|
|
|
|
|
prefix [priority rat.prio] - := rat.neg
|
2015-04-27 17:24:18 +00:00
|
|
|
|
|
2015-06-10 02:46:30 +00:00
|
|
|
|
definition sub [reducible] (a b : rat) : rat := a + (-b)
|
2015-04-27 17:24:18 +00:00
|
|
|
|
|
2015-07-01 00:34:35 +00:00
|
|
|
|
postfix [priority rat.prio] ⁻¹ := rat.inv
|
|
|
|
|
infix [priority rat.prio] - := rat.sub
|
2015-04-18 18:00:09 +00:00
|
|
|
|
|
|
|
|
|
/- properties -/
|
|
|
|
|
|
2015-05-23 02:21:08 +00:00
|
|
|
|
theorem of_int_add (a b : ℤ) : of_int (#int a + b) = of_int a + of_int b :=
|
|
|
|
|
quot.sound (prerat.of_int_add a b)
|
|
|
|
|
|
|
|
|
|
theorem of_int_mul (a b : ℤ) : of_int (#int a * b) = of_int a * of_int b :=
|
|
|
|
|
quot.sound (prerat.of_int_mul a b)
|
|
|
|
|
|
|
|
|
|
theorem of_int_neg (a : ℤ) : of_int (#int -a) = -(of_int a) :=
|
|
|
|
|
quot.sound (prerat.of_int_neg a)
|
|
|
|
|
|
|
|
|
|
theorem of_int_sub (a b : ℤ) : of_int (#int a - b) = of_int a - of_int b :=
|
|
|
|
|
calc
|
|
|
|
|
of_int (#int a - b) = of_int a + of_int (#int -b) : of_int_add
|
|
|
|
|
... = of_int a - of_int b : {of_int_neg b}
|
|
|
|
|
|
2015-06-10 02:46:30 +00:00
|
|
|
|
theorem of_int.inj {a b : ℤ} (H : of_int a = of_int b) : a = b :=
|
2015-06-29 05:16:58 +00:00
|
|
|
|
prerat.of_int.inj (quot.exact H)
|
2015-06-10 02:46:30 +00:00
|
|
|
|
|
2015-05-25 11:52:20 +00:00
|
|
|
|
theorem of_nat_eq (a : ℕ) : of_nat a = of_int (int.of_nat a) := rfl
|
|
|
|
|
|
|
|
|
|
theorem of_nat_add (a b : ℕ) : of_nat (#nat a + b) = of_nat a + of_nat b :=
|
|
|
|
|
by rewrite [*of_nat_eq, int.of_nat_add, rat.of_int_add]
|
|
|
|
|
|
|
|
|
|
theorem of_nat_mul (a b : ℕ) : of_nat (#nat a * b) = of_nat a * of_nat b :=
|
|
|
|
|
by rewrite [*of_nat_eq, int.of_nat_mul, rat.of_int_mul]
|
|
|
|
|
|
|
|
|
|
theorem of_nat_sub {a b : ℕ} (H : #nat a ≥ b) : of_nat (#nat a - b) = of_nat a - of_nat b :=
|
|
|
|
|
by rewrite [*of_nat_eq, int.of_nat_sub H, rat.of_int_sub]
|
|
|
|
|
|
2015-04-18 18:00:09 +00:00
|
|
|
|
theorem add.comm (a b : ℚ) : a + b = b + a :=
|
|
|
|
|
quot.induction_on₂ a b (take u v, quot.sound !prerat.add.comm)
|
|
|
|
|
|
|
|
|
|
theorem add.assoc (a b c : ℚ) : a + b + c = a + (b + c) :=
|
|
|
|
|
quot.induction_on₃ a b c (take u v w, quot.sound !prerat.add.assoc)
|
|
|
|
|
|
|
|
|
|
theorem add_zero (a : ℚ) : a + 0 = a :=
|
|
|
|
|
quot.induction_on a (take u, quot.sound !prerat.add_zero)
|
|
|
|
|
|
|
|
|
|
theorem zero_add (a : ℚ) : 0 + a = a := !add.comm ▸ !add_zero
|
|
|
|
|
|
|
|
|
|
theorem add.left_inv (a : ℚ) : -a + a = 0 :=
|
|
|
|
|
quot.induction_on a (take u, quot.sound !prerat.add.left_inv)
|
|
|
|
|
|
|
|
|
|
theorem mul.comm (a b : ℚ) : a * b = b * a :=
|
|
|
|
|
quot.induction_on₂ a b (take u v, quot.sound !prerat.mul.comm)
|
|
|
|
|
|
|
|
|
|
theorem mul.assoc (a b c : ℚ) : a * b * c = a * (b * c) :=
|
|
|
|
|
quot.induction_on₃ a b c (take u v w, quot.sound !prerat.mul.assoc)
|
|
|
|
|
|
|
|
|
|
theorem mul_one (a : ℚ) : a * 1 = a :=
|
|
|
|
|
quot.induction_on a (take u, quot.sound !prerat.mul_one)
|
|
|
|
|
|
|
|
|
|
theorem one_mul (a : ℚ) : 1 * a = a := !mul.comm ▸ !mul_one
|
|
|
|
|
|
|
|
|
|
theorem mul.left_distrib (a b c : ℚ) : a * (b + c) = a * b + a * c :=
|
|
|
|
|
quot.induction_on₃ a b c (take u v w, quot.sound !prerat.mul.left_distrib)
|
|
|
|
|
|
|
|
|
|
theorem mul.right_distrib (a b c : ℚ) : (a + b) * c = a * c + b * c :=
|
|
|
|
|
by rewrite [mul.comm, mul.left_distrib, *mul.comm c]
|
|
|
|
|
|
|
|
|
|
theorem mul_inv_cancel {a : ℚ} : a ≠ 0 → a * a⁻¹ = 1 :=
|
|
|
|
|
quot.induction_on a
|
|
|
|
|
(take u,
|
|
|
|
|
assume H,
|
|
|
|
|
quot.sound (!prerat.mul_inv_cancel (assume H1, H (quot.sound H1))))
|
|
|
|
|
|
|
|
|
|
theorem inv_mul_cancel {a : ℚ} (H : a ≠ 0) : a⁻¹ * a = 1 :=
|
|
|
|
|
!mul.comm ▸ mul_inv_cancel H
|
|
|
|
|
|
2015-06-10 02:46:30 +00:00
|
|
|
|
theorem zero_ne_one : (0 : ℚ) ≠ 1 :=
|
2015-04-18 18:00:09 +00:00
|
|
|
|
assume H, prerat.zero_not_equiv_one (quot.exact H)
|
|
|
|
|
|
|
|
|
|
definition has_decidable_eq [instance] : decidable_eq ℚ :=
|
|
|
|
|
take a b, quot.rec_on_subsingleton₂ a b
|
|
|
|
|
(take u v,
|
|
|
|
|
if H : prerat.num u * prerat.denom v = prerat.num v * prerat.denom u
|
|
|
|
|
then decidable.inl (quot.sound H)
|
|
|
|
|
else decidable.inr (assume H1, H (quot.exact H1)))
|
|
|
|
|
|
|
|
|
|
theorem inv_zero : inv 0 = 0 :=
|
|
|
|
|
quot.sound (prerat.inv_zero' ▸ !prerat.equiv.refl)
|
|
|
|
|
|
2015-06-10 02:46:30 +00:00
|
|
|
|
theorem quot_reduce (a : ℚ) : ⟦reduce a⟧ = a :=
|
|
|
|
|
quot.induction_on a (take u, quot.sound !prerat.reduce_equiv)
|
|
|
|
|
|
|
|
|
|
theorem mul_denom (a : ℚ) : a * denom a = num a :=
|
|
|
|
|
have H : ⟦reduce a⟧ * of_int (denom a) = of_int (num a), from quot.sound (!prerat.mul_denom_equiv),
|
|
|
|
|
quot_reduce a ▸ H
|
|
|
|
|
|
2015-08-14 12:48:38 +00:00
|
|
|
|
theorem coprime_num_denom (a : ℚ) : coprime (num a) (denom a) :=
|
|
|
|
|
decidable.by_cases
|
|
|
|
|
(suppose a = 0, by substvars)
|
|
|
|
|
(quot.induction_on a
|
|
|
|
|
(take u H,
|
|
|
|
|
assert H' : prerat.num u ≠ 0, from take H'', H (quot.sound (prerat.equiv_zero_of_num_eq_zero H'')),
|
|
|
|
|
begin
|
|
|
|
|
cases u with un ud udpos,
|
|
|
|
|
rewrite [▸*, ↑num, ↑denom, ↑reduce, ↑prerat.reduce, if_neg H', ▸*],
|
|
|
|
|
have gcd un ud ≠ 0, from ne_of_gt (!gcd_pos_of_ne_zero_left H'),
|
|
|
|
|
apply coprime_div_gcd_div_gcd this
|
|
|
|
|
end))
|
|
|
|
|
|
2015-05-12 04:44:31 +00:00
|
|
|
|
section migrate_algebra
|
2015-04-18 18:00:09 +00:00
|
|
|
|
open [classes] algebra
|
|
|
|
|
|
2015-05-12 04:44:31 +00:00
|
|
|
|
protected definition discrete_field [reducible] : algebra.discrete_field rat :=
|
2015-04-18 18:00:09 +00:00
|
|
|
|
⦃algebra.discrete_field,
|
|
|
|
|
add := add,
|
|
|
|
|
add_assoc := add.assoc,
|
|
|
|
|
zero := 0,
|
|
|
|
|
zero_add := zero_add,
|
|
|
|
|
add_zero := add_zero,
|
|
|
|
|
neg := neg,
|
|
|
|
|
add_left_inv := add.left_inv,
|
|
|
|
|
add_comm := add.comm,
|
|
|
|
|
mul := mul,
|
|
|
|
|
mul_assoc := mul.assoc,
|
|
|
|
|
one := (of_num 1),
|
|
|
|
|
one_mul := one_mul,
|
|
|
|
|
mul_one := mul_one,
|
|
|
|
|
left_distrib := mul.left_distrib,
|
|
|
|
|
right_distrib := mul.right_distrib,
|
|
|
|
|
mul_comm := mul.comm,
|
|
|
|
|
mul_inv_cancel := @mul_inv_cancel,
|
|
|
|
|
inv_mul_cancel := @inv_mul_cancel,
|
|
|
|
|
zero_ne_one := zero_ne_one,
|
|
|
|
|
inv_zero := inv_zero,
|
|
|
|
|
has_decidable_eq := has_decidable_eq⦄
|
|
|
|
|
|
2015-05-12 04:44:31 +00:00
|
|
|
|
local attribute rat.discrete_field [instance]
|
2015-07-31 19:42:11 +00:00
|
|
|
|
|
2015-05-12 11:46:34 +00:00
|
|
|
|
definition divide (a b : rat) := algebra.divide a b
|
2015-07-31 19:42:11 +00:00
|
|
|
|
infix [priority rat.prio] `/` := divide
|
|
|
|
|
|
2015-05-12 11:46:34 +00:00
|
|
|
|
definition dvd (a b : rat) := algebra.dvd a b
|
|
|
|
|
|
2015-07-31 19:42:11 +00:00
|
|
|
|
definition pow (a : ℚ) (n : ℕ) : ℚ := algebra.pow a n
|
|
|
|
|
infix [priority rat.prio] ^ := pow
|
2015-08-17 03:23:03 +00:00
|
|
|
|
definition nmul (n : ℕ) (a : ℚ) : ℚ := algebra.nmul n a
|
|
|
|
|
infix [priority rat.prio] `⬝` := nmul
|
|
|
|
|
definition imul (i : ℤ) (a : ℚ) : ℚ := algebra.imul i a
|
2015-07-31 19:42:11 +00:00
|
|
|
|
|
2015-04-18 18:00:09 +00:00
|
|
|
|
migrate from algebra with rat
|
2015-08-17 03:23:03 +00:00
|
|
|
|
replacing sub → rat.sub, divide → divide, dvd → dvd, pow → pow, nmul → nmul, imul → imul
|
2015-05-12 04:44:31 +00:00
|
|
|
|
|
|
|
|
|
end migrate_algebra
|
2015-06-10 02:46:30 +00:00
|
|
|
|
|
|
|
|
|
theorem eq_num_div_denom (a : ℚ) : a = num a / denom a :=
|
|
|
|
|
have H : of_int (denom a) ≠ 0, from assume H', ne_of_gt (denom_pos a) (of_int.inj H'),
|
2015-07-18 09:28:53 +00:00
|
|
|
|
iff.mpr (eq_div_iff_mul_eq H) (mul_denom a)
|
2015-06-10 02:46:30 +00:00
|
|
|
|
|
2015-08-14 17:16:07 +00:00
|
|
|
|
theorem of_int_div {a b : ℤ} (H : b ∣ a) : of_int (a div b) = of_int a / of_int b :=
|
2015-06-10 02:46:30 +00:00
|
|
|
|
decidable.by_cases
|
|
|
|
|
(assume bz : b = 0,
|
|
|
|
|
by rewrite [bz, div_zero, int.div_zero])
|
|
|
|
|
(assume bnz : b ≠ 0,
|
|
|
|
|
have bnz' : of_int b ≠ 0, from assume oibz, bnz (of_int.inj oibz),
|
|
|
|
|
have H' : of_int (a div b) * of_int b = of_int a, from
|
|
|
|
|
int.dvd.elim H
|
|
|
|
|
(take c, assume Hc : a = b * c,
|
|
|
|
|
by rewrite [Hc, !int.mul_div_cancel_left bnz, mul.comm]),
|
2015-07-18 09:28:53 +00:00
|
|
|
|
iff.mpr (eq_div_iff_mul_eq bnz') H')
|
2015-06-10 02:46:30 +00:00
|
|
|
|
|
2015-08-17 03:23:03 +00:00
|
|
|
|
theorem of_int_pow (a : ℤ) (n : ℕ) : of_int (a^n) = (of_int a)^n :=
|
|
|
|
|
begin
|
|
|
|
|
induction n with n ih,
|
|
|
|
|
apply eq.refl,
|
|
|
|
|
rewrite [pow_succ, int.pow_succ, of_int_mul, ih]
|
|
|
|
|
end
|
|
|
|
|
|
2015-04-18 18:00:09 +00:00
|
|
|
|
end rat
|