---
layout: default
file: "src/Setoid/Congruences/Finite/Basic.lagda.md"
title: "Setoid.Congruences.Finite.Basic module (The Agda Universal Algebra Library)"
date: "2026-07-12"
author: "the agda-algebras development team"
---
### Finitely enumerable congruence lattices
This is the [Setoid.Congruences.Finite.Basic][] module of the [Agda Universal Algebra Library][].
While [Setoid.Algebras.Finite][] defines the finiteness interface for a setoid algebra
(decidable `β` and a finite surjective enumeration of the carrier), this module
supplies the finiteness interface for congruences, that is, **decidable congruences**
(`DecCon`{.AgdaFunction}) and the record type `FiniteCongruences`{.AgdaRecord} `π¨`.
`FiniteCongruences`{.AgdaRecord} `π¨` packages a finite list `cons` of decidable
congruences of `π¨` along with a proof that this list is *complete* in the sense that
every congruence of `π¨` is, up to mutual containment `β`, one of those in `cons`.
This provides a searchable congruence lattice that finite-algebra theorems run their
algorithms over; its first consumer is the finite Birkhoff theorem of
[Setoid.Subalgebras.Subdirect.Finite][].
#### Why carrier finiteness does not suffice
Crucially, the data packaged here is *strictly stronger* than a
`FiniteAlgebra`{.AgdaRecord} witness, which is why the two interfaces are separate
records. Carrier-finiteness along with decidable setoid equality do not, by
themselves, admit a complete congruence enumeration constructively.
Indeed, a congruence is a `Type`-valued relation `π[ π¨ ] β π[ π¨ ] β Type β`, and an
arbitrary such relation on a finite carrier need not be decidable; e.g., on a bare
set of two elements, the relation that collapses the two points *iff* `P` holds is a
congruence for any proposition `P`, and it is `β`-equal to a decidable congruence
only iff `P` is decidable.
Thus, a complete enumeration of congruences-up-to-`β` is strictly stronger than
decidable equality on a finite set; it is exactly the classical content of "finite
algebra" for congruence-lattice purposes. Classically every finite algebra furnishes
these data; constructively they must be supplied, and this record is the interface
through which they are.
The two interfaces are logically independent in the other direction as well: an
infinite algebra can perfectly well have a finitely enumerable congruence lattice
(consider an algebra that is constructively simple, with decidable equality β its
complete list is the diagonal and the total congruence), so
`FiniteCongruences`{.AgdaRecord} does not presuppose a finite carrier.
There is, however, one overlap, recorded as `β-dec`{.AgdaFunction} below:
completeness forces the listed representative of the *diagonal* to decide setoid
equality, so the `_β_`{.AgdaField} field of `FiniteAlgebra`{.AgdaRecord} is derivable
from a `FiniteCongruences`{.AgdaRecord} witness.
<!--
```agda
{-# OPTIONS --cubical-compatible --exact-split --safe #-}
module Setoid.Congruences.Finite.Basic where
open import Agda.Primitive using () renaming ( Set to Type )
open import Data.List.Base using ( List ; [] ; _β·_ )
open import Data.List.Membership.Propositional using ( _β_ )
open import Data.List.Relation.Unary.Any using ( here )
open import Data.Product using ( _Γ_ ; _,_ ; Ξ£-syntax
; projβ ; projβ )
open import Data.Unit.Base using ( β€ ; tt )
open import Function using ( _β_ )
open import Level using ( Level ; _β_ ; Lift ; lift ; lower )
renaming ( suc to lsuc )
open import Relation.Binary using ( Setoid )
renaming ( Rel to BinaryRel )
open import Relation.Binary.PropositionalEquality using ( refl )
open import Relation.Nullary using ( Dec ; yes ; no )
open import Overture using ( π ; π₯ ; Signature ; π )
open import Setoid.Algebras.Basic using ( Algebra ; π[_] ; π»[_] )
open import Setoid.Algebras.Finite using ( π )
open import Setoid.Congruences.Basic using ( Con ; mkcon ; reflexive ; π[_] )
open import Setoid.Congruences.Lattice using ( _β_ )
private variable Ξ± Ο : Level
```
-->
#### Decidable congruences and the working level
A **decidable congruence** is a congruence whose membership relation is decidable.
The working congruence level is the absorbing level `π β π₯ β Ξ± β Ο`, at
which the generated (principal) congruences used downstream (e.g. for the monolith
in the finite Birkhoff construction) stay put β the same level discipline as in
[Setoid.Congruences.CompleteLattice][].
```agda
DecCon : {π : Signature π π₯}(π¨ : Algebra {π = π} Ξ± Ο)(β : Level) β Type (π β π₯ β Ξ± β Ο β lsuc β)
DecCon π¨ β = Ξ£[ (_ΞΈ_ , _) β Con π¨ β ] β x y β Dec (x ΞΈ y)
ConRel : {π¨ : Algebra {π = π} Ξ± Ο}{β : Level} β DecCon π¨ β β BinaryRel π[ π¨ ] β
ConRel ((ΞΈ , _) , _) = ΞΈ
```
#### The congruence-side finiteness interface
The record bundles a finite list `cons`{.AgdaField} of decidable congruences and a
proof `complete`{.AgdaField} that the list exhausts the congruence lattice up to
`β`. The `witness*`{.AgdaFunction} helpers project, for any congruence, its listed
representative together with the membership and `β`-equality proofs.[^1]
```agda
record FiniteCongruences {π : Signature π π₯}(π¨ : Algebra {π = π} Ξ± Ο) : Type (lsuc (π β π₯ β Ξ± β Ο)) where
field
cons : List (DecCon π¨ (π β π₯ β Ξ± β Ο))
complete : β Ο β Ξ£[ d β DecCon π¨ _ ] d β cons Γ Ο β projβ d
witness : β Ο β DecCon π¨ (π β π₯ β Ξ± β Ο)
witness = projβ β complete
witnessβ : β Ο β witness Ο β cons
witnessβ = projβ β projβ β complete
witnessβ : β Ο β Ο β projβ (witness Ο)
witnessβ = projβ β projβ β complete
```
As promised, a `FiniteCongruences`{.AgdaRecord} witness decides setoid equality:
the diagonal congruence `π[ π¨ ]` has a listed representative whose decidable
membership coincides, up to the two containments of `β`, with `β`.
```agda
module _ {π π₯ : Level}{π : Signature π π₯}{π¨ : Algebra {π = π} Ξ± Ο} (πͺ : FiniteCongruences π¨) where
open FiniteCongruences πͺ
open Setoid π»[ π¨ ] using ( _β_ )
private
Ξ : Con π¨ (π β π₯ β Ξ± β Ο)
Ξ = π[ π¨ ] {π β π₯ β Ξ± β Ο}
β-dec : (x y : π[ π¨ ]) β Dec (x β y)
β-dec x y with projβ (witness Ξ) x y
... | yes dxy = yes (lower (projβ (witnessβ Ξ) dxy))
... | no Β¬dxy = no Ξ» xβy β Β¬dxy (projβ (witnessβ Ξ) (lift xβy))
```
#### Non-vacuity: the one-element algebra
The one-element algebra `π`{.AgdaFunction} of [Setoid.Algebras.Finite][] has, up to
`β`, exactly one congruence β the all-relation, which on a one-point carrier is
also the diagonal β so its complete list is a singleton.
```agda
π-Ξ : {π π₯ : Level}{π : Signature π π₯} β DecCon (π {π = π}) (π β π₯)
π-Ξ {π = π}{π₯ = π₯} = ((Ξ» _ _ β Lift (π β π₯) β€)
, mkcon (Ξ» _ β lift tt)
(record { refl = lift tt ; sym = Ξ» _ β lift tt ; trans = Ξ» _ _ β lift tt })
(Ξ» _ _ β lift tt))
, (Ξ» _ _ β yes (lift tt))
open FiniteCongruences
π-FiniteCongruences : FiniteCongruences (π {π = π})
π-FiniteCongruences .cons = π-Ξ β· []
π-FiniteCongruences .complete ( _ , Οcon ) =
π-Ξ , here refl , (Ξ» _ β lift tt) , Ξ» x β reflexive Οcon tt
```
--------------------------------------
[^1]: In the definition of `FiniteCongruences`, each occurrence of
`β Ο β ...` could be expressed more explicitly as `Ο : Con π¨ (π β π₯ β Ξ± β Ο) β ...`.