{-# OPTIONS --safe #-} module Multiset.Relation.Base where open import Multiset.Prelude open import Multiset.Util.Relation public open import Cubical.Foundations.Function using (_∘_ ; idfun) open import Cubical.Foundations.Isomorphism open import Cubical.Foundations.HLevels open import Cubical.Foundations.Structure using (TypeWithStr) open import Cubical.Foundations.Structure using (⟨_⟩ ; str) public open import Cubical.Reflection.RecordEquiv using (declareRecordIsoΣ) open import Cubical.Relation.Binary using (Rel ; module BinaryRelation) open import Cubical.Data.Sigma.Properties using (Σ≡Prop) private variable ℓ ℓ′ ℓ≈ ℓ≈′ : Level open BinaryRelation using (isRefl ; isSym ; isTrans ; isEquivRel ; isPropValued) record IsRelation {A : Type ℓ} (_≈_ : Rel A A ℓ≈) : Type (ℓ-max ℓ ℓ≈) where no-eta-equality field is-set-carrier : isSet A is-prop-rel : isPropValued _≈_ record RelationStr (ℓ≈ : Level) (A : Type ℓ) : Type (ℓ-max ℓ (ℓ-suc ℓ≈)) where no-eta-equality field rel : Rel A A ℓ≈ is-relation : IsRelation rel open IsRelation is-relation public Relation : (ℓ ℓ≈ : Level) → Type _ Relation ℓ ℓ≈ = TypeWithStr ℓ (RelationStr ℓ≈) RelOf : (S : Relation ℓ ℓ≈) → Rel ⟨ S ⟩ ⟨ S ⟩ ℓ≈ RelOf S = str S .RelationStr.rel RelOf-syntax : (S : Relation ℓ ℓ≈) → Rel ⟨ S ⟩ ⟨ S ⟩ ℓ≈ RelOf-syntax = RelOf syntax RelOf-syntax S a b = a ≈⟨ S ⟩ b PathRelation : (A : Type ℓ) → isSet A → Relation ℓ ℓ PathRelation A setA .fst = A PathRelation A setA .snd .RelationStr.rel = Path A PathRelation A setA .snd .RelationStr.is-relation .IsRelation.is-set-carrier = setA PathRelation A setA .snd .RelationStr.is-relation .IsRelation.is-prop-rel = setA module _ {ℓ ℓ≈ ℓ′ ℓ≈′ : Level} (S : Relation ℓ ℓ≈) (R : Relation ℓ′ ℓ≈′) where open IsRelation open RelationStr PreservesRelation : (f : ⟨ S ⟩ → ⟨ R ⟩) → Type (ℓ-max (ℓ-max ℓ ℓ≈) ℓ≈′) PreservesRelation f = ∀ {a b : ⟨ S ⟩} → a ≈⟨ S ⟩ b → f a ≈⟨ R ⟩ f b isPropPreservesRelation : {f : ⟨ S ⟩ → ⟨ R ⟩} → isProp (PreservesRelation f) isPropPreservesRelation = isPropImplicitΠ2 λ _ _ → isPropΠ λ _ → str R .is-prop-rel _ _ record Rel[_⇒_] : Type (ℓ-max (ℓ-max ℓ ℓ′) (ℓ-max ℓ≈ ℓ≈′)) where constructor rel⇒ field morphism : ⟨ S ⟩ → ⟨ R ⟩ preserves-relation : PreservesRelation morphism open Rel[_⇒_] Rel⇒IsoΣ : Iso Rel[_⇒_] (Σ (⟨ S ⟩ → ⟨ R ⟩) PreservesRelation) Rel⇒IsoΣ .Iso.fun f .fst = f .morphism Rel⇒IsoΣ .Iso.fun f .snd = f .preserves-relation Rel⇒IsoΣ .Iso.inv p .morphism = p .fst Rel⇒IsoΣ .Iso.inv p .preserves-relation = p .snd Rel⇒IsoΣ .Iso.rightInv p = refl Rel⇒IsoΣ .Iso.leftInv f = refl isSetRel⇒ : isSet Rel[_⇒_] isSetRel⇒ = isOfHLevelRetractFromIso 2 Rel⇒IsoΣ (isSetΣSndProp (isSet→ (str R .is-set-carrier)) λ _ → isPropPreservesRelation) module _ where open Rel[_⇒_] private variable ℓ₀ ℓ₁ ℓ₂ ℓ₃ : Level ℓR₀ ℓR₁ ℓR₂ ℓR₃ : Level Rel⇒Path : ∀ {R : Relation ℓ ℓ≈} {S : Relation ℓ′ ℓ≈′} → {f g : Rel[ R ⇒ S ]} → f .morphism ≡ g .morphism → f ≡ g Rel⇒Path p i .morphism = p i Rel⇒Path {R = R} {S} {f} {g} p i .preserves-relation = isProp→PathP (λ i → isPropPreservesRelation R S {f = p i}) (f .preserves-relation) (g .preserves-relation) i idRel⇒ : {S : Relation ℓ ℓ≈} → Rel[ S ⇒ S ] idRel⇒ {S = S} .morphism = idfun ⟨ S ⟩ idRel⇒ {S = S} .preserves-relation {s₀} {s₁} = idfun (RelOf S s₀ s₁) module _ {R₀ : Relation ℓ₀ ℓR₀} {R₁ : Relation ℓ₁ ℓR₁} {R₂ : Relation ℓ₂ ℓR₂} where compPreservesRelation : ∀ {f g} → PreservesRelation R₀ R₁ f → PreservesRelation R₁ R₂ g → PreservesRelation R₀ R₂ (g ∘ f) compPreservesRelation pres-f pres-g = pres-g ∘ pres-f compRel⇒ : Rel[ R₀ ⇒ R₁ ] → Rel[ R₁ ⇒ R₂ ] → Rel[ R₀ ⇒ R₂ ] compRel⇒ f g .morphism = g .morphism ∘ f .morphism compRel⇒ f g .preserves-relation = compPreservesRelation (f .preserves-relation) (g .preserves-relation) _⋆Rel⇒_ = compRel⇒ infixl 9 _⋆Rel⇒_ ⋆Rel⇒IdL : {R : Relation ℓ ℓ≈} {S : Relation ℓ′ ℓ≈′} (f : Rel[ R ⇒ S ]) → idRel⇒ ⋆Rel⇒ f ≡ f ⋆Rel⇒IdL _ = refl ⋆Rel⇒IdR : {R : Relation ℓ ℓ≈} {S : Relation ℓ′ ℓ≈′} (f : Rel[ R ⇒ S ]) → f ⋆Rel⇒ idRel⇒ ≡ f ⋆Rel⇒IdR _ = refl module _ {R₀ : Relation ℓ₀ ℓR₀} {R₁ : Relation ℓ₁ ℓR₁} {R₂ : Relation ℓ₂ ℓR₂} {R₃ : Relation ℓ₃ ℓR₃} where ⋆Rel⇒Assoc : (f : Rel[ R₀ ⇒ R₁ ]) (g : Rel[ R₁ ⇒ R₂ ]) (h : Rel[ R₂ ⇒ R₃ ]) → (f ⋆Rel⇒ g) ⋆Rel⇒ h ≡ f ⋆Rel⇒ (g ⋆Rel⇒ h) ⋆Rel⇒Assoc f g h = refl