module Data.Fin.Closure where

Closure of finite setsπŸ”—

In this module, we prove that the finite sets are closed under β€œtypal arithmetic”: The initial and terminal objects are finite (they have 1 and 0 elements respectively), products of finite sets are finite, coproducts of finite sets are finite, and functions between finite sets are finite. Moreover, these operations all correspond to arithmetic operations on the natural number indices: etc.

Zero, one, successorsπŸ”—

The finite set is an initial object, and the finite set is a terminal object:

Finite-zero-is-initial : Fin 0 ≃ βŠ₯
Finite-zero-is-initial .fst ()
Finite-zero-is-initial .snd .is-eqv ()

Finite-one-is-contr : is-contr (Fin 1)
Finite-one-is-contr .centre = fzero
Finite-one-is-contr .paths i with fin-view i
... | zero = refl

The successor operation on indices corresponds to taking coproducts with the unit set.

Finite-successor : Fin (suc n) ≃ (⊀ ⊎ Fin n)
Finite-successor {n} = Fin-suc βˆ™e Maybe-is-sum

AdditionπŸ”—

For binary coproducts, we prove the correspondence with addition in steps, to make the proof clearer:

Finite-coproduct : (Fin n ⊎ Fin m) ≃ Fin (n + m)
Finite-coproduct {zero} {m}  =
  (Fin 0 ⊎ Fin m) β‰ƒβŸ¨ ⊎-apl Finite-zero-is-initial βŸ©β‰ƒ
  (βŠ₯ ⊎ Fin m)     β‰ƒβŸ¨ ⊎-zerol βŸ©β‰ƒ
  Fin m           β‰ƒβˆŽ
Finite-coproduct {suc n} {m} =
  (Fin (suc n) ⊎ Fin m) β‰ƒβŸ¨ ⊎-apl Finite-successor βŸ©β‰ƒ
  ((⊀ ⊎ Fin n) ⊎ Fin m) β‰ƒβŸ¨ ⊎-assoc βŸ©β‰ƒ
  (⊀ ⊎ (Fin n ⊎ Fin m)) β‰ƒβŸ¨ ⊎-apr (Finite-coproduct {n} {m}) βŸ©β‰ƒ
  (⊀ ⊎ Fin (n + m))     β‰ƒβŸ¨ Finite-successor e⁻¹ βŸ©β‰ƒ
  Fin (suc (n + m))     β‰ƒβˆŽ

SumsπŸ”—

We also have a correspondence between β€œcoproducts” and β€œaddition” in the iterated case: If you have a family of finite types (represented by a map to their cardinalities), the dependent sum of that family is equivalent to the iterated binary sum of the cardinalities:

sum : βˆ€ n β†’ (Fin n β†’ Nat) β†’ Nat
sum zero f = zero
sum (suc n) f = f fzero + sum n (f ∘ fsuc)

Finite-sum : (B : Fin n β†’ Nat) β†’ Ξ£ (Fin _) (Fin ∘ B) ≃ Fin (sum n B)
Finite-sum {zero} B .fst ()
Finite-sum {zero} B .snd .is-eqv ()
Finite-sum {suc n} B =
  Ξ£ (Fin (suc n)) (Fin ∘ B)              β‰ƒβŸ¨ Fin-suc-Ξ£ βŸ©β‰ƒ
  Fin (B 0) ⊎ Ξ£ (Fin n) (Fin ∘ B ∘ fsuc) β‰ƒβŸ¨ ⊎-apr (Finite-sum (B ∘ fsuc)) βŸ©β‰ƒ
  Fin (B 0) ⊎ Fin (sum n (B ∘ fsuc))     β‰ƒβŸ¨ Finite-coproduct βŸ©β‰ƒ
  Fin (sum (suc n) B)                    β‰ƒβˆŽ

MultiplicationπŸ”—

Recall (from middle school) that the product is the same thing as summing together copies of the number Correspondingly, we can use the theorem above for general sums to establish the case of binary products:

