Skip to content

Commit b276b59

Browse files
[ bug ] Fixed two bugs in Rational and simplified (#681)
1 parent e008167 commit b276b59

File tree

4 files changed

+112
-131
lines changed

4 files changed

+112
-131
lines changed

CHANGELOG.md

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -448,6 +448,22 @@ Non-backwards compatible changes
448448
`decSetoid` and `_==_` to be moved from `Data.(Char/String).Unsafe` to
449449
`Data.(Char/String).Properties`.
450450

451+
#### Overhaul of `Data.Rational`
452+
453+
* Many new operators have been added to `Data.Rational` including
454+
addition, substraction, multiplication, inverse etc.
455+
456+
* The existing operator `_÷_` has been renamed `_/_` and is now more liberal
457+
as it now accepts non-coprime arguments (e.g. `+ 2 / 4`) which are then
458+
normalised.
459+
460+
* The old name `_÷_` has been repurposed to represent division between two
461+
rationals.
462+
463+
* The proofs `drop-*≤*`, `≃⇒≡` and `≡⇒≃` have been moved from `Data.Rational`
464+
to `Data.Rational.Properties`.
465+
466+
451467
#### Changes in `Data.List`
452468

453469
* In `Data.List.Membership.Propositional.Properties`:
@@ -497,9 +513,6 @@ Non-backwards compatible changes
497513
* The type `Coprime` and proof `coprime-divisor` have been moved from
498514
`Data.Integer.Divisibility` to `Data.Integer.Coprimality`.
499515

500-
* The proofs `drop-*≤*`, `≃⇒≡` and `≡⇒≃` have been moved from `Data.Rational`
501-
to `Data.Rational.Properties`.
502-
503516
* The functions `fromMusical` and `toMusical` were moved from the `Codata` modules
504517
to the corresponding `Codata.Musical` modules.
505518

@@ -1136,7 +1149,6 @@ Other minor additions
11361149

11371150
* Added new functions to `Data.Rational`:
11381151
```agda
1139-
norm-mkℚ : (n : ℤ) (d : ℕ) → d ≢0 → ℚ
11401152
-_ : ℚ → ℚ
11411153
1/_ : (p : ℚ) → .{n≢0 : ∣ ℚ.numerator p ∣ ≢0} → ℚ
11421154
_*_ : ℚ → ℚ → ℚ

src/Data/Rational.agda

Lines changed: 1 addition & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -23,26 +23,11 @@ open import Data.Nat.Properties public
2323
using (_≟_; _≤?_)
2424

2525
------------------------------------------------------------------------
26-
-- Publicly re-export contents of core module
26+
-- Method for displaying rationals
2727

2828
show : String
2929
show p = ℤ.show (↥ p) ++ "/" ++ ℤ.show (↧ p)
3030

31-
------------------------------------------------------------------------------
32-
-- Some constants
33-
34-
0ℚ :
35-
0ℚ = + 0 ÷ 1
36-
37-
1ℚ :
38-
1ℚ = + 1 ÷ 1
39-
40-
½ :
41-
½ = + 1 ÷ 2
42-
43-
:
44-
= - ½
45-
4631
------------------------------------------------------------------------
4732
-- Deprecated
4833

src/Data/Rational/Base.agda

Lines changed: 70 additions & 86 deletions
Original file line numberDiff line numberDiff line change
@@ -11,18 +11,15 @@ module Data.Rational.Base where
1111
open import Function using (id)
1212
open import Data.Integer as ℤ using (ℤ; ∣_∣; +_; -[1+_])
1313
open import Data.Nat.GCD
14-
open import Data.Nat.Divisibility as ℕDiv using (_∣_ ; divides ; ∣-antisym)
15-
open import Data.Nat.Coprimality as C using (Coprime; coprime?; Bézout-coprime)
14+
open import Data.Nat.Divisibility as ℕDiv using (divides; 0∣⇒≡0)
15+
open import Data.Nat.Coprimality as C using (Coprime; Bézout-coprime)
1616
open import Data.Nat as ℕ using (ℕ; zero; suc)
17-
import Data.Nat.Properties as ℕ
1817
open import Data.Product
19-
open import Data.Unit using (tt)
2018
open import Level using (0ℓ)
21-
open import Relation.Nullary.Decidable
22-
using (True; False; toWitness)
19+
open import Relation.Nullary.Decidable using (False)
2320
open import Relation.Nullary.Negation using (contradiction)
24-
open import Relation.Binary using (Rel; Decidable; _⇒_)
25-
open import Relation.Binary.PropositionalEquality as P
21+
open import Relation.Binary using (Rel)
22+
open import Relation.Binary.PropositionalEquality
2623
using (_≡_; refl; subst; cong; cong₂; module ≡-Reasoning)
2724

2825
open ≡-Reasoning
@@ -38,13 +35,17 @@ record ℚ : Set where
3835
denominator-1 :
3936
.isCoprime : Coprime ∣ numerator ∣ (suc denominator-1)
4037

38+
denominatorℕ :
39+
denominatorℕ = suc denominator-1
40+
4141
denominator :
42-
denominator = + suc denominator-1
42+
denominator = + denominatorℕ
4343

4444
open public using ()
4545
renaming
46-
( numerator to ↥_
47-
; denominator to ↧_
46+
( numerator to ↥_
47+
; denominator to ↧_
48+
; denominatorℕ to ↧ₙ_
4849
)
4950

5051
------------------------------------------------------------------------
@@ -53,114 +54,97 @@ open ℚ public using ()
5354
infix 4 _≃_
5455

5556
_≃_ : Rel ℚ 0ℓ
56-
p ≃ q = (↥ p ℤ.* ↧ q) ≡ (↥ q) ℤ.* (↧ p)
57+
p ≃ q = (↥ p ℤ.* ↧ q) ≡ (↥ q ℤ.* ↧ p)
5758

5859
------------------------------------------------------------------------
5960
-- Ordering of rationals
6061

6162
infix 4 _≤_
6263

63-
data _≤_ : Set where
64+
data _≤_ : Rel ℚ 0ℓ where
6465
*≤* : {p q} (↥ p ℤ.* ↧ q) ℤ.≤ (↥ q ℤ.* ↧ p) p ≤ q
6566

6667
------------------------------------------------------------------------
67-
-- Two useful lemmas to help with constructing on rationals
68-
--
69-
-- normalize takes two natural numbers, say 6 and 21 and their gcd 3, and
70-
-- returns them normalized as 2 and 7 and a proof that they are coprime
68+
-- Negation
69+
70+
pattern +0 = + 0
71+
pattern +[1+_] n = + suc n
72+
73+
-_ :
74+
- mkℚ -[1+ n ] d prf = mkℚ +[1+ n ] d prf
75+
- mkℚ +0 d prf = mkℚ +0 d prf
76+
- mkℚ +[1+ n ] d prf = mkℚ -[1+ n ] d prf
77+
78+
------------------------------------------------------------------------
79+
-- Constructing rationals
7180

7281
infix 4 _≢0
7382
_≢0 : Set
7483
n ≢0 = False (n ℕ.≟ 0)
7584

76-
-- introducing a notation for that nasty pattern
77-
pattern ⟨_&_∧_&_⟩ p eqp q eqq = GCD.is (divides p eqp , divides q eqq) _
78-
79-
normalize : m n g .{m≢0 : m ≢0} .{n≢0 : n ≢0} .{g≢0 : g ≢0} GCD m n g
80-
Σ[ p ∈ ℕ ] Σ[ q ∈ ℕ ] Coprime (suc p) (suc q) × m ℕ.* suc q ≡ n ℕ.* suc p
81-
normalize 0 n g {m≢0 = ()} _
82-
normalize m 0 g {n≢0 = ()} _
83-
normalize m n 0 {g≢0 = ()} _
84-
normalize (suc _) n g ⟨ 0 & () ∧ q & n≡qg' ⟩
85-
normalize m (suc _) g ⟨ p & m≡pg' ∧ 0 & () ⟩
86-
normalize(suc _) (suc _) (suc g) G@(⟨ suc p & refl ∧ suc q & refl ⟩)
87-
= p , q , Bézout-coprime (Bézout.identity G) , (begin
88-
(suc p ℕ.* suc g) ℕ.* suc q ≡⟨ ℕ.*-assoc (suc p) (suc g) (suc q) ⟩
89-
suc p ℕ.* (suc g ℕ.* suc q) ≡⟨ cong (suc p ℕ.*_) (ℕ.*-comm (suc g) (suc q)) ⟩
90-
suc p ℕ.* (suc q ℕ.* suc g) ≡⟨ ℕ.*-comm (suc p) _ ⟩
91-
(suc q ℕ.* suc g) ℕ.* suc p ∎)
92-
93-
-- a version of gcd that returns a proof that the result is non-zero given
94-
-- that one of the inputs is non-zero
95-
96-
gcd≢0 : (m n : ℕ) {m≢0 : m ≢0} Σ[ d ∈ ℕ ] GCD m n d × d ≢0
97-
gcd≢0 m n {m≢0} with gcd m n
98-
... | (suc d , G) = (suc d , G , tt)
99-
... | (0 , GCD.is (0|m , _) _) with ℕDiv.0∣⇒≡0 0|m
100-
... | refl = contradiction m≢0 id
85+
-- A constructor for ℚ that takes two natural numbers, say 6 and 21,
86+
-- and returns them in a normalized form, e.g. say 2 and 7
10187

102-
pattern +0 = + 0
103-
pattern +[1+_] n = + suc n
88+
normalize : m n .{m≢0 : m ≢0} .{n≢0 : n ≢0}
89+
normalize (suc m) (suc n) with gcd (suc m) (suc n)
90+
... | zero , GCD.is (1+m∣0 , _) _ = contradiction (0∣⇒≡0 1+m∣0) λ()
91+
... | suc g , G@(GCD.is (divides (suc p) refl , divides (suc q) refl) _)
92+
= mkℚ (+ suc p) q (Bézout-coprime (Bézout.identity G))
10493

105-
norm-mkℚ : (n : ℤ) (d : ℕ) .{d≢0 : d ≢0}
106-
norm-mkℚ +0 d {d≢0} = mkℚ +0 0 (C.sym (C.1-coprimeTo 0))
107-
norm-mkℚ -[1+ n ] d {d≢0} =
108-
let (q , gcd , q≢0) = gcd≢0 (suc n) d
109-
(n′ , d′ , prf , eq) = normalize (suc n) d q {_} {d≢0} {q≢0} gcd
110-
in mkℚ -[1+ n′ ] d′ prf
111-
norm-mkℚ +[1+ n ] d {d≢0} =
112-
let (q , gcd , q≢0) = gcd≢0 (suc n) d
113-
(n′ , d′ , prf , eq) = normalize (suc n) d q {_} {d≢0} {q≢0} gcd
114-
in mkℚ (+ suc n′) d′ prf
94+
-- A constructor for ℚ that (unlike mkℚ) automatically normalises it's
95+
-- arguments. See the constants section below for how to use this operator.
11596

116-
------------------------------------------------------------------------------
117-
-- Operations on rationals
97+
infixl 7 _/_
11898

119-
infix 8 -_ 1/_
120-
infixl 7 _*_ _/_ _÷_
121-
infixl 6 _-_ _+_
122-
123-
-- unary negation
99+
_/_ : (n : ℤ) (d : ℕ) .{d≢0 : d ≢0}
100+
_/_ +0 d {d≢0} = mkℚ +0 0 (C.sym (C.1-coprimeTo 0))
101+
_/_ +[1+ n ] d {d≢0} = normalize (suc n) d {_} {d≢0}
102+
_/_ -[1+ n ] d {d≢0} = - normalize (suc n) d {_} {d≢0}
124103

125-
-_ :
126-
- mkℚ -[1+ n ] d prf = mkℚ +[1+ n ] d prf
127-
- mkℚ +0 d prf = mkℚ +0 d prf
128-
- mkℚ +[1+ n ] d prf = mkℚ -[1+ n ] d prf
104+
------------------------------------------------------------------------------
105+
-- Some constants
129106

130-
-- reciprocal: requires a proof that the numerator is not zero
107+
0ℚ :
108+
0ℚ = + 0 / 1
131109

132-
1/_ : (p : ℚ) .{n≢0 : ∣ ↥ p ∣ ≢0}
133-
(1/ mkℚ +0 d prf) {()}
134-
1/ mkℚ +[1+ n ] d prf = mkℚ +[1+ d ] n (C.sym prf)
135-
1/ mkℚ -[1+ n ] d prf = mkℚ -[1+ d ] n (C.sym prf)
110+
1ℚ :
111+
1ℚ = + 1 / 1
136112

137-
-- multiplication
113+
½ :
114+
½ = + 1 / 2
138115

139-
_*_ :
140-
mkℚ n₁ d₁ prf₁ * mkℚ n₂ d₂ prf₂ = norm-mkℚ (n₁ ℤ.* n₂) (suc d₁ ℕ.* suc d₂)
116+
:
117+
= - ½
141118

142-
-- division
119+
------------------------------------------------------------------------------
120+
-- Operations on rationals
143121

144-
_÷_ : (numerator : ℤ) (denominator : ℕ)
145-
.{coprime : True (coprime? ∣ numerator ∣ denominator)}
146-
{≢0 : denominator ≢0}
147-
148-
(n ÷ zero) {≢0 = ()}
149-
(n ÷ suc d) {c} = mkℚ n d (toWitness c)
122+
infix 8 -_ 1/_
123+
infixl 7 _*_ _÷_
124+
infixl 6 _-_ _+_
150125

151126
-- addition
152127

153128
_+_ :
154-
mkℚ n₁ d₁ prf₁ + mkℚ n₂ d₂ prf₂ = norm-mkℚ
155-
(n₁ ℤ.* (+[1+ d₂ ]) ℤ.+ n₂ ℤ.* (+[1+ d₂ ]))
156-
(suc d₁ ℕ.* suc d₂)
129+
p + q = (↥ p ℤ.* ↧ q ℤ.+ ↥ q ℤ.* ↧ p) / (↧ₙ p ℕ.* ↧ₙ q)
130+
131+
-- multiplication
132+
133+
_*_ :
134+
p * q = (↥ p ℤ.* ↥ q) / (↧ₙ p ℕ.* ↧ₙ q)
157135

158136
-- subtraction
159137

160138
_-_ :
161139
p - q = p + (- q)
162140

163-
-- division
141+
-- reciprocal: requires a proof that the numerator is not zero
142+
143+
1/_ : (p : ℚ) .{n≢0 : ∣ ↥ p ∣ ≢0}
144+
1/ mkℚ +[1+ n ] d prf = mkℚ +[1+ d ] n (C.sym prf)
145+
1/ mkℚ -[1+ n ] d prf = mkℚ -[1+ d ] n (C.sym prf)
146+
147+
-- division: requires a proof that the denominator is not zero
164148

165-
_/_ : (p q : ℚ) {n≢0 : ∣ ↥ q ∣ ≢0}
166-
(p / q) {n≢0} = p * (1/_ q {n≢0})
149+
_÷_ : (p q : ℚ) .{n≢0 : ∣ ↥ q ∣ ≢0}
150+
(p ÷ q) {n≢0} = p * (1/_ q {n≢0})

src/Data/Rational/Properties.agda

Lines changed: 25 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -9,19 +9,30 @@
99
module Data.Rational.Properties where
1010

1111
open import Function using (_∘_ ; _$_)
12-
open import Data.Integer as ℤ using (ℤ; ∣_∣; +_)
12+
open import Data.Integer as ℤ using (ℤ; ∣_∣; +_; -[1+_])
1313
open import Data.Integer.Coprimality using (coprime-divisor)
1414
import Data.Integer.Properties as ℤ
1515
open import Data.Rational.Base
1616
open import Data.Nat as ℕ using (ℕ; zero; suc)
17-
open import Data.Nat.Coprimality as C using (Coprime)
18-
open import Data.Nat.Divisibility
17+
import Data.Nat.Properties as ℕ
18+
open import Data.Nat.Coprimality as C using (Coprime; coprime?)
19+
open import Data.Nat.Divisibility hiding (/-cong)
20+
open import Data.Product using (_,_)
1921
open import Data.Sum
2022
open import Relation.Binary
21-
open import Relation.Binary.PropositionalEquality as P
22-
using (_≡_; refl; sym; cong; module ≡-Reasoning)
23+
open import Relation.Binary.PropositionalEquality
2324
open import Relation.Nullary using (Dec; yes; no; recompute)
24-
open import Relation.Nullary.Decidable using (True; fromWitness)
25+
open import Relation.Nullary.Decidable as Dec′ using (True; fromWitness)
26+
27+
open import Algebra.FunctionProperties {A = ℚ} _≡_
28+
open import Algebra.FunctionProperties.Consequences.Propositional
29+
30+
------------------------------------------------------------------------
31+
-- Helper lemmas
32+
33+
private
34+
recomputeCP : {n d} .(Coprime n (suc d)) Coprime n (suc d)
35+
recomputeCP {n} {d-1} c = recompute (coprime? n (suc d-1)) c
2536

2637
------------------------------------------------------------------------
2738
-- Equality
@@ -36,30 +47,21 @@ open import Relation.Nullary.Decidable using (True; fromWitness)
3647

3748
1+d₁∣1+d₂ : suc d₁ ∣ suc d₂
3849
1+d₁∣1+d₂ = coprime-divisor (+ suc d₁) n₁ (+ suc d₂)
39-
(C.sym (recompute (C.coprime? ∣ n₁ ∣ (suc d₁)) c₁)) $
50+
(C.sym (recomputeCP c₁)) $
4051
divides ∣ n₂ ∣ $ begin
4152
∣ n₁ ℤ.* + suc d₂ ∣ ≡⟨ cong ∣_∣ eq ⟩
4253
∣ n₂ ℤ.* + suc d₁ ∣ ≡⟨ ℤ.abs-*-commute n₂ (+ suc d₁) ⟩
4354
∣ n₂ ∣ ℕ.* suc d₁ ∎
4455

4556
1+d₂∣1+d₁ : suc d₂ ∣ suc d₁
4657
1+d₂∣1+d₁ = coprime-divisor (+ suc d₂) n₂ (+ suc d₁)
47-
(C.sym (recompute (C.coprime? ∣ n₂ ∣ (suc d₂)) c₂)) $
58+
(C.sym (recomputeCP c₂)) $
4859
divides ∣ n₁ ∣ (begin
49-
∣ n₂ ℤ.* + suc d₁ ∣ ≡⟨ cong ∣_∣ (P.sym eq) ⟩
60+
∣ n₂ ℤ.* + suc d₁ ∣ ≡⟨ cong ∣_∣ (sym eq) ⟩
5061
∣ n₁ ℤ.* + suc d₂ ∣ ≡⟨ ℤ.abs-*-commute n₁ (+ suc d₂) ⟩
5162
∣ n₁ ∣ ℕ.* suc d₂ ∎)
5263

53-
fromWitness′ : {p} {P : Set p} {Q : Dec P} .P True Q
54-
fromWitness′ {Q = Q} p = fromWitness (recompute Q p)
55-
56-
.c₁′ : True (C.coprime? ∣ n₁ ∣ (suc d₁))
57-
c₁′ = fromWitness′ {P = Coprime ∣ n₁ ∣ (suc d₁)} c₁
58-
59-
.c₂′ : True (C.coprime? ∣ n₂ ∣ (suc d₂))
60-
c₂′ = fromWitness′ {P = Coprime ∣ n₂ ∣ (suc d₂)} c₂
61-
62-
helper : (n₁ ÷ suc d₁) {c₁′} ≡ (n₂ ÷ suc d₂) {c₂′}
64+
helper : mkℚ n₁ d₁ c₁ ≡ mkℚ n₂ d₂ c₂
6365
helper with ∣-antisym 1+d₁∣1+d₂ 1+d₂∣1+d₁
6466
... | refl with ℤ.*-cancelʳ-≡ n₁ n₂ (+ suc d₁) (λ ()) eq
6567
... | refl = refl
@@ -86,9 +88,9 @@ drop-*≤* (*≤* pq≤qp) = pq≤qp
8688
≤-refl = ≤-reflexive refl
8789

8890
≤-trans : Transitive _≤_
89-
≤-trans {i = mkℚ n₁ d₁ c₁} {j = mkℚ n₂ d₂ c₂} {k = mkℚ n₃ d₃ c₃} (*≤* eq₁) (*≤* eq₂)
91+
≤-trans {i = p@(mkℚ n₁ d₁ c₁)} {j = q@(mkℚ n₂ d₂ c₂)} {k = r@(mkℚ n₃ d₃ c₃)} (*≤* eq₁) (*≤* eq₂)
9092
= *≤* $ ℤ.*-cancelʳ-≤-pos (n₁ ℤ.* ℤ.+ suc d₃) (n₃ ℤ.* ℤ.+ suc d₁) d₂ $ begin
91-
let sd₁ = ℤ.+ suc d₁; sd₂ = ℤ.+ suc d₂; sd₃ = ℤ.+ suc d₃ in
93+
let sd₁ = ↧ p; sd₂ = ↧ q; sd₃ = ↧ r in
9294
(n₁ ℤ.* sd₃) ℤ.* sd₂ ≡⟨ ℤ.*-assoc n₁ sd₃ sd₂ ⟩
9395
n₁ ℤ.* (sd₃ ℤ.* sd₂) ≡⟨ cong (n₁ ℤ.*_) (ℤ.*-comm sd₃ sd₂) ⟩
9496
n₁ ℤ.* (sd₂ ℤ.* sd₃) ≡⟨ sym (ℤ.*-assoc n₁ sd₂ sd₃) ⟩
@@ -110,13 +112,11 @@ drop-*≤* (*≤* pq≤qp) = pq≤qp
110112
(↥ q ℤ.* ↧ p))
111113

112114
_≤?_ : Decidable _≤_
113-
p ≤? q with (↥ p ℤ.* ↧ q) ℤ.≤? (↥ q ℤ.* ↧ p)
114-
... | yes pq≤qp = yes (*≤* pq≤qp)
115-
... | no ¬pq≤qp = no (λ { (*≤* pq≤qp) ¬pq≤qp pq≤qp })
115+
p ≤? q = Dec′.map′ *≤* drop-*≤* ((↥ p ℤ.* ↧ q) ℤ.≤? (↥ q ℤ.* ↧ p))
116116

117117
≤-isPreorder : IsPreorder _≡_ _≤_
118118
≤-isPreorder = record
119-
{ isEquivalence = P.isEquivalence
119+
{ isEquivalence = isEquivalence
120120
; reflexive = ≤-reflexive
121121
; trans = ≤-trans
122122
}

0 commit comments

Comments
 (0)