```module CoSub where

{-
This file deals with the relations between PermSets and NomSets.
-}

open import Basics
open import Atoms
open import Perms
open import PermProp
open import Nom
open import Group
open import PermSet
open import CatDef

-----------------------------------------------------------------------------------------------
--all finitely supported functions to 𝔹
-----------------------------------------------------------------------------------------------

Ωˣ : (X : Nominal) → Nominal
Ωˣ X = NomExp X 𝔹Nom

----------------------------------------------------------------------------------------------
--subset of all finitely supported elements of P
----------------------------------------------------------------------------------------------

record FinSupp (P : PermSet) : Set where
field
pel : AₛP P
psupp : List Atom
psuppAx : (b c : Atom) → (b ∉ psupp) → (c ∉ psupp) → (≈ₐP P) ((ActP P) [(b , c)] pel) pel

open FinSupp public

-----------------------------------------------------------------------------------------------
--equivalence relation on this subset
-----------------------------------------------------------------------------------------------

≈FS : (P : PermSet) → Rel (FinSupp P)
≈FS P = λ ρ₁ ρ₂ → (≈ₐP P) (pel ρ₁) (pel ρ₂)

eq≈FS : (P : PermSet) → isEquivalence (FinSupp P) (≈FS P)
eq≈FS P = record { Reflex = λ {ρ} → (Reflex (eq≈ₐP P)) {pel ρ}
;  Symm = λ {ρ₁}{ρ₂} → λ ρ₁≈ρ₂ → (Symm (eq≈ₐP P)) ρ₁≈ρ₂
;  Trans = λ ρ₁≈ρ₂ ρ₂≈ρ₃ → (Trans (eq≈ₐP P)) ρ₁≈ρ₂ ρ₂≈ρ₃
}

-------------------------------------------------------------------------------------------
--This is closed under action
-------------------------------------------------------------------------------------------

ActFS : (P : PermSet) → (π : Perm) → FinSupp P → FinSupp P
ActFS P π ρ = record { pel = (ActP P) π (pel ρ)
; psupp = (flatten π) ++ (psupp ρ)
; psuppAx = λ b c b∉πρ c∉πρ → let πₛ = flatten π in let ρₛ = psupp ρ in let b∉π = ∉⊆₁ {πₛ}{ρₛ} b b∉πρ in let b∉ρ = ∉⊆₂ {πₛ}{ρₛ} b b∉πρ
in let c∉π = ∉⊆₁ {πₛ}{ρₛ} c c∉πρ in let c∉ρ = ∉⊆₂ {πₛ}{ρₛ} c c∉πρ in let πρ = (ActP P) π (pel ρ) in
let πρ≈πρ = ((ActP P) [(b , c)] πρ)   ≣< ((ActP P) (π ++ [(b , c)]) (pel ρ)) and πρ by (≈ₐP P) as (eq≈ₐP P) on
((p₁p₂↠P P) [(b , c)] π {pel ρ}) >
(((ActP P) (π ++ [(b , c)]) (pel ρ))
≣< ((ActP P) ([(b , c)] ++ π) (pel ρ)) and πρ by (≈ₐP P) as (eq≈ₐP P) on
((Symm (eq≈ₐP P)) ((resP P) (λ {w} → ab∉pcom b c π b∉π c∉π {w}) (≈≡ (eq≈ₐP P) {pel ρ}{pel ρ} refl))) >
(((ActP P) ([(b , c)] ++ π) (pel ρ))
≣< ((ActP P) π ((ActP P) [(b , c)] (pel ρ))) and πρ by (≈ₐP P) as (eq≈ₐP P) on
((Symm (eq≈ₐP P)) ((p₁p₂↠P P) π [(b , c)] {pel ρ})) >
(((ActP P) π ((ActP P) [(b , c)] (pel ρ)))
≣< πρ and πρ by (≈ₐP P) as (eq≈ₐP P) on
((resP P) (λ {w} → P≡≈ π {w}) ((psuppAx ρ) b c b∉ρ c∉ρ)) >
(πρ by (≈ₐP P) as (eq≈ₐP P) ▴)))) in πρ≈πρ
}
-----------------------------------------------------------------------------------------------------------------------------------------
--FUNCTOR FROM NOM TO PERM & VICE-VERSA
-----------------------------------------------------------------------------------------------------------------------------------------

-----------------------------------------------------------------------------------------------
--Nominal Set to Perm Set object
-----------------------------------------------------------------------------------------------

NomPerm : (N : Nominal) → PermSet
NomPerm N = record {AₛP = Aₛ N
; ≈ₐP = ≈ₐ N
; eq≈ₐP = eq≈ₐ N
; ActP = Act N
; resP = res N
; p₁p₂↠P = p₁p₂↠ N
; ι↠P = ι↠ N
}

----------------------------------------------------------------------------------------------
--PermSet to Nominal Set object
----------------------------------------------------------------------------------------------

PermNom : (P : PermSet) → Nominal
PermNom P = record { Aₛ = FinSupp P
; ≈ₐ = ≈FS P
; eq≈ₐ = eq≈FS P
; Act = λ π ρ → ActFS P π ρ
; res = λ {π₁}{π₂}{ρ₁}{ρ₂} → λ π₁≈π₂ ρ₁≈ρ₂ → (resP P) π₁≈π₂ ρ₁≈ρ₂
; p₁p₂↠ = λ π₁ π₂ {ρ} → (p₁p₂↠P P) π₁ π₂ {pel ρ}
; ι↠ = λ {ρ} → (ι↠P P) {pel ρ}
; some_supp = λ ρ → psupp ρ
; suppAx = λ ρ → λ b c b∉ρ c∉ρ → (psuppAx ρ) b c b∉ρ c∉ρ
}

------------------------------------------------------------------------------------------------------------
--Nominal to Perm morphism
------------------------------------------------------------------------------------------------------------

NomPermEq : (M N : Nominal) → (F : Equivar M N) → EquivarP (NomPerm M) (NomPerm N)
NomPermEq M N F = record { pufun = λ m → (ufun F) m
; peqi≈ = λ m₁≈m₂ → (eqi≈ F) m₁≈m₂
; pequiv = λ π m → (equiv F) π m
}

-------------------------------------------------------------------------------------------------------
--Perm to Norm Morphism
-------------------------------------------------------------------------------------------------------

PermNomEq : (P Q : PermSet) → (G : EquivarP P Q) → Equivar (PermNom P) (PermNom Q)
PermNomEq P Q G = record { ufun = λ ρ → record { pel = (pufun G) (pel ρ)
;  psupp = psupp ρ
; psuppAx = λ b c b∉ρ c∉ρ → let gρ = (pufun G) (pel ρ) in
let gρ≈gρ = ((ActP Q) [(b , c)] gρ)   ≣< ((pufun G) ((ActP P) [(b , c)] (pel ρ))) and gρ by (≈ₐP Q) as (eq≈ₐP Q) on
((pequiv G) [(b , c)] (pel ρ)) >
(((pufun G) ((ActP P) [(b , c)] (pel ρ)))
≣< gρ and gρ by (≈ₐP Q) as (eq≈ₐP Q) on
((peqi≈ G) ((psuppAx ρ) b c b∉ρ c∉ρ)) >
(gρ by (≈ₐP Q) as (eq≈ₐP Q) ▴)) in gρ≈gρ
}
; eqi≈ = λ ρ₁≈ρ₂ → (peqi≈ G) ρ₁≈ρ₂
; equiv = λ π ρ → (pequiv G) π (pel ρ)
}

-------------------------------------------------------------------------------------------------------------
--functors
-------------------------------------------------------------------------------------------------------------

Nom→Perm : Functor NomCat PermCat
Nom→Perm = record { onObj = λ N → NomPerm N
; onMor = λ M N → λ MN → NomPermEq M N MN
; res≈ = λ M N → λ MN MN' → λ MNN' → λ m → MNN' m
; onId = λ M → λ m → (Reflex (eq≈ₐP (NomPerm M))) {m}
; onComp = λ M N O → λ F G → λ m → let Pₒ = NomPerm O in let PF = NomPermEq M N F in let PG = NomPermEq N O G in
let gfm = ((pufun PG) ∘ (pufun PF)) m in (Reflex (eq≈ₐP Pₒ)) {gfm}
}

Perm→Nom : Functor PermCat NomCat
Perm→Nom = record { onObj = λ P → PermNom P
; onMor = λ P Q → λ PQ → PermNomEq P Q PQ
; res≈ = λ P Q → λ PQ PQ' → λ PQQ' → λ p → PQQ' (pel p)
; onId = λ P → λ p → (Reflex (eq≈ₐ (PermNom P))) {p}
; onComp = λ P Q R → λ I J → λ p → (Reflex (eq≈ₐ (PermNom R))) {((ufun (PermNomEq Q R J)) ∘ (ufun (PermNomEq P Q I))) p}
}

----------------------------------------------------------------------------------------------
--counit
---------------------------------------------------------------------------------------------

NPN : (P : PermSet) → (EquivarP (NomPerm (PermNom P)) P)
NPN P = record { pufun = λ ρ → pel ρ
; peqi≈ = λ ρ₁≈ρ₂ → ρ₁≈ρ₂
; pequiv = λ π ρ → (Reflex (eq≈ₐP P)) {(ActP P) π (pel ρ)}
}

-----------------------------------------------------------------------------------------
--unique morphism
-----------------------------------------------------------------------------------------

NP⟶NP : (P : PermSet) → (N : Nominal) → (EquivarP (NomPerm N) P) → Equivar N (PermNom P)
NP⟶NP P N J = record { ufun = λ n → record { pel = (pufun J) n
; psupp = (some_supp N) n
; psuppAx = λ b c b∉n c∉n → let jn = (pufun J) n in
let n≈n = ((ActP P) [(b , c)] jn)  ≣< ((pufun J) ((Act N) [(b , c)] n)) and jn by (≈ₐP P) as (eq≈ₐP P) on ((pequiv J) [(b , c)] n) >
(((pufun J) ((Act N) [(b , c)] n)) ≣< jn and jn by (≈ₐP P) as (eq≈ₐP P) on ((peqi≈ J) ((suppAx N) n b c b∉n c∉n)) >
(jn by (≈ₐP P) as (eq≈ₐP P) ▴)) in n≈n
}
; eqi≈ = λ n₁≈n₂ → (peqi≈ J) n₁≈n₂
; equiv = λ π n → (pequiv J) π n
}

-----------------------------------------------------------------------------------------------
--coreflective subcategory
-----------------------------------------------------------------------------------------------

CoR : Adjoint NomCat PermCat Nom→Perm Perm→Nom
CoR = record { counit = λ P → NPN P
;  f̂ = λ P N F → NP⟶NP P N F
;  f̂ε = λ P N F → λ n → (Reflex (eq≈ₐP P)) {(pufun F) n}
;  unif̂ = λ P N F G G∘C → λ n → G∘C n
}

----------------------------------------------------------------------------------------------------------------------------------------
--PowerSets
---------------------------------------------------------------------------------------------------------------------------------------

ℙX : (X : PermSet) → PermSet
ℙX X = record { AₛP = FunPerm X 𝔹Perm
; ≈ₐP = λ f g → ∀ (x : AₛP X) → ((underFun f) x) ≡ ((underFun g) x)
; eq≈ₐP = record { Reflex = λ {f} → λ x → refl
; Symm = λ f≈g → λ x → sym (f≈g x)
; Trans = λ {f}{g}{h} f≈g g≈h → λ x → ((underFun f) x) ≡< f≈g x > (((underFun g) x) ≡< g≈h x > (((underFun h) x) ▪))
}
; ActP = λ π f → FP (λ x → (underFun f) ((ActP X) (invPerm π) x)) (λ {x₁}{x₂} x₁≈x₂ → (congFun f) ((resP X) (λ {w} → P≡≈ (invPerm π) {w}) x₁≈x₂))
; resP = λ {π₁}{π₂}{f}{g} π₁≈π₂ f≈g → λ x →
(underFun f (ActP X (invPerm π₁) x))
≡< (congFun f) ((resP X) (p≈q⇒p⁻¹≈q⁻¹ π₁ π₂ π₁≈π₂) (≈≡ (eq≈ₐP X) {x}{x} refl)) >
(((underFun f) (ActP X (invPerm π₂) x))
≡< f≈g (ActP X (invPerm π₂) x) >
((underFun g (ActP X (invPerm π₂) x)) ▪))
; p₁p₂↠P = λ π₁ π₂ {f} → λ x → let  π₁π₂ix = (ActP X (invPerm π₂) (ActP X (invPerm π₁) x)) in let π₁₂ix = (ActP X (invPerm (π₂ ++ π₁)) x) in
let π₁π₂π₁₂ = π₁π₂ix ≣< (ActP X ((invPerm π₁) ++ (invPerm π₂)) x) and π₁₂ix by (≈ₐP X) as (eq≈ₐP X) on (p₁p₂↠P X) (invPerm π₂) (invPerm π₁) {x} >
((ActP X ((invPerm π₁) ++ (invPerm π₂)) x) ≣< π₁₂ix and π₁₂ix by (≈ₐP X) as (eq≈ₐP X) on ((Symm (eq≈ₐP X)) ((resP X) (p₁p₂⁻¹≈p₂⁻¹p₁⁻¹ π₂ π₁)
(≈≡ (eq≈ₐP X) {x}{x} refl))) >
(π₁₂ix by (≈ₐP X) as (eq≈ₐP X) ▴)) in (congFun f) π₁π₂π₁₂
; ι↠P = λ {f} → λ x → congFun f (ι↠P X)
}

PₛX : (X : Nominal) → Nominal
PₛX X = PermNom (ℙX (NomPerm X))

------------------------------------------------------------------------------------------------
--finitely supported subsets of PermSet constitute the powerset of NomSet
------------------------------------------------------------------------------------------------

Power : (X : Nominal) → Iso {NomCat} (Ωˣ X) (PₛX X)
Power X = record { liso = record { ufun = λ F → record { pel =  FP (λ x → (ffun F) x) (λ x₁≈x₂ → (feqi≈ F) x₁≈x₂)
; psupp = fsupp F
; psuppAx = λ b c b∉p c∉p → λ x → (fsuppAx F) b c b∉p c∉p x
}
;  eqi≈ = λ F≈G → λ x → F≈G x
;  equiv = λ π F → λ x → (((ffun F) ((Act X) (invPerm π) x)) ▪)
}
; riso = record { ufun = λ X₁ → record { ffun = λ x → (underFun (pel X₁)) x
; fsupp = psupp X₁
; fsuppAx = λ b c b∉x c∉x x → (psuppAx X₁) b c b∉x c∉x x
; feqi≈ = λ x₁≈x₂ → (congFun (pel X₁)) x₁≈x₂
}
; eqi≈ = λ X₁≈X₂ → λ x → X₁≈X₂ x
; equiv = λ π X₁ → λ x → (((underFun (pel X₁)) ((Act X) (invPerm π) x)) ▪)
}
; idisl = λ F x → (((ffun F) x) ▪)
; idisr =  λ X₁ x → (((underFun (pel X₁)) x) ▪)
}

--------------------------------------------------------------------------------------------------------------
```