@@ -20,7 +20,7 @@ Then we define two sorting algorithms:
20
20
21
21
open List.Perm
22
22
23
- universe u
23
+ universe u v
24
24
25
25
namespace List
26
26
@@ -31,7 +31,7 @@ namespace List
31
31
32
32
section Sorted
33
33
34
- variable {α : Type u} {r : α → α → Prop } {a : α} {l : List α}
34
+ variable {α : Type u} {β : Type v} { r : α → α → Prop } {s : β → β → Prop } {a : α} {l : List α}
35
35
36
36
/-- `Sorted r l` is the same as `List.Pairwise r l`, preferred in the case that `r`
37
37
is a `<` or `≤`-like relation (transitive and antisymmetric or asymmetric) -/
@@ -162,9 +162,11 @@ end Monotone
162
162
163
163
section sort
164
164
165
- variable {α : Type u} (r : α → α → Prop ) [DecidableRel r]
165
+ variable {α : Type u} {β : Type v} (r : α → α → Prop ) (s : β → β → Prop )
166
+ variable [DecidableRel r] [DecidableRel s]
166
167
167
168
local infixl :50 " ≼ " => r
169
+ local infixl :50 " ≼ " => s
168
170
169
171
/-! ### Insertion sort -/
170
172
@@ -220,6 +222,18 @@ theorem mem_orderedInsert {a b : α} {l : List α} :
220
222
· simp [orderedInsert]
221
223
· rw [mem_cons, mem_cons, mem_orderedInsert, or_left_comm]
222
224
225
+ theorem map_orderedInsert (f : α → β) (l : List α) (x : α)
226
+ (hl₁ : ∀ a ∈ l, a ≼ x ↔ f a ≼ f x) (hl₂ : ∀ a ∈ l, x ≼ a ↔ f x ≼ f a) :
227
+ (l.orderedInsert r x).map f = (l.map f).orderedInsert s (f x) := by
228
+ induction l with
229
+ | nil => simp
230
+ | cons x xs ih =>
231
+ rw [List.forall_mem_cons] at hl₁ hl₂
232
+ simp only [List.map, List.orderedInsert, ← hl₁.1 , ← hl₂.1 ]
233
+ split_ifs
234
+ · rw [List.map, List.map]
235
+ · rw [List.map, ih (fun _ ha => hl₁.2 _ ha) (fun _ ha => hl₂.2 _ ha)]
236
+
223
237
section Correctness
224
238
225
239
open Perm
@@ -241,6 +255,25 @@ theorem perm_insertionSort : ∀ l : List α, insertionSort r l ~ l
241
255
| b :: l => by
242
256
simpa [insertionSort] using (perm_orderedInsert _ _ _).trans ((perm_insertionSort l).cons b)
243
257
258
+ @[simp]
259
+ theorem mem_insertionSort {l : List α} {x : α} : x ∈ l.insertionSort r ↔ x ∈ l :=
260
+ (perm_insertionSort r l).mem_iff
261
+
262
+ @[simp]
263
+ theorem length_insertionSort (l : List α) : (insertionSort r l).length = l.length :=
264
+ (perm_insertionSort r _).length_eq
265
+
266
+ theorem map_insertionSort (f : α → β) (l : List α) (hl : ∀ a ∈ l, ∀ b ∈ l, a ≼ b ↔ f a ≼ f b) :
267
+ (l.insertionSort r).map f = (l.map f).insertionSort s := by
268
+ induction l with
269
+ | nil => simp
270
+ | cons x xs ih =>
271
+ simp_rw [List.forall_mem_cons, forall_and] at hl
272
+ simp_rw [List.map, List.insertionSort]
273
+ rw [List.map_orderedInsert _ s, ih hl.2 .2 ]
274
+ · simpa only [mem_insertionSort] using hl.2 .1
275
+ · simpa only [mem_insertionSort] using hl.1 .2
276
+
244
277
variable {r}
245
278
246
279
/-- If `l` is already `List.Sorted` with respect to `r`, then `insertionSort` does not change
@@ -347,6 +380,17 @@ def split : List α → List α × List α
347
380
theorem split_cons_of_eq (a : α) {l l₁ l₂ : List α} (h : split l = (l₁, l₂)) :
348
381
split (a :: l) = (a :: l₂, l₁) := by rw [split, h]
349
382
383
+ @[simp]
384
+ theorem map_split (f : α → β) :
385
+ ∀ l : List α, (map f l).split = (l.split.1 .map f, l.split.2 .map f)
386
+ | [] => rfl
387
+ | a :: l => by simp [map_split]
388
+
389
+ @[simp]
390
+ theorem mem_split_iff {x : α} : ∀ {l : List α}, x ∈ l.split.1 ∨ x ∈ l.split.2 ↔ x ∈ l
391
+ | [] => by simp
392
+ | a :: l => by simp_rw [split, mem_cons, or_assoc, or_comm, mem_split_iff]
393
+
350
394
theorem length_split_le :
351
395
∀ {l l₁ l₂ : List α}, split l = (l₁, l₂) → length l₁ ≤ length l ∧ length l₂ ≤ length l
352
396
| [], _, _, rfl => ⟨Nat.le_refl 0 , Nat.le_refl 0 ⟩
@@ -407,6 +451,10 @@ theorem perm_mergeSort : ∀ l : List α, mergeSort r l ~ l
407
451
((perm_mergeSort l₁).append (perm_mergeSort l₂)).trans (perm_split e).symm
408
452
termination_by l => length l
409
453
454
+ @[simp]
455
+ theorem mem_mergeSort {l : List α} {x : α} : x ∈ l.mergeSort r ↔ x ∈ l :=
456
+ (perm_mergeSort r l).mem_iff
457
+
410
458
@[simp]
411
459
theorem length_mergeSort (l : List α) : (mergeSort r l).length = l.length :=
412
460
(perm_mergeSort r _).length_eq
@@ -472,6 +520,45 @@ theorem mergeSort_nil : [].mergeSort r = [] := by rw [List.mergeSort]
472
520
@[simp]
473
521
theorem mergeSort_singleton (a : α) : [a].mergeSort r = [a] := by rw [List.mergeSort]
474
522
523
+ theorem map_merge (f : α → β) (r : α → α → Bool) (s : β → β → Bool) (l l' : List α)
524
+ (hl : ∀ a ∈ l, ∀ b ∈ l', r a b = s (f a) (f b)) :
525
+ (l.merge r l').map f = (l.map f).merge s (l'.map f) := by
526
+ match l, l' with
527
+ | [], x' => simp
528
+ | x, [] => simp
529
+ | x :: xs, x' :: xs' =>
530
+ simp_rw [List.forall_mem_cons, forall_and] at hl
531
+ simp_rw [List.map, List.cons_merge_cons]
532
+ rw [← hl.1 .1 ]
533
+ split
534
+ · rw [List.map, map_merge _ r s, List.map]
535
+ simp_rw [List.forall_mem_cons, forall_and]
536
+ exact ⟨hl.2 .1 , hl.2 .2 ⟩
537
+ · rw [List.map, map_merge _ r s, List.map]
538
+ simp_rw [List.forall_mem_cons]
539
+ exact ⟨hl.1 .2 , hl.2 .2 ⟩
540
+
541
+ theorem map_mergeSort (f : α → β) (l : List α) (hl : ∀ a ∈ l, ∀ b ∈ l, a ≼ b ↔ f a ≼ f b) :
542
+ (l.mergeSort r).map f = (l.map f).mergeSort s :=
543
+ match l with
544
+ | [] => by simp
545
+ | [x] => by simp
546
+ | a :: b :: l => by
547
+ simp_rw [← mem_split_iff (l := a :: b :: l), or_imp, forall_and] at hl
548
+ set l₁ := (split (a :: b :: l)).1
549
+ set l₂ := (split (a :: b :: l)).2
550
+ have e : split (a :: b :: l) = (l₁, l₂) := rfl
551
+ have fe : split (f a :: f b :: l.map f) = (l₁.map f, l₂.map f) := by
552
+ rw [← map, ← map, map_split, e]
553
+ have := length_split_fst_le l
554
+ have := length_split_snd_le l
555
+ simp_rw [List.map]
556
+ rw [List.mergeSort_cons_cons _ e, List.mergeSort_cons_cons _ fe,
557
+ map_merge _ (r · ·) (s · ·), map_mergeSort _ l₁ hl.1 .1 , map_mergeSort _ l₂ hl.2 .2 ]
558
+ simp_rw [mem_mergeSort, decide_eq_decide]
559
+ exact hl.1 .2
560
+ termination_by length l
561
+
475
562
end MergeSort
476
563
477
564
end sort
0 commit comments