# HG changeset patch # User haftmann # Date 1743502245 -7200 # Node ID 88064da0ae76ac6f98fd3e77585c0b7189a6e166 # Parent b161057bdd41daa02d931f65e1c951e863041e24 more on sorting diff -r b161057bdd41 -r 88064da0ae76 src/HOL/Library/Comparator.thy --- a/src/HOL/Library/Comparator.thy Tue Apr 01 10:20:14 2025 +0200 +++ b/src/HOL/Library/Comparator.thy Tue Apr 01 12:10:45 2025 +0200 @@ -188,6 +188,18 @@ end +lemma compare_default_eq_Less_iff [simp]: + \compare default x y = Less \ x < y\ + by transfer simp + +lemma compare_default_eq_Equiv_iff [simp]: + \compare default x y = Equiv \ x = y\ + by transfer auto + +lemma compare_default_eq_Greater_iff [simp]: + \compare default x y = Greater \ x > y\ + by transfer auto + text \A rudimentary quickcheck setup\ instantiation comparator :: (enum) equal @@ -237,6 +249,10 @@ by standard (auto intro: trans_equiv trans_less simp: greater_iff_sym_less) qed +lemma compare_reversed_apply [simp]: + \compare (reversed cmp) x y = compare cmp y x\ + by transfer simp + lift_definition key :: \('b \ 'a) \ 'a comparator \ 'b comparator\ is \\f cmp a b. cmp (f a) (f b)\ proof - @@ -247,6 +263,43 @@ by standard (auto intro: trans_equiv trans_less simp: greater_iff_sym_less) qed +lemma compare_key_apply [simp]: + \compare (key f cmp) x y = compare cmp (f x) (f y)\ + by transfer simp + +lift_definition prod_lex :: \'a comparator \ 'b comparator \ ('a \ 'b) comparator\ + is \\f g (a, c) (b, d). case f a b of Less \ Less | Equiv \ g c d | Greater \ Greater\ +proof - + fix f :: \'a \ 'a \ comp\ and g :: \'b \ 'b \ comp\ + assume \comparator f\ + then interpret f: comparator f . + assume \comparator g\ + then interpret g: comparator g . + define h where \h = (\(a, c) (b, d). case f a b of Less \ Less | Equiv \ g c d | Greater \ Greater)\ + then have h_apply [simp]: \h (a, c) (b, d) = (case f a b of Less \ Less | Equiv \ g c d | Greater \ Greater)\ for a b c d + by simp + have h_equiv: \h p q = Equiv \ f (fst p) (fst q) = Equiv \ g (snd p) (snd q) = Equiv\ for p q + by (cases p; cases q) (simp split: comp.split) + have h_less: \h p q = Less \ f (fst p) (fst q) = Less \ f (fst p) (fst q) = Equiv \ g (snd p) (snd q) = Less\ for p q + by (cases p; cases q) (simp split: comp.split) + have h_greater: \h p q = Greater \ f (fst p) (fst q) = Greater \ f (fst p) (fst q) = Equiv \ g (snd p) (snd q) = Greater\ for p q + by (cases p; cases q) (simp split: comp.split) + have \comparator h\ + apply standard + apply (simp_all add: h_equiv h_less h_greater f.greater_iff_sym_less g.greater_iff_sym_less f.sym g.sym) + apply (auto intro: f.trans_equiv g.trans_equiv f.trans_less g.trans_less f.trans_less_equiv f.trans_equiv_less) + done + then show \comparator (\(a, c) (b, d). case f a b of Less \ Less + | Equiv \ g c d + | Greater \ Greater)\ + by (simp add: h_def) +qed + +lemma compare_prod_lex_apply: + \compare (prod_lex cmp1 cmp2) p q = + (case compare (key fst cmp1) p q of Less \ Less | Equiv \ compare (key snd cmp2) p q | Greater \ Greater)\ + by transfer (simp add: split_def) + subsection \Direct implementations for linear orders on selected types\ @@ -257,7 +310,7 @@ \compare comparator_bool = (\p q. if p then if q then Equiv else Greater else if q then Less else Equiv)\ - by (auto simp add: fun_eq_iff) (transfer; simp)+ + by (auto simp add: fun_eq_iff) definition raw_comparator_nat :: \nat \ nat \ comp\ where [simp]: \raw_comparator_nat = compare default\ diff -r b161057bdd41 -r 88064da0ae76 src/HOL/Library/Sorting_Algorithms.thy --- a/src/HOL/Library/Sorting_Algorithms.thy Tue Apr 01 10:20:14 2025 +0200 +++ b/src/HOL/Library/Sorting_Algorithms.thy Tue Apr 01 12:10:45 2025 +0200 @@ -667,4 +667,89 @@ end + +subsection \Lexicographic products\ + +lemma sorted_prod_lex_imp_sorted_fst: + \sorted (key fst cmp1) ps\ if \sorted (prod_lex cmp1 cmp2) ps\ +using that proof (induction rule: sorted_induct) + case Nil + then show ?case + by simp +next + case (Cons p ps) + have \compare (key fst cmp1) p q \ Greater\ if \ps = q # qs\ for q qs + using that Cons.hyps(2) [of q] by (simp add: compare_prod_lex_apply split: comp.splits) + with Cons.IH show ?case + by (rule sorted_ConsI) simp +qed + +lemma sorted_prod_lex_imp_sorted_snd: + \sorted (key snd cmp2) ps\ if \sorted (prod_lex cmp1 cmp2) ps\ \\a' b'. (a', b') \ set ps \ compare cmp1 a a' = Equiv\ +using that proof (induction rule: sorted_induct) + case Nil + then show ?case + by simp +next + case (Cons p ps) + then show ?case + apply (cases p) + apply (rule sorted_ConsI) + apply (simp_all add: compare_prod_lex_apply) + apply (auto cong del: comp.case_cong_weak) + apply (metis comp.simps(8) compare.equiv_subst_left) + done +qed + +lemma sort_comp_fst_snd_eq_sort_prod_lex: + \sort (key fst cmp1) \ sort (key snd cmp2) = sort (prod_lex cmp1 cmp2)\ (is \sort ?cmp1 \ sort ?cmp2 = sort ?cmp\) +proof + fix ps :: \('a \ 'b) list\ + have \sort ?cmp1 (sort ?cmp2 ps) = sort ?cmp ps\ + proof (rule sort_eqI) + show \mset (sort ?cmp2 ps) = mset (sort ?cmp ps)\ + by simp + show \sorted ?cmp1 (sort ?cmp ps)\ + by (rule sorted_prod_lex_imp_sorted_fst [of _ cmp2]) simp + next + fix p :: \'a \ 'b\ + define a b where ab: \a = fst p\ \b = snd p\ + moreover assume \p \ set (sort ?cmp2 ps)\ + ultimately have \(a, b) \ set (sort ?cmp2 ps)\ + by simp + let ?qs = \filter (\(a', _). compare cmp1 a a' = Equiv) ps\ + have \sort ?cmp2 ?qs = sort ?cmp ?qs\ + proof (rule sort_eqI) + show \mset ?qs = mset (sort ?cmp ?qs)\ + by simp + show \sorted ?cmp2 (sort ?cmp ?qs)\ + by (rule sorted_prod_lex_imp_sorted_snd) auto + next + fix q :: \'a \ 'b\ + define c d where \c = fst q\ \d = snd q\ + moreover assume \q \ set ?qs\ + ultimately have \(c, d) \ set ?qs\ + by simp + from sorted_stable_segment [of ?cmp \(a, d)\ ps] + have \sorted ?cmp (filter (\(c, b). compare (prod_lex cmp1 cmp2) (a, d) (c, b) = Equiv) ps)\ + by (simp only: case_prod_unfold prod.collapse) + also have \(\(c, b). compare (prod_lex cmp1 cmp2) (a, d) (c, b) = Equiv) = + (\(c, b). compare cmp1 a c = Equiv \ compare cmp2 d b = Equiv)\ + by (simp add: fun_eq_iff compare_prod_lex_apply split: comp.split) + finally have *: \sorted ?cmp (filter (\(c, b). compare cmp1 a c = Equiv \ compare cmp2 d b = Equiv) ps)\ . + let ?rs = \filter (\(_, d'). compare cmp2 d d' = Equiv) ?qs\ + have \sort ?cmp ?rs = ?rs\ + by (rule sort_eqI) (use * in \simp_all add: case_prod_unfold\) + then show \filter (\r. compare ?cmp2 q r = Equiv) ?qs = + filter (\r. compare ?cmp2 q r = Equiv) (sort ?cmp ?qs)\ + by (simp add: filter_sort case_prod_unfold flip: \d = snd q\) + qed + then show \filter (\q. compare ?cmp1 p q = Equiv) (sort ?cmp2 ps) = + filter (\q. compare ?cmp1 p q = Equiv) (sort ?cmp ps)\ + by (simp add: filter_sort case_prod_unfold flip: ab) + qed + then show \(sort (key fst cmp1) \ sort (key snd cmp2)) ps = sort (prod_lex cmp1 cmp2) ps\ + by simp +qed + end