# HG changeset patch # User nipkow # Date 1587568937 -7200 # Node ID 3ab4b989f8c8621f2302cd148a60ca9aa2e073ff # Parent ad91684444d717a457b5c06c9679d742d98ddc07 new funs successive and distinct_adj diff -r ad91684444d7 -r 3ab4b989f8c8 src/HOL/List.thy --- a/src/HOL/List.thy Wed Apr 22 11:50:23 2020 +0200 +++ b/src/HOL/List.thy Wed Apr 22 17:22:17 2020 +0200 @@ -215,6 +215,14 @@ "distinct [] \ True" | "distinct (x # xs) \ x \ set xs \ distinct xs" +fun successively :: "('a \ 'a \ bool) \ 'a list \ bool" where +"successively P [] = True" | +"successively P [x] = True" | +"successively P (x # y # xs) = (P x y \ successively P (y#xs))" + +definition distinct_adj where +"distinct_adj = successively (\)" + primrec remdups :: "'a list \ 'a list" where "remdups [] = []" | "remdups (x # xs) = (if x \ set xs then remdups xs else x # remdups xs)" @@ -300,6 +308,7 @@ @{lemma "fold f [a,b,c] x = f c (f b (f a x))" by simp}\\ @{lemma "foldr f [a,b,c] x = f a (f b (f c x))" by simp}\\ @{lemma "foldl f x [a,b,c] = f (f (f x a) b) c" by simp}\\ +@{lemma "successively (\) [True,False,True,False]" by simp}\\ @{lemma "zip [a,b,c] [x,y,z] = [(a,x),(b,y),(c,z)]" by simp}\\ @{lemma "zip [a,b] [x,y,z] = [(a,x),(b,y)]" by simp}\\ @{lemma "enumerate 3 [a,b,c] = [(3,a),(4,b),(5,c)]" by normalization}\\ @@ -347,7 +356,7 @@ that should give an intuitive understanding of the above functions. \ -text\The following simple sort functions are intended for proofs, +text\The following simple sort(ed) functions are intended for proofs, not for efficient implementations.\ text \A sorted predicate w.r.t. a relation:\ @@ -3452,6 +3461,83 @@ by(simp add: upto_aux_def) + +subsubsection \\<^const>\successively\\ + +lemma successively_Cons: + "successively P (x # xs) \ xs = [] \ P x (hd xs) \ successively P xs" +by (cases xs) auto + +lemma successively_cong [cong]: + assumes "\x y. x \ set xs \ y \ set xs \ P x y \ Q x y" "xs = ys" + shows "successively P xs \ successively Q ys" + unfolding assms(2) [symmetric] using assms(1) + by (induction xs) (auto simp: successively_Cons) + + +lemma successively_append_iff: + "successively P (xs @ ys) \ + successively P xs \ successively P ys \ + (xs = [] \ ys = [] \ P (last xs) (hd ys))" +by (induction xs) (auto simp: successively_Cons) + +lemma successively_if_sorted_wrt: "sorted_wrt P xs \ successively P xs" +by (induction xs rule: induct_list012) auto + + +lemma successively_iff_sorted_wrt_strong: + assumes "\x y z. x \ set xs \ y \ set xs \ z \ set xs \ + P x y \ P y z \ P x z" + shows "successively P xs \ sorted_wrt P xs" +proof + assume "successively P xs" + from this and assms show "sorted_wrt P xs" + proof (induction xs rule: induct_list012) + case (3 x y xs) + from "3.prems" have "P x y" + by auto + have IH: "sorted_wrt P (y # xs)" + using "3.prems" + by(intro "3.IH"(2) list.set_intros(2))(simp, blast intro: list.set_intros(2)) + have "P x z" if asm: "z \ set xs" for z + proof - + from IH and asm have "P y z" + by auto + with \P x y\ show "P x z" + using "3.prems" asm by auto + qed + with IH and \P x y\ show ?case by auto + qed auto +qed (use successively_if_sorted_wrt in blast) + +lemma successively_conv_sorted_wrt: + assumes "transp P" + shows "successively P xs \ sorted_wrt P xs" + using assms unfolding transp_def + by (intro successively_iff_sorted_wrt_strong) blast + +lemma successively_rev [simp]: "successively P (rev xs) \ successively (\x y. P y x) xs" + by (induction xs rule: remdups_adj.induct) + (auto simp: successively_append_iff successively_Cons) + +lemma successively_map: "successively P (map f xs) \ successively (\x y. P (f x) (f y)) xs" + by (induction xs rule: induct_list012) auto + +lemma successively_mono: + assumes "successively P xs" + assumes "\x y. x \ set xs \ y \ set xs \ P x y \ Q x y" + shows "successively Q xs" + using assms by (induction Q xs rule: successively.induct) auto + +lemma successively_altdef: + "successively = (\P. rec_list True (\x xs b. case xs of [] \ True | y # _ \ P x y \ b))" +proof (intro ext) + fix P and xs :: "'a list" + show "successively P xs = rec_list True (\x xs b. case xs of [] \ True | y # _ \ P x y \ b) xs" + by (induction xs) (auto simp: successively_Cons split: list.splits) +qed + + subsubsection \\<^const>\distinct\ and \<^const>\remdups\ and \<^const>\remdups_adj\\ lemma distinct_tl: "distinct xs \ distinct (tl xs)" @@ -3976,6 +4062,65 @@ ultimately show ?thesis by simp qed +lemma successively_remdups_adjI: + "successively P xs \ successively P (remdups_adj xs)" +by (induction xs rule: remdups_adj.induct) (auto simp: successively_Cons) + +lemma successively_remdups_adj_iff: + "(\x. x \ set xs \ P x x) \ + successively P (remdups_adj xs) \ successively P xs" +by (induction xs rule: remdups_adj.induct)(auto simp: successively_Cons) + + +subsection \@{const distinct_adj}\ + +lemma distinct_adj_Nil [simp]: "distinct_adj []" + and distinct_adj_singleton [simp]: "distinct_adj [x]" + and distinct_adj_Cons_Cons [simp]: "distinct_adj (x # y # xs) \ x \ y \ distinct_adj (y # xs)" +by (auto simp: distinct_adj_def) + +lemma distinct_adj_Cons: "distinct_adj (x # xs) \ xs = [] \ x \ hd xs \ distinct_adj xs" +by (cases xs) auto + +lemma distinct_adj_ConsD: "distinct_adj (x # xs) \ distinct_adj xs" +by (cases xs) auto + +lemma distinct_adj_remdups_adj[simp]: "distinct_adj (remdups_adj xs)" +by (induction xs rule: remdups_adj.induct) (auto simp: distinct_adj_Cons) + +lemma distinct_adj_altdef: "distinct_adj xs \ remdups_adj xs = xs" +proof + assume "remdups_adj xs = xs" + with distinct_adj_remdups_adj[of xs] show "distinct_adj xs" + by simp +next + assume "distinct_adj xs" + thus "remdups_adj xs = xs" + by (induction xs rule: induct_list012) auto +qed + +lemma distinct_adj_rev [simp]: "distinct_adj (rev xs) \ distinct_adj xs" +by (simp add: distinct_adj_def eq_commute) + +lemma distinct_adj_append_iff: + "distinct_adj (xs @ ys) \ + distinct_adj xs \ distinct_adj ys \ (xs = [] \ ys = [] \ last xs \ hd ys)" +by (auto simp: distinct_adj_def successively_append_iff) + +lemma distinct_adj_appendD1 [dest]: "distinct_adj (xs @ ys) \ distinct_adj xs" + and distinct_adj_appendD2 [dest]: "distinct_adj (xs @ ys) \ distinct_adj ys" + by (auto simp: distinct_adj_append_iff) + +lemma distinct_adj_mapI: "distinct_adj xs \ inj_on f (set xs) \ distinct_adj (map f xs)" + unfolding distinct_adj_def successively_map + by (erule successively_mono) (auto simp: inj_on_def) + +lemma distinct_adj_mapD: "distinct_adj (map f xs) \ distinct_adj xs" +unfolding distinct_adj_def successively_map by (erule successively_mono) auto + +lemma distinct_adj_map_iff: "inj_on f (set xs) \ distinct_adj (map f xs) \ distinct_adj xs" +using distinct_adj_mapD distinct_adj_mapI by blast + subsubsection \\<^const>\insert\\ @@ -7606,11 +7751,36 @@ shows "(A ===> list_all2 A ===> list_all2 A) removeAll removeAll" unfolding removeAll_def by transfer_prover +lemma successively_transfer [transfer_rule]: + "((A ===> A ===> (=)) ===> list_all2 A ===> (=)) successively successively" + unfolding successively_altdef by transfer_prover + lemma distinct_transfer [transfer_rule]: assumes [transfer_rule]: "bi_unique A" shows "(list_all2 A ===> (=)) distinct distinct" unfolding distinct_def by transfer_prover +lemma distinct_adj_transfer [transfer_rule]: + assumes "bi_unique A" + shows "(list_all2 A ===> (=)) distinct_adj distinct_adj" + unfolding rel_fun_def +proof (intro allI impI) + fix xs ys assume "list_all2 A xs ys" + thus "distinct_adj xs \ distinct_adj ys" + proof (induction rule: list_all2_induct) + case (Cons x xs y ys) + note * = this + show ?case + proof (cases xs) + case [simp]: (Cons x' xs') + with * obtain y' ys' where [simp]: "ys = y' # ys'" + by (cases ys) auto + from * show ?thesis + using assms by (auto simp: distinct_adj_Cons bi_unique_def) + qed (use * in auto) + qed auto +qed + lemma remdups_transfer [transfer_rule]: assumes [transfer_rule]: "bi_unique A" shows "(list_all2 A ===> list_all2 A) remdups remdups"