Finite-multiply : (Fin n Γ— Fin m) ≃ Fin (n * m)
Finite-multiply {n} {m} =
  (Fin n Γ— Fin m)       β‰ƒβŸ¨ Finite-sum (Ξ» _ β†’ m) βŸ©β‰ƒ
  Fin (sum n (Ξ» _ β†’ m)) β‰ƒβŸ¨ pathβ†’equiv (ap Fin (sum≑* n m)) βŸ©β‰ƒ
  Fin (n * m)           β‰ƒβˆŽ
  where
    sum≑* : βˆ€ n m β†’ sum n (Ξ» _ β†’ m) ≑ n * m
    sum≑* zero m = refl
    sum≑* (suc n) m = ap (m +_) (sum≑* n m)

ProductsπŸ”—

Similarly to the case for sums, the cardinality of a dependent product of finite sets is the product of the cardinalities:

product : βˆ€ n β†’ (Fin n β†’ Nat) β†’ Nat
product zero f = 1
product (suc n) f = f fzero * product n (f ∘ fsuc)

Finite-product : (B : Fin n β†’ Nat) β†’ (βˆ€ x β†’ Fin (B x)) ≃ Fin (product n B)
Finite-product {zero} B .fst _ = fzero
Finite-product {zero} B .snd = is-iso→is-equiv λ where
  .is-iso.inv  _ ()
  .is-iso.linv _ β†’ funext Ξ» ()

  .is-iso.rinv fzero                      β†’ refl
  .is-iso.rinv (fin (suc i) ⦃ forget p ⦄) β†’ absurd (Β¬suc≀0 (≀-peel p))
Finite-product {suc n} B =
  (βˆ€ x β†’ Fin (B x))                          β‰ƒβŸ¨ Fin-suc-Ξ  βŸ©β‰ƒ
  Fin (B fzero) Γ— (βˆ€ x β†’ Fin (B (fsuc x)))   β‰ƒβŸ¨ Ξ£-ap-snd (Ξ» _ β†’ Finite-product (B ∘ fsuc)) βŸ©β‰ƒ
  Fin (B fzero) Γ— Fin (product n (B ∘ fsuc)) β‰ƒβŸ¨ Finite-multiply βŸ©β‰ƒ
  Fin (B fzero * product n (B ∘ fsuc))       β‰ƒβˆŽ

PermutationsπŸ”—

