aboutsummaryrefslogtreecommitdiff
path: root/Data
diff options
context:
space:
mode:
authorJacques Comeaux <jacquesrcomeaux@protonmail.com>2025-07-18 17:34:52 -0500
committerJacques Comeaux <jacquesrcomeaux@protonmail.com>2025-07-18 17:34:52 -0500
commit2184a8f47f72a415e3387a9aaca042dd63c80fd9 (patch)
treeedad952c4582fab639c4478dfcdfc1773abb3706 /Data
parent3b460f16ecc99253cb7f5bae32a3a076717fa12f (diff)
Sorted lists with the same elements are equal
Diffstat (limited to 'Data')
-rw-r--r--Data/Permutation/Sort.agda176
1 files changed, 176 insertions, 0 deletions
diff --git a/Data/Permutation/Sort.agda b/Data/Permutation/Sort.agda
new file mode 100644
index 0000000..977443a
--- /dev/null
+++ b/Data/Permutation/Sort.agda
@@ -0,0 +1,176 @@
+{-# OPTIONS --without-K --safe #-}
+
+open import Relation.Binary.Bundles using (DecTotalOrder)
+
+module Data.Permutation.Sort {ℓ₁ ℓ₂ ℓ₃} (dto : DecTotalOrder ℓ₁ ℓ₂ ℓ₃) where
+
+open DecTotalOrder dto
+ using
+ ( _≈_ ; module Eq
+ ; totalOrder
+ ; _≤_ ; _≤?_
+ ; ≤-respˡ-≈ ; ≤-respʳ-≈
+ ; antisym
+ )
+ renaming (Carrier to A; trans to ≤-trans; reflexive to ≤-reflexive)
+
+open import Data.Fin.Base using (Fin)
+open import Data.List.Base using (List; _++_; [_])
+open import Data.List.Membership.Setoid Eq.setoid using (_∈_)
+open import Data.List.Relation.Binary.Pointwise using (module Pointwise)
+open import Data.List.Relation.Binary.Equality.Setoid Eq.setoid using (_≋_; ≋-refl; ≋-sym; ≋-trans)
+open import Data.List.Relation.Unary.Linked using (Linked)
+open import Data.List.Relation.Unary.Sorted.TotalOrder totalOrder using (Sorted)
+open import Data.List.Relation.Binary.Permutation.Propositional using (_↭_; ↭-trans; ↭-sym)
+open import Data.List.Relation.Binary.Permutation.Propositional.Properties using (↭-length)
+open import Data.List.Relation.Unary.Any using (Any)
+open import Data.List.Sort dto using (sort; sort-↭; sort-↗)
+open import Relation.Nullary.Decidable.Core using (yes; no)
+open Fin
+open _↭_
+open Any
+open List
+open Linked
+open Pointwise
+
+insert : List A → A → List A
+insert [] x = [ x ]
+insert (x₀ ∷ xs) x with x ≤? x₀
+... | yes _ = x ∷ x₀ ∷ xs
+... | no _ = x₀ ∷ insert xs x
+
+insert-resp-≋ : {xs ys : List A} (v : A) → xs ≋ ys → insert xs v ≋ insert ys v
+insert-resp-≋ _ [] = ≋-refl
+insert-resp-≋ {x ∷ xs} {y ∷ ys} v (x≈y ∷ xs≋ys)
+ with v ≤? x | v ≤? y
+... | yes v≤x | yes v≤y = Eq.refl ∷ x≈y ∷ xs≋ys
+... | yes v≤x | no v≰y with () ← v≰y (≤-respʳ-≈ x≈y v≤x)
+... | no v≰x | yes v≤y with () ← v≰x (≤-respʳ-≈ (Eq.sym x≈y) v≤y)
+... | no v≰x | no v≰y = x≈y ∷ insert-resp-≋ v xs≋ys
+
+remove : {x : A} (xs : List A) → x ∈ xs → List A
+remove (_ ∷ xs) (here _) = xs
+remove (x ∷ xs) (there elem) = x ∷ remove xs elem
+
+remove-sorted : {x : A} {xs : List A} → Sorted xs → (x∈xs : x ∈ xs) → Sorted (remove xs x∈xs)
+remove-sorted [-] (here x≡x₀) = []
+remove-sorted (x₀≤x₁ ∷ s-xs) (here px) = s-xs
+remove-sorted (x₀≤x₁ ∷ [-]) (there (here px)) = [-]
+remove-sorted (x₀≤x₁ ∷ x₁≤x₂ ∷ s-xs) (there (here px)) = ≤-trans x₀≤x₁ x₁≤x₂ ∷ s-xs
+remove-sorted (x₀≤x₁ ∷ x₁≤x₂ ∷ s-xs) (there (there x∈xs)) = x₀≤x₁ ∷ remove-sorted (x₁≤x₂ ∷ s-xs) (there x∈xs)
+
+head : {xs : List A} {x : A} → .(x ∈ xs) → A
+head {x ∷ _} _ = x
+
+tail : {xs : List A} {x : A} → .(x ∈ xs) → List A
+tail {_ ∷ xs} _ = xs
+
+head-≤ : {xs : List A}
+ {x : A}
+ → Sorted xs
+ → (x∈xs : x ∈ xs)
+ → head x∈xs ≤ x
+head-≤ {x ∷ []} [-] (here px) = ≤-reflexive (Eq.sym px)
+head-≤ {x₀ ∷ x₁ ∷ xs} (x₀≤x₁ ∷ s-xs) (here px) = ≤-reflexive (Eq.sym px)
+head-≤ {x₀ ∷ x₁ ∷ xs} (x₀≤x₁ ∷ s-xs) (there x∈xs) = ≤-trans x₀≤x₁ (head-≤ s-xs x∈xs)
+
+remove-head
+ : {xs : List A}
+ {x : A}
+ → Sorted xs
+ → (x∈xs : x ∈ xs)
+ → x ≈ head x∈xs
+ → remove xs x∈xs ≋ tail x∈xs
+remove-head _ (here _) _ = ≋-refl
+remove-head {x₀ ∷ x₁ ∷ xs} {x} (x₀≤x₁ ∷ s-xs) (there x∈xs) x≈x₀ =
+ x₀≈x₁ ∷ remove-head s-xs x∈xs x≈x₁
+ where
+ x₀≈x₁ : x₀ ≈ x₁
+ x₀≈x₁ = antisym x₀≤x₁ (≤-respʳ-≈ x≈x₀ (head-≤ s-xs x∈xs))
+ x≈x₁ : x ≈ x₁
+ x≈x₁ = Eq.trans x≈x₀ x₀≈x₁
+
+insert-remove
+ : {xs : List A}
+ {x : A}
+ → (s-xs : Sorted xs)
+ → (x∈xs : x ∈ xs)
+ → insert (remove xs x∈xs) x ≋ xs
+insert-remove [-] (here px) = px ∷ []
+insert-remove {x₀ ∷ x₁ ∷ xs} {x} (x₀≤x₁ ∷ s-xs) (here px) with x ≤? x₁
+... | yes x≤x₁ = px ∷ ≋-refl
+... | no x≰x₁ with () ← x≰x₁ (≤-respˡ-≈ (Eq.sym px) x₀≤x₁)
+insert-remove {x₀ ∷ x₁ ∷ xs} {x} (x₀≤x₁ ∷ s-xs) (there x∈xs) with x ≤? x₀
+... | yes x≤x₀ =
+ antisym x≤x₀ (≤-trans x₀≤x₁ x₁≤x) ∷
+ antisym x₀≤x₁ (≤-trans x₁≤x x≤x₀) ∷
+ remove-head s-xs x∈xs (antisym (≤-trans x≤x₀ x₀≤x₁) (head-≤ s-xs x∈xs))
+ where
+ x₁≤x : x₁ ≤ x
+ x₁≤x = head-≤ s-xs x∈xs
+... | no x≰x₀ = Eq.refl ∷ insert-remove s-xs x∈xs
+
+apply : {xs ys : List A} {x : A} → xs ↭ ys → x ∈ xs → x ∈ ys
+apply refl x-in-xs = x-in-xs
+apply (prep x xs↭ys) (here px) = here px
+apply (prep x xs↭ys) (there x-in-xs) = there (apply xs↭ys x-in-xs)
+apply (swap x y xs↭ys) (here px) = there (here px)
+apply (swap x y xs↭ys) (there (here px)) = here px
+apply (swap x y xs↭ys) (there (there x-in-xs)) = there (there (apply xs↭ys x-in-xs))
+apply (trans xs↭ys ys↭zs) x-in-xs = apply ys↭zs (apply xs↭ys x-in-xs)
+
+↭-remove
+ : {xs ys : List A}
+ {x : A}
+ → (xs↭ys : xs ↭ ys)
+ → (x∈xs : x ∈ xs)
+ → let x∈ys = apply xs↭ys x∈xs in
+ remove xs x∈xs ↭ remove ys x∈ys
+↭-remove refl x∈xs = refl
+↭-remove (prep x xs↭ys) (here px) = xs↭ys
+↭-remove (prep x xs↭ys) (there x∈xs) = prep x (↭-remove xs↭ys x∈xs)
+↭-remove (swap x y xs↭ys) (here px) = prep y xs↭ys
+↭-remove (swap x y xs↭ys) (there (here px)) = prep x xs↭ys
+↭-remove (swap x y xs↭ys) (there (there x∈xs)) = swap x y (↭-remove xs↭ys x∈xs)
+↭-remove (trans xs↭ys ys↭zs) x∈xs = trans (↭-remove xs↭ys x∈xs) (↭-remove ys↭zs (apply xs↭ys x∈xs))
+
+sorted-unique
+ : {xs ys : List A}
+ → xs ↭ ys
+ → Sorted xs
+ → Sorted ys
+ → xs ≋ ys
+sorted-unique {[]} {ys} xs↭ys s-xs s-ys with .(↭-length xs↭ys)
+sorted-unique {[]} {[]} xs↭ys s-xs s-ys | _ = []
+sorted-unique xs@{x ∷ xs′} {ys} xs↭ys s-xs s-ys = ≋-trans ≋xs (≋-trans xs≋ys″ ≋ys)
+ where
+ x∈xs : x ∈ xs
+ x∈xs = here Eq.refl
+ x∈ys : x ∈ ys
+ x∈ys = apply xs↭ys x∈xs
+ s-xs′ : Sorted (remove xs x∈xs)
+ s-xs′ = remove-sorted s-xs x∈xs
+ s-ys′ : Sorted (remove ys x∈ys)
+ s-ys′ = remove-sorted s-ys x∈ys
+ xs↭ys′ : remove xs x∈xs ↭ remove ys x∈ys
+ xs↭ys′ = ↭-remove xs↭ys x∈xs
+ xs≋ys′ : remove xs x∈xs ≋ remove ys x∈ys
+ xs≋ys′ = sorted-unique {xs′} xs↭ys′ s-xs′ s-ys′
+ xs≋ys″ : insert (remove xs x∈xs) x ≋ insert (remove ys x∈ys) x
+ xs≋ys″ = insert-resp-≋ x xs≋ys′
+ ≋xs : xs ≋ insert (remove xs x∈xs) x
+ ≋xs = ≋-sym (insert-remove s-xs x∈xs)
+ ≋ys : insert (remove ys x∈ys) x ≋ ys
+ ≋ys = insert-remove s-ys x∈ys
+
+sorted-≋
+ : {xs ys : List A}
+ → xs ↭ ys
+ → sort xs ≋ sort ys
+sorted-≋ {xs} {ys} xs↭ys =
+ sorted-unique
+ (↭-trans
+ (sort-↭ xs)
+ (↭-trans xs↭ys (↭-sym (sort-↭ ys))))
+ (sort-↗ xs)
+ (sort-↗ ys)