|
| 1 | +------------------------------------------------------------------------ |
| 2 | +-- The Agda standard library |
| 3 | +-- |
| 4 | +-- Combinatorial operations |
| 5 | +------------------------------------------------------------------------ |
| 6 | + |
| 7 | +{-# OPTIONS --without-K --safe #-} |
| 8 | + |
| 9 | +module Data.Nat.Combinatorics where |
| 10 | + |
| 11 | +open import Data.Nat.Base |
| 12 | +open import Data.Nat.DivMod |
| 13 | +open import Data.Nat.Divisibility |
| 14 | +open import Data.Nat.Properties |
| 15 | +open import Relation.Binary.PropositionalEquality |
| 16 | + using (_≡_; refl; sym; cong; subst) |
| 17 | + |
| 18 | +import Data.Nat.Combinatorics.Base as Base |
| 19 | +import Data.Nat.Combinatorics.Specification as Specification |
| 20 | + |
| 21 | +open ≤-Reasoning |
| 22 | + |
| 23 | +private |
| 24 | + variable |
| 25 | + n k : ℕ |
| 26 | + |
| 27 | +------------------------------------------------------------------------ |
| 28 | +-- Definitions |
| 29 | + |
| 30 | +open Base public |
| 31 | + using (_P_; _C_) |
| 32 | + |
| 33 | +------------------------------------------------------------------------ |
| 34 | +-- Properties of _P_ |
| 35 | + |
| 36 | +open Specification public |
| 37 | + using (nPk≡n!/[n∸k]!; k>n⇒nPk≡0; [n∸k]!k!∣n!) |
| 38 | + |
| 39 | +nPn≡n! : ∀ n → n P n ≡ n ! |
| 40 | +nPn≡n! n = begin-equality |
| 41 | + n P n ≡⟨ nPk≡n!/[n∸k]! (≤-refl {n}) ⟩ |
| 42 | + n ! / (n ∸ n) ! ≡⟨ /-congʳ (cong _! (n∸n≡0 n)) ⟩ |
| 43 | + n ! / 0 ! ≡⟨⟩ |
| 44 | + n ! / 1 ≡⟨ n/1≡n (n !) ⟩ |
| 45 | + n ! ∎ |
| 46 | + where instance |
| 47 | + _ = (n ∸ n) !≢0 |
| 48 | + |
| 49 | +------------------------------------------------------------------------ |
| 50 | +-- Properties of _C_ |
| 51 | + |
| 52 | +open Specification public |
| 53 | + using (nCk≡n!/k![n-k]!; k>n⇒nCk≡0) |
| 54 | + |
| 55 | +nCk≡nC[n∸k] : k ≤ n → n C k ≡ n C (n ∸ k) |
| 56 | +nCk≡nC[n∸k] {k} {n} k≤n = begin-equality |
| 57 | + n C k ≡⟨ nCk≡n!/k![n-k]! k≤n ⟩ |
| 58 | + n ! / (k ! * (n ∸ k) !) ≡˘⟨ /-congʳ (*-comm ((n ∸ k) !) (k !)) ⟩ |
| 59 | + n ! / ((n ∸ k) ! * k !) ≡˘⟨ /-congʳ (cong ((n ∸ k) ! *_) (cong _! (m∸[m∸n]≡n k≤n))) ⟩ |
| 60 | + n ! / ((n ∸ k) ! * (n ∸ (n ∸ k)) !) ≡˘⟨ nCk≡n!/k![n-k]! (m≤n⇒n∸m≤n k≤n) ⟩ |
| 61 | + n C (n ∸ k) ∎ |
| 62 | + where instance |
| 63 | + _ = (n ∸ k) !* k !≢0 |
| 64 | + _ = k !* (n ∸ k) !≢0 |
| 65 | + _ = (n ∸ k) !* (n ∸ (n ∸ k)) !≢0 |
| 66 | + |
| 67 | +nCk≡nPk/k! : k ≤ n → n C k ≡ (n P k / k !) {{k !≢0}} |
| 68 | +nCk≡nPk/k! {k} {n} k≤n = begin-equality |
| 69 | + n C k ≡⟨ nCk≡n!/k![n-k]! k≤n ⟩ |
| 70 | + n ! / (k ! * (n ∸ k) !) ≡˘⟨ /-congʳ (*-comm ((n ∸ k)!) (k !)) ⟩ |
| 71 | + n ! / ((n ∸ k) ! * k !) ≡˘⟨ m/n/o≡m/[n*o] (n !) ((n ∸ k) !) (k !) ([n∸k]!k!∣n! k≤n) ⟩ |
| 72 | + (n ! / (n ∸ k) !) / k ! ≡˘⟨ /-congˡ (nPk≡n!/[n∸k]! k≤n) ⟩ |
| 73 | + (n P k) / k ! ∎ |
| 74 | + where instance |
| 75 | + _ = k !≢0 |
| 76 | + _ = (n ∸ k) !≢0 |
| 77 | + _ = (n ∸ k) !* k !≢0 |
| 78 | + _ = k !* (n ∸ k) !≢0 |
| 79 | + |
| 80 | +nCn≡1 : ∀ n → n C n ≡ 1 |
| 81 | +nCn≡1 n = begin-equality |
| 82 | + n C n ≡⟨ nCk≡nPk/k! (≤-refl {n}) ⟩ |
| 83 | + (n P n) / n ! ≡⟨ /-congˡ (nPn≡n! n) ⟩ |
| 84 | + n ! / n ! ≡⟨ n/n≡1 (n !) ⟩ |
| 85 | + 1 ∎ |
| 86 | + where instance |
| 87 | + _ = n !≢0 |
0 commit comments