Lane Biocini, 21 January 2026

The equational theory of PSL2Z. Although s² = 1 and r³ = 1 hold
definitionally (by computation), we provide propositional witnesses
for use in equational reasoning chains. The main result is that
PSL2Z has decidable equality, making it a set (h-level 2).

The decidability proof exploits the mutual inductive structure:
S-edge and R-edge each have decidable equality by structural
recursion, and the disjoint sum PSL2Z = S-edge + R-edge inherits
decidability.

\begin{code}

{-# OPTIONS --safe --without-K #-}

module Groups.ModularGroup.Properties where

open import MLTT.Spartan
open import MLTT.Two-Properties
open import MLTT.Plus-Properties using (+disjoint; +functor; inl-lc; inr-lc)
open import MLTT.Unit-Properties using (𝟙-is-not-𝟘)
open import UF.DiscreteAndSeparated using (is-discrete; discrete-types-are-sets)
open import UF.Sets using (is-set)
open import Groups.ModularGroup.Type
open import Groups.ModularGroup.Base

 : (x : PSL2Z)  s (s x)  x
 (η e₀)  = refl
 (η e₁)  = refl
 (s∙ re) = refl
 (θ re)  = refl

 : (x : PSL2Z)  r (r (r x))  x
 (η e₀)            = refl
 (η e₁)            = refl
 (s∙ re)           = refl
 (r∙ e₀)           = refl
 (r∙ e₁)           = refl
 (r∙ cross re)     = refl
 (r²∙ e₀)          = refl
 (r²∙ e₁)          = refl
 (r²∙ cross re)    = refl

r²-r : (x : PSL2Z)   (r x)  x
r²-r = 

r-r² : (x : PSL2Z)  r ( x)  x
r-r² = 

s-E : s E  S
s-E = refl

s-S : s S  E
s-S = refl

r-E : r E  R
r-E = refl

r-R : r R  
r-R = refl

r-R² : r   E
r-R² = refl

r²-E :  E  
r²-E = refl

r²-R :  R  E
r²-R = refl

r²-R² :    R
r²-R² = refl

r-η : (se : S-edge)  r (η se)  r∙ se
r-η e₀         = refl
r-η e₁         = refl
r-η (cross re) = refl

r²-η : (se : S-edge)   (η se)  r²∙ se
r²-η e₀         = refl
r²-η e₁         = refl
r²-η (cross re) = refl

r-θ-r+ : (se : S-edge)  r (θ (r+ se))  θ (r- se)
r-θ-r+ e₀         = refl
r-θ-r+ e₁         = refl
r-θ-r+ (cross re) = refl

r-θ-r- : (se : S-edge)  r (θ (r- se))  η se
r-θ-r- e₀         = refl
r-θ-r- e₁         = refl
r-θ-r- (cross re) = refl

r²-θ-r+ : (se : S-edge)   (θ (r+ se))  η se
r²-θ-r+ se = ap r (r-θ-r+ se)  r-θ-r- se

r²-θ-r- : (se : S-edge)   (θ (r- se))  θ (r+ se)
r²-θ-r- se = ap r (r-θ-r- se)  r-η se

sr-η : (se : S-edge)  s (r (η se))  sr∙ se
sr-η e₀         = refl
sr-η e₁         = refl
sr-η (cross re) = refl

sr²-η : (se : S-edge)  s ( (η se))  sr²∙ se
sr²-η e₀         = refl
sr²-η e₁         = refl
sr²-η (cross re) = refl

rs-θ : (re : R-edge)  r (s (θ re))  rs∙ re
rs-θ (r+ se) = refl
rs-θ (r- se) = refl

r²s-θ : (re : R-edge)   (s (θ re))  r²s∙ re
r²s-θ (r+ se) = refl
r²s-θ (r- se) = refl

srs-θ : (re : R-edge)  s (r (s (θ re)))  s∙ r+ cross re
srs-θ (r+ se) = refl
srs-θ (r- se) = refl

sr²s-θ : (re : R-edge)  s ( (s (θ re)))  s∙ r- cross re
sr²s-θ (r+ se) = refl
sr²s-θ (r- se) = refl

\end{code}

Cancellation lemmas follow from the order relations. Since s² = 1 and
r³ = 1, the generators are self-inverse (s⁻¹ = s, r⁻¹ = r²) and thus
left-cancellable.

\begin{code}

s-lc : left-cancellable s
s-lc {x} {y} p =  x ⁻¹  ap s p   y

r-lc : left-cancellable r
r-lc {x} {y} p =  x ⁻¹  ap  p   y

r²-lc : left-cancellable 
r²-lc = r-lc  r-lc

private
 η-helper : PSL2Z  S-edge
 η-helper (η se) = se
 η-helper (θ _) = e₀  -- dummy, but won't be used in valid cases

 θ-helper : PSL2Z  R-edge
 θ-helper (η _) = r+ e₀  -- dummy
 θ-helper (θ re) = re

 cross-helper : S-edge  R-edge
 cross-helper (cross re) = re
 cross-helper e₀ = step  e₀
 cross-helper e₁ = step  e₁

 r-helper : R-edge  S-edge
 r-helper (r+ se) = se
 r-helper (r- se) = se

 r-sgn : R-edge  R-sgn
 r-sgn (step d _) = d

\end{code}

The injections η and θ are left-cancellable, enabling us to reduce
equality in PSL2Z to equality in the component types.

\begin{code}

η-lc : {x y : S-edge}  Id {𝓤₀} {PSL2Z} (η x) (η y)  x  y
η-lc refl = refl

θ-lc : {x y : R-edge}  Id {𝓤₀} {PSL2Z} (θ x) (θ y)  x  y
θ-lc refl = refl

S-is-not-E : S  E
S-is-not-E p = 𝟙-is-not-𝟘 (g (η-lc {e₁} {e₀} p))
 where
  f : S-edge  𝓤₀ ̇
  f e₀ = 𝟘
  f e₁ = 𝟙
  f (cross _) = 𝟘

  g : e₁  e₀  𝟙  𝟘
  g = ap f

η-is-not-θ : (x : S-edge) (y : R-edge)  η x  θ y
η-is-not-θ x y p = +disjoint p

θ-is-not-η : (x : R-edge) (y : S-edge)  θ x  η y
θ-is-not-η x y p = +disjoint (p ⁻¹)

fibers-of-η-over-E : (x : S-edge)  is-decidable (η x  E)
fibers-of-η-over-E e₀ = inl refl
fibers-of-η-over-E e₁ = inr S-is-not-E
fibers-of-η-over-E (cross x) = inr  p  θ-is-not-η x e₁ (ap s p))

