---
layout: default
title : "Setoid.Overture.Inverses module"
date : "2021-09-13"
author: "the agda-algebras development team"
---
### Inverses for functions with structure
This is the [Setoid.Functions.Inverses][] module of the [agda-algebras][] library.
<!--
```agda
{-# OPTIONS --cubical-compatible --exact-split --safe #-}
module Setoid.Functions.Inverses where
open import Agda.Primitive using ( _⊔_ ; Level ) renaming ( Set to Type )
open import Function using ( _$_ ) renaming ( Func to _⟶_ )
open import Data.Product using ( _,_ ; Σ-syntax )
renaming ( _×_ to _∧_)
open import Relation.Unary using ( Pred ; _∈_ )
open import Relation.Binary using ( Setoid ; _Preserves_⟶_ )
open import Overture using ( proj₁ ; proj₂ ; ∃-syntax )
private variable α ρᵃ β ρᵇ : Level
```
-->
```agda
module _ {𝑨 : Setoid α ρᵃ}{𝑩 : Setoid β ρᵇ} where
open Setoid 𝑨 using() renaming ( Carrier to A ; _≈_ to _≈₁_ )
renaming ( refl to refl₁ ; sym to sym₁ ; trans to trans₁ )
open Setoid 𝑩 using() renaming ( Carrier to B ; _≈_ to _≈₂_ )
renaming ( refl to refl₂ ; sym to sym₂ ; trans to trans₂ )
open _⟶_ {a = α}{ρᵃ}{β}{ρᵇ}{From = 𝑨}{To = 𝑩} renaming (to to _⟨$⟩_ )
```
We begin by defining two data types that represent the semantic concept of the
*image* of a function. The first of these is for functions on bare types, while
the second is for functions on setoids.
```agda
data Img_∋_ (f : A → B) : B → Type (α ⊔ β ⊔ ρᵇ) where
eq : {b : B} → (a : A) → b ≈₂ (f a) → Img f ∋ b
data Image_∋_ (F : 𝑨 ⟶ 𝑩) : B → Type (α ⊔ β ⊔ ρᵇ) where
eq : {b : B} → (a : A) → b ≈₂ (F ⟨$⟩ a) → Image F ∋ b
open Image_∋_
IsInRange : (𝑨 ⟶ 𝑩) → Pred B (α ⊔ ρᵇ)
IsInRange F b = ∃[ a ∈ A ] (F ⟨$⟩ a) ≈₂ b
Image⊆Range : ∀ {F b} → Image F ∋ b → b ∈ IsInRange F
Image⊆Range (eq a x) = a , (sym₂ x)
IsInRange→IsInImage : ∀ {F b} → b ∈ IsInRange F → Image F ∋ b
IsInRange→IsInImage (a , x) = eq a (sym₂ x)
Imagef∋f : ∀ {F a} → Image F ∋ (F ⟨$⟩ a)
Imagef∋f = eq _ refl₂
range : (𝑨 ⟶ 𝑩) → Type (α ⊔ β ⊔ ρᵇ)
range F = Σ[ b ∈ B ] ∃[ a ∈ A ](F ⟨$⟩ a) ≈₂ b
image : (F : 𝑨 ⟶ 𝑩) → range F → B
image F (b , (_ , _)) = b
preimage : (F : 𝑨 ⟶ 𝑩) → range F → A
preimage F (_ , (a , _)) = a
f∈range : ∀ {F} → A → range F
f∈range {F} a = (F ⟨$⟩ a) , (a , refl₂)
⌜_⌝ : (F : 𝑨 ⟶ 𝑩) → A → range F
⌜ F ⌝ a = f∈range{F} a
Ran : (𝑨 ⟶ 𝑩) → Setoid (α ⊔ β ⊔ ρᵇ) ρᵇ
Ran F = record { Carrier = range F
; _≈_ = λ x y → (image F) x ≈₂ (image F) y
; isEquivalence = record { refl = refl₂
; sym = sym₂
; trans = trans₂
}
}
RRan : (𝑨 ⟶ 𝑩) → Setoid (α ⊔ β ⊔ ρᵇ) (ρᵃ ⊔ ρᵇ)
RRan F = record { Carrier = range F
; _≈_ = λ x y → (preimage F) x ≈₁ (preimage F) y
∧ (image F) x ≈₂ (image F) y
; isEquivalence =
record { refl = refl₁ , refl₂
; sym = λ x → sym₁ (proj₁ x) , sym₂ (proj₂ x)
; trans = λ x y → trans₁ (proj₁ x) (proj₁ y) , trans₂ (proj₂ x) (proj₂ y)
}
}
preimage≈image : ∀ F r → F ⟨$⟩ (preimage F) r ≈₂ (image F) r
preimage≈image F (_ , (_ , p)) = p
Dom : (𝑨 ⟶ 𝑩) → Setoid α ρᵇ
Dom F = record { Carrier = A
; _≈_ = λ x y → F ⟨$⟩ x ≈₂ F ⟨$⟩ y
; isEquivalence = record { refl = refl₂
; sym = sym₂
; trans = trans₂
}
}
```
An inhabitant of `Image f ∋ b` is a dependent pair `(a , p)`, where `a : A` and `p : b ≡ f a` is a proof that `f` maps `a` to `b`. Since the proof that `b` belongs to the image of `f` is always accompanied by a witness `a : A`, we can actually *compute* a (pseudo)inverse of `f`. For convenience, we define this inverse function, which we call `Inv`, and which takes an arbitrary `b : B` and a (*witness*, *proof*)-pair, `(a , p) : Image f ∋ b`, and returns the witness `a`.
```agda
inv : (f : A → B) {b : B} → Img f ∋ b → A
inv _ (eq a _) = a
Inv : (F : 𝑨 ⟶ 𝑩) {b : B} → Image F ∋ b → A
Inv _ (eq a _) = a
Inv' : (F : 𝑨 ⟶ 𝑩) {b : B} → b ∈ IsInRange F → A
Inv' _ (a , _) = a
[_]⁻¹ : (F : 𝑨 ⟶ 𝑩) → range F → A
[ F ]⁻¹ = preimage F
⟦_⟧⁻¹ : (F : 𝑨 ⟶ 𝑩) → Ran F ⟶ Dom F
⟦ F ⟧⁻¹ = record
{ to = preimage F
; cong = λ {x}{y} ix≈iy → trans₂ (preimage≈image F x)
(trans₂ ix≈iy $ sym₂ $ preimage≈image F y)
}
```
We can prove that `Inv f` is the range-restricted right-inverse of `f`, as follows.
```agda
invIsInvʳ : {f : A → B} {b : B} (q : Img f ∋ b) → f (inv f q) ≈₂ b
invIsInvʳ (eq _ p) = sym₂ p
InvIsInverseʳ : {F : 𝑨 ⟶ 𝑩} {b : B} (q : Image F ∋ b) → F ⟨$⟩ (Inv F q) ≈₂ b
InvIsInverseʳ (eq _ p) = sym₂ p
⁻¹IsInverseʳ : {F : 𝑨 ⟶ 𝑩} {bap : range F} → F ⟨$⟩ ([ F ]⁻¹ bap ) ≈₂ bap .proj₁
⁻¹IsInverseʳ {bap = (_ , (_ , p))} = p
```
Of course, the "range-restricted" qualifier is needed because `Inf f` is not defined outside the range of `f`.
In the following sense, `Inv f` is also a (range-restricted) *left-inverse*.
```agda
InvIsInverseˡ : ∀ {F a} → Inv F {b = F ⟨$⟩ a} Imagef∋f ≈₁ a
InvIsInverseˡ = refl₁
⁻¹IsInverseˡ : ∀ {F a} → [ F ]⁻¹ (f∈range{F} a) ≈₁ a
⁻¹IsInverseˡ = refl₁
```