@@ -29,6 +29,7 @@ the `SortOpsInsertHead` model. This insertionSort evaluates identically to the u
2929- `insertionSort_sorted` : `insertionSort` outputs a sorted list.
3030- `insertionSort_complexity` : `insertionSort` takes at most n * (n + 1) comparisons and
3131 (n + 1) * (n + 2) list head-insertions.
32+ - `insertionSort_stable` : `insertionSort` is a stable sorting algorithm.
3233 -/
3334
3435namespace Cslib
@@ -88,6 +89,67 @@ theorem insertionSort_complexity (l : List α) (le : α → α → Bool) :
8889 grind [insertOrd_complexity_upper_bound, List.length_insertionSort, SortOpsCost.le_def,
8990 insertionSort_time_compares, insertionSort_time_inserts]
9091
92+ section Stability
93+
94+ private lemma filter_orderedInsert_of_neg {r : α → α → Prop } [DecidableRel r]
95+ (a : α) (l : List α) (p : α → Bool) (ha : p a = false ) :
96+ (l.orderedInsert r a).filter p = l.filter p := by
97+ induction l with
98+ | nil => rw [List.orderedInsert_nil]; simp [ha]
99+ | cons b l ih =>
100+ rw [List.orderedInsert_cons]
101+ split
102+ · simp [List.filter, ha]
103+ · simp only [List.filter]; split <;> simp [ih]
104+
105+ private lemma filter_orderedInsert_of_pos {r : α → α → Prop } [DecidableRel r]
106+ (a : α) (l : List α) (p : α → Bool)
107+ (ha : p a = true )
108+ (hcompat : ∀ b, p b = true → r a b)
109+ (hsorted : l.Pairwise r) :
110+ (l.orderedInsert r a).filter p = a :: l.filter p := by
111+ induction l with
112+ | nil => rw [List.orderedInsert_nil]; simp [ha]
113+ | cons b l ih =>
114+ rw [List.orderedInsert_cons]
115+ rw [List.pairwise_cons] at hsorted
116+ split
117+ · simp [List.filter, ha]
118+ · rename_i hnr
119+ have hnpb : p b = false := by
120+ by_contra h; push_neg at h
121+ cases hpb : p b with
122+ | false => simp [hpb] at h
123+ | true => exact hnr (hcompat b hpb)
124+ simp only [List.filter, hnpb]
125+ exact ih hsorted.2
126+
127+ theorem insertionSort_stable
128+ (xs : List α) (le : α → α → Bool)
129+ [Std.Total (fun x y => le x y = true )]
130+ [IsTrans α (fun x y => le x y = true )] :
131+ let ys := (insertionSort xs).eval (sortModel le)
132+ ∀ k : α, ys.filter (fun x => le x k && le k x) = xs.filter (fun x => le x k && le k x) := by
133+ simp only [insertionSort_eval]
134+ intro k
135+ induction xs with
136+ | nil => simp
137+ | cons a rest ih =>
138+ rw [List.insertionSort_cons]
139+ have hsorted : (rest.insertionSort (fun x y => le x y = true )).Pairwise
140+ (fun x y => le x y = true ) :=
141+ List.pairwise_insertionSort _ rest
142+ rcases hab : (le a k && le k a) with _ | _
143+ · rw [filter_orderedInsert_of_neg a _ (fun x => le x k && le k x) hab]
144+ simp [hab, ih]
145+ · rw [filter_orderedInsert_of_pos a _ (fun x => le x k && le k x) hab _ hsorted]
146+ · simp [hab, ih]
147+ · intro b hb
148+ simp only [Bool.and_eq_true] at hab hb
149+ exact IsTrans.trans (r := fun x y => le x y = true ) a k b hab.1 hb.2
150+
151+ end Stability
152+
91153end Algorithms
92154
93155end Cslib
0 commit comments