fibers-of-η-over-S : (x : S-edge)  is-decidable (η x  S)
fibers-of-η-over-S e₀ = inr  p  S-is-not-E (p ⁻¹))
fibers-of-η-over-S e₁ = inl refl
fibers-of-η-over-S (cross x) = inr  p  θ-is-not-η x e₀ (ap s p))

\end{code}

Decidability of equality is established by mutual recursion on the
graph structure. We decide equality fiber-by-fiber over each
constructor, using the order relations to distinguish r+ from r-.

\begin{code}

fibers-of-η-over-cross : (x : S-edge) (y : R-edge)
                        is-decidable ((inl x)  inl (cross y))
fibers-of-θ-over-r+ : (x : R-edge) (y : S-edge)
                     is-decidable ((inr x)  inr (r+ y))
fibers-of-θ-over-r- : (x : R-edge) (y : S-edge)
                     is-decidable ((inr x)  inr (r- y))

S-edge-is-discrete : is-discrete S-edge
R-edge-is-discrete : is-discrete R-edge

η-is-decidable : (x y : S-edge)
                is-decidable ((inl {𝓤₀} {𝓤₀} {S-edge} {R-edge} x)  inl y)
θ-is-decidable : (x y : R-edge)
                is-decidable ((inr {𝓤₀} {𝓤₀} {S-edge} {R-edge} x)  inr y)

fibers-of-η-over-cross e₀ y = inr (η-is-not-θ e₁ y  ap s)
fibers-of-η-over-cross e₁ y = inr (η-is-not-θ e₀ y  ap s)
fibers-of-η-over-cross (cross x) y =
 +functor (ap  re  η (cross re)))
          (contrapositive cross-inj)
          (R-edge-is-discrete x y)
 where
  cross-inj : {a b : R-edge}  η (cross a)  η (cross b)  a  b
  cross-inj p = ap (θ-helper  s) p

fibers-of-θ-over-r+ (r+ x) y =
 +functor (ap  se  θ (r+ se)))
          (contrapositive r+inj)
          (S-edge-is-discrete x y)
 where
  r+inj : {a b : S-edge}  θ (r+ a)  θ (r+ b)  a  b
  r+inj {a} {b} p = η-lc (r²-θ-r+ a ⁻¹  ap  p  r²-θ-r+ b)
