1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
|
{-# OPTIONS --without-K --safe #-}
open import Level using (Level)
module Data.Permutation {ℓ : Level} (A : Set ℓ) where
import Data.Fin as Fin
import Data.Fin.Properties as FinProp
import Data.Fin.Permutation as ↔-Fin
import Data.List as List
import Data.List.Properties as ListProp
import Data.List.Relation.Binary.Permutation.Propositional as ↭-List
import Data.Nat as Nat
import Data.Vec.Functional as Vector
import Data.Vec.Functional.Properties as VectorProp
import Data.Vec.Functional.Relation.Binary.Permutation as ↭-Vec
import Data.Vec.Functional.Relation.Binary.Permutation.Properties as ↭-VecProp
open import Relation.Binary.PropositionalEquality as ≡ using (_≡_)
open import Data.Product.Base using (_,_; proj₁; proj₂)
open import Data.Vec.Functional.Relation.Unary.Any using (Any)
open import Function.Base using (_∘_)
open ↭-Vec using () renaming (_↭_ to _↭′_)
open ↭-List using (_↭_; ↭-sym; module PermutationReasoning)
open ↔-Fin using (Permutation; _⟨$⟩ˡ_; _⟨$⟩ʳ_)
open List using (List) hiding (module List)
open Fin using (Fin; cast) hiding (module Fin)
open Vector using (Vector; toList; fromList)
open Fin.Fin
open Nat using (ℕ; zero; suc)
open _↭_
module _ where
open Fin using (#_)
open ↔-Fin using (lift₀; insert)
open ↭-VecProp using (↭-refl; ↭-trans)
-- convert a List permutation to a Vector permutation
fromList-↭
: {A : Set}
{xs ys : List A}
→ xs ↭ ys
→ fromList xs ↭′ fromList ys
fromList-↭ refl = ↭-refl
fromList-↭ (prep _ xs↭ys)
with n↔m , xs↭ys′ ← fromList-↭ xs↭ys = lift₀ n↔m , λ where
zero → ≡.refl
(suc i) → xs↭ys′ i
fromList-↭ (swap x y xs↭ys)
with n↔m , xs↭ys′ ← fromList-↭ xs↭ys = insert (# 0) (# 1) (lift₀ n↔m) , λ where
zero → ≡.refl
(suc zero) → ≡.refl
(suc (suc i)) → xs↭ys′ i
fromList-↭ (trans {xs} xs↭ys ys↭zs) =
↭-trans {_} {_} {_} {i = fromList xs} (fromList-↭ xs↭ys) (fromList-↭ ys↭zs)
-- witness for an element in a Vector
_∈_ : A → {n : ℕ} → Vector A n → Set ℓ
x ∈ xs = Any (x ≡_) xs
-- apply a permutation to a witness
apply
: {n m : ℕ}
{xs : Vector A n}
{ys : Vector A m}
{x : A}
→ (xs↭ys : xs ↭′ ys)
→ x ∈ xs
→ x ∈ ys
apply {suc n} {zero} (↔n , _) (i , _) with () ← ↔n ⟨$⟩ˡ i
apply {suc n} {suc m} {xs} {ys} {x} (↔n , ↔≗) (i , x≡xs-i) = i′ , x≡ys-i′
where
i′ : Fin (suc m)
i′ = ↔n ⟨$⟩ˡ i
open ≡.≡-Reasoning
x≡ys-i′ : x ≡ ys i′
x≡ys-i′ = begin
x ≡⟨ x≡xs-i ⟩
xs i ≡⟨ ≡.cong xs (↔-Fin.inverseʳ ↔n) ⟨
xs (↔n ⟨$⟩ʳ (↔n ⟨$⟩ˡ i)) ≡⟨⟩
xs (↔n ⟨$⟩ʳ i′) ≡⟨ ↔≗ i′ ⟩
ys i′ ∎
-- remove an element from a Vector
remove : {n : ℕ} {x : A} (xs : Vector A (suc n)) → x ∈ xs → Vector A n
remove xs (i , _) = Vector.removeAt xs i
-- remove an element and its image from a permutation
↭-remove
: {n m : ℕ}
{xs : Vector A (suc n)}
{ys : Vector A (suc m)}
{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 {n} {m} {xs} {ys} {x} xs↭ys@(ρ , ↔≗) x∈xs@(k , _) = ρ⁻ , ↔≗⁻
where
k′ : Fin (suc m)
k′ = ρ ⟨$⟩ˡ k
x∈ys : x ∈ ys
x∈ys = apply xs↭ys x∈xs
ρ⁻ : Permutation m n
ρ⁻ = ↔-Fin.remove k′ ρ
xs⁻ : Vector A n
xs⁻ = remove xs x∈xs
ys⁻ : Vector A m
ys⁻ = remove ys x∈ys
open ≡.≡-Reasoning
open Fin using (punchIn)
↔≗⁻ : (i : Fin m) → xs⁻ (ρ⁻ ⟨$⟩ʳ i) ≡ ys⁻ i
↔≗⁻ i = begin
xs⁻ (ρ⁻ ⟨$⟩ʳ i) ≡⟨⟩
remove xs x∈xs (ρ⁻ ⟨$⟩ʳ i) ≡⟨⟩
xs (punchIn k (ρ⁻ ⟨$⟩ʳ i)) ≡⟨ ≡.cong xs (↔-Fin.punchIn-permute′ ρ k i) ⟨
xs (ρ ⟨$⟩ʳ (punchIn k′ i)) ≡⟨ ↔≗ (punchIn k′ i) ⟩
ys (punchIn k′ i) ≡⟨⟩
remove ys x∈ys i ≡⟨⟩
ys⁻ i ∎
open List.List
open List using (length; insertAt)
-- build a permutation which moves the first element of a list to an arbitrary position
↭-insert-half
: {x₀ : A}
{xs : List A}
→ (i : Fin (suc (length xs)))
→ x₀ ∷ xs ↭ insertAt xs i x₀
↭-insert-half zero = refl
↭-insert-half {x₀} {x₁ ∷ xs} (suc i) = trans (swap x₀ x₁ refl) (prep x₁ (↭-insert-half i))
-- add a mapping to a permutation, given a value and its start and end positions
↭-insert
: {xs ys : List A}
→ xs ↭ ys
→ (i : Fin (suc (length xs)))
(j : Fin (suc (length ys)))
(x : A)
→ insertAt xs i x ↭ insertAt ys j x
↭-insert {xs} {ys} xs↭ys i j x = xs↭ys⁺
where
open PermutationReasoning
xs↭ys⁺ : insertAt xs i x ↭ insertAt ys j x
xs↭ys⁺ = begin
insertAt xs i x ↭⟨ ↭-insert-half i ⟨
x ∷ xs <⟨ xs↭ys ⟩
x ∷ ys ↭⟨ ↭-insert-half j ⟩
insertAt ys j x ∎
open ListProp using (length-tabulate; tabulate-cong)
insertAt-toList
: {n : ℕ}
{v : Vector A n}
(i : Fin (suc (length (toList v))))
(i′ : Fin (suc n))
→ i ≡ cast (≡.cong suc (≡.sym (length-tabulate v))) i′
→ (x : A)
→ insertAt (toList v) i x
≡ toList (Vector.insertAt v i′ x)
insertAt-toList zero zero _ x = ≡.refl
insertAt-toList {suc n} {v} (suc i) (suc i′) ≡.refl x =
≡.cong (v zero ∷_) (insertAt-toList i i′ ≡.refl x)
-- convert a Vector permutation to a List permutation
toList-↭
: {n m : ℕ}
{xs : Vector A n}
{ys : Vector A m}
→ xs ↭′ ys
→ toList xs ↭ toList ys
toList-↭ {zero} {zero} _ = refl
toList-↭ {zero} {suc m} (ρ , _) with () ← ρ ⟨$⟩ʳ zero
toList-↭ {suc n} {zero} (ρ , _) with () ← ρ ⟨$⟩ˡ zero
toList-↭ {suc n} {suc m} {xs} {ys} xs↭ys′ = xs↭ys
where
-- first element and its image
x₀ : A
x₀ = xs zero
x₀∈xs : x₀ ∈ xs
x₀∈xs = zero , ≡.refl
x₀∈ys : x₀ ∈ ys
x₀∈ys = apply xs↭ys′ x₀∈xs
-- reduce the problem by removing those elements
xs⁻ : Vector A n
xs⁻ = remove xs x₀∈xs
ys⁻ : Vector A m
ys⁻ = remove ys x₀∈ys
xs↭ys⁻ : xs⁻ ↭′ ys⁻
xs↭ys⁻ = ↭-remove xs↭ys′ x₀∈xs
-- recursion on the reduced problem
xs↭ys⁻′ : toList xs⁻ ↭ toList ys⁻
xs↭ys⁻′ = toList-↭ xs↭ys⁻
-- indices for working with vectors
i : Fin (suc n)
i = proj₁ x₀∈xs
j : Fin (suc m)
j = proj₁ x₀∈ys
i′ : Fin (suc (length (toList xs⁻)))
i′ = cast (≡.sym (≡.cong suc (length-tabulate xs⁻))) i
j′ : Fin (suc (length (toList ys⁻)))
j′ = cast (≡.sym (≡.cong suc (length-tabulate ys⁻))) j
-- main construction
open VectorProp using (insertAt-removeAt)
open PermutationReasoning
open Vector using () renaming (insertAt to insertAt′)
xs↭ys : toList xs ↭ toList ys
xs↭ys = begin
toList xs ≡⟨ tabulate-cong (insertAt-removeAt xs i) ⟨
toList (insertAt′ xs⁻ i x₀) ≡⟨ insertAt-toList i′ i ≡.refl x₀ ⟨
insertAt (toList xs⁻) i′ x₀ ↭⟨ ↭-insert xs↭ys⁻′ i′ j′ x₀ ⟩
insertAt (toList ys⁻) j′ x₀ ≡⟨ insertAt-toList j′ j ≡.refl x₀ ⟩
toList (insertAt′ ys⁻ j x₀) ≡⟨ ≡.cong (toList ∘ insertAt′ ys⁻ j) (proj₂ x₀∈ys) ⟩
toList (insertAt′ ys⁻ j (ys j)) ≡⟨ tabulate-cong (insertAt-removeAt ys j) ⟩
toList ys ∎
|