|
| 1 | +------------------------------------------------------------------------ |
| 2 | +-- The Agda standard library |
| 3 | +-- |
| 4 | +-- Properties of insertion sort |
| 5 | +------------------------------------------------------------------------ |
| 6 | + |
| 7 | +{-# OPTIONS --cubical-compatible --safe #-} |
| 8 | + |
| 9 | +open import Relation.Binary.Bundles using (DecTotalOrder) |
| 10 | + |
| 11 | +module Data.List.Sort.InsertionSort.Properties |
| 12 | + {a ℓ₁ ℓ₂} |
| 13 | + (O : DecTotalOrder a ℓ₁ ℓ₂) |
| 14 | + where |
| 15 | + |
| 16 | +open import Data.Bool.Base using (true; false; if_then_else_) |
| 17 | +open import Data.List.Base using (List; []; _∷_) |
| 18 | +open import Data.List.Relation.Binary.Pointwise using ([]; _∷_; decidable; setoid) |
| 19 | +open import Data.List.Relation.Binary.Permutation.Propositional |
| 20 | +import Data.List.Relation.Binary.Permutation.Propositional.Properties as Perm |
| 21 | +open import Data.List.Relation.Unary.Linked using ([]; [-]; _∷_) |
| 22 | +open import Relation.Binary.Bundles using (Setoid) |
| 23 | +open import Relation.Binary.Definitions using (Decidable) |
| 24 | +open import Relation.Binary.Properties.DecTotalOrder O using (≰⇒≥) |
| 25 | +open import Relation.Nullary.Decidable.Core using (does; yes; no) |
| 26 | +open import Relation.Nullary.Negation.Core using (contradiction) |
| 27 | + |
| 28 | +open DecTotalOrder O renaming (Carrier to A; trans to ≤-trans) |
| 29 | + using (totalOrder; _≤?_; _≤_; module Eq; _≈_; ≤-respʳ-≈; ≤-respˡ-≈; antisym) |
| 30 | + |
| 31 | +open import Data.List.Relation.Binary.Equality.Setoid Eq.setoid |
| 32 | + using (_≋_; ≋-refl; ≋-sym; ≋-trans) |
| 33 | +open import Data.List.Relation.Unary.Sorted.TotalOrder totalOrder using (Sorted) |
| 34 | +open import Data.List.Sort.Base totalOrder using (SortingAlgorithm) |
| 35 | +open import Data.List.Sort.InsertionSort.Base O |
| 36 | +import Relation.Binary.Reasoning.Setoid (setoid Eq.setoid) as ≋-Reasoning |
| 37 | + |
| 38 | +------------------------------------------------------------------------ |
| 39 | +-- Permutation property |
| 40 | + |
| 41 | +insert-↭ : ∀ x xs → insert x xs ↭ x ∷ xs |
| 42 | +insert-↭ x [] = ↭-refl |
| 43 | +insert-↭ x (y ∷ xs) with does (x ≤? y) |
| 44 | +... | true = ↭-refl |
| 45 | +... | false = begin |
| 46 | + y ∷ insert x xs ↭⟨ prep y (insert-↭ x xs) ⟩ |
| 47 | + y ∷ x ∷ xs ↭⟨ swap y x refl ⟩ |
| 48 | + x ∷ y ∷ xs ∎ |
| 49 | + where open PermutationReasoning |
| 50 | + |
| 51 | +insert-cong-↭ : ∀ {x xs ys} → xs ↭ ys → insert x xs ↭ x ∷ ys |
| 52 | +insert-cong-↭ {x} {xs} {ys} eq = begin |
| 53 | + insert x xs ↭⟨ insert-↭ x xs ⟩ |
| 54 | + x ∷ xs ↭⟨ prep x eq ⟩ |
| 55 | + x ∷ ys ∎ |
| 56 | + where open PermutationReasoning |
| 57 | + |
| 58 | +sort-↭ : ∀ (xs : List A) → sort xs ↭ xs |
| 59 | +sort-↭ [] = ↭-refl |
| 60 | +sort-↭ (x ∷ xs) = insert-cong-↭ (sort-↭ xs) |
| 61 | + |
| 62 | +------------------------------------------------------------------------ |
| 63 | +-- Sorted property |
| 64 | + |
| 65 | +insert-↗ : ∀ x {xs} → Sorted xs → Sorted (insert x xs) |
| 66 | +insert-↗ x [] = [-] |
| 67 | +insert-↗ x ([-] {y}) with x ≤? y |
| 68 | +... | yes x≤y = x≤y ∷ [-] |
| 69 | +... | no x≰y = ≰⇒≥ x≰y ∷ [-] |
| 70 | +insert-↗ x (_∷_ {y} {z} {ys} y≤z z≤ys) with x ≤? y |
| 71 | +... | yes x≤y = x≤y ∷ y≤z ∷ z≤ys |
| 72 | +... | no x≰y with ih ← insert-↗ x z≤ys | x ≤? z |
| 73 | +... | yes _ = ≰⇒≥ x≰y ∷ ih |
| 74 | +... | no _ = y≤z ∷ ih |
| 75 | + |
| 76 | +sort-↗ : ∀ xs → Sorted (sort xs) |
| 77 | +sort-↗ [] = [] |
| 78 | +sort-↗ (x ∷ xs) = insert-↗ x (sort-↗ xs) |
| 79 | + |
| 80 | +------------------------------------------------------------------------ |
| 81 | +-- Algorithm |
| 82 | + |
| 83 | +insertionSort : SortingAlgorithm |
| 84 | +insertionSort = record |
| 85 | + { sort = sort |
| 86 | + ; sort-↭ = sort-↭ |
| 87 | + ; sort-↗ = sort-↗ |
| 88 | + } |
| 89 | + |
| 90 | +------------------------------------------------------------------------ |
| 91 | +-- Congruence properties |
| 92 | + |
| 93 | +insert-congʳ : ∀ z {xs ys} → xs ≋ ys → insert z xs ≋ insert z ys |
| 94 | +insert-congʳ z [] = ≋-refl |
| 95 | +insert-congʳ z (_∷_ {x} {y} {xs} {ys} x∼y eq) with z ≤? x | z ≤? y |
| 96 | +... | yes _ | yes _ = Eq.refl ∷ x∼y ∷ eq |
| 97 | +... | no z≰x | yes z≤y = contradiction (≤-respʳ-≈ (Eq.sym x∼y) z≤y) z≰x |
| 98 | +... | yes z≤x | no z≰y = contradiction (≤-respʳ-≈ x∼y z≤x) z≰y |
| 99 | +... | no _ | no _ = x∼y ∷ insert-congʳ z eq |
| 100 | + |
| 101 | +insert-congˡ : ∀ {x y} xs → x ≈ y → insert x xs ≋ insert y xs |
| 102 | +insert-congˡ {x} {y} [] eq = eq ∷ [] |
| 103 | +insert-congˡ {x} {y} (z ∷ xs) eq with x ≤? z | y ≤? z |
| 104 | +... | yes _ | yes _ = eq ∷ ≋-refl |
| 105 | +... | no x≰z | yes y≤z = contradiction (≤-respˡ-≈ (Eq.sym eq) y≤z) x≰z |
| 106 | +... | yes x≤z | no y≰z = contradiction (≤-respˡ-≈ eq x≤z) y≰z |
| 107 | +... | no _ | no _ = Eq.refl ∷ insert-congˡ xs eq |
| 108 | + |
| 109 | +insert-cong : ∀ {x y xs ys} → x ≈ y → xs ≋ ys → insert x xs ≋ insert y ys |
| 110 | +insert-cong {y = y} {xs} eq₁ eq₂ = ≋-trans (insert-congˡ xs eq₁) (insert-congʳ y eq₂) |
| 111 | + |
| 112 | +sort-cong : ∀ {xs ys} → xs ≋ ys → sort xs ≋ sort ys |
| 113 | +sort-cong [] = [] |
| 114 | +sort-cong (x∼y ∷ eq) = insert-cong x∼y (sort-cong eq) |
| 115 | + |
| 116 | +private |
| 117 | + insert-swap-≤ : ∀ {x y} xs → x ≤ y → insert x (insert y xs) ≋ insert y (insert x xs) |
| 118 | + insert-swap-≤ {x} {y} [] x≤y with x ≤? y |
| 119 | + ... | no xy = contradiction x≤y xy |
| 120 | + ... | yes xy with y ≤? x |
| 121 | + ... | yes yx = Eq.sym eq ∷ eq ∷ [] where eq = antisym yx xy |
| 122 | + ... | no _ = ≋-refl |
| 123 | + insert-swap-≤ {x} {y} (z ∷ xs) x≤y with y ≤? z |
| 124 | + insert-swap-≤ {x} {y} (z ∷ xs) x≤y | yes yz with x ≤? y |
| 125 | + insert-swap-≤ {x} {y} (z ∷ xs) x≤y | yes yz | yes xy with x ≤? z |
| 126 | + insert-swap-≤ {x} {y} (z ∷ xs) x≤y | yes yz | yes xy | yes xz with y ≤? x |
| 127 | + insert-swap-≤ {x} {y} (z ∷ xs) x≤y | yes yz | yes xy | yes xz | yes yx = |
| 128 | + Eq.sym eq ∷ eq ∷ ≋-refl where eq = antisym yx xy |
| 129 | + insert-swap-≤ {x} {y} (z ∷ xs) x≤y | yes yz | yes xy | yes xz | no yx with y ≤? z |
| 130 | + insert-swap-≤ {x} {y} (z ∷ xs) x≤y | yes yz | yes xy | yes xz | no yx | yes yz' = ≋-refl |
| 131 | + insert-swap-≤ {x} {y} (z ∷ xs) x≤y | yes yz | yes xy | yes xz | no yx | no yz' = contradiction yz yz' |
| 132 | + insert-swap-≤ {x} {y} (z ∷ xs) x≤y | yes yz | yes xy | no xz = contradiction (≤-trans xy yz) xz |
| 133 | + insert-swap-≤ {x} {y} (z ∷ xs) x≤y | yes yz | no xy = contradiction x≤y xy |
| 134 | + insert-swap-≤ {x} {y} (z ∷ xs) x≤y | no yz with x ≤? z |
| 135 | + insert-swap-≤ {x} {y} (z ∷ xs) x≤y | no yz | yes xz with y ≤? x |
| 136 | + insert-swap-≤ {x} {y} (z ∷ xs) x≤y | no yz | yes xz | yes yx = contradiction (≤-trans yx xz) yz |
| 137 | + insert-swap-≤ {x} {y} (z ∷ xs) x≤y | no yz | yes xz | no yx with y ≤? z |
| 138 | + insert-swap-≤ {x} {y} (z ∷ xs) x≤y | no yz | yes xz | no yx | yes yz' = contradiction yz' yz |
| 139 | + insert-swap-≤ {x} {y} (z ∷ xs) x≤y | no yz | yes xz | no yx | no yz' = ≋-refl |
| 140 | + insert-swap-≤ {x} {y} (z ∷ xs) x≤y | no yz | no xz with y ≤? z |
| 141 | + insert-swap-≤ {x} {y} (z ∷ xs) x≤y | no yz | no xz | yes yz' = contradiction yz' yz |
| 142 | + insert-swap-≤ {x} {y} (z ∷ xs) x≤y | no yz | no xz | no yz' = Eq.refl ∷ (insert-swap-≤ xs x≤y) |
| 143 | + |
| 144 | +insert-swap : ∀ x y xs → insert x (insert y xs) ≋ insert y (insert x xs) |
| 145 | +insert-swap x y xs with x ≤? y |
| 146 | +... | yes x≤y = insert-swap-≤ xs x≤y |
| 147 | +... | no x≰y = ≋-sym (insert-swap-≤ xs (≰⇒≥ x≰y)) |
| 148 | + |
| 149 | +insert-swap-cong : ∀ {x y x′ y′ xs ys} → x ≈ x′ → y ≈ y′ → xs ≋ ys → |
| 150 | + insert x (insert y xs) ≋ insert y′ (insert x′ ys) |
| 151 | +insert-swap-cong {x} {y} {x′} {y′} {xs} {ys} eq₁ eq₂ eq₃ = begin |
| 152 | + insert x (insert y xs) ≈⟨ insert-cong eq₁ (insert-cong eq₂ eq₃) ⟩ |
| 153 | + insert x′ (insert y′ ys) ≈⟨ insert-swap x′ y′ ys ⟩ |
| 154 | + insert y′ (insert x′ ys) ∎ |
| 155 | + where open ≋-Reasoning |
0 commit comments