fibers-of-θ-over-r+ (r- x) y = inr lemma
 where
  lemma : θ (r- x)  θ (r+ y)  𝟘
  lemma p = η-is-not-θ x (r- y) (r-θ-r- x ⁻¹  ap r p  r-θ-r+ y)
fibers-of-θ-over-r- (r+ x) y = inr lemma
 where
  lemma : θ (r+ x)  θ (r- y)  𝟘
  lemma p = η-is-not-θ x (r+ y) (r²-θ-r+ x ⁻¹  ap  p  r²-θ-r- y)
fibers-of-θ-over-r- (r- x) y =
  +functor (ap  se  θ (r- se)))
           (contrapositive r-inj)
           (S-edge-is-discrete x y)
  where
    r-inj : {a b : S-edge}  θ (r- a)  θ (r- b)  a  b
    r-inj {a} {b} p = η-lc (r-θ-r- a ⁻¹  ap r p  r-θ-r- b)

S-edge-is-discrete e₀ e₀ = inl refl
S-edge-is-discrete e₀ e₁ = inr  p  S-is-not-E (ap inl (p ⁻¹)))
S-edge-is-discrete e₀ (cross y) = inr  p  η-is-not-θ e₁ y (ap s (ap inl p)))
S-edge-is-discrete e₁ e₀ = inr  p  S-is-not-E (ap inl p))
S-edge-is-discrete e₁ e₁ = inl refl
S-edge-is-discrete e₁ (cross y) = inr  p  η-is-not-θ e₀ y (ap s (ap inl p)))
S-edge-is-discrete (cross x) e₀ =
  inr  p  η-is-not-θ e₁ x (ap s (ap inl (p ⁻¹))))
S-edge-is-discrete (cross x) e₁ =
  inr  p  η-is-not-θ e₀ x (ap s (ap inl (p ⁻¹))))
S-edge-is-discrete (cross x) (cross y) =
  +functor (ap cross) (contrapositive cross-inj) (R-edge-is-discrete x y)
  where
    cross-inj : {a b : R-edge}  cross a  cross b  a  b
    cross-inj {a} {b} p = ap cross-helper p

R-edge-is-discrete (r+ x) (r+ y) =
 +functor (ap  se  r+ se)) (contrapositive r+inj) (S-edge-is-discrete x y)
 where
   r+inj : {a b : S-edge}  r+ a  r+ b  a  b
   r+inj {a} {b} p = ap r-helper p
R-edge-is-discrete (r+ x) (r- y) = inr  p  zero-is-not-one (ap r-sgn p))
R-edge-is-discrete (r- x) (r+ y) = inr  p  one-is-not-zero (ap r-sgn p))
R-edge-is-discrete (r- x) (r- y) =
 +functor (ap  se  r- se)) (contrapositive r-inj) (S-edge-is-discrete x y)
 where
   r-inj : {a b : S-edge}  r- a  r- b  a  b
   r-inj {a} {b} p = ap r-helper p

η-is-decidable x e₀ = fibers-of-η-over-E x
η-is-decidable x e₁ = fibers-of-η-over-S x
η-is-decidable x (cross y) = fibers-of-η-over-cross x y

θ-is-decidable x (r+ y) = fibers-of-θ-over-r+ x y
θ-is-decidable x (r- y) = fibers-of-θ-over-r- x y

PSL2Z-is-discrete : is-discrete PSL2Z
PSL2Z-is-discrete (η x) (η y) = η-is-decidable x y
PSL2Z-is-discrete (η x) (θ y) = inr (η-is-not-θ x y)
PSL2Z-is-discrete (θ x) (η y) = inr (≠-sym (η-is-not-θ y x))
PSL2Z-is-discrete (θ x) (θ y) = θ-is-decidable x y

PSL2Z-is-set : is-set PSL2Z
PSL2Z-is-set = discrete-types-are-sets PSL2Z-is-discrete

\end{code}

Although we have our main result, why not these as well.

\begin{code}

S-edge-is-set : is-set S-edge
S-edge-is-set = discrete-types-are-sets S-edge-is-discrete

R-edge-is-set : is-set R-edge
R-edge-is-set = discrete-types-are-sets R-edge-is-discrete

\end{code}