Skip to content

Commit f3b7699

Browse files
Add Data.Nat.Combinatorics (#1463)
1 parent 122a031 commit f3b7699

9 files changed

Lines changed: 398 additions & 11 deletions

File tree

CHANGELOG.md

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -672,6 +672,13 @@ Deprecated names
672672
id-↔ ↦ ↔-id
673673
```
674674

675+
* Factorial, combinations and permutations for ℕ.
676+
```
677+
Data.Nat.Combinatorics
678+
Data.Nat.Combinatorics.Base
679+
Data.Nat.Combinatorics.Spec
680+
```
681+
675682
* In `Function.Construct.Symmetry`:
676683
```
677684
sym-⤖ ↦ ⤖-sym
@@ -1033,21 +1040,37 @@ Other minor changes
10331040
n≮0 : n ≮ 0
10341041
n+1+m≢m : n + suc m ≢ m
10351042
m*n≡0⇒m≡0 : .{{_ : NonZero n}} → m * n ≡ 0 → m ≡ 0
1043+
n>0⇒n≢0 : n > 0 → n ≢ 0
10361044
m^n≢0 : .{{_ : NonZero m}} → NonZero (m ^ n)
1037-
1038-
1045+
m*n≢0 : .{{_ : NonZero m}} .{{_ : NonZero n}} → NonZero (m * n)
1046+
m≤n⇒n∸m≤n : m ≤ n → n ∸ m ≤ n
1047+
1048+
1≤n! : 1 ≤ n !
1049+
_!≢0 : NonZero (n !)
1050+
_!*_!≢0 : NonZero (m ! * n !)
1051+
10391052
anyUpTo? : ∀ (P? : U.Decidable P) (v : ℕ) → Dec (∃ λ n → n < v × P n)
10401053
allUpTo? : ∀ (P? : U.Decidable P) (v : ℕ) → Dec (∀ {n} → n < v → P n)
10411054
```
10421055

1056+
* Added new functions in `Data.Nat`:
1057+
```agda
1058+
_! : ℕ → ℕ
1059+
```
1060+
10431061
* Added new proofs in `Data.Nat.DivMod`:
10441062
```agda
1045-
m%n≤n : .{{_ : NonZero n}} → m % n ≤ n
1063+
m%n≤n : .{{_ : NonZero n}} → m % n ≤ n
1064+
m*n/m!≡n/[m∸1]! : .{{_ : NonZero m}} → m * n / m ! ≡ n / (pred m) !
10461065
```
10471066

10481067
* Added new proofs in `Data.Nat.Divisibility`:
10491068
```agda
1050-
n∣m*n*o : n ∣ m * n * o
1069+
n∣m*n*o : n ∣ m * n * o
1070+
m*n∣⇒m∣ : m * n ∣ i → m ∣ i
1071+
m*n∣⇒n∣ : m * n ∣ i → n ∣ i
1072+
m≤n⇒m!∣n! : m ≤ n → m ! ∣ n !
1073+
m/n/o≡m/[n*o] : .{{NonZero n}} .{{NonZero o}} → n * o ∣ m → (m / n) / o ≡ m / (n * o)
10511074
```
10521075

10531076
* Added new patterns in `Data.Nat.Reflection`:

README/Data/Default.agda

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
module README.Data.Default where
1111

1212
open import Data.Default
13-
open import Data.Nat.Base
13+
open import Data.Nat.Base hiding (_!)
1414
open import Relation.Binary.PropositionalEquality
1515

1616
-- An argument of type `WithDefault {a} {A} x` is an argument of type

src/Data/Nat/Base.agda

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ open import Relation.Binary.Core using (Rel)
1717
open import Relation.Binary.PropositionalEquality.Core
1818
using (_≡_; _≢_; refl)
1919
open import Relation.Nullary using (¬_)
20-
open import Relation.Nullary.Negation.Core using (contradiction)
20+
open import Relation.Nullary.Negation using (contradiction)
2121
open import Relation.Unary using (Pred)
2222

2323
------------------------------------------------------------------------
@@ -123,6 +123,7 @@ open import Agda.Builtin.Nat
123123
pred :
124124
pred n = n ∸ 1
125125

126+
infix 8 _!
126127
infixl 7 _⊓_ _/_ _%_
127128
infixl 6 _+⋎_ _⊔_
128129

@@ -183,6 +184,12 @@ m / (suc n) = div-helper 0 n m n
183184
_%_ : (dividend divisor : ℕ) .{{_ : NonZero divisor}}
184185
m % (suc n) = mod-helper 0 n m n
185186

187+
-- Factorial
188+
189+
_! :
190+
zero ! = 1
191+
suc n ! = suc n * n !
192+
186193
------------------------------------------------------------------------
187194
-- Alternative definition of _≤_
188195

src/Data/Nat/Combinatorics.agda

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
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
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
------------------------------------------------------------------------
2+
-- The Agda standard library
3+
--
4+
-- Combinatorics operations
5+
------------------------------------------------------------------------
6+
7+
{-# OPTIONS --without-K --safe #-}
8+
9+
module Data.Nat.Combinatorics.Base where
10+
11+
open import Data.Bool.Base using (if_then_else_)
12+
open import Data.Nat.Base
13+
open import Data.Nat.Properties using (_!≢0)
14+
15+
-- NOTE: These operators are not implemented as efficiently as they
16+
-- could be. See the following link for more details.
17+
--
18+
-- https://math.stackexchange.com/questions/202554/how-do-i-compute-binomial-coefficients-efficiently
19+
20+
------------------------------------------------------------------------
21+
-- Permutations / falling factorial
22+
23+
-- The number of ways, including order, that k objects can be chosen
24+
-- from among n objects.
25+
26+
-- n P k = n ! / (n ∸ k) !
27+
28+
-- Base definition. Only valid for k ≤ n.
29+
30+
_P′_ :
31+
n P′ zero = 1
32+
n P′ (suc k) = (n ∸ k) * (n P′ k)
33+
34+
-- Main definition. Valid for all k as deals with boundary case.
35+
36+
_P_ :
37+
n P k = if k ≤ᵇ n then n P′ k else 0
38+
39+
------------------------------------------------------------------------
40+
-- Combinations / binomial coefficient
41+
42+
-- The number of ways, disregarding order, that k objects can be chosen
43+
-- from among n objects.
44+
45+
-- n C k = n ! / (k ! * (n ∸ k) !)
46+
47+
-- Base definition. Only valid for k ≤ n.
48+
49+
_C′_ :
50+
n C′ k = (n P′ k) / k !
51+
where instance _ = k !≢0
52+
53+
-- Main definition. Valid for all k.
54+
-- Deals with boundary case and exploits symmetry to improve performance.
55+
56+
_C_ :
57+
n C k = if k ≤ᵇ n then n C′ (k ⊓ (n ∸ k)) else 0

0 commit comments

Comments
 (0)