We show that the set of permutations is finite with cardinality (the factorial of

We start by showing that a permutation of is determined by what happens to and by the remaining permutation of

Fin-permutations-suc
  : βˆ€ n β†’ (Fin (suc n) ≃ Fin (suc n)) ≃ (Fin (suc n) Γ— (Fin n ≃ Fin n))
Fin-permutations-suc n = to , is-iso→is-equiv is where
  to : (Fin (suc n) ≃ Fin (suc n)) β†’ Fin (suc n) Γ— (Fin n ≃ Fin n)
  to e .fst = e # 0
  to e .snd .fst i = avoid (e # 0) (e # (fsuc i)) Ξ» p β†’
    zero≠suc (ap lower (Equiv.injective e p))
  to e .snd .snd = Fin-injection→equiv _ λ p →
    fsuc-inj (Equiv.injective e (avoid-injective (e # 0) p))

  is : is-iso to
  is .is-iso.inv (n , e) = record { fst = fun ; snd = Fin-injection→equiv _ inj  } module inv where
    fun : Fin (suc _) β†’ Fin (suc _)
    fun i with fin-view i
    ... | zero  = n
    ... | suc x = skip n (e # x)

    inj : injective fun
    inj {i} {j} p with fin-view i | fin-view j
    ... | zero  | zero  = refl
    ... | zero  | suc y = absurd (skip-skips n _ (sym p))
    ... | suc i | zero  = absurd (skip-skips n _ p)
    ... | suc i | suc j = ap fsuc (Equiv.injective e (skip-injective n _ _ p))
  is .is-iso.rinv (n , e) = Ξ£-pathp refl (ext Ξ» i β†’ avoid-skip n (e # i))
  is .is-iso.linv e = ext p where
    p : βˆ€ x β†’ inv.fun (e # 0) (to e .snd) x ≑ e .fst x
    p x with fin-view x
    ... | zero  = refl
    ... | suc i = skip-avoid (e # 0) (e # fsuc i)

We can now show that by induction.

Fin-permutations : βˆ€ n β†’ (Fin n ≃ Fin n) ≃ Fin (factorial n)
Fin-permutations zero = is-contr→≃
  (contr id≃ Ξ» _ β†’ ext Ξ» ()) Finite-one-is-contr
Fin-permutations (suc n) =
  Fin (suc n) ≃ Fin (suc n)       β‰ƒβŸ¨ Fin-permutations-suc n βŸ©β‰ƒ
  Fin (suc n) Γ— (Fin n ≃ Fin n)   β‰ƒβŸ¨ Ξ£-ap-snd (Ξ» _ β†’ Fin-permutations n) βŸ©β‰ƒ
  Fin (suc n) Γ— Fin (factorial n) β‰ƒβŸ¨ Finite-multiply βŸ©β‰ƒ
  Fin (factorial (suc n))         β‰ƒβˆŽ

Decidable subsetsπŸ”—

Given a decidable predicate on we can compute such that is equivalent to the subset of on which the predicate holds: a decidable proposition is finite (it has either or elements), so we can reuse our proof that finite sums of finite types are finite.

Dec→Fin
  : βˆ€ {β„“} {A : Type β„“} β†’ is-prop A β†’ Dec A
  β†’ Ξ£ Nat Ξ» n β†’ Fin n ≃ A
Dec→Fin ap (no ¬a) .fst = 0
Dec→Fin ap (no ¬a) .snd =
  is-empty→≃ (Finite-zero-is-initial .fst) Β¬a
Dec→Fin ap (yes a) .fst = 1
Dec→Fin ap (yes a) .snd =
  is-contr→≃ Finite-one-is-contr (is-propβˆ™β†’is-contr ap a)

Finite-subset
  : βˆ€ {n} (P : Fin n β†’ Type β„“)
  β†’ ⦃ βˆ€ {x} β†’ H-Level (P x) 1 ⦄
  β†’ ⦃ dec : βˆ€ {x} β†’ Dec (P x) ⦄
  β†’ Ξ£ Nat Ξ» s β†’ Fin s ≃ Ξ£ (Fin n) P
Finite-subset {n = n} P ⦃ dec = dec ⦄ =
  sum n ns , Finite-sum ns e⁻¹ βˆ™e Ξ£-ap-snd es
  where
    ns : Fin n β†’ Nat
    ns i = Dec→Fin (hlevel 1) dec .fst
    es : (i : Fin n) β†’ Fin (ns i) ≃ P i
    es i = Dec→Fin (hlevel 1) dec .snd

Decidable quotientsπŸ”—

As a first step towards coequalisers, we show that the quotient of a finite set by a decidable congruence is finite.

Finite-quotient
  : βˆ€ {n β„“} (R : Congruence (Fin n) β„“) (open Congruence R)
  β†’ ⦃ _ : βˆ€ {x y} β†’ Dec (x ∼ y) ⦄
  β†’ Ξ£ Nat Ξ» q β†’ Fin q ≃ Fin n / _∼_

This amounts to counting the number of equivalence classes of We proceed by induction on the base case is trivial.

Finite-quotient {zero} R .fst = 0
Finite-quotient {zero} R .snd .fst ()
Finite-quotient {zero} R .snd .snd .is-eqv = elim! Ξ» ()

For the induction step, we restrict along the successor map to get a congruence on whose quotient is finite.

Finite-quotient {suc n} {β„“} R = go where
  module R = Congruence R

  R₁ : Congruence (Fin n) β„“
  R₁ = Congruence-pullback fsuc R
  module R₁ = Congruence R₁

  n/R₁ : Ξ£ Nat Ξ» q β†’ Fin q ≃ Fin n / R₁._∼_
  n/R₁ = Finite-quotient {n} R₁

In order to compute the size of the quotient we decide whether is related by to any using the omniscience of finite sets.

  go
    : ⦃ Dec (Ξ£ (Fin n) (Ξ» i β†’ fzero R.∼ fsuc i)) ⦄
    β†’ Ξ£ Nat (Ξ» q β†’ Fin q ≃ Fin (suc n) / R._∼_)

If so, lives in the same equivalence class as and the size of the quotient remains unchanged.

  go ⦃ yes (i , r) ⦄ .fst = n/R₁ .fst
  go ⦃ yes (i , r) ⦄ .snd = n/R₁ .snd βˆ™e Isoβ†’Equiv is where
    is : Iso (Fin n / R₁._∼_) (Fin (suc n) / R._∼_)
    is .fst = Coeq-rec (Ξ» x β†’ inc (fsuc x)) Ξ» (x , y , s) β†’ quot s
    is .snd .inv = Coeq-rec fn Ξ» (i , j , s) β†’ resp i j s where
      fn : Fin (suc n) β†’ Fin n / R₁._∼_
      fn j with fin-view j
      ... | zero  = inc i
      ... | suc x = inc x

      resp : βˆ€ i j β†’ i R.∼ j β†’ fn i ≑ fn j
      resp i j s with fin-view i | fin-view j
      ... | zero  | zero  = refl
      ... | zero  | suc y = quot (R.symᢜ r R.βˆ™αΆœ s)
      ... | suc x | zero  = quot (s R.βˆ™αΆœ r)
      ... | suc x | suc y = quot s
    is .snd .rinv = elim! (Fin-cases (quot (R.symᢜ r)) (Ξ» _ β†’ refl))
    is .snd .linv = elim! Ξ» _ β†’ refl

Otherwise, creates a new equivalence class for itself.

  go ⦃ no Β¬r ⦄ .fst = suc (n/R₁ .fst)
  go ⦃ no Β¬r ⦄ .snd = Finite-successor βˆ™e ⊎-apr (n/R₁ .snd) βˆ™e Isoβ†’Equiv is where
    to : Fin (suc n) β†’ ⊀ ⊎ (Fin n / R₁._∼_)
    to i with fin-view i
    ... | zero  = inl _
    ... | suc x = inr (inc x)

    resp : βˆ€ i j β†’ i R.∼ j β†’ to i ≑ to j
    resp i j s with fin-view i | fin-view j
    ... | zero  | zero  = refl
    ... | zero  | suc y = absurd (Β¬r (y , s))
    ... | suc x | zero  = absurd (¬r (x , R.symᢜ s))
    ... | suc x | suc y = ap inr (quot s)

    is : Iso (⊀ ⊎ (Fin n / R₁._∼_)) (Fin (suc n) / R._∼_)
    is .fst (inl tt) = inc 0
    is .fst (inr x) = Coeq-rec (Ξ» x β†’ inc (fsuc x)) (Ξ» (x , y , s) β†’ quot s) x
    is .snd .inv = Coeq-rec to Ξ» (x , y , r) β†’ resp x y r
    is .snd .rinv = elim! (Fin-cases refl (Ξ» _ β†’ refl))
    is .snd .linv (inl tt) = refl
    is .snd .linv (inr x) = elim x where
      elim : βˆ€ x β†’ is .snd .inv (is .fst (inr x)) ≑ inr x
      elim = elim! Ξ» _ β†’ refl

CoequalisersπŸ”—

Given two functions we can compute such that is equivalent to the coequaliser of and We start by expressing the coequaliser as the quotient of by the congruence generated by the relation so that we can apply the result above. Since this relation is clearly decidable by the omniscience of all that remains is to show that the closure of a decidable relation on a finite set is decidable.

instance
  Closure-Fin-Dec
    : βˆ€ {n β„“} {R : Fin n β†’ Fin n β†’ Type β„“}
    β†’ ⦃ βˆ€ {x y} β†’ Dec (R x y) ⦄
    β†’ βˆ€ {x y} β†’ Dec (Closure R x y)

This amounts to writing a (verified!) pathfinding algorithm: given we need to decide whether there is a path between and in the undirected graph whose edges are given by

We proceed by induction on the base case is trivial, so we are left with the inductive case The simplest1 way forward is to find a decidable congruence that is equivalent to the closure

We start by defining the restriction of along the successor map written as well as the symmetric closure of written

  Closure-Fin-Dec {suc n} {β„“} {R} {x} {y} = R*-dec where
    open Congruence
    module R = Congruence (Closure-congruence R)

    R₁ : Fin n β†’ Fin n β†’ Type _
    R₁ x y = R (fsuc x) (fsuc y)
    module R₁ = Congruence (Closure-congruence R₁)

    R₁→R : βˆ€ {x y} β†’ Closure R₁ x y β†’ Closure R (fsuc x) (fsuc y)
    R₁→R = Closure-rec-congruence R₁
      (Congruence-pullback fsuc (Closure-congruence R)) inc

    RΛ’ : Fin (suc n) β†’ Fin (suc n) β†’ Type _
    R˒ x y = R x y ⊎ R y x

    RΛ’β†’R : βˆ€ {x y} β†’ RΛ’ x y β†’ Closure R x y
    RΛ’β†’R = [ inc , R.symᢜ ∘ inc ]

We build by cases. is trivial, since the closure is reflexive.

    D' : {i j : Fin (suc n)} β†’ Fin-view i β†’ Fin-view j β†’ Type β„“
    D' zero zero = Lift _ ⊀

For we use the omniscience of to search for an such that and Here we rely on the closure of being decidable by the induction hypothesis. The case is symmetric.

    D' zero (suc y) = Ξ£[ x ∈ Fin n ] RΛ’ 0 (fsuc x) Γ— Closure R₁ x y
    D' (suc x) zero = Ξ£[ y ∈ Fin n ] Closure R₁ x y Γ— RΛ’ (fsuc y) 0

Finally, in order to decide whether and are related by we have two possibilities: either there is a path from to in which we can find using the induction hypothesis, or there are are paths from to and from to in which we can find using the previous two cases.

    D' (suc x) (suc y) = Closure R₁ x y ⊎ D' (suc x) zero Γ— D' zero (suc y)

Proving that (the propositional truncation of) is a decidable congruence is tedious but not difficult.

    D-cong : Congruence (Fin (suc n)) _
    instance D-Dec : βˆ€ {x y} β†’ Dec (D x y)
    D-refl : βˆ€ x β†’ D x x
    D-refl i with fin-view i
    ... | zero  = _
    ... | suc x = inl R₁.reflᢜ

    D-trans : βˆ€ x y z β†’ D x y β†’ D y z β†’ D x z
    D-trans i j k p q with fin-view i | fin-view j | fin-view k | p | q
    ... | zero  | zero  | z     | _            | d            = d
    ... | zero  | suc y | zero  | _            | _            = _
    ... | zero  | suc y | suc z | y' , ry , cy | inl c        = y' , ry , cy R₁.βˆ™αΆœ c
    ... | zero  | suc y | suc z | _            | inr (_ , dz) = dz
    ... | suc x | zero  | zero  | d            | _            = d
    ... | suc x | zero  | suc z | dx           | dy           = inr (dx , dy)
    ... | suc x | suc y | zero  | inl c        | y' , cy , ry = y' , c R₁.βˆ™αΆœ cy , ry
    ... | suc x | suc y | zero  | inr (dx , _) | _            = dx
    ... | suc x | suc y | suc z | inl c        | inl d = inl (c R₁.βˆ™αΆœ d)
    ... | suc x | suc y | suc z | inl c        | inr ((y' , cy , ry) , dz) =
      inr ((y' , c R₁.βˆ™αΆœ cy , ry) , dz)
    ... | suc x | suc y | suc z | inr (dx , (y' , ry , cy)) | inl c =
      inr (dx , y' , ry , cy R₁.βˆ™αΆœ c)
    ... | suc x | suc y | suc z | inr (dx , dy) | inr (dy' , dz) =
      inr (dx , dz)

    D-sym : βˆ€ {i j} (x : Fin-view i) (y : Fin-view j) β†’ D' x y β†’ D' y x
    D-sym zero zero    _            = _
    D-sym zero (suc y) (y' , r , c) = y' , R₁.symᢜ c , ⊎-comm .fst r
    D-sym (suc x) zero (x' , c , r) = x' , ⊎-comm .fst r , R₁.symᢜ c
    D-sym (suc x) (suc y) (inl r)   = inl (R₁.symᢜ r)
    D-sym (suc x) (suc y) (inr (dx , dy)) =
      inr (D-sym zero (suc y) dy , D-sym (suc x) zero dx)

    D-cong ._∼_ x y = βˆ₯ D x y βˆ₯
    D-cong .has-is-prop _ _ = hlevel 1
    D-cong .reflᢜ {x} = inc (D-refl x)
    D-cong ._βˆ™αΆœ_ {x} {y} {z} = βˆ₯-βˆ₯-mapβ‚‚ (D-trans x y z)
    D-cong .symᢜ {x} {y} = map (D-sym (fin-view x) (fin-view y))

    {-# INCOHERENT D-Dec #-}
    D-Dec {i} {j} with fin-view i | fin-view j
    ... | zero  | zero  = auto
    ... | zero  | suc y = auto
    ... | suc x | zero  = auto
    ... | suc x | suc y = auto

To complete the proof, we show that is indeed equivalent to it suffices to show that lies between and

    Rβ†’D : βˆ€ {x y} β†’ R x y β†’ D x y
    R→D {i} {j} r with fin-view i | fin-view j
    ... | zero  | zero  = _
    ... | zero  | suc y = y , inl r , R₁.reflᢜ
    ... | suc x | zero  = x , R₁.reflᢜ , inl r
    ... | suc x | suc y = inl (inc r)

    Dβ†’R* : βˆ€ {x y i j} β†’ D' {x} {y} i j β†’ Closure R x y
    Dβ†’R* {i = zero}  {j = zero}  _ = R.reflᢜ
    Dβ†’R* {i = zero}  {j = suc y} (y' , r , c) = RΛ’β†’R r R.βˆ™αΆœ R₁→R c
    Dβ†’R* {i = suc x} {j = zero}  (x' , c , r) = R₁→R c R.βˆ™αΆœ RΛ’β†’R r
    Dβ†’R* {i = suc x} {j = suc y} (inl r) = R₁→R r
    D→R* {i = suc x} {j = suc y} (inr (dx , dy)) =
      Dβ†’R* {i = suc x} {j = zero} dx R.βˆ™αΆœ Dβ†’R* {i = zero} {suc y} dy

    R*β†’D : βˆ€ {x y} β†’ Closure R x y β†’ βˆ₯ D x y βˆ₯
    R*β†’D = Closure-rec-congruence R D-cong (inc ∘ Rβ†’D)

    R*-dec : Dec (Closure R x y)
    R*-dec = invmap (rec! Dβ†’R*) R*β†’D (holds? βˆ₯ D x y βˆ₯)

We can finally assemble the pieces together: given the coequaliser of and is equivalent to the quotient of by the decidable relation induced by and and hence by its congruence closure But we know that quotients of finite sets by decidable congruences are finite, and we just proved that the closure of a decidable relation on a finite set is decidable, so we’re done.

Finite-coequaliser
  : βˆ€ {n m} (f g : Fin m β†’ Fin n)
  β†’ Ξ£ Nat Ξ» q β†’ Fin q ≃ Coeq f g
Finite-coequaliser {n} f g
  = n/R .fst
  , n/R .snd
    βˆ™e Closure-quotient R e⁻¹
    βˆ™e Coeq≃quotient f g e⁻¹
  where
    R = span→R f g

    n/R : Ξ£ Nat Ξ» q β†’ Fin q ≃ Fin n / Closure R
    n/R = Finite-quotient (Closure-congruence R)

  1. In terms of ease of implementation; the complexity of the resulting algorithm is catastrophic.β†©οΈŽ