# HG changeset patch # User nipkow # Date 1622569594 -7200 # Node ID 9db620f007fab45cad634020f69d17b155042c87 # Parent 26c0ccf17f318614a645ec9136edea1e845989e2 More general fold function for maps diff -r 26c0ccf17f31 -r 9db620f007fa src/HOL/Finite_Set.thy --- a/src/HOL/Finite_Set.thy Mon May 31 20:27:45 2021 +0000 +++ b/src/HOL/Finite_Set.thy Tue Jun 01 19:46:34 2021 +0200 @@ -710,21 +710,23 @@ subsection \A basic fold functional for finite sets\ -text \The intended behaviour is - \fold f z {x\<^sub>1, \, x\<^sub>n} = f x\<^sub>1 (\ (f x\<^sub>n z)\)\ - if \f\ is ``left-commutative'': +text \ + The intended behaviour is \fold f z {x\<^sub>1, \, x\<^sub>n} = f x\<^sub>1 (\ (f x\<^sub>n z)\)\ + if \f\ is ``left-commutative''. + The commutativity requirement is relativised to the carrier set \S\: \ -locale comp_fun_commute = +locale comp_fun_commute_on = + fixes S :: "'a set" fixes f :: "'a \ 'b \ 'b" - assumes comp_fun_commute: "f y \ f x = f x \ f y" + assumes comp_fun_commute_on: "x \ S \ y \ S \ f y \ f x = f x \ f y" begin -lemma fun_left_comm: "f y (f x z) = f x (f y z)" - using comp_fun_commute by (simp add: fun_eq_iff) +lemma fun_left_comm: "x \ S \ y \ S \ f y (f x z) = f x (f y z)" + using comp_fun_commute_on by (simp add: fun_eq_iff) -lemma commute_left_comp: "f y \ (f x \ g) = f x \ (f y \ g)" - by (simp add: o_assoc comp_fun_commute) +lemma commute_left_comp: "x \ S \ y \ S \ f y \ (f x \ g) = f x \ (f y \ g)" + by (simp add: o_assoc comp_fun_commute_on) end @@ -776,7 +778,7 @@ by (subst fold_graph_closed_eq[where B=B and g=g]) (auto simp: that) text \ - A tempting alternative for the definiens is + A tempting alternative for the definition is \<^term>\if finite A then THE y. fold_graph f z A y else e\. It allows the removal of finiteness assumptions from the theorems \fold_comm\, \fold_reindex\ and \fold_distrib\. @@ -789,7 +791,7 @@ subsubsection \From \<^const>\fold_graph\ to \<^term>\fold\\ -context comp_fun_commute +context comp_fun_commute_on begin lemma fold_graph_finite: @@ -798,7 +800,10 @@ using assms by induct simp_all lemma fold_graph_insertE_aux: - "fold_graph f z A y \ a \ A \ \y'. y = f a y' \ fold_graph f z (A - {a}) y'" + assumes "A \ S" + assumes "fold_graph f z A y" "a \ A" + shows "\y'. y = f a y' \ fold_graph f z (A - {a}) y'" + using assms(2-,1) proof (induct set: fold_graph) case emptyI then show ?case by simp @@ -812,8 +817,9 @@ case False then obtain y' where y: "y = f a y'" and y': "fold_graph f z (A - {a}) y'" using insertI by auto - have "f x y = f a (f x y')" - unfolding y by (rule fun_left_comm) + from insertI have "x \ S" "a \ S" by auto + then have "f x y = f a (f x y')" + unfolding y by (intro fun_left_comm; simp) moreover have "fold_graph f z (insert x A - {a}) (f x y')" using y' and \x \ a\ and \x \ A\ by (simp add: insert_Diff_if fold_graph.insertI) @@ -823,35 +829,41 @@ qed lemma fold_graph_insertE: + assumes "insert x A \ S" assumes "fold_graph f z (insert x A) v" and "x \ A" obtains y where "v = f x y" and "fold_graph f z A y" - using assms by (auto dest: fold_graph_insertE_aux [OF _ insertI1]) + using assms by (auto dest: fold_graph_insertE_aux[OF \insert x A \ S\ _ insertI1]) -lemma fold_graph_determ: "fold_graph f z A x \ fold_graph f z A y \ y = x" +lemma fold_graph_determ: + assumes "A \ S" + assumes "fold_graph f z A x" "fold_graph f z A y" + shows "y = x" + using assms(2-,1) proof (induct arbitrary: y set: fold_graph) case emptyI then show ?case by fast next case (insertI x A y v) - from \fold_graph f z (insert x A) v\ and \x \ A\ + from \insert x A \ S\ and \fold_graph f z (insert x A) v\ and \x \ A\ obtain y' where "v = f x y'" and "fold_graph f z A y'" by (rule fold_graph_insertE) - from \fold_graph f z A y'\ have "y' = y" - by (rule insertI) + from \fold_graph f z A y'\ insertI have "y' = y" + by simp with \v = f x y'\ show "v = f x y" by simp qed -lemma fold_equality: "fold_graph f z A y \ fold f z A = y" +lemma fold_equality: "A \ S \ fold_graph f z A y \ fold f z A = y" by (cases "finite A") (auto simp add: fold_def intro: fold_graph_determ dest: fold_graph_finite) lemma fold_graph_fold: + assumes "A \ S" assumes "finite A" shows "fold_graph f z A (fold f z A)" proof - - from assms have "\x. fold_graph f z A x" + from \finite A\ have "\x. fold_graph f z A x" by (rule finite_imp_fold_graph) - moreover note fold_graph_determ + moreover note fold_graph_determ[OF \A \ S\] ultimately have "\!x. fold_graph f z A x" by (rule ex_ex1I) then have "fold_graph f z A (The (fold_graph f z A))" @@ -871,12 +883,13 @@ text \The various recursion equations for \<^const>\fold\:\ lemma fold_insert [simp]: + assumes "insert x A \ S" assumes "finite A" and "x \ A" shows "fold f z (insert x A) = f x (fold f z A)" -proof (rule fold_equality) +proof (rule fold_equality[OF \insert x A \ S\]) fix z - from \finite A\ have "fold_graph f z A (fold f z A)" - by (rule fold_graph_fold) + from \insert x A \ S\ \finite A\ have "fold_graph f z A (fold f z A)" + by (blast intro: fold_graph_fold) with \x \ A\ have "fold_graph f z (insert x A) (f x (fold f z A))" by (rule fold_graph.insertI) then show "fold_graph f z (insert x A) (f x (fold f z A))" @@ -886,20 +899,33 @@ declare (in -) empty_fold_graphE [rule del] fold_graph.intros [rule del] \ \No more proofs involve these.\ -lemma fold_fun_left_comm: "finite A \ f x (fold f z A) = fold f (f x z) A" +lemma fold_fun_left_comm: + assumes "insert x A \ S" "finite A" + shows "f x (fold f z A) = fold f (f x z) A" + using assms(2,1) proof (induct rule: finite_induct) case empty then show ?case by simp next - case insert - then show ?case - by (simp add: fun_left_comm [of x]) + case (insert y F) + then have "fold f (f x z) (insert y F) = f y (fold f (f x z) F)" + by simp + also have "\ = f x (f y (fold f z F))" + using insert by (simp add: fun_left_comm[where ?y=x]) + also have "\ = f x (fold f z (insert y F))" + proof - + from insert have "insert y F \ S" by simp + from fold_insert[OF this] insert show ?thesis by simp + qed + finally show ?case .. qed -lemma fold_insert2: "finite A \ x \ A \ fold f z (insert x A) = fold f (f x z) A" +lemma fold_insert2: + "insert x A \ S \ finite A \ x \ A \ fold f z (insert x A) = fold f (f x z) A" by (simp add: fold_fun_left_comm) lemma fold_rec: + assumes "A \ S" assumes "finite A" and "x \ A" shows "fold f z A = f x (fold f z (A - {x}))" proof - @@ -908,11 +934,12 @@ then have "fold f z A = fold f z (insert x (A - {x}))" by simp also have "\ = f x (fold f z (A - {x}))" - by (rule fold_insert) (simp add: \finite A\)+ + by (rule fold_insert) (use assms in \auto\) finally show ?thesis . qed lemma fold_insert_remove: + assumes "insert x A \ S" assumes "finite A" shows "fold f z (insert x A) = f x (fold f z (A - {x}))" proof - @@ -921,20 +948,77 @@ moreover have "x \ insert x A" by auto ultimately have "fold f z (insert x A) = f x (fold f z (insert x A - {x}))" - by (rule fold_rec) + using \insert x A \ S\ by (blast intro: fold_rec) then show ?thesis by simp qed lemma fold_set_union_disj: + assumes "A \ S" "B \ S" assumes "finite A" "finite B" "A \ B = {}" shows "Finite_Set.fold f z (A \ B) = Finite_Set.fold f (Finite_Set.fold f z A) B" - using assms(2,1,3) by induct simp_all + using \finite B\ assms(1,2,3,5) +proof induct + case (insert x F) + have "fold f z (A \ insert x F) = f x (fold f (fold f z A) F)" + using insert by auto + also have "\ = fold f (fold f z A) (insert x F)" + using insert by (blast intro: fold_insert[symmetric]) + finally show ?case . +qed simp + end text \Other properties of \<^const>\fold\:\ +lemma fold_graph_image: + assumes "inj_on g A" + shows "fold_graph f z (g ` A) = fold_graph (f \ g) z A" +proof + fix w + show "fold_graph f z (g ` A) w = fold_graph (f o g) z A w" + proof + assume "fold_graph f z (g ` A) w" + then show "fold_graph (f \ g) z A w" + using assms + proof (induct "g ` A" w arbitrary: A) + case emptyI + then show ?case by (auto intro: fold_graph.emptyI) + next + case (insertI x A r B) + from \inj_on g B\ \x \ A\ \insert x A = image g B\ obtain x' A' + where "x' \ A'" and [simp]: "B = insert x' A'" "x = g x'" "A = g ` A'" + by (rule inj_img_insertE) + from insertI.prems have "fold_graph (f \ g) z A' r" + by (auto intro: insertI.hyps) + with \x' \ A'\ have "fold_graph (f \ g) z (insert x' A') ((f \ g) x' r)" + by (rule fold_graph.insertI) + then show ?case + by simp + qed + next + assume "fold_graph (f \ g) z A w" + then show "fold_graph f z (g ` A) w" + using assms + proof induct + case emptyI + then show ?case + by (auto intro: fold_graph.emptyI) + next + case (insertI x A r) + from \x \ A\ insertI.prems have "g x \ g ` A" + by auto + moreover from insertI have "fold_graph f z (g ` A) r" + by simp + ultimately have "fold_graph f z (insert (g x) (g ` A)) (f (g x) r)" + by (rule fold_graph.insertI) + then show ?case + by simp + qed + qed +qed + lemma fold_image: assumes "inj_on g A" shows "fold f z (g ` A) = fold (f \ g) z A" @@ -944,70 +1028,26 @@ by (auto dest: finite_imageD simp add: fold_def) next case True - have "fold_graph f z (g ` A) = fold_graph (f \ g) z A" - proof - fix w - show "fold_graph f z (g ` A) w \ fold_graph (f \ g) z A w" (is "?P \ ?Q") - proof - assume ?P - then show ?Q - using assms - proof (induct "g ` A" w arbitrary: A) - case emptyI - then show ?case by (auto intro: fold_graph.emptyI) - next - case (insertI x A r B) - from \inj_on g B\ \x \ A\ \insert x A = image g B\ obtain x' A' - where "x' \ A'" and [simp]: "B = insert x' A'" "x = g x'" "A = g ` A'" - by (rule inj_img_insertE) - from insertI.prems have "fold_graph (f \ g) z A' r" - by (auto intro: insertI.hyps) - with \x' \ A'\ have "fold_graph (f \ g) z (insert x' A') ((f \ g) x' r)" - by (rule fold_graph.insertI) - then show ?case - by simp - qed - next - assume ?Q - then show ?P - using assms - proof induct - case emptyI - then show ?case - by (auto intro: fold_graph.emptyI) - next - case (insertI x A r) - from \x \ A\ insertI.prems have "g x \ g ` A" - by auto - moreover from insertI have "fold_graph f z (g ` A) r" - by simp - ultimately have "fold_graph f z (insert (g x) (g ` A)) (f (g x) r)" - by (rule fold_graph.insertI) - then show ?case - by simp - qed - qed - qed - with True assms show ?thesis - by (auto simp add: fold_def) + then show ?thesis + by (auto simp add: fold_def fold_graph_image[OF assms]) qed lemma fold_cong: - assumes "comp_fun_commute f" "comp_fun_commute g" - and "finite A" + assumes "comp_fun_commute_on S f" "comp_fun_commute_on S g" + and "A \ S" "finite A" and cong: "\x. x \ A \ f x = g x" and "s = t" and "A = B" shows "fold f s A = fold g t B" proof - have "fold f s A = fold g s A" - using \finite A\ cong + using \finite A\ \A \ S\ cong proof (induct A) case empty then show ?case by simp next case insert - interpret f: comp_fun_commute f by (fact \comp_fun_commute f\) - interpret g: comp_fun_commute g by (fact \comp_fun_commute g\) + interpret f: comp_fun_commute_on S f by (fact \comp_fun_commute_on S f\) + interpret g: comp_fun_commute_on S g by (fact \comp_fun_commute_on S g\) from insert show ?case by simp qed with assms show ?thesis by simp @@ -1016,14 +1056,15 @@ text \A simplified version for idempotent functions:\ -locale comp_fun_idem = comp_fun_commute + - assumes comp_fun_idem: "f x \ f x = f x" +locale comp_fun_idem_on = comp_fun_commute_on + + assumes comp_fun_idem_on: "x \ S \ f x \ f x = f x" begin -lemma fun_left_idem: "f x (f x z) = f x z" - using comp_fun_idem by (simp add: fun_eq_iff) +lemma fun_left_idem: "x \ S \ f x (f x z) = f x z" + using comp_fun_idem_on by (simp add: fun_eq_iff) lemma fold_insert_idem: + assumes "insert x A \ S" assumes fin: "finite A" shows "fold f z (insert x A) = f x (fold f z A)" proof cases @@ -1031,33 +1072,42 @@ then obtain B where "A = insert x B" and "x \ B" by (rule set_insert) then show ?thesis - using assms by (simp add: comp_fun_idem fun_left_idem) + using assms by (simp add: comp_fun_idem_on fun_left_idem) next assume "x \ A" then show ?thesis - using assms by simp + using assms by auto qed declare fold_insert [simp del] fold_insert_idem [simp] -lemma fold_insert_idem2: "finite A \ fold f z (insert x A) = fold f (f x z) A" +lemma fold_insert_idem2: "insert x A \ S \ finite A \ fold f z (insert x A) = fold f (f x z) A" by (simp add: fold_fun_left_comm) end -subsubsection \Liftings to \comp_fun_commute\ etc.\ - -lemma (in comp_fun_commute) comp_comp_fun_commute: "comp_fun_commute (f \ g)" - by standard (simp_all add: comp_fun_commute) +subsubsection \Liftings to \comp_fun_commute_on\ etc.\ + +lemma (in comp_fun_commute_on) comp_comp_fun_commute_on: + "range g \ S \ comp_fun_commute_on R (f \ g)" + by standard (force intro: comp_fun_commute_on) -lemma (in comp_fun_idem) comp_comp_fun_idem: "comp_fun_idem (f \ g)" - by (rule comp_fun_idem.intro, rule comp_comp_fun_commute, unfold_locales) - (simp_all add: comp_fun_idem) +lemma (in comp_fun_idem_on) comp_comp_fun_idem_on: + assumes "range g \ S" + shows "comp_fun_idem_on R (f \ g)" +proof + interpret f_g: comp_fun_commute_on R "f o g" + by (fact comp_comp_fun_commute_on[OF \range g \ S\]) + show "x \ R \ y \ R \ (f \ g) y \ (f \ g) x = (f \ g) x \ (f \ g) y" for x y + by (fact f_g.comp_fun_commute_on) +qed (use \range g \ S\ in \force intro: comp_fun_idem_on\) -lemma (in comp_fun_commute) comp_fun_commute_funpow: "comp_fun_commute (\x. f x ^^ g x)" +lemma (in comp_fun_commute_on) comp_fun_commute_on_funpow: + "comp_fun_commute_on S (\x. f x ^^ g x)" proof - show "f y ^^ g y \ f x ^^ g x = f x ^^ g x \ f y ^^ g y" for x y + fix x y assume "x \ S" "y \ S" + show "f y ^^ g y \ f x ^^ g x = f x ^^ g x \ f y ^^ g y" proof (cases "x = y") case True then show ?thesis by simp @@ -1082,8 +1132,8 @@ by auto from Suc h_def have "g y = Suc (h y)" by simp - then show ?case - by (simp add: comp_assoc hyp) (simp add: o_assoc comp_fun_commute) + with \x \ S\ \y \ S\ show ?case + by (simp add: comp_assoc hyp) (simp add: o_assoc comp_fun_commute_on) qed define h where "h z = (if z = x then g x - 1 else g z)" for z with Suc have "n = h x" @@ -1101,6 +1151,67 @@ qed +subsubsection \\<^term>\UNIV\ as carrier set\ + +locale comp_fun_commute = + fixes f :: "'a \ 'b \ 'b" + assumes comp_fun_commute: "f y \ f x = f x \ f y" +begin + +lemma (in -) comp_fun_commute_def': "comp_fun_commute f = comp_fun_commute_on UNIV f" + unfolding comp_fun_commute_def comp_fun_commute_on_def by blast + +text \ + We abuse the \rewrites\ functionality of locales to remove trivial assumptions that + result from instantiating the carrier set to \<^term>\UNIV\. +\ +sublocale comp_fun_commute_on UNIV f + rewrites "\X. (X \ UNIV) \ True" + and "\x. x \ UNIV \ True" + and "\P. (True \ P) \ Trueprop P" + and "\P Q. (True \ PROP P \ PROP Q) \ (PROP P \ True \ PROP Q)" +proof - + show "comp_fun_commute_on UNIV f" + by standard (simp add: comp_fun_commute) +qed simp_all + +end + +lemma (in comp_fun_commute) comp_comp_fun_commute: "comp_fun_commute (f o g)" + unfolding comp_fun_commute_def' by (fact comp_comp_fun_commute_on) + +lemma (in comp_fun_commute) comp_fun_commute_funpow: "comp_fun_commute (\x. f x ^^ g x)" + unfolding comp_fun_commute_def' by (fact comp_fun_commute_on_funpow) + +locale comp_fun_idem = comp_fun_commute + + assumes comp_fun_idem: "f x o f x = f x" +begin + +lemma (in -) comp_fun_idem_def': "comp_fun_idem f = comp_fun_idem_on UNIV f" + unfolding comp_fun_idem_on_def comp_fun_idem_def comp_fun_commute_def' + unfolding comp_fun_idem_axioms_def comp_fun_idem_on_axioms_def + by blast + +text \ + Again, we abuse the \rewrites\ functionality of locales to remove trivial assumptions that + result from instantiating the carrier set to \<^term>\UNIV\. +\ +sublocale comp_fun_idem_on UNIV f + rewrites "\X. (X \ UNIV) \ True" + and "\x. x \ UNIV \ True" + and "\P. (True \ P) \ Trueprop P" + and "\P Q. (True \ PROP P \ PROP Q) \ (PROP P \ True \ PROP Q)" +proof - + show "comp_fun_idem_on UNIV f" + by standard (simp_all add: comp_fun_idem comp_fun_commute) +qed simp_all + +end + +lemma (in comp_fun_idem) comp_comp_fun_idem: "comp_fun_idem (f o g)" + unfolding comp_fun_idem_def' by (fact comp_comp_fun_idem_on) + + subsubsection \Expressing set operations via \<^const>\fold\\ lemma comp_fun_commute_const: "comp_fun_commute (\_. f)" @@ -1150,8 +1261,12 @@ assumes "finite A" shows "Set.filter P A = fold (\x A'. if P x then Set.insert x A' else A') {} A" using assms - by induct - (auto simp add: Set.filter_def comp_fun_commute.fold_insert[OF comp_fun_commute_filter_fold]) +proof - + interpret commute_insert: comp_fun_commute "(\x A'. if P x then Set.insert x A' else A')" + by (fact comp_fun_commute_filter_fold) + from \finite A\ show ?thesis + by induct (auto simp add: Set.filter_def) +qed lemma inter_Set_filter: assumes "finite B" @@ -1190,7 +1305,7 @@ qed lemma comp_fun_commute_Pow_fold: "comp_fun_commute (\x A. A \ Set.insert x ` A)" - by (clarsimp simp: fun_eq_iff comp_fun_commute_def) blast (* somewhat slow *) + by (clarsimp simp: fun_eq_iff comp_fun_commute_def) blast lemma Pow_fold: assumes "finite A" @@ -1219,9 +1334,12 @@ lemma product_fold: assumes "finite A" "finite B" shows "A \ B = fold (\x z. fold (\y. Set.insert (x, y)) z B) {} A" - using assms unfolding Sigma_def - by (induct A) - (simp_all add: comp_fun_commute.fold_insert[OF comp_fun_commute_product_fold] fold_union_pair) +proof - + interpret commute_product: comp_fun_commute "(\x z. fold (\y. Set.insert (x, y)) z B)" + by (fact comp_fun_commute_product_fold[OF \finite B\]) + from assms show ?thesis unfolding Sigma_def + by (induct A) (simp_all add: fold_union_pair) +qed context complete_lattice begin @@ -1309,61 +1427,67 @@ subsubsection \The natural case\ -locale folding = +locale folding_on = + fixes S :: "'a set" fixes f :: "'a \ 'b \ 'b" and z :: "'b" - assumes comp_fun_commute: "f y \ f x = f x \ f y" + assumes comp_fun_commute_on: "x \ S \ y \ S \ f y o f x = f x o f y" begin -interpretation fold?: comp_fun_commute f - by standard (use comp_fun_commute in \simp add: fun_eq_iff\) +interpretation fold?: comp_fun_commute_on S f + by standard (simp add: comp_fun_commute_on) definition F :: "'a set \ 'b" - where eq_fold: "F A = fold f z A" + where eq_fold: "F A = Finite_Set.fold f z A" -lemma empty [simp]:"F {} = z" +lemma empty [simp]: "F {} = z" by (simp add: eq_fold) lemma infinite [simp]: "\ finite A \ F A = z" by (simp add: eq_fold) lemma insert [simp]: - assumes "finite A" and "x \ A" + assumes "insert x A \ S" and "finite A" and "x \ A" shows "F (insert x A) = f x (F A)" proof - from fold_insert assms - have "fold f z (insert x A) = f x (fold f z A)" by simp + have "Finite_Set.fold f z (insert x A) + = f x (Finite_Set.fold f z A)" + by simp with \finite A\ show ?thesis by (simp add: eq_fold fun_eq_iff) qed lemma remove: - assumes "finite A" and "x \ A" + assumes "A \ S" and "finite A" and "x \ A" shows "F A = f x (F (A - {x}))" proof - from \x \ A\ obtain B where A: "A = insert x B" and "x \ B" by (auto dest: mk_disjoint_insert) moreover from \finite A\ A have "finite B" by simp - ultimately show ?thesis by simp + ultimately show ?thesis + using \A \ S\ by auto qed -lemma insert_remove: "finite A \ F (insert x A) = f x (F (A - {x}))" - by (cases "x \ A") (simp_all add: remove insert_absorb) +lemma insert_remove: + assumes "insert x A \ S" and "finite A" + shows "F (insert x A) = f x (F (A - {x}))" + using assms by (cases "x \ A") (simp_all add: remove insert_absorb) end subsubsection \With idempotency\ -locale folding_idem = folding + - assumes comp_fun_idem: "f x \ f x = f x" +locale folding_idem_on = folding_on + + assumes comp_fun_idem_on: "x \ S \ y \ S \ f x \ f x = f x" begin declare insert [simp del] -interpretation fold?: comp_fun_idem f - by standard (insert comp_fun_commute comp_fun_idem, simp add: fun_eq_iff) +interpretation fold?: comp_fun_idem_on S f + by standard (simp_all add: comp_fun_commute_on comp_fun_idem_on) lemma insert_idem [simp]: - assumes "finite A" + assumes "insert x A \ S" and "finite A" shows "F (insert x A) = f x (F A)" proof - from fold_insert_idem assms @@ -1373,6 +1497,57 @@ end +subsubsection \\<^term>\UNIV\ as the carrier set\ + +locale folding = + fixes f :: "'a \ 'b \ 'b" and z :: "'b" + assumes comp_fun_commute: "f y \ f x = f x \ f y" +begin + +lemma (in -) folding_def': "folding f = folding_on UNIV f" + unfolding folding_def folding_on_def by blast + +text \ + Again, we abuse the \rewrites\ functionality of locales to remove trivial assumptions that + result from instantiating the carrier set to \<^term>\UNIV\. +\ +sublocale folding_on UNIV f + rewrites "\X. (X \ UNIV) \ True" + and "\x. x \ UNIV \ True" + and "\P. (True \ P) \ Trueprop P" + and "\P Q. (True \ PROP P \ PROP Q) \ (PROP P \ True \ PROP Q)" +proof - + show "folding_on UNIV f" + by standard (simp add: comp_fun_commute) +qed simp_all + +end + +locale folding_idem = folding + + assumes comp_fun_idem: "f x \ f x = f x" +begin + +lemma (in -) folding_idem_def': "folding_idem f = folding_idem_on UNIV f" + unfolding folding_idem_def folding_def' folding_idem_on_def + unfolding folding_idem_axioms_def folding_idem_on_axioms_def + by blast + +text \ + Again, we abuse the \rewrites\ functionality of locales to remove trivial assumptions that + result from instantiating the carrier set to \<^term>\UNIV\. +\ +sublocale folding_idem_on UNIV f + rewrites "\X. (X \ UNIV) \ True" + and "\x. x \ UNIV \ True" + and "\P. (True \ P) \ Trueprop P" + and "\P Q. (True \ PROP P \ PROP Q) \ (PROP P \ True \ PROP Q)" +proof - + show "folding_idem_on UNIV f" + by standard (simp add: comp_fun_idem) +qed simp_all + +end + subsection \Finite cardinality\ @@ -1384,7 +1559,7 @@ \ global_interpretation card: folding "\_. Suc" 0 - defines card = "folding.F (\_. Suc) 0" + defines card = "folding_on.F (\_. Suc) 0" by standard rule lemma card_insert_disjoint: "finite A \ x \ A \ card (insert x A) = Suc (card A)" diff -r 26c0ccf17f31 -r 9db620f007fa src/HOL/Library/AList.thy --- a/src/HOL/Library/AList.thy Mon May 31 20:27:45 2021 +0000 +++ b/src/HOL/Library/AList.thy Tue Jun 01 19:46:34 2021 +0200 @@ -423,6 +423,9 @@ finally show ?thesis . qed +lemma graph_map_of: "Map.graph (map_of al) = set (clearjunk al)" + by (metis distinct_clearjunk graph_map_of_if_distinct_ran map_of_clearjunk) + lemma clearjunk_update: "clearjunk (update k v al) = update k v (clearjunk al)" by (induct al rule: clearjunk.induct) (simp_all add: delete_update) diff -r 26c0ccf17f31 -r 9db620f007fa src/HOL/Library/AList_Mapping.thy --- a/src/HOL/Library/AList_Mapping.thy Mon May 31 20:27:45 2021 +0000 +++ b/src/HOL/Library/AList_Mapping.thy Tue Jun 01 19:46:34 2021 +0200 @@ -34,6 +34,25 @@ "Mapping.ordered_keys (Mapping xs) = sort (remdups (map fst xs))" by (simp only: ordered_keys_def keys_Mapping sorted_list_of_set_sort_remdups) simp +lemma entries_Mapping [code]: + "Mapping.entries (Mapping xs) = set (AList.clearjunk xs)" + by transfer (fact graph_map_of) + +lemma ordered_entries_Mapping [code]: + "Mapping.ordered_entries (Mapping xs) = sort_key fst (AList.clearjunk xs)" +proof - + have distinct: "distinct (sort_key fst (AList.clearjunk xs))" + using distinct_clearjunk distinct_map distinct_sort by blast + note folding_Map_graph.idem_if_sorted_distinct[where ?m="map_of xs", OF _ sorted_sort_key distinct] + then show ?thesis + unfolding ordered_entries_def + by (transfer fixing: xs) (auto simp: graph_map_of) +qed + +lemma fold_Mapping [code]: + "Mapping.fold f (Mapping xs) a = List.fold (case_prod f) (sort_key fst (AList.clearjunk xs)) a" + by (simp add: Mapping.fold_def ordered_entries_Mapping) + lemma size_Mapping [code]: "Mapping.size (Mapping xs) = length (remdups (map fst xs))" by (simp add: size_def length_remdups_card_conv dom_map_of_conv_image_fst) diff -r 26c0ccf17f31 -r 9db620f007fa src/HOL/Library/FSet.thy --- a/src/HOL/Library/FSet.thy Mon May 31 20:27:45 2021 +0000 +++ b/src/HOL/Library/FSet.thy Tue Jun 01 19:46:34 2021 +0200 @@ -726,7 +726,8 @@ "\x. x |\| A \ f x = g x" and "s = t" and "A = B" shows "ffold f s A = ffold g t B" -using assms by transfer (metis Finite_Set.fold_cong) + using assms[unfolded comp_fun_commute_def'] + by transfer (meson Finite_Set.fold_cong subset_UNIV) context comp_fun_idem begin diff -r 26c0ccf17f31 -r 9db620f007fa src/HOL/Library/Finite_Lattice.thy --- a/src/HOL/Library/Finite_Lattice.thy Mon May 31 20:27:45 2021 +0000 +++ b/src/HOL/Library/Finite_Lattice.thy Tue Jun 01 19:46:34 2021 +0200 @@ -170,15 +170,36 @@ context finite_distrib_lattice_complete begin subclass finite_distrib_lattice - apply standard - apply (simp_all add: Inf_def Sup_def bot_def top_def) - apply (metis (mono_tags) insert_UNIV local.Sup_fin.eq_fold local.bot_def local.finite_UNIV local.top_def) - apply (simp add: comp_fun_idem.fold_insert_idem local.comp_fun_idem_inf) - apply (metis (mono_tags) insert_UNIV local.Inf_fin.eq_fold local.finite_UNIV) - apply (simp add: comp_fun_idem.fold_insert_idem local.comp_fun_idem_sup) - apply (metis (mono_tags) insert_UNIV local.Inf_fin.eq_fold local.finite_UNIV) - apply (metis (mono_tags) insert_UNIV local.Sup_fin.eq_fold local.finite_UNIV) - done +proof - + show "class.finite_distrib_lattice Inf Sup inf (\) (<) sup bot top" + proof + show "bot = Inf UNIV" + unfolding bot_def top_def Inf_def + using Inf_fin.eq_fold Inf_fin.insert inf.absorb2 by force + next + show "top = Sup UNIV" + unfolding bot_def top_def Sup_def + using Sup_fin.eq_fold Sup_fin.insert by force + next + show "Inf {} = Sup UNIV" + unfolding Inf_def Sup_def bot_def top_def + using Sup_fin.eq_fold Sup_fin.insert by force + next + show "Sup {} = Inf UNIV" + unfolding Inf_def Sup_def bot_def top_def + using Inf_fin.eq_fold Inf_fin.insert inf.absorb2 by force + next + interpret comp_fun_idem_inf: comp_fun_idem inf + by (fact comp_fun_idem_inf) + show "Inf (insert a A) = inf a (Inf A)" for a A + using comp_fun_idem_inf.fold_insert_idem Inf_def finite by simp + next + interpret comp_fun_idem_sup: comp_fun_idem sup + by (fact comp_fun_idem_sup) + show "Sup (insert a A) = sup a (Sup A)" for a A + using comp_fun_idem_sup.fold_insert_idem Sup_def finite by simp + qed +qed end instance finite_distrib_lattice_complete \ complete_distrib_lattice .. diff -r 26c0ccf17f31 -r 9db620f007fa src/HOL/Library/Mapping.thy --- a/src/HOL/Library/Mapping.thy Mon May 31 20:27:45 2021 +0000 +++ b/src/HOL/Library/Mapping.thy Tue Jun 01 19:46:34 2021 +0200 @@ -5,7 +5,7 @@ section \An abstract view on maps for code generation.\ theory Mapping -imports Main +imports Main AList begin subsection \Parametricity transfer rules\ @@ -43,6 +43,16 @@ shows "((A ===> rel_option B) ===> rel_set A) dom dom" unfolding dom_def [abs_def] Option.is_none_def [symmetric] by transfer_prover +lemma graph_parametric: + assumes "bi_total A" + shows "((A ===> rel_option B) ===> rel_set (rel_prod A B)) Map.graph Map.graph" +proof + fix f g assume "(A ===> rel_option B) f g" + with assms[unfolded bi_total_def] show "rel_set (rel_prod A B) (Map.graph f) (Map.graph g)" + unfolding graph_def rel_set_def rel_fun_def + by auto (metis option_rel_Some1 option_rel_Some2)+ +qed + lemma map_of_parametric [transfer_rule]: assumes [transfer_rule]: "bi_unique R1" shows "(list_all2 (rel_prod R1 R2) ===> R1 ===> rel_option R2) map_of map_of" @@ -129,6 +139,9 @@ lift_definition keys :: "('a, 'b) mapping \ 'a set" is dom parametric dom_parametric . +lift_definition entries :: "('a, 'b) mapping \ ('a \ 'b) set" + is Map.graph parametric graph_parametric . + lift_definition tabulate :: "'a list \ ('a \ 'b) \ ('a, 'b) mapping" is "\ks f. (map_of (List.map (\k. (k, f k)) ks))" parametric tabulate_parametric . @@ -166,6 +179,13 @@ definition ordered_keys :: "('a::linorder, 'b) mapping \ 'a list" where "ordered_keys m = (if finite (keys m) then sorted_list_of_set (keys m) else [])" +definition ordered_entries :: "('a::linorder, 'b) mapping \ ('a \ 'b) list" + where "ordered_entries m = (if finite (entries m) then sorted_key_list_of_set fst (entries m) + else [])" + +definition fold :: "('a::linorder \ 'b \ 'c \ 'c) \ ('a, 'b) mapping \ 'c \ 'c" + where "fold f m a = List.fold (case_prod f) (ordered_entries m) a" + definition is_empty :: "('a, 'b) mapping \ bool" where "is_empty m \ keys m = {}" @@ -462,7 +482,13 @@ by transfer rule lemma keys_empty [simp]: "keys empty = {}" - by transfer simp + by transfer (fact dom_empty) + +lemma in_keysD: "k \ keys m \ \v. lookup m k = Some v" + by transfer (fact domD) + +lemma in_entriesI: "lookup m k = Some v \ (k, v) \ entries m" + by transfer (fact in_graphI) lemma keys_update [simp]: "keys (update k v m) = insert k (keys m)" by transfer simp @@ -515,7 +541,7 @@ "finite (keys m) \ k \ keys m \ ordered_keys (update k v m) = insort k (ordered_keys m)" by (simp_all add: ordered_keys_def) - (auto simp only: sorted_list_of_set_insert [symmetric] insert_absorb) + (auto simp only: sorted_list_of_set_insert_remove[symmetric] insert_absorb) lemma ordered_keys_delete [simp]: "ordered_keys (delete k m) = remove1 k (ordered_keys m)" proof (cases "finite (keys m)") @@ -559,14 +585,14 @@ lemma ordered_keys_bulkload [simp]: "ordered_keys (bulkload ks) = [0..k m. update k (f k) m) xs empty" +lemma tabulate_fold: "tabulate xs f = List.fold (\k m. update k (f k) m) xs empty" proof transfer fix f :: "'a \ 'b" and xs have "map_of (List.map (\k. (k, f k)) xs) = foldr (\k m. m(k \ f k)) xs Map.empty" by (simp add: foldr_map comp_def map_of_foldr) - also have "foldr (\k m. m(k \ f k)) xs = fold (\k m. m(k \ f k)) xs" + also have "foldr (\k m. m(k \ f k)) xs = List.fold (\k m. m(k \ f k)) xs" by (rule foldr_fold) (simp add: fun_eq_iff) - ultimately show "map_of (List.map (\k. (k, f k)) xs) = fold (\k m. m(k \ f k)) xs Map.empty" + ultimately show "map_of (List.map (\k. (k, f k)) xs) = List.fold (\k m. m(k \ f k)) xs Map.empty" by simp qed @@ -647,10 +673,262 @@ end +subsubsection \@{term [source] entries}, @{term [source] ordered_entries}, + and @{term [source] fold}\ + +context linorder +begin + +sublocale folding_Map_graph: folding_insort_key "(\)" "(<)" "Map.graph m" fst for m + by unfold_locales (fact inj_on_fst_graph) + +end + +lemma sorted_fst_list_of_set_insort_Map_graph[simp]: + assumes "finite (dom m)" "fst x \ dom m" + shows "sorted_key_list_of_set fst (insert x (Map.graph m)) + = insort_key fst x (sorted_key_list_of_set fst (Map.graph m))" +proof(cases x) + case (Pair k v) + with \fst x \ dom m\ have "Map.graph m \ Map.graph (m(k \ v))" + by(auto simp: graph_def) + moreover from Pair \fst x \ dom m\ have "(k, v) \ Map.graph m" + using graph_domD by fastforce + ultimately show ?thesis + using Pair assms folding_Map_graph.sorted_key_list_of_set_insert[where ?m="m(k \ v)"] + by auto +qed + +lemma sorted_fst_list_of_set_insort_insert_Map_graph[simp]: + assumes "finite (dom m)" "fst x \ dom m" + shows "sorted_key_list_of_set fst (insert x (Map.graph m)) + = insort_insert_key fst x (sorted_key_list_of_set fst (Map.graph m))" +proof(cases x) + case (Pair k v) + with \fst x \ dom m\ have "Map.graph m \ Map.graph (m(k \ v))" + by(auto simp: graph_def) + with assms Pair show ?thesis + unfolding sorted_fst_list_of_set_insort_Map_graph[OF assms] insort_insert_key_def + using folding_Map_graph.set_sorted_key_list_of_set in_graphD by (fastforce split: if_splits) +qed + +lemma linorder_finite_Map_induct[consumes 1, case_names empty update]: + fixes m :: "'a::linorder \ 'b" + assumes "finite (dom m)" + assumes "P Map.empty" + assumes "\k v m. \ finite (dom m); k \ dom m; (\k'. k' \ dom m \ k' \ k); P m \ + \ P (m(k \ v))" + shows "P m" +proof - + let ?key_list = "\m. sorted_list_of_set (dom m)" + from assms(1,2) show ?thesis + proof(induction "length (?key_list m)" arbitrary: m) + case 0 + then have "sorted_list_of_set (dom m) = []" + by auto + with \finite (dom m)\ have "m = Map.empty" + by auto + with \P Map.empty\ show ?case by simp + next + case (Suc n) + then obtain x xs where x_xs: "sorted_list_of_set (dom m) = xs @ [x]" + by (metis append_butlast_last_id length_greater_0_conv zero_less_Suc) + have "sorted_list_of_set (dom (m(x := None))) = xs" + proof - + have "distinct (xs @ [x])" + by (metis sorted_list_of_set.distinct_sorted_key_list_of_set x_xs) + then have "remove1 x (xs @ [x]) = xs" + by (simp add: remove1_append) + with \finite (dom m)\ x_xs show ?thesis + by (simp add: sorted_list_of_set_remove) + qed + moreover have "k \ x" if "k \ dom (m(x := None))" for k + proof - + from x_xs have "sorted (xs @ [x])" + by (metis sorted_list_of_set.sorted_sorted_key_list_of_set) + moreover from \k \ dom (m(x := None))\ have "k \ set xs" + using \finite (dom m)\ \sorted_list_of_set (dom (m(x := None))) = xs\ + by auto + ultimately show "k \ x" + by (simp add: sorted_append) + qed + moreover from \finite (dom m)\ have "finite (dom (m(x := None)))" "x \ dom (m(x := None))" + by simp_all + moreover have "P (m(x := None))" + using Suc \sorted_list_of_set (dom (m(x := None))) = xs\ x_xs by auto + ultimately show ?case + using assms(3)[where ?m="m(x := None)"] by (metis fun_upd_triv fun_upd_upd not_Some_eq) + qed +qed + +lemma delete_insort_fst[simp]: "AList.delete k (insort_key fst (k, v) xs) = AList.delete k xs" + by (induction xs) simp_all + +lemma insort_fst_delete: "\ fst x \ k2; sorted (List.map fst xs) \ + \ insort_key fst x (AList.delete k2 xs) = AList.delete k2 (insort_key fst x xs)" + by (induction xs) (fastforce simp add: insort_is_Cons order_trans)+ + +lemma sorted_fst_list_of_set_Map_graph_fun_upd_None[simp]: + "sorted_key_list_of_set fst (Map.graph (m(k := None))) + = AList.delete k (sorted_key_list_of_set fst (Map.graph m))" +proof(cases "finite (Map.graph m)") + assume "finite (Map.graph m)" + from this[unfolded finite_graph_iff_finite_dom] show ?thesis + proof(induction rule: finite_Map_induct) + let ?list_of="sorted_key_list_of_set fst" + case (update k2 v2 m) + note [simp] = \k2 \ dom m\ \finite (dom m)\ + + have right_eq: "AList.delete k (?list_of (Map.graph (m(k2 \ v2)))) + = AList.delete k (insort_key fst (k2, v2) (?list_of (Map.graph m)))" + by simp + + show ?case + proof(cases "k = k2") + case True + then have "?list_of (Map.graph ((m(k2 \ v2))(k := None))) + = AList.delete k (insort_key fst (k2, v2) (?list_of (Map.graph m)))" + using fst_graph_eq_dom update.IH by auto + then show ?thesis + using right_eq by metis + next + case False + then have "AList.delete k (insort_key fst (k2, v2) (?list_of (Map.graph m))) + = insort_key fst (k2, v2) (?list_of (Map.graph (m(k := None))))" + by (auto simp add: insort_fst_delete update.IH + folding_Map_graph.sorted_sorted_key_list_of_set[OF subset_refl]) + also have "\ = ?list_of (insert (k2, v2) (Map.graph (m(k := None))))" + by auto + also from False \k2 \ dom m\ have "\ = ?list_of (Map.graph ((m(k2 \ v2))(k := None)))" + by (metis graph_map_upd domIff fun_upd_triv fun_upd_twist) + finally show ?thesis using right_eq by metis + qed + qed simp +qed simp + +lemma entries_lookup: "entries m = Map.graph (lookup m)" + by transfer rule + +lemma entries_empty[simp]: "entries empty = {}" + by transfer (fact graph_empty) + +lemma finite_entries_iff_finite_keys[simp]: + "finite (entries m) = finite (keys m)" + by transfer (fact finite_graph_iff_finite_dom) + +lemma entries_update[simp]: + "entries (update k v m) = insert (k, v) (entries (delete k m))" + by transfer (fact graph_map_upd) + +lemma Mapping_delete_if_notin_keys[simp]: + "k \ Mapping.keys m \ delete k m = m" + by transfer simp + +lemma entries_delete: + "entries (delete k m) = {e \ entries m. fst e \ k}" + by transfer (fact graph_fun_upd_None) + +lemma entries_of_alist[simp]: + "distinct (List.map fst xs) \ entries (of_alist xs) = set xs" + by transfer (fact graph_map_of_if_distinct_ran) + +lemma entries_keysD: + "x \ entries m \ fst x \ keys m" + by transfer (fact graph_domD) + +lemma finite_keys_entries[simp]: + "finite (keys (update k v m)) = finite (keys m)" + by transfer simp + +lemma set_ordered_entries[simp]: + "finite (Mapping.keys m) \ set (ordered_entries m) = entries m" + unfolding ordered_entries_def + by transfer (auto simp: folding_Map_graph.set_sorted_key_list_of_set[OF subset_refl]) + +lemma distinct_ordered_entries[simp]: "distinct (List.map fst (ordered_entries m))" + unfolding ordered_entries_def + by transfer (simp add: folding_Map_graph.distinct_sorted_key_list_of_set[OF subset_refl]) + +lemma sorted_ordered_entries[simp]: "sorted (List.map fst (ordered_entries m))" + unfolding ordered_entries_def + by transfer (auto intro: folding_Map_graph.sorted_sorted_key_list_of_set) + +lemma ordered_entries_infinite[simp]: + "\ finite (Mapping.keys m) \ ordered_entries m = []" + by (simp add: ordered_entries_def) + +lemma ordered_entries_empty[simp]: "ordered_entries empty = []" + by (simp add: ordered_entries_def) + +lemma ordered_entries_update[simp]: + assumes "finite (keys m)" + shows "ordered_entries (update k v m) + = insort_insert_key fst (k, v) (AList.delete k (ordered_entries m))" +proof - + let ?list_of="sorted_key_list_of_set fst" and ?insort="insort_insert_key fst" + + have *: "?list_of (insert (k, v) (Map.graph (m(k := None)))) + = ?insort (k, v) (AList.delete k (?list_of (Map.graph m)))" if "finite (dom m)" for m + proof - + from \finite (dom m)\ have "?list_of (insert (k, v) (Map.graph (m(k := None)))) + = ?insort (k, v) (?list_of (Map.graph (m(k := None))))" + by (intro sorted_fst_list_of_set_insort_insert_Map_graph) (simp_all add: subset_insertI) + then show ?thesis by simp + qed + from assms show ?thesis + unfolding ordered_entries_def + apply (transfer fixing: k v) using "*" by auto +qed + +lemma ordered_entries_delete[simp]: + "ordered_entries (delete k m) = AList.delete k (ordered_entries m)" + unfolding ordered_entries_def by transfer auto + +lemma fold_empty[simp]: "fold f empty a = a" + unfolding fold_def by simp + +lemma insort_key_is_snoc_if_sorted_and_distinct: + assumes "sorted (List.map f xs)" "f y \ f ` set xs" "\x \ set xs. f x \ f y" + shows "insort_key f y xs = xs @ [y]" + using assms by (induction xs) (auto dest!: insort_is_Cons) + +lemma fold_update: + assumes "finite (keys m)" + assumes "k \ keys m" "\k'. k' \ keys m \ k' \ k" + shows "fold f (update k v m) a = f k v (fold f m a)" +proof - + from assms have k_notin_entries: "k \ fst ` set (ordered_entries m)" + using entries_keysD by fastforce + with assms have "ordered_entries (update k v m) + = insort_insert_key fst (k, v) (ordered_entries m)" + by simp + also from k_notin_entries have "\ = ordered_entries m @ [(k, v)]" + proof - + from assms have "\x \ set (ordered_entries m). fst x \ fst (k, v)" + unfolding ordered_entries_def + by transfer (fastforce simp: folding_Map_graph.set_sorted_key_list_of_set[OF order_refl] + dest: graph_domD) + from insort_key_is_snoc_if_sorted_and_distinct[OF _ _ this] k_notin_entries show ?thesis + unfolding insort_insert_key_def by auto + qed + finally show ?thesis unfolding fold_def by simp +qed + +lemma linorder_finite_Mapping_induct[consumes 1, case_names empty update]: + fixes m :: "('a::linorder, 'b) mapping" + assumes "finite (keys m)" + assumes "P empty" + assumes "\k v m. + \ finite (keys m); k \ keys m; (\k'. k' \ keys m \ k' \ k); P m \ + \ P (update k v m)" + shows "P m" + using assms by transfer (simp add: linorder_finite_Map_induct) + subsection \Code generator setup\ hide_const (open) empty is_empty rep lookup lookup_default filter update delete ordered_keys keys size replace default map_entry map_default tabulate bulkload map map_values combine of_alist + entries ordered_entries fold end diff -r 26c0ccf17f31 -r 9db620f007fa src/HOL/Library/Multiset.thy --- a/src/HOL/Library/Multiset.thy Mon May 31 20:27:45 2021 +0000 +++ b/src/HOL/Library/Multiset.thy Tue Jun 01 19:46:34 2021 +0200 @@ -1610,7 +1610,7 @@ by (simp add: not_in_iff) from False have "Finite_Set.fold (\y. f y ^^ count (add_mset x M) y) s (set_mset M) = Finite_Set.fold (\y. f y ^^ count M y) s (set_mset M)" - by (auto intro!: Finite_Set.fold_cong comp_fun_commute_funpow) + by (auto intro!: Finite_Set.fold_cong comp_fun_commute_on_funpow) with False * show ?thesis by (simp add: fold_mset_def del: count_add_mset) next @@ -1619,7 +1619,7 @@ from N_def True have *: "set_mset M = insert x N" "x \ N" "finite N" by auto then have "Finite_Set.fold (\y. f y ^^ count (add_mset x M) y) s N = Finite_Set.fold (\y. f y ^^ count M y) s N" - by (auto intro!: Finite_Set.fold_cong comp_fun_commute_funpow) + by (auto intro!: Finite_Set.fold_cong comp_fun_commute_on_funpow) with * show ?thesis by (simp add: fold_mset_def del: count_add_mset) simp qed qed @@ -1984,7 +1984,7 @@ by (induct xs) simp_all global_interpretation mset_set: folding add_mset "{#}" - defines mset_set = "folding.F add_mset {#}" + defines mset_set = "folding_on.F add_mset {#}" by standard (simp add: fun_eq_iff) lemma sum_multiset_singleton [simp]: "sum (\n. {#n#}) A = mset_set A" diff -r 26c0ccf17f31 -r 9db620f007fa src/HOL/Library/RBT.thy --- a/src/HOL/Library/RBT.thy Mon May 31 20:27:45 2021 +0000 +++ b/src/HOL/Library/RBT.thy Tue Jun 01 19:46:34 2021 +0200 @@ -196,6 +196,9 @@ lemma distinct_entries: "distinct (List.map fst (entries t))" by transfer (simp add: distinct_entries) +lemma sorted_entries: "sorted (List.map fst (entries t))" + by (transfer) (simp add: rbt_sorted_entries) + lemma non_empty_keys: "t \ empty \ keys t \ []" by transfer (simp add: non_empty_rbt_keys) diff -r 26c0ccf17f31 -r 9db620f007fa src/HOL/Library/RBT_Mapping.thy --- a/src/HOL/Library/RBT_Mapping.thy Mon May 31 20:27:45 2021 +0000 +++ b/src/HOL/Library/RBT_Mapping.thy Tue Jun 01 19:46:34 2021 +0200 @@ -57,6 +57,24 @@ unfolding ordered_keys_def by (transfer fixing: t) (auto simp add: lookup_keys intro: sorted_distinct_set_unique) +lemma Map_graph_lookup: "Map.graph (RBT.lookup t) = set (RBT.entries t)" + by (metis RBT.distinct_entries RBT.map_of_entries graph_map_of_if_distinct_ran) + +lemma entries_Mapping [code]: "Mapping.entries (Mapping t) = set (RBT.entries t)" + by (transfer fixing: t) (fact Map_graph_lookup) + +lemma ordered_entries_Mapping [code]: "Mapping.ordered_entries (Mapping t) = RBT.entries t" +proof - + note folding_Map_graph.idem_if_sorted_distinct[ + where ?m="RBT.lookup t", OF _ _ folding_Map_graph.distinct_if_distinct_map] + then show ?thesis + unfolding ordered_entries_def + by (transfer fixing: t) (auto simp: Map_graph_lookup distinct_entries sorted_entries) +qed + +lemma fold_Mapping [code]: "Mapping.fold f (Mapping t) a = RBT.fold f t a" + by (simp add: Mapping.fold_def fold_fold ordered_entries_Mapping) + lemma Mapping_size_card_keys: (*FIXME*) "Mapping.size m = card (Mapping.keys m)" unfolding size_def by transfer simp @@ -100,7 +118,7 @@ lemma equal_Mapping [code]: "HOL.equal (Mapping t1) (Mapping t2) \ RBT.entries t1 = RBT.entries t2" - by (transfer fixing: t1 t2) (simp add: entries_lookup) + by (transfer fixing: t1 t2) (simp add: RBT.entries_lookup) lemma [code nbe]: "HOL.equal (x :: (_, _) mapping) x \ True" diff -r 26c0ccf17f31 -r 9db620f007fa src/HOL/Library/RBT_Set.thy --- a/src/HOL/Library/RBT_Set.thy Mon May 31 20:27:45 2021 +0000 +++ b/src/HOL/Library/RBT_Set.thy Tue Jun 01 19:46:34 2021 +0200 @@ -58,6 +58,8 @@ assumes "comp_fun_commute f" shows "Finite_Set.fold f A (set (RBT.entries t)) = RBT.fold (curry f) t A" proof - + interpret comp_fun_commute: comp_fun_commute f + by (fact assms) have *: "remdups (RBT.entries t) = RBT.entries t" using distinct_entries distinct_map by (auto intro: distinct_remdups_id) show ?thesis using assms by (auto simp: fold_def_alt comp_fun_commute.fold_set_fold_remdups *) diff -r 26c0ccf17f31 -r 9db620f007fa src/HOL/Lifting_Set.thy --- a/src/HOL/Lifting_Set.thy Mon May 31 20:27:45 2021 +0000 +++ b/src/HOL/Lifting_Set.thy Tue Jun 01 19:46:34 2021 +0200 @@ -329,4 +329,44 @@ shows "rel_set R (\(f ` A)) (\(g ` B))" by transfer_prover +context + includes lifting_syntax +begin + +lemma fold_graph_transfer[transfer_rule]: + assumes "bi_unique R" "right_total R" + shows "((R ===> (=) ===> (=)) ===> (=) ===> rel_set R ===> (=) ===> (=)) fold_graph fold_graph" +proof(intro rel_funI) + fix f1 :: "'a \ 'c \ 'c" and f2 :: "'b \ 'c \ 'c" + assume rel_f: "(R ===> (=) ===> (=)) f1 f2" + fix z1 z2 :: 'c assume [simp]: "z1 = z2" + fix A1 A2 assume rel_A: "rel_set R A1 A2" + fix y1 y2 :: 'c assume [simp]: "y1 = y2" + + from \bi_unique R\ \right_total R\ have The_y: "\y. \!x. R x y" + unfolding bi_unique_def right_total_def by auto + define r where "r \ \y. THE x. R x y" + + from The_y have r_y: "R (r y) y" for y + unfolding r_def using the_equality by fastforce + with assms rel_A have "inj_on r A2" "A1 = r ` A2" + unfolding r_def rel_set_def inj_on_def bi_unique_def + apply(auto simp: image_iff) by metis+ + with \bi_unique R\ rel_f r_y have "(f1 o r) y = f2 y" for y + unfolding bi_unique_def rel_fun_def by auto + then have "(f1 o r) = f2" + by blast + then show "fold_graph f1 z1 A1 y1 = fold_graph f2 z2 A2 y2" + by (fastforce simp: fold_graph_image[OF \inj_on r A2\] \A1 = r ` A2\) +qed + +lemma fold_transfer[transfer_rule]: + assumes [transfer_rule]: "bi_unique R" "right_total R" + shows "((R ===> (=) ===> (=)) ===> (=) ===> rel_set R ===> (=)) Finite_Set.fold Finite_Set.fold" + unfolding Finite_Set.fold_def + by transfer_prover + end + + +end diff -r 26c0ccf17f31 -r 9db620f007fa src/HOL/List.thy --- a/src/HOL/List.thy Mon May 31 20:27:45 2021 +0000 +++ b/src/HOL/List.thy Tue Jun 01 19:46:34 2021 +0200 @@ -3124,13 +3124,16 @@ text \\<^const>\Finite_Set.fold\ and \<^const>\fold\\ -lemma (in comp_fun_commute) fold_set_fold_remdups: - "Finite_Set.fold f y (set xs) = fold f (remdups xs) y" - by (rule sym, induct xs arbitrary: y) (simp_all add: fold_fun_left_comm insert_absorb) - -lemma (in comp_fun_idem) fold_set_fold: - "Finite_Set.fold f y (set xs) = fold f xs y" - by (rule sym, induct xs arbitrary: y) (simp_all add: fold_fun_left_comm) +lemma (in comp_fun_commute_on) fold_set_fold_remdups: + assumes "set xs \ S" + shows "Finite_Set.fold f y (set xs) = fold f (remdups xs) y" + by (rule sym, use assms in \induct xs arbitrary: y\) + (simp_all add: insert_absorb fold_fun_left_comm) + +lemma (in comp_fun_idem_on) fold_set_fold: + assumes "set xs \ S" + shows "Finite_Set.fold f y (set xs) = fold f xs y" + by (rule sym, use assms in \induct xs arbitrary: y\) (simp_all add: fold_fun_left_comm) lemma union_set_fold [code]: "set xs \ A = fold Set.insert xs A" proof - @@ -5785,6 +5788,10 @@ lemma distinct_insort: "distinct (insort_key f x xs) = (x \ set xs \ distinct xs)" by(induct xs)(auto simp: set_insort_key) +lemma distinct_insort_key: + "distinct (map f (insort_key f x xs)) = (f x \ f ` set xs \ (distinct (map f xs)))" +by (induct xs) (auto simp: set_insort_key) + lemma distinct_sort[simp]: "distinct (sort_key f xs) = distinct xs" by (induct xs) (simp_all add: distinct_insort) @@ -5897,8 +5904,8 @@ "filter P (sort_key f xs) = sort_key f (filter P xs)" by (induct xs) (simp_all add: filter_insort_triv filter_insort) -lemma remove1_insort [simp]: - "remove1 x (insort x xs) = xs" +lemma remove1_insort_key [simp]: + "remove1 x (insort_key f x xs) = xs" by (induct xs) simp_all end @@ -6087,98 +6094,149 @@ qed -subsubsection \\sorted_list_of_set\\ - -text\This function maps (finite) linearly ordered sets to sorted -lists. Warning: in most cases it is not a good idea to convert from -sets to lists but one should convert in the other direction (via -\<^const>\set\).\ - -context linorder +subsubsection \\sorted_key_list_of_set\\ + +text\ + This function maps (finite) linearly ordered sets to sorted lists. + The linear order is obtained by a key function that maps the elements of the set to a type + that is linearly ordered. + Warning: in most cases it is not a good idea to convert from + sets to lists but one should convert in the other direction (via \<^const>\set\). + + Note: this is a generalisation of the older \sorted_list_of_set\ that is obtained by setting + the key function to the identity. Consequently, new theorems should be added to the locale + below. They should also be aliased to more convenient names for use with \sorted_list_of_set\ + as seen further below. +\ + +definition (in linorder) sorted_key_list_of_set :: "('b \ 'a) \ 'b set \ 'b list" + where "sorted_key_list_of_set f \ folding_on.F (insort_key f) []" + +locale folding_insort_key = lo?: linorder "less_eq :: 'a \ 'a \ bool" less + for less_eq (infix "\" 50) and less (infix "\" 50) + + fixes S + fixes f :: "'b \ 'a" + assumes inj_on: "inj_on f S" begin -definition sorted_list_of_set :: "'a set \ 'a list" where - "sorted_list_of_set = folding.F insort []" - -sublocale sorted_list_of_set: folding insort Nil -rewrites - "folding.F insort [] = sorted_list_of_set" +lemma insort_key_commute: + "x \ S \ y \ S \ insort_key f y o insort_key f x = insort_key f x o insort_key f y" +proof(rule ext, goal_cases) + case (1 xs) + with inj_on show ?case by (induction xs) (auto simp: inj_onD) +qed + +sublocale fold_insort_key: folding_on S "insort_key f" "[]" + rewrites "folding_on.F (insort_key f) [] = sorted_key_list_of_set f" proof - - interpret comp_fun_commute insort by (fact comp_fun_commute_insort) - show "folding insort" by standard (fact comp_fun_commute) - show "folding.F insort [] = sorted_list_of_set" by (simp only: sorted_list_of_set_def) -qed - -lemma sorted_list_of_set_empty: - "sorted_list_of_set {} = []" - by (fact sorted_list_of_set.empty) - -lemma sorted_list_of_set_insert [simp]: - "finite A \ sorted_list_of_set (insert x A) = insort x (sorted_list_of_set (A - {x}))" - by (fact sorted_list_of_set.insert_remove) - -lemma sorted_list_of_set_eq_Nil_iff [simp]: - "finite A \ sorted_list_of_set A = [] \ A = {}" - by (auto simp: sorted_list_of_set.remove) - -lemma set_sorted_list_of_set [simp]: - "finite A \ set (sorted_list_of_set A) = A" - by(induct A rule: finite_induct) (simp_all add: set_insort_key) - -lemma sorted_sorted_list_of_set [simp]: "sorted (sorted_list_of_set A)" + show "folding_on S (insort_key f)" + by standard (simp add: insort_key_commute) +qed (simp add: sorted_key_list_of_set_def) + +lemma idem_if_sorted_distinct: + assumes "set xs \ S" and "sorted (map f xs)" "distinct xs" + shows "sorted_key_list_of_set f (set xs) = xs" +proof(cases "S = {}") + case True + then show ?thesis using \set xs \ S\ by auto +next + case False + with assms show ?thesis + proof(induction xs) + case (Cons a xs) + with Cons show ?case by (cases xs) auto + qed simp +qed + +lemma sorted_key_list_of_set_empty: + "sorted_key_list_of_set f {} = []" + by (fact fold_insort_key.empty) + +lemma sorted_key_list_of_set_insert: + assumes "insert x A \ S" and "finite A" "x \ A" + shows "sorted_key_list_of_set f (insert x A) + = insort_key f x (sorted_key_list_of_set f A)" + using assms by (fact fold_insort_key.insert) + +lemma sorted_key_list_of_set_insert_remove [simp]: + assumes "insert x A \ S" and "finite A" + shows "sorted_key_list_of_set f (insert x A) + = insort_key f x (sorted_key_list_of_set f (A - {x}))" + using assms by (fact fold_insort_key.insert_remove) + +lemma sorted_key_list_of_set_eq_Nil_iff [simp]: + assumes "A \ S" and "finite A" + shows "sorted_key_list_of_set f A = [] \ A = {}" + using assms by (auto simp: fold_insort_key.remove) + +lemma set_sorted_key_list_of_set [simp]: + assumes "A \ S" and "finite A" + shows "set (sorted_key_list_of_set f A) = A" + using assms(2,1) + by (induct A rule: finite_induct) (simp_all add: set_insort_key) + +lemma sorted_sorted_key_list_of_set [simp]: + assumes "A \ S" + shows "sorted (map f (sorted_key_list_of_set f A))" proof (cases "finite A") - case True thus ?thesis by(induction A) (simp_all add: sorted_insort) + case True thus ?thesis using \A \ S\ + by (induction A) (simp_all add: sorted_insort_key) next case False thus ?thesis by simp qed -lemma distinct_sorted_list_of_set [simp]: "distinct (sorted_list_of_set A)" +lemma distinct_if_distinct_map: "distinct (map f xs) \ distinct xs" + using inj_on by (simp add: distinct_map) + +lemma distinct_sorted_key_list_of_set [simp]: + assumes "A \ S" + shows "distinct (map f (sorted_key_list_of_set f A))" proof (cases "finite A") - case True thus ?thesis by(induction A) (simp_all add: distinct_insort) -next + case True thus ?thesis using \A \ S\ inj_on + by (induction A) (force simp: distinct_insort_key dest: inj_onD)+ + next case False thus ?thesis by simp qed -lemma length_sorted_list_of_set [simp]: "length (sorted_list_of_set A) = card A" +lemma length_sorted_key_list_of_set [simp]: + assumes "A \ S" + shows "length (sorted_key_list_of_set f A) = card A" proof (cases "finite A") case True - then show ?thesis - by(metis distinct_card distinct_sorted_list_of_set set_sorted_list_of_set) + with assms inj_on show ?thesis + using distinct_card[symmetric, OF distinct_sorted_key_list_of_set] + by (auto simp: subset_inj_on intro!: card_image) qed auto -lemmas sorted_list_of_set = set_sorted_list_of_set sorted_sorted_list_of_set distinct_sorted_list_of_set - -lemma sorted_list_of_set_sort_remdups [code]: - "sorted_list_of_set (set xs) = sort (remdups xs)" -proof - - interpret comp_fun_commute insort by (fact comp_fun_commute_insort) - show ?thesis by (simp add: sorted_list_of_set.eq_fold sort_conv_fold fold_set_fold_remdups) -qed - -lemma sorted_list_of_set_remove: - assumes "finite A" - shows "sorted_list_of_set (A - {x}) = remove1 x (sorted_list_of_set A)" +lemmas sorted_key_list_of_set = + set_sorted_key_list_of_set sorted_sorted_key_list_of_set distinct_sorted_key_list_of_set + +lemma sorted_key_list_of_set_remove: + assumes "insert x A \ S" and "finite A" + shows "sorted_key_list_of_set f (A - {x}) = remove1 x (sorted_key_list_of_set f A)" proof (cases "x \ A") - case False with assms have "x \ set (sorted_list_of_set A)" by simp + case False with assms have "x \ set (sorted_key_list_of_set f A)" by simp with False show ?thesis by (simp add: remove1_idem) next case True then obtain B where A: "A = insert x B" by (rule Set.set_insert) with assms show ?thesis by simp qed -lemma strict_sorted_list_of_set [simp]: "sorted_wrt (<) (sorted_list_of_set A)" - by (simp add: strict_sorted_iff) +lemma strict_sorted_key_list_of_set [simp]: + "A \ S \ sorted_wrt (\) (map f (sorted_key_list_of_set f A))" + by (cases "finite A") (auto simp: strict_sorted_iff subset_inj_on[OF inj_on]) lemma finite_set_strict_sorted: - assumes "finite A" - obtains l where "sorted_wrt (<) l" "set l = A" "length l = card A" - by (metis assms distinct_card distinct_sorted_list_of_set set_sorted_list_of_set strict_sorted_list_of_set) - -lemma strict_sorted_equal: + assumes "A \ S" and "finite A" + obtains l where "sorted_wrt (\) (map f l)" "set l = A" "length l = card A" + using assms + by (meson length_sorted_key_list_of_set set_sorted_key_list_of_set strict_sorted_key_list_of_set) + +lemma (in linorder) strict_sorted_equal: assumes "sorted_wrt (<) xs" - and "sorted_wrt (<) ys" - and "set ys = set xs" - shows "ys = xs" + and "sorted_wrt (<) ys" + and "set ys = set xs" + shows "ys = xs" using assms proof (induction xs arbitrary: ys) case (Cons x xs) @@ -6197,22 +6255,73 @@ using local.Cons by blast qed qed auto - -lemma strict_sorted_equal_Uniq: "\\<^sub>\\<^sub>1xs. sorted_wrt (<) xs \ set xs = A" + +lemma (in linorder) strict_sorted_equal_Uniq: "\\<^sub>\\<^sub>1xs. sorted_wrt (<) xs \ set xs = A" by (simp add: Uniq_def strict_sorted_equal) -lemma sorted_list_of_set_inject: - assumes "sorted_list_of_set A = sorted_list_of_set B" "finite A" "finite B" +lemma sorted_key_list_of_set_inject: + assumes "A \ S" "B \ S" + assumes "sorted_key_list_of_set f A = sorted_key_list_of_set f B" "finite A" "finite B" shows "A = B" - using assms set_sorted_list_of_set by fastforce - -lemma sorted_list_of_set_unique: - assumes "finite A" - shows "sorted_wrt (<) l \ set l = A \ length l = card A \ sorted_list_of_set A = l" - using assms strict_sorted_equal by force + using assms set_sorted_key_list_of_set by metis + +lemma sorted_key_list_of_set_unique: + assumes "A \ S" and "finite A" + shows "sorted_wrt (\) (map f l) \ set l = A \ length l = card A + \ sorted_key_list_of_set f A = l" + using assms + by (auto simp: strict_sorted_iff card_distinct idem_if_sorted_distinct) end +context linorder +begin + +definition "sorted_list_of_set \ sorted_key_list_of_set (\x::'a. x)" + +text \ + We abuse the \rewrites\ functionality of locales to remove trivial assumptions that result + from instantiating the key function to the identity. +\ +sublocale sorted_list_of_set: folding_insort_key "(\)" "(<)" UNIV "(\x. x)" + rewrites "sorted_key_list_of_set (\x. x) = sorted_list_of_set" + and "\xs. map (\x. x) xs \ xs" + and "\X. (X \ UNIV) \ True" + and "\x. x \ UNIV \ True" + and "\P. (True \ P) \ Trueprop P" + and "\P Q. (True \ PROP P \ PROP Q) \ (PROP P \ True \ PROP Q)" +proof - + show "folding_insort_key (\) (<) UNIV (\x. x)" + by standard simp +qed (simp_all add: sorted_list_of_set_def) + +text \Alias theorems for backwards compatibility and ease of use.\ +lemmas sorted_list_of_set = sorted_list_of_set.sorted_key_list_of_set and + sorted_list_of_set_empty = sorted_list_of_set.sorted_key_list_of_set_empty and + sorted_list_of_set_insert = sorted_list_of_set.sorted_key_list_of_set_insert and + sorted_list_of_set_insert_remove = sorted_list_of_set.sorted_key_list_of_set_insert_remove and + sorted_list_of_set_eq_Nil_iff = sorted_list_of_set.sorted_key_list_of_set_eq_Nil_iff and + set_sorted_list_of_set = sorted_list_of_set.set_sorted_key_list_of_set and + sorted_sorted_list_of_set = sorted_list_of_set.sorted_sorted_key_list_of_set and + distinct_sorted_list_of_set = sorted_list_of_set.distinct_sorted_key_list_of_set and + length_sorted_list_of_set = sorted_list_of_set.length_sorted_key_list_of_set and + sorted_list_of_set_remove = sorted_list_of_set.sorted_key_list_of_set_remove and + strict_sorted_list_of_set = sorted_list_of_set.strict_sorted_key_list_of_set and + sorted_list_of_set_inject = sorted_list_of_set.sorted_key_list_of_set_inject and + sorted_list_of_set_unique = sorted_list_of_set.sorted_key_list_of_set_unique and + finite_set_strict_sorted = sorted_list_of_set.finite_set_strict_sorted + +lemma sorted_list_of_set_sort_remdups [code]: + "sorted_list_of_set (set xs) = sort (remdups xs)" +proof - + interpret comp_fun_commute insort by (fact comp_fun_commute_insort) + show ?thesis + by (simp add: sorted_list_of_set.fold_insort_key.eq_fold sort_conv_fold fold_set_fold_remdups) +qed + +end + + lemma sorted_list_of_set_range [simp]: "sorted_list_of_set {m.. {}" shows "sorted_list_of_set A = Min A # sorted_list_of_set (A - {Min A})" - using assms by (auto simp: less_le simp flip: sorted_list_of_set_unique intro: Min_in) + using assms + by (auto simp: less_le simp flip: sorted_list_of_set.sorted_key_list_of_set_unique intro: Min_in) lemma sorted_list_of_set_greaterThanLessThan: assumes "Suc i < j" diff -r 26c0ccf17f31 -r 9db620f007fa src/HOL/Map.thy --- a/src/HOL/Map.thy Mon May 31 20:27:45 2021 +0000 +++ b/src/HOL/Map.thy Tue Jun 01 19:46:34 2021 +0200 @@ -42,6 +42,10 @@ "ran m = {b. \a. m a = Some b}" definition + graph :: "('a \ 'b) \ ('a \ 'b) set" where + "graph m = {(a, b) | a b. m a = Some b}" + +definition map_le :: "('a \ 'b) \ ('a \ 'b) \ bool" (infix "\\<^sub>m" 50) where "(m\<^sub>1 \\<^sub>m m\<^sub>2) \ (\a \ dom m\<^sub>1. m\<^sub>1 a = m\<^sub>2 a)" @@ -660,6 +664,9 @@ unfolding ran_def by force +lemma fun_upd_None_if_notin_dom[simp]: "k \ dom m \ m(k := None) = m" + by auto + lemma ran_map_add: assumes "dom m1 \ dom m2 = {}" shows "ran (m1 ++ m2) = ran m1 \ ran m2" @@ -710,6 +717,62 @@ lemma ran_map_option: "ran (\x. map_option f (m x)) = f ` ran m" by (auto simp add: ran_def) +subsection \@{term [source] graph}\ + +lemma graph_empty[simp]: "graph empty = {}" + unfolding graph_def by simp + +lemma in_graphI: "m k = Some v \ (k, v) \ graph m" + unfolding graph_def by blast + +lemma in_graphD: "(k, v) \ graph m \ m k = Some v" + unfolding graph_def by blast + +lemma graph_map_upd[simp]: "graph (m(k \ v)) = insert (k, v) (graph (m(k := None)))" + unfolding graph_def by (auto split: if_splits) + +lemma graph_fun_upd_None: "graph (m(k := None)) = {e \ graph m. fst e \ k}" + unfolding graph_def by (auto split: if_splits) + +lemma graph_restrictD: + assumes "(k, v) \ graph (m |` A)" + shows "k \ A" and "m k = Some v" + using assms unfolding graph_def + by (auto simp: restrict_map_def split: if_splits) + +lemma graph_map_comp[simp]: "graph (m1 \\<^sub>m m2) = graph m2 O graph m1" + unfolding graph_def by (auto simp: map_comp_Some_iff relcomp_unfold) + +lemma graph_map_add: "dom m1 \ dom m2 = {} \ graph (m1 ++ m2) = graph m1 \ graph m2" + unfolding graph_def using map_add_comm by force + +lemma graph_eq_to_snd_dom: "graph m = (\x. (x, the (m x))) ` dom m" + unfolding graph_def dom_def by force + +lemma fst_graph_eq_dom: "fst ` graph m = dom m" + unfolding graph_eq_to_snd_dom by force + +lemma graph_domD: "x \ graph m \ fst x \ dom m" + using fst_graph_eq_dom by (metis imageI) + +lemma snd_graph_ran: "snd ` graph m = ran m" + unfolding graph_def ran_def by force + +lemma graph_ranD: "x \ graph m \ snd x \ ran m" + using snd_graph_ran by (metis imageI) + +lemma finite_graph_map_of: "finite (graph (map_of al))" + unfolding graph_eq_to_snd_dom finite_dom_map_of + using finite_dom_map_of by blast + +lemma graph_map_of_if_distinct_ran: "distinct (map fst al) \ graph (map_of al) = set al" + unfolding graph_def by auto + +lemma finite_graph_iff_finite_dom[simp]: "finite (graph m) = finite (dom m)" + by (metis graph_eq_to_snd_dom finite_imageI fst_graph_eq_dom) + +lemma inj_on_fst_graph: "inj_on fst (graph m)" + unfolding graph_def inj_on_def by force subsection \\map_le\\ @@ -857,6 +920,23 @@ qed qed -hide_const (open) Map.empty +lemma finite_Map_induct[consumes 1, case_names empty update]: + assumes "finite (dom m)" + assumes "P Map.empty" + assumes "\k v m. finite (dom m) \ k \ dom m \ P m \ P (m(k \ v))" + shows "P m" + using assms(1) +proof(induction "dom m" arbitrary: m rule: finite_induct) + case empty + then show ?case using assms(2) unfolding dom_def by simp +next + case (insert x F) + then have "finite (dom (m(x:=None)))" "x \ dom (m(x:=None))" "P (m(x:=None))" + by (metis Diff_insert_absorb dom_fun_upd)+ + with assms(3)[OF this] show ?case + by (metis fun_upd_triv fun_upd_upd option.exhaust) +qed + +hide_const (open) Map.empty Map.graph end diff -r 26c0ccf17f31 -r 9db620f007fa src/HOL/Relation.thy --- a/src/HOL/Relation.thy Mon May 31 20:27:45 2021 +0000 +++ b/src/HOL/Relation.thy Tue Jun 01 19:46:34 2021 +0200 @@ -1242,9 +1242,12 @@ assumes "finite R" "finite S" shows "R O S = Finite_Set.fold (\(x,y) A. Finite_Set.fold (\(w,z) A'. if y = w then Set.insert (x,z) A' else A') A S) {} R" - using assms - by (induct R) - (auto simp: comp_fun_commute.fold_insert comp_fun_commute_relcomp_fold insert_relcomp_fold - cong: if_cong) +proof - + interpret commute_relcomp_fold: comp_fun_commute + "(\(x, y) A. Finite_Set.fold (\(w, z) A'. if y = w then insert (x, z) A' else A') A S)" + by (fact comp_fun_commute_relcomp_fold[OF \finite S\]) + from assms show ?thesis + by (induct R) (auto simp: comp_fun_commute_relcomp_fold insert_relcomp_fold cong: if_cong) +qed end diff -r 26c0ccf17f31 -r 9db620f007fa src/HOL/Topological_Spaces.thy --- a/src/HOL/Topological_Spaces.thy Mon May 31 20:27:45 2021 +0000 +++ b/src/HOL/Topological_Spaces.thy Tue Jun 01 19:46:34 2021 +0200 @@ -35,7 +35,7 @@ using open_Union [of "B ` A"] by simp lemma open_Inter [continuous_intros, intro]: "finite S \ \T\S. open T \ open (\S)" - by (induct set: finite) auto + by (induction set: finite) auto lemma open_INT [continuous_intros, intro]: "finite A \ \x\A. open (B x) \ open (\x\A. B x)" using open_Inter [of "B ` A"] by simp