module Data.Nat.Prime where
Prime and composite numbers🔗
A number is prime when it is greater than two (which we split into being positive and being apart from 1), and, if is any other number that divides then either or Since we’ve assumed these cases are disjoint, so being a prime is a proposition.
record is-prime (n : Nat) : Type where
field
: Positive n
⦃ positive ⦄ : n ≠1
prime≠1 : ∀ d → d ∣ n → (d ≡ 1) ⊎ (d ≡ n) primality
We note that a prime number has no proper divisors, in that, if and then does not divide
: ∀ {d} → d ≠1 → d ≠n → ¬ d ∣ n
¬proper-divisor with primality _ d∣n
¬proper-divisor ¬d=1 ¬d=n d∣n ... | inl d=1 = ¬d=1 d=1
... | inr d=n = ¬d=n d=n
Conversely, if
is a number that is not prime, it is called composite.
Instead of defining is-composite
to
be the literal negation of is-prime
, we instead define this notion
positively: To say that a number is composite is to give a prime
and a number
such that
and
is the smallest divisor of
record is-composite (n : Nat) : Type where
field
{p q} : Nat
: is-prime p
p-prime : 1 < q
q-proper
: q * p ≡ n
factors : ∀ p' → 1 < p' → p' ∣ n → p ≤ p' least
Note that the assumption that is a prime is simply for convenience: the least proper divisor of any number is always a prime.
least-divisor→is-prime: ∀ p n → 1 < p → p ∣ n → (∀ p' → 1 < p' → p' ∣ n → p ≤ p') → is-prime p
.positive = ≤-trans ≤-ascend gt
least-divisor→is-prime p n gt div least .prime≠1 q = <-irrefl (sym q) gt
least-divisor→is-prime p n gt div least @(suc p') n gt div least .primality 0 x = absurd (suc≠zero x)
least-divisor→is-prime p@(suc p') n gt div least .primality 1 x = inl refl
least-divisor→is-prime p@(suc p') n gt div least .primality m@(suc (suc k)) x =
least-divisor→is-prime p(≤-antisym (m∣sn→m≤sn x) (least m (s≤s (s≤s 0≤x)) (∣-trans x div))) inr
Primality testing🔗
: ∀ n → 1 < n → is-prime n ⊎ is-composite n
is-prime-or-composite @(suc (suc m)) (s≤s p)
is-prime-or-composite nwith Fin-omniscience {n = n} (λ k → 1 < to-nat k × to-nat k ∣ n)
... | inr prime = inl record { prime≠1 = suc≠zero ∘ suc-inj ; primality = no-divisors→prime } where
: ∀ d → d ∣ n → d ≡ 1 ⊎ d ≡ n
no-divisors→prime with d ≡? 1
no-divisors→prime d div ... | yes p = inl p
... | no ¬d=1 with d ≡? n
... | yes p = inr p
... | no ¬d=n =
let
: d < n
ord = proper-divisor-< ¬d=n div
ord
: d ≡ to-nat (from-ℕ< (d , ord))
coh = sym (ap fst (to-from-â„•< (d , ord)))
coh
= case d return (λ x → ¬ x ≡ 1 → x ∣ n → 1 < x) of λ where
no 0 p1 div → absurd (<-irrefl (sym div) (s≤s 0≤x))
1 p1 div → absurd (p1 refl)
(suc (suc n)) p1 div → s≤s (s≤s 0≤x)
in absurd (prime (from-ℕ< (d , ord)) ((subst (1 <_) coh (no ¬d=1 div)) , subst (_∣ n) coh div))
... | inl (ix , (proper , div) , least)
= inr record { p-prime = prime ; q-proper = proper' ; factors = path ; least = least' } where
open Σ (∣→fibre div) renaming (fst to quot ; snd to path)
abstract
: (p' : Nat) → 1 < p' → p' ∣ n → to-nat ix ≤ p'
least' with ≤-strengthen (m∣n→m≤n div)
least' p' x div ... | inl same = ≤-trans ≤-ascend (subst (to-nat ix <_) (sym same) (to-ℕ< ix .snd))
... | inr less =
let
: â„•< n
it = p' , less
it
: p' ≡ to-nat (from-ℕ< it)
coh = sym (ap fst (to-from-â„•< it))
coh
= least (from-ℕ< it) (subst (1 <_) coh x , subst (_∣ n) coh div)
orig in ≤-trans orig (subst (to-nat (from-ℕ< it) ≤_) (sym coh) ≤-refl)
: is-prime (to-nat ix)
prime = least-divisor→is-prime (to-nat ix) n proper div least'
prime
: 1 < quot
proper' with quot | path
proper' ... | 0 | q = absurd (<-irrefl q (s≤s 0≤x))
... | 1 | q = absurd (<-irrefl (sym (+-zeror (to-nat ix)) ∙ q) (to-ℕ< ix .snd))
... | suc (suc n) | p = s≤s (s≤s 0≤x)
record Factorisation (n : Nat) : Type where
constructor factored
field
: List Nat
primes : product primes ≡ n
factors : All is-prime primes
is-primes
: ∀ {x} → x ∈ₗ primes → x ∣ n
prime-divides {x} h = subst (x ∣_) factors (work _ _ h) where
prime-divides : ∀ x xs → x ∈ₗ xs → x ∣ product xs
work (y ∷ xs) (here p) = subst (λ e → x ∣ e * product xs) p (∣-*l {x} {product xs})
work x (y ∷ xs) (there p) =
work x let
= work x xs p
it (div , p) = ∣→fibre it
in fibre→∣ (y * div , *-associative y div x ∙ ap (y *_) p)
: ∀ {x} → is-prime x → x ∣ n → x ∈ₗ primes
find-prime-factor {num} x d =
find-prime-factor _ primes x (λ _ → all-∈ is-primes) (subst (num ∣_) (sym factors) d)
work where
: ∀ x xs → is-prime x → (∀ x → x ∈ₗ xs → is-prime x) → x ∣ product xs → x ∈ₗ xs
work = absurd (prime≠1 xp (∣-1 xd))
work x [] xp ps xd (y ∷ xs) xp ps xd with x ≡? y
work x ... | yes x=y = here x=y
... | no ¬p = there $ work x xs xp (λ x w → ps x (there w))
(|-*-coprime-cancel x y (product xs)
(here refl) .positive ⦄
⦃ auto ⦄ ⦃ ps y (distinct-primes→coprime xp (ps y (here refl)) ¬p))
xd
open is-composite using (factors)
open Factorisation
: ∀ {n} (a b : Factorisation n) → ∀ p → p ∈ₗ a .primes → p ∈ₗ b .primes
factorisation-unique' =
factorisation-unique' a b p p∈a let
= prime-divides a p∈a
p∣n in find-prime-factor b (all-∈ (a .is-primes) p∈a) p∣n
factorisation-worker: ∀ n → (∀ k → k < n → .⦃ _ : Positive k ⦄ → Factorisation k)
→ .⦃ _ : Positive n ⦄ → Factorisation n
1 ind = factored [] refl []
factorisation-worker @(suc (suc m)) ind with is-prime-or-composite n (s≤s (s≤s 0≤x))
factorisation-worker n... | inl prime = factored (n ∷ []) (ap (2 +_) (*-oner m)) (prime ∷ [])
... | inr composite@record{p = p; q = q} =
let
instance
_ : Positive q
_ = ≤-trans ≤-ascend (composite .q-proper)
= ind q $
factored ps path primes (composite .p-prime) (composite .factors)
prime-divisor-lt p q n in record
{ primes = p ∷ ps
; factors = ap (p *_) path ·· *-commutative p q ·· composite .factors
; is-primes = composite .p-prime ∷ primes
}
: Nat → Nat
factorial = 1
factorial zero (suc n) = suc n * factorial n
factorial
: ∀ n → Positive (factorial n)
factorial-positive = s≤s 0≤x
factorial-positive zero (suc n) = *-preserves-≤ 1 (suc n) 1 (factorial n) (s≤s 0≤x) (factorial-positive n)
factorial-positive
: ∀ n → n ≤ factorial n
≤-factorial = 0≤x
≤-factorial zero (suc n) = subst (_≤ factorial (suc n)) (*-oner (suc n)) (*-preserves-≤ (suc n) (suc n) 1 (factorial n) ≤-refl (factorial-positive n))
≤-factorial
: ∀ n {m} → m < n → suc m ∣ factorial n
∣-factorial (suc n) {m} m≤n with suc m ≡? suc n
∣-factorial ... | yes m=n = subst (_∣ factorial (suc n)) (sym m=n) (∣-*l {suc n} {factorial n})
... | no m≠n = |-*l-pres {suc m} {suc n} {factorial n} $
{m} (≤-uncap (suc m) n m≠n m≤n)
∣-factorial n
: (n : Nat) .⦃ _ : Positive n ⦄ → Factorisation n
factorise = Wf-induction _<_ <-wf _ factorisation-worker
factorise
: (n : Nat) → Σ[ p ∈ Nat ] n < p × is-prime p
new-prime with is-prime-or-composite (suc (factorial n)) (s≤s (factorial-positive n))
new-prime n | inl prime = suc (factorial n) , s≤s (≤-factorial n) , prime
new-prime n | inr c@record{p = p} with holds? (suc n ≤ p)
new-prime n | inr c@record{p = p} | yes n<p = p , n<p , c .p-prime
new-prime n | inr c@record{p = suc p; q = q} | no ¬n<p =
new-prime n let
= ∣-factorial n (<-from-not-≤ _ _ (¬n<p ∘ s≤s))
rem : suc p ≡ 1
rem' = ∣-1 (∣-+-cancel' {n = suc p} {a = 1} {b = factorial n} rem (fibre→∣ (q , c .factors)))
rem' in absurd (c .p-prime .prime≠1 rem')