{-# OPTIONS --cubical-compatible --safe #-} module prime where open import Data.Nat open import Data.Nat.Properties open import Data.Empty open import Data.Unit using (⊤ ; tt) open import Relation.Nullary open import Relation.Binary.PropositionalEquality open import Relation.Binary.Definitions open import gcd open import nat record Prime (i : ℕ ) : Set where field p>1 : i > 1 isPrime : ( j : ℕ ) → j < i → 0 < j → gcd i j ≡ 1 record NonPrime ( n : ℕ ) : Set where field factor : ℕ prime : Prime factor dividable : Dividable factor n PrimeP : ( n : ℕ ) → Dec ( Prime n ) PrimeP 0 = no (λ p → ⊥-elim ( nat-<> (Prime.p>1 p) (s≤s z≤n))) PrimeP 1 = no (λ p → ⊥-elim ( nat-≤> (Prime.p>1 p) (s≤s (≤-refl)))) PrimeP (suc (suc n)) = isPrime1 (suc (suc n)) (suc n) (s≤s (s≤s z≤n)) a n ¬a ¬b c = ⊥-elim ( nat-≤> c i 1 → m < n → ( (i : ℕ) → m < i → i < n → gcd n i ≡ 1 ) → Dec ( Prime n ) isPrime1 n zero n>1 m1 = n>1 } isPrime1 n (suc m) n>1 m ( gcd>0 n (suc m) (<-trans (s≤s z≤n) n>1) (s≤s z≤n)) a ) ... | tri≈ ¬a b ¬c = isPrime1 n m n>1 (<-trans a ¬a ¬b c = ⊥-elim ( nat-≤> m ¬a ¬b c = no ( λ p → nat-≡< (sym (Prime.isPrime p (suc m) m n≤j j ¬a ¬b c = ⊥-elim ( nat-≤> m1 = 1 ( gcd>0 n m (<-trans (s≤s z≤n) 1 a (subst (λ k → 1 < k) (sym (gcd20 n)) 1 ¬a ¬b c with PrimeP ( gcd n m ) ... | yes y = record { factor = gcd n m ; prime = y ; dividable = proj1 (gcd-dividable n m ) } ... | no ngcd = np2 where skip-case : NonPrime (gcd n m) → NonPrime n skip-case cc = record { factor = NonPrime.factor cc ; prime = NonPrime.prime cc ; dividable = record { factor = (Dividable.factor (proj1 (gcd-dividable n m))) * (Dividable.factor (NonPrime.dividable cc)) ; is-factor = begin Dividable.factor (proj1 (gcd-dividable n m)) * Dividable.factor (NonPrime.dividable cc) * NonPrime.factor cc + 0 ≡⟨ refl ⟩ g * d * p + 0 ≡⟨ +-comm _ 0 ⟩ g * d * p ≡⟨ *-assoc g d p ⟩ g * (d * p) ≡⟨ cong (λ k → g * k ) (+-comm 0 _) ⟩ g * (d * p + 0) ≡⟨ cong (λ k → g * k ) (Dividable.is-factor (NonPrime.dividable cc) ) ⟩ g * gcd n m ≡⟨ +-comm 0 _ ⟩ g * gcd n m + 0 ≡⟨ Dividable.is-factor (proj1 (gcd-dividable n m)) ⟩ n ∎ }} where open ≡-Reasoning g = Dividable.factor (proj1 (gcd-dividable n m)) d = Dividable.factor (NonPrime.dividable cc) p = NonPrime.factor cc np2 : NonPrime n np2 with <-cmp (gcd n m) m ... | tri< a ¬b ¬c = skip-case (np1 (gcd n m) m ngcd c (skipFactor (gcd n m) a )) ... | tri≈ ¬a b ¬c = skip-case (np1 (gcd n m) m ngcd c (subst (λ k → Factoring m k) (sym b) (findFactor m ≤-refl (λ j n≤j j n≤j j ¬a ¬b' c with <-cmp 0 m ... | tri< a ¬b ¬c = ⊥-elim ( nat-≤> (subst (λ k → k ≤ m) (gcdsym {m} {n}) (gcd-≤ a (<-trans a m≤n))) c ) ... | tri≈ ¬a' b' ¬c = ⊥-elim ( np record { isPrime = λ j lt 01 = 1 a n ¬a ¬b c = np1 n m np 1 n≤j j ¬a ¬b c = ⊥-elim ( nat-≤> c nm : {m : ℕ} → suc m < suc (factorial (suc m)) f>m {m} = begin suc (suc m) ≡⟨ cong (λ k → 1 + suc k ) (+-comm _ m) ⟩ suc (1 + 1 * m) ≡⟨ cong (λ k → suc (1 + k )) (*-comm 1 m) ⟩ suc (1 + m * 1) ≤⟨ s≤s (s≤s (*-monoʳ-≤ m (factorial≥1 {m}) )) ⟩ suc (1 + m * factorial m) ≤⟨ s≤s (+-monoˡ-≤ _ (factorial≥1 {m})) ⟩ suc (factorial m + m * factorial m) ≡⟨ refl ⟩ suc (factorial (suc m)) ∎ where open ≤-Reasoning prime-is-infinite : (max-prime : ℕ ) → ¬ ( (j : ℕ) → max-prime < j → ¬ Prime j ) prime-is-infinite zero pmax = pmax 3 (s≤s z≤n) record { isPrime = λ n lt 01 = s≤s (s≤s z≤n) } where pif3 : (n : ℕ) → n < 3 → 0 < n → gcd 3 n ≡ 1 pif3 .1 (s≤s (s≤s z≤n)) _ = refl pif3 .2 (s≤s (s≤s (s≤s z≤n))) _ = refl prime-is-infinite (suc m) pmax = newPrime where prime ¬a ¬b c = ⊥-elim ( pmax n c p ) fact : (n : ℕ) → Prime n → Dividable n ( factorial (suc m) ) fact n p = fact< m n (<-trans (s≤s z≤n) (Prime.p>1 p)) ( prime 1 → Dividable k i → ¬ Dividable k (suc i) newPrime : ⊥ newPrime with PrimeP ( suc (factorial (suc m)) ) ... | yes p = pmax _ f>m p -- yes, we found a prime not in list ... | no np = div+1 (Prime.p>1 (NonPrime.prime p1)) (fact (NonPrime.factor p1) (NonPrime.prime p1) ) (NonPrime.dividable p1) where -- n!+1 cannot be dividable, because n! is dividable -- the factor need not be a prime, but anyway we prove that there is a prime factor in NonPrime p1 : NonPrime ( suc (factorial (suc m)) ) p1 = nonPrime (begin 2 ≤⟨ s≤s ( s≤s z≤n) ⟩ suc (suc m) ≤⟨ s≤s (m