lemma finite_induct [case_names empty insert, induct set: finite]:
― ‹Discharging ‹x ∉ F› entails extra work.› assumes"finite F" assumes"P {}" and insert: "∧x F. finite F ==> x ∉ F ==> P F ==> P (insert x F)" shows"P F" using‹finite F› proof induct show"P {}"by fact next fix x F assume F: "finite F"and P: "P F" show"P (insert x F)" proof cases assume"x ∈ F" thenhave"insert x F = F"by (rule insert_absorb) with P show ?thesis by (simp only:) next assume"x ∉ F" from F this P show ?thesis by (rule insert) qed qed
lemma infinite_finite_induct [case_names infinite empty insert]: assumes infinite: "∧A. ¬ finite A ==> P A" and empty: "P {}" and insert: "∧x F. finite F ==> x ∉ F ==> P F ==> P (insert x F)" shows"P A" proof (cases "finite A") case False with infinite show ?thesis . next case True thenshow ?thesis by (induct A) (fact empty insert)+ qed
subsubsection‹Choice principles›
lemma ex_new_if_finite: ― ‹does not depend on def of finite at all› assumes"¬ finite (UNIV :: 'a set)"and"finite A" shows"∃a::'a. a ∉ A" proof - from assms have"A ≠ UNIV"by blast thenshow ?thesis by blast qed
text‹A finite choice principle. Does not need the SOME choice operator.›
lemma finite_set_choice: "finite A ==>∀x∈A. ∃y. P x y ==>∃f. ∀x∈A. P x (f x)" proof (induct rule: finite_induct) case empty thenshow ?caseby simp next case (insert a A) thenobtain f b where f: "∀x∈A. P x (f x)"and ab: "P a b" by auto show ?case (is"∃f. ?P f") proof show"?P (λx. if x = a then b else f x)" using f ab by auto qed qed
subsubsection‹Finite sets are the images of initial segments of natural numbers›
lemma finite_imp_nat_seg_image_inj_on: assumes"finite A" shows"∃(n::nat) f. A = f ` {i. i < n} ∧ inj_on f {i. i < n}" using assms proof induct case empty show ?case proof show"∃f. {} = f ` {i::nat. i < 0} ∧ inj_on f {i. i < 0}" by simp qed next case (insert a A) have notinA: "a ∉ A"by fact from insert.hyps obtain n f where"A = f ` {i::nat. i < n}""inj_on f {i. i < n}" by blast thenhave"insert a A = f(n:=a) ` {i. i < Suc n}"and"inj_on (f(n:=a)) {i. i < Suc n}" using notinA by (auto simp add: image_def Ball_def inj_on_def less_Suc_eq) thenshow ?caseby blast qed
lemma nat_seg_image_imp_finite: "A = f ` {i::nat. i < n} ==> finite A" proof (induct n arbitrary: A) case0 thenshow ?caseby simp next case (Suc n) let ?B = "f ` {i. i < n}" have finB: "finite ?B"by (rule Suc.hyps[OF refl]) show ?case proof (cases "∃k<n. f n = f k") case True thenhave"A = ?B" using Suc.prems by (auto simp:less_Suc_eq) thenshow ?thesis using finB by simp next case False thenhave"A = insert (f n) ?B" using Suc.prems by (auto simp:less_Suc_eq) thenshow ?thesis using finB by simp qed qed
lemma finite_conv_nat_seg_image: "finite A ⟷ (∃n f. A = f ` {i::nat. i < n})" by (blast intro: nat_seg_image_imp_finite dest: finite_imp_nat_seg_image_inj_on)
lemma finite_imp_inj_to_nat_seg: assumes"finite A" shows"∃f n. f ` A = {i::nat. i < n} ∧ inj_on f A" proof - from finite_imp_nat_seg_image_inj_on [OF ‹finite A›] obtain f and n :: nat where bij: "bij_betw f {i. i<n} A" by (auto simp: bij_betw_def) let ?f = "the_inv_into {i. i<n} f" have"inj_on ?f A ∧ ?f ` A = {i. i<n}" by (fold bij_betw_def) (rule bij_betw_the_inv_into[OF bij]) thenshow ?thesis by blast qed
lemma finite_Collect_less_nat [iff]: "finite {n::nat. n < k}" by (fastforce simp: finite_conv_nat_seg_image)
lemma finite_Collect_le_nat [iff]: "finite {n::nat. n ≤ k}" by (simp add: le_eq_less_or_eq Collect_disj_eq)
subsection‹Finiteness and common set operations›
lemma rev_finite_subset: "finite B ==> A ⊆ B ==> finite A" proof (induct arbitrary: A rule: finite_induct) case empty thenshow ?caseby simp next case (insert x F A) have A: "A ⊆ insert x F"and r: "A - {x} ⊆ F ==> finite (A - {x})" by fact+ show"finite A" proof cases assume x: "x ∈ A" with A have"A - {x} ⊆ F"by (simp add: subset_insert_iff) with r have"finite (A - {x})" . thenhave"finite (insert x (A - {x}))" .. alsohave"insert x (A - {x}) = A" using x by (rule insert_Diff) finallyshow ?thesis . next show ?thesis when "A ⊆ F" using that by fact assume"x ∉ A" with A show"A ⊆ F" by (simp add: subset_insert_iff) qed qed
lemma finite_subset: "A ⊆ B ==> finite B ==> finite A" by (rule rev_finite_subset)
simproc_setup finite ("finite A") = ‹
val finite_subset = @{thm finite_subset}
val Eq_TrueI = @{thm Eq_TrueI}
fun is_subset A th = case Thm.prop_of th of
(_ $ 🍋‹less_eq 🍋‹set _› for A' B›)
=> if A aconv A' then SOME(B,th) else NONE
| _ => NONE;
fun is_finite th = case Thm.prop_of th of
(_ $ 🍋‹finite _ for A›) => SOME(A,th)
| _ => NONE;
fun comb (A,sub_th) (A',fin_th) ths = if A aconv A' then (sub_th,fin_th) :: ths else ths
fun proc ctxt ct =
(let
val _ $ A = Thm.term_of ct
val prems = Simplifier.prems_of ctxt
val fins = map_filter is_finite prems
val subsets = map_filter (is_subset A) prems
in case fold_product comb subsets fins [] of
(sub_th,fin_th) :: _ => SOME((fin_th RS (sub_th RS finite_subset)) RS Eq_TrueI)
| _ => NONE
end)
K proc end ›
(* Needs to be used with care *) declare [[simproc del: finite]]
lemma finite_UnI: assumes"finite F"and"finite G" shows"finite (F ∪ G)" using assms by induct simp_all
lemma finite_insert [simp]: "finite (insert a A) ⟷ finite A" proof - have"finite {a} ∧ finite A ⟷ finite A"by simp thenhave"finite ({a} ∪ A) ⟷ finite A"by (simp only: finite_Un) thenshow ?thesis by simp qed
lemma finite_Int [simp, intro]: "finite F ∨ finite G ==> finite (F ∩ G)" by (blast intro: finite_subset)
lemma finite_Collect_conjI [simp, intro]: "finite {x. P x} ∨ finite {x. Q x} ==> finite {x. P x ∧ Q x}" by (simp add: Collect_conj_eq)
lemma finite_Collect_disjI [simp]: "finite {x. P x ∨ Q x} ⟷ finite {x. P x} ∧ finite {x. Q x}" by (simp add: Collect_disj_eq)
lemma finite_Diff [simp, intro]: "finite A ==> finite (A - B)" by (rule finite_subset, rule Diff_subset)
lemma finite_Diff2 [simp]: assumes"finite B" shows"finite (A - B) ⟷ finite A" proof - have"finite A ⟷ finite ((A - B) ∪ (A ∩ B))" by (simp add: Un_Diff_Int) alsohave"…⟷ finite (A - B)" using‹finite B›by simp finallyshow ?thesis .. qed
lemma finite_Diff_insert [iff]: "finite (A - insert a B) ⟷ finite (A - B)" proof - have"finite (A - B) ⟷ finite (A - B - {a})"by simp moreoverhave"A - insert a B = A - B - {a}"by auto ultimatelyshow ?thesis by simp qed
lemma finite_compl [simp]: "finite (A :: 'a set) ==> finite (- A) ⟷ finite (UNIV :: 'a set)" by (simp add: Compl_eq_Diff_UNIV)
lemma finite_Collect_not [simp]: "finite {x :: 'a. P x} ==> finite {x. ¬ P x} ⟷ finite (UNIV :: 'a set)" by (simp add: Collect_neg_eq)
lemma finite_Union [simp, intro]: "finite A ==> (∧M. M ∈ A ==> finite M) ==> finite (∪A)" by (induct rule: finite_induct) simp_all
lemma finite_UN_I [intro]: "finite A ==> (∧a. a ∈ A ==> finite (B a)) ==> finite (∪a∈A. B a)" by (induct rule: finite_induct) simp_all
lemma finite_UN [simp]: "finite A ==> finite (∪(B ` A)) ⟷ (∀x∈A. finite (B x))" by (blast intro: finite_subset)
lemma finite_Inter [intro]: "∃A∈M. finite A ==> finite (∩M)" by (blast intro: Inter_lower finite_subset)
lemma finite_INT [intro]: "∃x∈I. finite (A x) ==> finite (∩x∈I. A x)" by (blast intro: INT_lower finite_subset)
lemma finite_imageI [simp, intro]: "finite F ==> finite (h ` F)" by (induct rule: finite_induct) simp_all
lemma finite_image_set [simp]: "finite {x. P x} ==> finite {f x |x. P x}" by (simp add: image_Collect [symmetric])
lemma finite_image_set2: "finite {x. P x} ==> finite {y. Q y} ==> finite {f x y |x y. P x ∧ Q y}" by (rule finite_subset [where B = "∪x ∈ {x. P x}. ∪y ∈ {y. Q y}. {f x y}"]) auto
lemma finite_imageD: assumes"finite (f ` A)"and"inj_on f A" shows"finite A" using assms proof (induct "f ` A" arbitrary: A) case empty thenshow ?caseby simp next case (insert x B) thenhave B_A: "insert x B = f ` A" by simp thenobtain y where"x = f y"and"y ∈ A" by blast from B_A ‹x ∉ B›have"B = f ` A - {x}" by blast with B_A ‹x ∉ B›‹x = f y›‹inj_on f A›‹y ∈ A›have"B = f ` (A - {y})" by (simp add: inj_on_image_set_diff) moreoverfrom‹inj_on f A›have"inj_on f (A - {y})" by (rule inj_on_diff) ultimatelyhave"finite (A - {y})" by (rule insert.hyps) thenshow"finite A" by simp qed
lemma finite_image_iff: "inj_on f A ==> finite (f ` A) ⟷ finite A" using finite_imageD by blast
lemma finite_surj: "finite A ==> B ⊆ f ` A ==> finite B" by (erule finite_subset) (rule finite_imageI)
lemma finite_range_imageI: "finite (range g) ==> finite (range (λx. f (g x)))" by (drule finite_imageI) (simp add: range_composition)
lemma finite_subset_image: assumes"finite B" shows"B ⊆ f ` A ==>∃C⊆A. finite C ∧ B = f ` C" using assms proof induct case empty thenshow ?caseby simp next case insert thenshow ?case by (clarsimp simp del: image_insert simp add: image_insert [symmetric]) blast qed
lemma all_subset_image: "(∀B. B ⊆ f ` A ⟶ P B) ⟷ (∀B. B ⊆ A ⟶ P(f ` B))" by (safe elim!: subset_imageE) (use image_mono in‹blast+›) (* slow *)
lemma all_finite_subset_image: "(∀B. finite B ∧ B ⊆ f ` A ⟶ P B) ⟷ (∀B. finite B ∧ B ⊆ A ⟶ P (f ` B))" proof safe fix B :: "'a set" assume B: "finite B""B ⊆ f ` A"and P: "∀B. finite B ∧ B ⊆ A ⟶ P (f ` B)" show"P B" using finite_subset_image [OF B] P by blast qed blast
lemma ex_finite_subset_image: "(∃B. finite B ∧ B ⊆ f ` A ∧ P B) ⟷ (∃B. finite B ∧ B ⊆ A ∧ P (f ` B))" proof safe fix B :: "'a set" assume B: "finite B""B ⊆ f ` A"and"P B" show"∃B. finite B ∧ B ⊆ A ∧ P (f ` B)" using finite_subset_image [OF B] ‹P B›by blast qed blast
lemma finite_vimage_IntI: "finite F ==> inj_on h A ==> finite (h -` F ∩ A)" proof (induct rule: finite_induct) case (insert x F) thenshow ?case by (simp add: vimage_insert [of h x F] finite_subset [OF inj_on_vimage_singleton] Int_Un_distrib2) qed simp
lemma finite_finite_vimage_IntI: assumes"finite F" and"∧y. y ∈ F ==> finite ((h -` {y}) ∩ A)" shows"finite (h -` F ∩ A)" proof - have *: "h -` F ∩ A = (∪ y∈F. (h -` {y}) ∩ A)" by blast show ?thesis by (simp only: * assms finite_UN_I) qed
lemma finite_vimageI: "finite F ==> inj h ==> finite (h -` F)" using finite_vimage_IntI[of F h UNIV] by auto
lemma finite_vimageD': "finite (f -` A) ==> A ⊆ range f ==> finite A" by (auto simp add: subset_image_iff intro: finite_subset[rotated])
lemma finite_vimageD: "finite (h -` F) ==> surj h ==> finite F" by (auto dest: finite_vimageD')
lemma finite_vimage_iff: "bij h ==> finite (h -` F) ⟷ finite F" unfolding bij_def by (auto elim: finite_vimageD finite_vimageI)
lemma finite_inverse_image_gen: assumes"finite A""inj_on f D" shows"finite {j∈D. f j ∈ A}" using finite_vimage_IntI [OF assms] by (simp add: Collect_conj_eq inf_commute vimage_def)
lemma finite_inverse_image: assumes"finite A""inj f" shows"finite {j. f j ∈ A}" using finite_inverse_image_gen [OF assms] by simp
lemma finite_Collect_bex [simp]: assumes"finite A" shows"finite {x. ∃y∈A. Q x y} ⟷ (∀y∈A. finite {x. Q x y})" proof - have"{x. ∃y∈A. Q x y} = (∪y∈A. {x. Q x y})"by auto with assms show ?thesis by simp qed
lemma finite_Collect_bounded_ex [simp]: assumes"finite {y. P y}" shows"finite {x. ∃y. P y ∧ Q x y} ⟷ (∀y. P y ⟶ finite {x. Q x y})" proof - have"{x. ∃y. P y ∧ Q x y} = (∪y∈{y. P y}. {x. Q x y})" by auto with assms show ?thesis by simp qed
lemma finite_Plus: "finite A ==> finite B ==> finite (A <+> B)" by (simp add: Plus_def)
lemma finite_PlusD: fixes A :: "'a set"and B :: "'b set" assumes fin: "finite (A <+> B)" shows"finite A""finite B" proof - have"Inl ` A ⊆ A <+> B" by auto thenhave"finite (Inl ` A :: ('a + 'b) set)" using fin by (rule finite_subset) thenshow"finite A" by (rule finite_imageD) (auto intro: inj_onI) next have"Inr ` B ⊆ A <+> B" by auto thenhave"finite (Inr ` B :: ('a + 'b) set)" using fin by (rule finite_subset) thenshow"finite B" by (rule finite_imageD) (auto intro: inj_onI) qed
lemma finite_Plus_iff [simp]: "finite (A <+> B) ⟷ finite A ∧ finite B" by (auto intro: finite_PlusD finite_Plus)
lemma finite_SigmaI [simp, intro]: "finite A ==> (∧a. a∈A ==> finite (B a)) ==> finite (SIGMA a:A. B a)" unfolding Sigma_def by blast
lemma finite_SigmaI2: assumes"finite {x∈A. B x ≠ {}}" and"∧a. a ∈ A ==> finite (B a)" shows"finite (Sigma A B)" proof - from assms have"finite (Sigma {x∈A. B x ≠ {}} B)" by auto alsohave"Sigma {x:A. B x ≠ {}} B = Sigma A B" by auto finallyshow ?thesis . qed
lemma finite_cartesian_product: "finite A ==> finite B ==> finite (A × B)" by (rule finite_SigmaI)
lemma finite_cartesian_productD1: assumes"finite (A × B)"and"B ≠ {}" shows"finite A" proof - from assms obtain n f where"A × B = f ` {i::nat. i < n}" by (auto simp add: finite_conv_nat_seg_image) thenhave"fst ` (A × B) = fst ` f ` {i::nat. i < n}" by simp with‹B ≠ {}›have"A = (fst ∘ f) ` {i::nat. i < n}" by (simp add: image_comp) thenhave"∃n f. A = f ` {i::nat. i < n}" by blast thenshow ?thesis by (auto simp add: finite_conv_nat_seg_image) qed
lemma finite_cartesian_productD2: assumes"finite (A × B)"and"A ≠ {}" shows"finite B" proof - from assms obtain n f where"A × B = f ` {i::nat. i < n}" by (auto simp add: finite_conv_nat_seg_image) thenhave"snd ` (A × B) = snd ` f ` {i::nat. i < n}" by simp with‹A ≠ {}›have"B = (snd ∘ f) ` {i::nat. i < n}" by (simp add: image_comp) thenhave"∃n f. B = f ` {i::nat. i < n}" by blast thenshow ?thesis by (auto simp add: finite_conv_nat_seg_image) qed
lemma finite_cartesian_product_iff: "finite (A × B) ⟷ (A = {} ∨ B = {} ∨ (finite A ∧ finite B))" by (auto dest: finite_cartesian_productD1 finite_cartesian_productD2 finite_cartesian_product)
lemma finite_prod: "finite (UNIV :: ('a × 'b) set) ⟷ finite (UNIV :: 'a set) ∧ finite (UNIV :: 'b set)" using finite_cartesian_product_iff[of UNIV UNIV] by simp
lemma finite_Pow_iff [iff]: "finite (Pow A) ⟷ finite A" proof assume"finite (Pow A)" thenhave"finite ((λx. {x}) ` A)" by (blast intro: finite_subset) (* somewhat slow *) thenshow"finite A" by (rule finite_imageD [unfolded inj_on_def]) simp next assume"finite A" thenshow"finite (Pow A)" by induct (simp_all add: Pow_insert) qed
corollary finite_Collect_subsets [simp, intro]: "finite A ==> finite {B. B ⊆ A}" by (simp add: Pow_def [symmetric])
lemma finite_set: "finite (UNIV :: 'a set set) ⟷ finite (UNIV :: 'a set)" by (simp only: finite_Pow_iff Pow_UNIV[symmetric])
lemma finite_bind: assumes"finite S" assumes"∀x ∈ S. finite (f x)" shows"finite (Set.bind S f)" using assms by (simp add: bind_UNION)
lemma finite_filter [simp]: "finite S ==> finite (Set.filter P S)" by (simp add:)
lemma finite_set_of_finite_funs: assumes"finite A""finite B" shows"finite {f. ∀x. (x ∈ A ⟶ f x ∈ B) ∧ (x ∉ A ⟶ f x = d)}" (is"finite ?S") proof - let ?F = "λf. {(a,b). a ∈ A ∧ b = f a}" have"?F ` ?S ⊆ Pow(A × B)" by auto from finite_subset[OF this] assms have1: "finite (?F ` ?S)" by simp have2: "inj_on ?F ?S" by (fastforce simp add: inj_on_def set_eq_iff fun_eq_iff) (* somewhat slow *) show ?thesis by (rule finite_imageD [OF 12]) qed
lemma not_finite_existsD: assumes"¬ finite {a. P a}" shows"∃a. P a" proof (rule classical) assume"¬ ?thesis" with assms show ?thesis by auto qed
lemma finite_Domain: "finite r ==> finite (Domain r)" by (induct set: finite) auto
lemma finite_Range: "finite r ==> finite (Range r)" by (induct set: finite) auto
lemma finite_Field: "finite r ==> finite (Field r)" by (simp add: Field_def finite_Domain finite_Range)
lemma finite_Image[simp]: "finite R ==> finite (R `` A)" by(rule finite_subset[OF _ finite_Range]) auto
subsection‹Further induction rules on finite sets›
lemma finite_ne_induct [case_names singleton insert, consumes 2]: assumes"finite F"and"F ≠ {}" assumes"∧x. P {x}" and"∧x F. finite F ==> F ≠ {} ==> x ∉ F ==> P F ==> P (insert x F)" shows"P F" using assms proof induct case empty thenshow ?caseby simp next case (insert x F) thenshow ?caseby cases auto qed
lemma finite_subset_induct [consumes 2, case_names empty insert]: assumes"finite F"and"F ⊆ A" and empty: "P {}" and insert: "∧a F. finite F ==> a ∈ A ==> a ∉ F ==> P F ==> P (insert a F)" shows"P F" using‹finite F›‹F ⊆ A› proof induct show"P {}"by fact next fix x F assume"finite F"and"x ∉ F"and P: "F ⊆ A ==> P F"and i: "insert x F ⊆ A" show"P (insert x F)" proof (rule insert) from i show"x ∈ A"by blast from i have"F ⊆ A"by blast with P show"P F" . show"finite F"by fact show"x ∉ F"by fact qed qed
lemma finite_empty_induct: assumes"finite A" and"P A" and remove: "∧a A. finite A ==> a ∈ A ==> P A ==> P (A - {a})" shows"P {}" proof - have"P (A - B)"if"B ⊆ A"for B :: "'a set" proof - from‹finite A› that have"finite B" by (rule rev_finite_subset) from this ‹B ⊆ A›show"P (A - B)" proof induct case empty from‹P A›show ?caseby simp next case (insert b B) have"P (A - B - {b})" proof (rule remove) from‹finite A›show"finite (A - B)" by induct auto from insert show"b ∈ A - B" by simp from insert show"P (A - B)" by simp qed alsohave"A - B - {b} = A - insert b B" by (rule Diff_insert [symmetric]) finallyshow ?case . qed qed thenhave"P (A - A)"by blast thenshow ?thesis by simp qed
lemma finite_update_induct [consumes 1, case_names const update]: assumes finite: "finite {a. f a ≠ c}" and const: "P (λa. c)" and update: "∧a b f. finite {a. f a ≠ c} ==> f a = c ==> b ≠ c ==> P f ==> P (f(a := b))" shows"P f" using finite proof (induct "{a. f a ≠ c}" arbitrary: f) case empty with const show ?caseby simp next case (insert a A) thenhave"A = {a'. (f(a := c)) a' ≠ c}"and"f a ≠ c" by auto with‹finite A›have"finite {a'. (f(a := c)) a' ≠ c}" by simp have"(f(a := c)) a = c" by simp from insert ‹A = {a'. (f(a := c)) a' ≠ c}›have"P (f(a := c))" by simp with‹finite {a'. (f(a := c)) a' ≠ c}›‹(f(a := c)) a = c›‹f a ≠ c› have"P ((f(a := c))(a := f a))" by (rule update) thenshow ?caseby simp qed
lemma finite_subset_induct' [consumes 2, case_names empty insert]: assumes"finite F"and"F ⊆ A" and empty: "P {}" and insert: "∧a F. [finite F; a ∈ A; F ⊆ A; a ∉ F; P F ]==> P (insert a F)" shows"P F" using assms(1,2) proof induct show"P {}"by fact next fix x F assume"finite F"and"x ∉ F"and
P: "F ⊆ A ==> P F"and i: "insert x F ⊆ A" show"P (insert x F)" proof (rule insert) from i show"x ∈ A"by blast from i have"F ⊆ A"by blast with P show"P F" . show"finite F"by fact show"x ∉ F"by fact show"F ⊆ A"by fact qed qed
subsection‹Class ‹finite››
class finite = assumes finite_UNIV: "finite (UNIV :: 'a set)" begin
lemma finite [simp]: "finite (A :: 'a set)" by (rule subset_UNIV finite_UNIV finite_subset)+
lemma finite_code [code]: "finite (A :: 'a set) ⟷ True" by simp
end
instance prod :: (finite, finite) finite by standard (simp only: UNIV_Times_UNIV [symmetric] finite_cartesian_product finite)
lemma inj_graph: "inj (λf. {(x, y). y = f x})" by (rule inj_onI) (auto simp add: set_eq_iff fun_eq_iff)
instance"fun" :: (finite, finite) finite proof show"finite (UNIV :: ('a ==> 'b) set)" proof (rule finite_imageD) let ?graph = "λf::'a ==> 'b. {(x, y). y = f x}" have"range ?graph ⊆ Pow UNIV" by simp moreoverhave"finite (Pow (UNIV :: ('a * 'b) set))" by (simp only: finite_Pow_iff finite) ultimatelyshow"finite (range ?graph)" by (rule finite_subset) show"inj ?graph" by (rule inj_graph) qed qed
instance bool :: finite by standard (simp add: UNIV_bool)
instance set :: (finite) finite by standard (simp only: Pow_UNIV [symmetric] finite_Pow_iff finite)
instance unit :: finite by standard (simp add: UNIV_unit)
instance sum :: (finite, finite) finite by standard (simp only: UNIV_Plus_UNIV [symmetric] finite_Plus finite)
subsection‹A basic fold functional for finite sets›
text‹
The intended behaviour is ‹fold f z {x1, …, xn} = f x1 (… (f xn z)…)›
if ‹f› is ``left-commutative''.
The commutativity requirement is relativised to the carrier set ‹S›: ›
locale comp_fun_commute_on = fixes S :: "'a set" fixes f :: "'a ==> 'b ==> 'b" assumes comp_fun_commute_on: "x ∈ S ==> y ∈ S ==> f y ∘ f x = f x ∘ f y" begin
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: "x ∈ S ==> y ∈ S ==> f y ∘ (f x ∘ g) = f x ∘ (f y ∘ g)" by (simp add: o_assoc comp_fun_commute_on)
end
inductive fold_graph :: "('a ==> 'b ==> 'b) ==> 'b ==> 'a set ==> 'b ==> bool" for f :: "'a ==> 'b ==> 'b"and z :: 'b where
emptyI [intro]: "fold_graph f z {} z"
| insertI [intro]: "x ∉ A ==> fold_graph f z A y ==> fold_graph f z (insert x A) (f x y)"
inductive_cases empty_fold_graphE [elim!]: "fold_graph f z {} x"
lemma fold_graph_closed_lemma: "fold_graph f z A x ∧ x ∈ B" if"fold_graph g z A x" "∧a b. a ∈ A ==> b ∈ B ==> f a b = g a b" "∧a b. a ∈ A ==> b ∈ B ==> g a b ∈ B" "z ∈ B" using that(1-3) proof (induction rule: fold_graph.induct) case (insertI x A y) have"fold_graph f z A y""y ∈ B" unfolding atomize_conj by (rule insertI.IH) (auto intro: insertI.prems) thenhave"g x y ∈ B"and f_eq: "f x y = g x y" by (auto simp: insertI.prems) moreoverhave"fold_graph f z (insert x A) (f x y)" by (rule fold_graph.insertI; fact) ultimately show ?case by (simp add: f_eq) qed (auto intro!: that)
lemma fold_graph_closed_eq: "fold_graph f z A = fold_graph g z A" if"∧a b. a ∈ A ==> b ∈ B ==> f a b = g a b" "∧a b. a ∈ A ==> b ∈ B ==> g a b ∈ B" "z ∈ B" using fold_graph_closed_lemma[of f z A _ B g] fold_graph_closed_lemma[of g z A _ B f] that by auto
definition fold :: "('a ==> 'b ==> 'b) ==> 'b ==> 'a set ==> 'b" where"fold f z A = (if finite A then (THE y. fold_graph f z A y) else z)"
lemma fold_closed_eq: "fold f z A = fold g z A" if"∧a b. a ∈ A ==> b ∈ B ==> f a b = g a b" "∧a b. a ∈ A ==> b ∈ B ==> g a b ∈ B" "z ∈ B" unfolding Finite_Set.fold_def by (subst fold_graph_closed_eq[where B=B and g=g]) (auto simp: that)
text‹
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›.
The proofs become ugly. It is not worth the effort. (???) ›
lemma finite_imp_fold_graph: "finite A ==>∃x. fold_graph f z A x" by (induct rule: finite_induct) auto
subsubsection‹From const‹fold_graph› to term‹fold››
context comp_fun_commute_on begin
lemma fold_graph_finite: assumes"fold_graph f z A y" shows"finite A" using assms by induct simp_all
lemma fold_graph_insertE_aux: 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 thenshow ?caseby simp next case (insertI x A y) show ?case proof (cases "x = a") case True with insertI show ?thesis by auto next case False thenobtain y' where y: "y = f a y'"and y': "fold_graph f z (A - {a}) y'" using insertI by auto from insertI have"x ∈ S""a ∈ S"by auto thenhave"f x y = f a (f x y')" unfolding y by (intro fun_left_comm; simp) moreoverhave"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) ultimatelyshow ?thesis by fast qed 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 ‹insert x A ⊆ S› _ insertI1])
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 thenshow ?caseby fast next case (insertI x A y v) 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'› insertI have"y' = y" by simp with‹v = f x y'›show"v = f x y" by simp qed
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‹finite A›have"∃x. fold_graph f z A x" by (rule finite_imp_fold_graph) moreovernote fold_graph_determ[OF ‹A ⊆ S›] ultimatelyhave"∃!x. fold_graph f z A x" by (rule ex_ex1I) thenhave"fold_graph f z A (The (fold_graph f z A))" by (rule theI') with assms show ?thesis by (simp add: fold_def) qed
text‹The base case for ‹fold›:›
lemma (in -) fold_infinite [simp]: "¬ finite A ==> fold f z A = z" by (auto simp: fold_def)
lemma (in -) fold_empty [simp]: "fold f z {} = z" by (auto simp: fold_def)
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[OF ‹insert x A ⊆ S›]) fix z 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) thenshow"fold_graph f z (insert x A) (f x (fold f z A))" by simp qed
declare (in -) empty_fold_graphE [rule del] fold_graph.intros [rule del]
― ‹No more proofs involve these.›
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 thenshow ?caseby simp next case (insert y F) thenhave"fold f (f x z) (insert y F) = f y (fold f (f x z) F)" by simp alsohave"… = f x (f y (fold f z F))" using insert by (simp add: fun_left_comm[where ?y=x]) alsohave"… = 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 finallyshow ?case .. qed
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 - have A: "A = insert x (A - {x})" using‹x ∈ A›by blast thenhave"fold f z A = fold f z (insert x (A - {x}))" by simp alsohave"… = f x (fold f z (A - {x}))" by (rule fold_insert) (use assms in‹auto›) finallyshow ?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 - from‹finite A›have"finite (insert x A)" by auto moreoverhave"x ∈ insert x A" by auto ultimatelyhave"fold f z (insert x A) = f x (fold f z (insert x A - {x}))" using‹insert x A ⊆ S›by (blast intro: fold_rec) thenshow ?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‹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 alsohave"… = fold f (fold f z A) (insert x F)" using insert by (blast intro: fold_insert[symmetric]) finallyshow ?case . qed simp
end
text‹Other properties of const‹fold›:›
lemma finite_set_fold_single [simp]: "Finite_Set.fold f z {x} = f x z" proof - have"fold_graph f z {x} (f x z)" by (auto intro: fold_graph.intros) moreover
{ fix X y have"fold_graph f z X y ==> (X = {} ⟶ y = z) ∧ (X = {x} ⟶ y = f x z)" by (induct rule: fold_graph.induct) auto
} ultimatelyhave"(THE y. fold_graph f z {x} y) = f x z" by blast thus ?thesis by (simp add: Finite_Set.fold_def) qed
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" thenshow"fold_graph (f ∘ g) z A w" using assms proof (induct "g ` A" w arbitrary: A) case emptyI thenshow ?caseby (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) thenshow ?case by simp qed next assume"fold_graph (f ∘ g) z A w" thenshow"fold_graph f z (g ` A) w" using assms proof induct case emptyI thenshow ?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 moreoverfrom insertI have"fold_graph f z (g ` A) r" by simp ultimatelyhave"fold_graph f z (insert (g x) (g ` A)) (f (g x) r)" by (rule fold_graph.insertI) thenshow ?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" proof (cases "finite A") case False with assms show ?thesis by (auto dest: finite_imageD simp add: fold_def) next case True thenshow ?thesis by (auto simp add: fold_def fold_graph_image[OF assms]) qed
lemma fold_cong: 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›‹A ⊆ S› cong proof (induct A) case empty thenshow ?caseby simp next case insert 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 ?caseby simp qed with assms show ?thesis by simp qed
text‹A simplified version for idempotent functions:›
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: "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 assume"x ∈ A" thenobtain B where"A = insert x B"and"x ∉ B" by (rule set_insert) thenshow ?thesis using assms by (simp add: comp_fun_idem_on fun_left_idem) next assume"x ∉ A" thenshow ?thesis using assms by auto qed
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_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_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_on) comp_fun_commute_on_funpow: "comp_fun_commute_on S (λx. f x ^^ g x)" proof 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 thenshow ?thesis by simp next case False show ?thesis proof (induct "g x" arbitrary: g) case0 thenshow ?caseby simp next case (Suc n g) have hyp1: "f y ^^ g y ∘ f x = f x ∘ f y ^^ g y" proof (induct "g y" arbitrary: g) case0 thenshow ?caseby simp next case (Suc n g)
define h where"h z = g z - 1"for z with Suc have"n = h y" by simp with Suc have hyp: "f y ^^ h y ∘ f x = f x ∘ f y ^^ h y" by auto from Suc h_def have"g y = Suc (h y)" by simp 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" by simp with Suc have"f y ^^ h y ∘ f x ^^ h x = f x ^^ h x ∘ f y ^^ h y" by auto with False h_def have hyp2: "f y ^^ g y ∘ f x ^^ h x = f x ^^ h x ∘ f y ^^ g y" by simp from Suc h_def have"g x = Suc (h x)" by simp thenshow ?case by (simp del: funpow.simps add: funpow_Suc_right o_assoc hyp2) (simp add: comp_assoc hyp1) qed qed 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)" by standard (rule refl)
lemma comp_fun_idem_insert: "comp_fun_idem insert" by standard auto
lemma comp_fun_idem_remove: "comp_fun_idem Set.remove" by standard auto
lemma (in semilattice_inf) comp_fun_idem_inf: "comp_fun_idem inf" by standard (auto simp add: inf_left_commute)
lemma (in semilattice_sup) comp_fun_idem_sup: "comp_fun_idem sup" by standard (auto simp add: sup_left_commute)
lemma union_fold_insert: assumes"finite A" shows"A ∪ B = fold insert B A" proof - interpret comp_fun_idem insert by (fact comp_fun_idem_insert) from‹finite A›show ?thesis by (induct A arbitrary: B) simp_all qed
lemma minus_fold_remove: assumes"finite A" shows"B - A = fold Set.remove B A" proof - interpret comp_fun_idem Set.remove by (fact comp_fun_idem_remove) from‹finite A›have"fold Set.remove B A = B - A" by (induct A arbitrary: B) auto (* slow *) thenshow ?thesis .. qed
lemma comp_fun_commute_filter_fold: "comp_fun_commute (λx A'. if P x then Set.insert x A' else A')" proof - interpret comp_fun_idem Set.insert by (fact comp_fun_idem_insert) show ?thesis by standard (auto simp: fun_eq_iff) qed
lemma Set_filter_fold: assumes"finite A" shows"Set.filter P A = fold (λx A'. if P x then Set.insert x A' else A') {} A" using assms 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_eq_iff) qed
lemma inter_Set_filter: assumes"finite B" shows"A ∩ B = Set.filter (λx. x ∈ A) B" using assms by (simp add: set_eq_iff ac_simps)
lemma image_fold_insert: assumes"finite A" shows"image f A = fold (λk A. Set.insert (f k) A) {} A" proof - interpret comp_fun_commute "λk A. Set.insert (f k) A" by standard auto show ?thesis using assms by (induct A) auto qed
lemma Ball_fold: assumes"finite A" shows"Ball A P = fold (λk s. s ∧ P k) True A" proof - interpret comp_fun_commute "λk s. s ∧ P k" by standard auto show ?thesis using assms by (induct A) auto qed
lemma Bex_fold: assumes"finite A" shows"Bex A P = fold (λk s. s ∨ P k) False A" proof - interpret comp_fun_commute "λk s. s ∨ P k" by standard auto show ?thesis using assms by (induct A) auto 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
lemma Pow_fold: assumes"finite A" shows"Pow A = fold (λx A. A ∪ Set.insert x ` A) {{}} A" proof - interpret comp_fun_commute "λx A. A ∪ Set.insert x ` A" by (rule comp_fun_commute_Pow_fold) show ?thesis using assms by (induct A) (auto simp: Pow_insert) qed
lemma fold_union_pair: assumes"finite B" shows"(∪y∈B. {(x, y)}) ∪ A = fold (λy. Set.insert (x, y)) A B" proof - interpret comp_fun_commute "λy. Set.insert (x, y)" by standard auto show ?thesis using assms by (induct arbitrary: A) simp_all qed
lemma comp_fun_commute_product_fold: "finite B ==> comp_fun_commute (λx z. fold (λy. Set.insert (x, y)) z B)" by standard (auto simp: fold_union_pair [symmetric])
lemma product_fold: assumes"finite A""finite B" shows"A × B = fold (λx z. fold (λy. Set.insert (x, y)) z B) {} A" 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
lemma inf_Inf_fold_inf: assumes"finite A" shows"inf (Inf A) B = fold inf B A" proof - interpret comp_fun_idem inf by (fact comp_fun_idem_inf) from‹finite A› fold_fun_left_comm show ?thesis by (induct A arbitrary: B) (simp_all add: inf_commute fun_eq_iff) qed
lemma sup_Sup_fold_sup: assumes"finite A" shows"sup (Sup A) B = fold sup B A" proof - interpret comp_fun_idem sup by (fact comp_fun_idem_sup) from‹finite A› fold_fun_left_comm show ?thesis by (induct A arbitrary: B) (simp_all add: sup_commute fun_eq_iff) qed
lemma Inf_fold_inf: "finite A ==> Inf A = fold inf top A" using inf_Inf_fold_inf [of A top] by (simp add: inf_absorb2)
lemma Sup_fold_sup: "finite A ==> Sup A = fold sup bot A" using sup_Sup_fold_sup [of A bot] by (simp add: sup_absorb2)
lemma inf_INF_fold_inf: assumes"finite A" shows"inf B (⊓(f ` A)) = fold (inf ∘ f) B A" (is"?inf = ?fold") proof - interpret comp_fun_idem inf by (fact comp_fun_idem_inf) interpret comp_fun_idem "inf ∘ f"by (fact comp_comp_fun_idem) from‹finite A›have"?fold = ?inf" by (induct A arbitrary: B) (simp_all add: inf_left_commute) thenshow ?thesis .. qed
lemma sup_SUP_fold_sup: assumes"finite A" shows"sup B (⊔(f ` A)) = fold (sup ∘ f) B A" (is"?sup = ?fold") proof - interpret comp_fun_idem sup by (fact comp_fun_idem_sup) interpret comp_fun_idem "sup ∘ f"by (fact comp_comp_fun_idem) from‹finite A›have"?fold = ?sup" by (induct A arbitrary: B) (simp_all add: sup_left_commute) thenshow ?thesis .. qed
lemma INF_fold_inf: "finite A ==>⊓(f ` A) = fold (inf ∘ f) top A" using inf_INF_fold_inf [of A top] by simp
lemma SUP_fold_sup: "finite A ==>⊔(f ` A) = fold (sup ∘ f) bot A" using sup_SUP_fold_sup [of A bot] by simp
lemma finite_Inf_in: assumes"finite A""A≠{}"and inf: "∧x y. [x ∈ A; y ∈ A]==> inf x y ∈ A" shows"Inf A ∈ A" proof - have"Inf B ∈ A"if"B ≤ A""B≠{}"for B using finite_subset [OF ‹B ⊆ A›‹finite A›] that by (induction B) (use inf in‹force+›) thenshow ?thesis by (simp add: assms) qed
lemma finite_Sup_in: assumes"finite A""A≠{}"and sup: "∧x y. [x ∈ A; y ∈ A]==> sup x y ∈ A" shows"Sup A ∈ A" proof - have"Sup B ∈ A"if"B ≤ A""B≠{}"for B using finite_subset [OF ‹B ⊆ A›‹finite A›] that by (induction B) (use sup in‹force+›) thenshow ?thesis by (simp add: assms) qed
end
subsubsection‹Expressing relation operations via const‹fold››
lemma Id_on_fold: assumes"finite A" shows"Id_on A = Finite_Set.fold (λx. Set.insert (Pair x x)) {} A" proof - interpret comp_fun_commute "λx. Set.insert (Pair x x)" by standard auto from assms show ?thesis unfolding Id_on_def by (induct A) simp_all qed
lemma comp_fun_commute_Image_fold: "comp_fun_commute (λ(x,y) A. if x ∈ S then Set.insert y A else A)" proof - interpret comp_fun_idem Set.insert by (fact comp_fun_idem_insert) show ?thesis by standard (auto simp: fun_eq_iff comp_fun_commute split: prod.split) qed
lemma Image_fold: assumes"finite R" shows"R `` S = Finite_Set.fold (λ(x,y) A. if x ∈ S then Set.insert y A else A) {} R" proof - interpret comp_fun_commute "(λ(x,y) A. if x ∈ S then Set.insert y A else A)" by (rule comp_fun_commute_Image_fold) have *: "∧x F. Set.insert x F `` S = (if fst x ∈ S then Set.insert (snd x) (F `` S) else (F `` S))" by (force intro: rev_ImageI) show ?thesis using assms by (induct R) (auto simp: * ) qed
lemma insert_relcomp_union_fold: assumes"finite S" shows"{x} O S ∪ X = Finite_Set.fold (λ(w,z) A'. if snd x = w then Set.insert (fst x,z) A' else A') X S" proof - interpret comp_fun_commute "λ(w,z) A'. if snd x = w then Set.insert (fst x,z) A' else A'" proof - interpret comp_fun_idem Set.insert by (fact comp_fun_idem_insert) show"comp_fun_commute (λ(w,z) A'. if snd x = w then Set.insert (fst x,z) A' else A')" by standard (auto simp add: fun_eq_iff split: prod.split) qed have *: "{x} O S = {(x', z). x' = fst x ∧ (snd x, z) ∈ S}" by (auto simp: relcomp_unfold intro!: exI) show ?thesis unfolding * using‹finite S›by (induct S) (auto split: prod.split) qed
lemma insert_relcomp_fold: assumes"finite S" shows"Set.insert x R O S = Finite_Set.fold (λ(w,z) A'. if snd x = w then Set.insert (fst x,z) A' else A') (R O S) S" proof - have"Set.insert x R O S = ({x} O S) ∪ (R O S)" by auto thenshow ?thesis by (auto simp: insert_relcomp_union_fold [OF assms]) qed
lemma comp_fun_commute_relcomp_fold: assumes"finite S" shows"comp_fun_commute (λ(x,y) A. Finite_Set.fold (λ(w,z) A'. if y = w then Set.insert (x,z) A' else A') A S)" proof - have *: "∧a b A. Finite_Set.fold (λ(w, z) A'. if b = w then Set.insert (a, z) A' else A') A S = {(a,b)} O S ∪ A" by (auto simp: insert_relcomp_union_fold[OF assms] cong: if_cong) show ?thesis by standard (auto simp: * ) qed
lemma relcomp_fold: 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" 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
subsection‹Locales as mini-packages for fold operations›
subsubsection‹The natural case›
locale folding_on = fixes S :: "'a set" fixes f :: "'a ==> 'b ==> 'b"and z :: "'b" 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_on S f by standard (simp add: comp_fun_commute_on)
definition F :: "'a set ==> 'b" where eq_fold: "F A = Finite_Set.fold f z A"
lemma infinite [simp]: "¬ finite A ==> F A = z" by (simp add: eq_fold)
lemma insert [simp]: 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"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"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) moreoverfrom‹finite A› A have"finite B"by simp ultimatelyshow ?thesis using‹A ⊆ S›by auto qed
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_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_on S f by standard (simp_all add: comp_fun_commute_on comp_fun_idem_on)
lemma insert_idem [simp]: assumes"insert x A ⊆ S"and"finite A" shows"F (insert x A) = f x (F A)" proof - from fold_insert_idem assms have"fold f z (insert x A) = f x (fold f z A)"by simp with‹finite A›show ?thesis by (simp add: eq_fold fun_eq_iff) qed
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›
text‹
The traditional definition prop‹card A ≡ LEAST n. ∃f. A = {f i |i. i < n}›
is ugly to work with.
But now that we have const‹fold› things are easy: ›
global_interpretation card: folding "λ_. Suc"0 defines card = "folding_on.F (λ_. Suc) 0" by standard (rule refl)
lemma card_insert_disjoint: "finite A ==> x ∉ A ==> card (insert x A) = Suc (card A)" by (fact card.insert)
lemma card_insert_if: "finite A ==> card (insert x A) = (if x ∈ A then card A else Suc (card A))" by auto (simp add: card.insert_remove card.remove)
lemma card_ge_0_finite: "card A > 0 ==> finite A" by (rule ccontr) simp
lemma card_0_eq [simp]: "finite A ==> card A = 0 ⟷ A = {}" by (auto dest: mk_disjoint_insert)
lemma finite_UNIV_card_ge_0: "finite (UNIV :: 'a set) ==> card (UNIV :: 'a set) > 0" by (rule ccontr) simp
lemma card_eq_0_iff: "card A = 0 ⟷ A = {} ∨¬ finite A" by auto
lemma card_gt_0_iff: "0 < card A ⟷ A ≠ {} ∧ finite A" by (simp add: neq0_conv [symmetric] card_eq_0_iff)
lemma card_Suc_Diff1: assumes"finite A""x ∈ A"shows"Suc (card (A - {x})) = card A" proof - have"Suc (card (A - {x})) = card (insert x (A - {x}))" using assms by (simp add: card.insert_remove) alsohave"... = card A" using assms by (simp add: card_insert_if) finallyshow ?thesis . qed
lemma card_insert_le_m1: assumes"n > 0""card y ≤ n - 1"shows"card (insert x y) ≤ n" using assms by (cases "finite y") (auto simp: card_insert_if)
lemma card_Diff_singleton: assumes"x ∈ A"shows"card (A - {x}) = card A - 1" proof (cases "finite A") case True with assms show ?thesis by (simp add: card_Suc_Diff1 [symmetric]) qed auto
lemma card_Diff_singleton_if: "card (A - {x}) = (if x ∈ A then card A - 1 else card A)" by (simp add: card_Diff_singleton)
lemma card_Diff_insert[simp]: assumes"a ∈ A"and"a ∉ B" shows"card (A - insert a B) = card (A - B) - 1" proof - have"A - insert a B = (A - B) - {a}" using assms by blast thenshow ?thesis using assms by (simp add: card_Diff_singleton) qed
lemma card_insert_le: "card A ≤ card (insert x A)" proof (cases "finite A") case True thenshow ?thesis by (simp add: card_insert_if) qed auto
lemma card_Collect_less_nat[simp]: "card {i::nat. i < n} = n" by (induct n) (simp_all add:less_Suc_eq Collect_disj_eq)
lemma card_Collect_le_nat[simp]: "card {i::nat. i ≤ n} = Suc n" using card_Collect_less_nat[of "Suc n"] by (simp add: less_Suc_eq_le)
lemma card_mono: assumes"finite B"and"A ⊆ B" shows"card A ≤ card B" proof - from assms have"finite A" by (auto intro: finite_subset) thenshow ?thesis using assms proof (induct A arbitrary: B) case empty thenshow ?caseby simp next case (insert x A) thenhave"x ∈ B" by simp from insert have"A ⊆ B - {x}"and"finite (B - {x})" by auto with insert.hyps have"card A ≤ card (B - {x})" by auto with‹finite A›‹x ∉ A›‹finite B›‹x ∈ B›show ?case by simp (simp only: card.remove) qed qed
lemma card_seteq: assumes"finite B"and A: "A ⊆ B""card B ≤ card A" shows"A = B" using assms proof (induction arbitrary: A rule: finite_induct) case (insert b B) thenhave A: "finite A""A - {b} ⊆ B" by force+ thenhave"card B ≤ card (A - {b})" using insert by (auto simp add: card_Diff_singleton_if) thenhave"A - {b} = B" using A insert.IH by auto thenshow ?case using insert.hyps insert.prems by auto qed auto
lemma psubset_card_mono: "finite B ==> A < B ==> card A < card B" using card_seteq [of B A] by (auto simp add: psubset_eq)
lemma card_Un_Int: assumes"finite A""finite B" shows"card A + card B = card (A ∪ B) + card (A ∩ B)" using assms proof (induct A) case empty thenshow ?caseby simp next case insert thenshow ?case by (auto simp add: insert_absorb Int_insert_left) qed
lemma card_Un_disjoint: "finite A ==> finite B ==> A ∩ B = {} ==> card (A ∪ B) = card A + card B" using card_Un_Int [of A B] by simp
lemma card_Un_disjnt: "[finite A; finite B; disjnt A B]==> card (A ∪ B) = card A + card B" by (simp add: card_Un_disjoint disjnt_def)
lemma card_Un_le: "card (A ∪ B) ≤ card A + card B" proof (cases "finite A ∧ finite B") case True thenshow ?thesis using le_iff_add card_Un_Int [of A B] by auto qed auto
lemma card_Diff_subset: assumes"finite B" and"B ⊆ A" shows"card (A - B) = card A - card B" using assms proof (cases "finite A") case False with assms show ?thesis by simp next case True with assms show ?thesis by (induct B arbitrary: A) simp_all qed
lemma card_Diff_subset_Int: assumes"finite (A ∩ B)" shows"card (A - B) = card A - card (A ∩ B)" proof - have"A - B = A - A ∩ B"by auto with assms show ?thesis by (simp add: card_Diff_subset) qed
lemma card_Int_Diff: assumes"finite A" shows"card A = card (A ∩ B) + card (A - B)" by (simp add: assms card_Diff_subset_Int card_mono)
lemma diff_card_le_card_Diff: assumes"finite B" shows"card A - card B ≤ card (A - B)" proof - have"card A - card B ≤ card A - card (A ∩ B)" using card_mono[OF assms Int_lower2, of A] by arith alsohave"… = card (A - B)" using assms by (simp add: card_Diff_subset_Int) finallyshow ?thesis . qed
lemma card_le_sym_Diff: assumes"finite A""finite B""card A ≤ card B" shows"card(A - B) ≤ card(B - A)" proof - have"card(A - B) = card A - card (A ∩ B)"using assms(1,2) by(simp add: card_Diff_subset_Int) alsohave"…≤ card B - card (A ∩ B)"using assms(3) by linarith alsohave"… = card(B - A)"using assms(1,2) by(simp add: card_Diff_subset_Int Int_commute) finallyshow ?thesis . qed
lemma card_less_sym_Diff: assumes"finite A""finite B""card A < card B" shows"card(A - B) < card(B - A)" proof - have"card(A - B) = card A - card (A ∩ B)"using assms(1,2) by(simp add: card_Diff_subset_Int) alsohave"… < card B - card (A ∩ B)"using assms(1,3) by (simp add: card_mono diff_less_mono) alsohave"… = card(B - A)"using assms(1,2) by(simp add: card_Diff_subset_Int Int_commute) finallyshow ?thesis . qed
lemma card_Diff1_less_iff: "card (A - {x}) < card A ⟷ finite A ∧ x ∈ A" proof (cases "finite A ∧ x ∈ A") case True thenshow ?thesis by (auto simp: card_gt_0_iff intro: diff_less) qed auto
lemma card_Diff1_less: "finite A ==> x ∈ A ==> card (A - {x}) < card A" unfolding card_Diff1_less_iff by auto
lemma card_Diff2_less: assumes"finite A""x ∈ A""y ∈ A"shows"card (A - {x} - {y}) < card A" proof (cases "x = y") case True with assms show ?thesis by (simp add: card_Diff1_less del: card_Diff_insert) next case False thenhave"card (A - {x} - {y}) < card (A - {x})""card (A - {x}) < card A" using assms by (intro card_Diff1_less; simp)+ thenshow ?thesis by (blast intro: less_trans) qed
lemma card_Diff1_le: "card (A - {x}) ≤ card A" proof (cases "finite A") case True thenshow ?thesis by (cases "x ∈ A") (simp_all add: card_Diff1_less less_imp_le) qed auto
lemma card_psubset: "finite B ==> A ⊆ B ==> card A < card B ==> A < B" by (erule psubsetI) blast
lemma card_le_inj: assumes fA: "finite A" and fB: "finite B" and c: "card A ≤ card B" shows"∃f. f ` A ⊆ B ∧ inj_on f A" using fA fB c proof (induct arbitrary: B rule: finite_induct) case empty thenshow ?caseby simp next case (insert x s t) thenshow ?case proof (induct rule: finite_induct [OF insert.prems(1)]) case1 thenshow ?caseby simp next case (2 y t) from"2.prems"(1,2,5) "2.hyps"(1,2) have cst: "card s ≤ card t" by simp from"2.prems"(3) [OF "2.hyps"(1) cst] obtain f where *: "f ` s ⊆ t""inj_on f s" by blast let ?g = "(λa. if a = x then y else f a)" have"?g ` insert x s ⊆ insert y t ∧ inj_on ?g (insert x s)" using * "2.prems"(2) "2.hyps"(2) unfolding inj_on_def by auto thenshow ?caseby (rule exI[where ?x="?g"]) qed qed
lemma card_subset_eq: assumes fB: "finite B" and AB: "A ⊆ B" and c: "card A = card B" shows"A = B" proof - from fB AB have fA: "finite A" by (auto intro: finite_subset) from fA fB have fBA: "finite (B - A)" by auto have e: "A ∩ (B - A) = {}" by blast have eq: "A ∪ (B - A) = B" using AB by blast from card_Un_disjoint[OF fA fBA e, unfolded eq c] have"card (B - A) = 0" by arith thenhave"B - A = {}" unfolding card_eq_0_iff using fA fB by simp with AB show"A = B" by blast qed
lemma insert_partition: "x ∉ F ==>∀c1 ∈ insert x F. ∀c2 ∈ insert x F. c1 ≠ c2 ⟶ c1 ∩ c2 = {} ==> x ∩∪F = {}" by auto
lemma finite_psubset_induct [consumes 1, case_names psubset]: assumes finite: "finite A" and major: "∧A. finite A ==> (∧B. B ⊂ A ==> P B) ==> P A" shows"P A" using finite proof (induct A taking: card rule: measure_induct_rule) case (less A) have fin: "finite A"by fact have ih: "card B < card A ==> finite B ==> P B"for B by fact have"P B"if"B ⊂ A"for B proof - from that have"card B < card A" using psubset_card_mono fin by blast moreover from that have"B ⊆ A" by auto thenhave"finite B" using fin finite_subset by blast ultimatelyshow ?thesis using ih by simp qed with fin show"P A"using major by blast qed
lemma finite_induct_select [consumes 1, case_names empty select]: assumes"finite S" and"P {}" and select: "∧T. T ⊂ S ==> P T ==>∃s∈S - T. P (insert s T)" shows"P S" proof - have"0 ≤ card S"by simp thenhave"∃T ⊆ S. card T = card S ∧ P T" proof (induct rule: dec_induct) case base with‹P {}› show ?case by (intro exI[of _ "{}"]) auto next case (step n) thenobtain T where T: "T ⊆ S""card T = n""P T" by auto with‹n < card S›have"T ⊂ S""P T" by auto with select[of T] obtain s where"s ∈ S""s ∉ T""P (insert s T)" by auto with step(2) T ‹finite S›show ?case by (intro exI[of _ "insert s T"]) (auto dest: finite_subset) qed with‹finite S›show"P S" by (auto dest: card_subset_eq) qed
lemma remove_induct [case_names empty infinite remove]: assumes empty: "P ({} :: 'a set)" and infinite: "¬ finite B ==> P B" and remove: "∧A. finite A ==> A ≠ {} ==> A ⊆ B ==> (∧x. x ∈ A ==> P (A - {x})) ==> P A" shows"P B" proof (cases "finite B") case False thenshow ?thesis by (rule infinite) next case True
define A where"A = B" with True have"finite A""A ⊆ B" by simp_all thenshow"P A" proof (induct "card A" arbitrary: A) case0 thenhave"A = {}"by auto with empty show ?caseby simp next case (Suc n A) from‹A ⊆ B›and‹finite B›have"finite A" by (rule finite_subset) moreoverfrom Suc.hyps have"A ≠ {}"by auto moreovernote‹A ⊆ B› moreoverhave"P (A - {x})"if x: "x ∈ A"for x using x Suc.prems ‹Suc n = card A›by (intro Suc) auto ultimatelyshow ?caseby (rule remove) qed qed
lemma finite_remove_induct [consumes 1, case_names empty remove]: fixes P :: "'a set ==> bool" assumes"finite B" and"P {}" and"∧A. finite A ==> A ≠ {} ==> A ⊆ B ==> (∧x. x ∈ A ==> P (A - {x})) ==> P A" defines"B' ≡ B" shows"P B'" by (induct B' rule: remove_induct) (simp_all add: assms)
text‹Main cardinality theorem.› lemma card_partition [rule_format]: "finite C ==> finite (∪C) ==> (∀c∈C. card c = k) ==> (∀c1 ∈ C. ∀c2 ∈ C. c1 ≠ c2 ⟶ c1 ∩ c2 = {}) ==> k * card C = card (∪C)" proof (induct rule: finite_induct) case empty thenshow ?caseby simp next case (insert x F) thenshow ?case by (simp add: card_Un_disjoint insert_partition finite_subset [of _ "∪(insert _ _)"]) qed
lemma card_eq_UNIV_imp_eq_UNIV: assumes fin: "finite (UNIV :: 'a set)" and card: "card A = card (UNIV :: 'a set)" shows"A = (UNIV :: 'a set)" proof show"A ⊆ UNIV"by simp show"UNIV ⊆ A" proof show"x ∈ A"for x proof (rule ccontr) assume"x ∉ A" thenhave"A ⊂ UNIV"by auto with fin have"card A < card (UNIV :: 'a set)" by (fact psubset_card_mono) with card show False by simp qed qed qed
text‹The form of a finite set of given cardinality›
lemma card_eq_SucD: assumes"card A = Suc k" shows"∃b B. A = insert b B ∧ b ∉ B ∧ card B = k ∧ (k = 0 ⟶ B = {})" proof - have fin: "finite A" using assms by (auto intro: ccontr) moreoverhave"card A ≠ 0" using assms by auto ultimatelyobtain b where b: "b ∈ A" by auto show ?thesis proof (intro exI conjI) show"A = insert b (A - {b})" using b by blast show"b ∉ A - {b}" by blast show"card (A - {b}) = k"and"k = 0 ⟶ A - {b} = {}" using assms b fin by (fastforce dest: mk_disjoint_insert)+ qed qed
lemma card_Suc_eq: "card A = Suc k ⟷ (∃b B. A = insert b B ∧ b ∉ B ∧ card B = k ∧ (k = 0 ⟶ B = {}))" by (auto simp: card_insert_if card_gt_0_iff elim!: card_eq_SucD)
lemma card_Suc_eq_finite: "card A = Suc k ⟷ (∃b B. A = insert b B ∧ b ∉ B ∧ card B = k ∧ finite B)" unfolding card_Suc_eq using card_gt_0_iff by fastforce
lemma card_1_singletonE: assumes"card A = 1" obtains x where"A = {x}" using assms by (auto simp: card_Suc_eq)
lemma is_singleton_iff_card_eq_Suc_0 [code]: ‹is_singleton A ⟷ card A = Suc 0› by (simp add: is_singleton_def card_Suc_eq)
lemma is_singleton_altdef: ‹is_singleton A ⟷ card A = 1› by (simp add: is_singleton_iff_card_eq_Suc_0)
lemma card_eq_Suc_0_iff_is_singleton: ‹card A = Suc 0 ⟷ is_singleton A› by (simp add: is_singleton_altdef)
lemma card_1_singleton_iff: ‹card A = Suc 0 ⟷ (∃x. A = {x})› by (simp add: card_eq_Suc_0_iff_is_singleton is_singleton_def)
lemma card_le_Suc0_iff_eq: assumes"finite A" shows"card A ≤ Suc 0 ⟷ (∀a1 ∈ A. ∀a2 ∈ A. a1 = a2)" (is"?C = ?A") proof assume ?C thus ?A using assms by (auto simp: le_Suc_eq dest: card_eq_SucD) next assume ?A show ?C proof cases assume"A = {}"thus ?C using‹?A›by simp next assume"A ≠ {}" thenobtain a where"A = {a}"using‹?A›by blast thus ?C by simp qed qed
lemma card_le_Suc_iff: "Suc n ≤ card A = (∃a B. A = insert a B ∧ a ∉ B ∧ n ≤ card B ∧ finite B)" proof (cases "finite A") case True thenshow ?thesis by (fastforce simp: card_Suc_eq less_eq_nat.simps split: nat.splits) qed auto
lemma finite_fun_UNIVD2: assumes fin: "finite (UNIV :: ('a ==> 'b) set)" shows"finite (UNIV :: 'b set)" proof - from fin have"finite (range (λf :: 'a ==> 'b. f arbitrary))"for arbitrary by (rule finite_imageI) moreoverhave"UNIV = range (λf :: 'a ==> 'b. f arbitrary)"for arbitrary by (rule UNIV_eq_I) auto ultimatelyshow"finite (UNIV :: 'b set)" by simp qed
lemma card_UNIV_unit [simp]: "card (UNIV :: unit set) = 1" unfolding UNIV_unit by simp
lemma infinite_arbitrarily_large: assumes"¬ finite A" shows"∃B. finite B ∧ card B = n ∧ B ⊆ A" proof (induction n) case0 show ?caseby (intro exI[of _ "{}"]) auto next case (Suc n) thenobtain B where B: "finite B ∧ card B = n ∧ B ⊆ A" .. with‹¬ finite A›have"A ≠ B"by auto with B have"B ⊂ A"by auto thenhave"∃x. x ∈ A - B" by (elim psubset_imp_ex_mem) thenobtain x where x: "x ∈ A - B" .. with B have"finite (insert x B) ∧ card (insert x B) = Suc n ∧ insert x B ⊆ A" by auto thenshow"∃B. finite B ∧ card B = Suc n ∧ B ⊆ A" .. qed
corollary finite_arbitrarily_large_disj: "[¬ finite(UNIV::'a set); finite (A::'a set) ]==>∃B. finite B ∧ card B = n ∧A ∩ B = {}" using infinite_arbitrarily_large[of "UNIV - A"] by fastforce
text‹Sometimes, to prove that a set is finite, it is convenient to work with finite subsets
to show that their cardinalities are uniformly bounded. This possibility is formalized in
next criterion.›
lemma finite_if_finite_subsets_card_bdd: assumes"∧G. G ⊆ F ==> finite G ==> card G ≤ C" shows"finite F ∧ card F ≤ C" proof (cases "finite F") case False obtain n::nat where n: "n > max C 0"by auto obtain G where G: "G ⊆ F""card G = n"using infinite_arbitrarily_large[OF False] by auto hence"finite G"using‹n > max C 0›using card.infinite gr_implies_not0 by blast hence False using assms G n not_less by auto thus ?thesis .. next case True thus ?thesis using assms[of F] by auto qed
lemma obtain_subset_with_card_n: assumes"n ≤ card S" obtains T where"T ⊆ S""card T = n""finite T" proof - obtain n' where"card S = n + n'" using le_Suc_ex[OF assms] by blast with that show thesis proof (induct n' arbitrary: S) case0 thus ?caseby (cases "finite S") auto next case Suc thus ?caseby (auto simp add: card_Suc_eq) qed qed
lemma exists_subset_between: assumes "card A ≤ n" "n ≤ card C" "A ⊆ C" "finite C" shows"∃B. A ⊆ B ∧ B ⊆ C ∧ card B = n" using assms proof (induct n arbitrary: A C) case0 thus ?caseusing finite_subset[of A C] by (intro exI[of _ "{}"], auto) next case (Suc n A C) show ?case proof (cases "A = {}") case True from obtain_subset_with_card_n[OF Suc(3)] obtain B where"B ⊆ C""card B = Suc n"by blast thus ?thesis unfolding True by blast next case False thenobtain a where a: "a ∈ A"by auto let ?A = "A - {a}" let ?C = "C - {a}" have1: "card ?A ≤ n"using Suc(2-) a using finite_subset by fastforce have2: "card ?C ≥ n"using Suc(2-) a by auto from Suc(1)[OF 12 _ finite_subset[OF _ Suc(5)]] Suc(2-) obtain B where"?A ⊆ B""B ⊆ ?C""card B = n"by blast thus ?thesis using a Suc(2-) by (intro exI[of _ "insert a B"], auto intro!: card_insert_disjoint finite_subset[of B C]) qed qed
subsubsection‹Cardinality of image›
lemma card_image_le: "finite A ==> card (f ` A) ≤ card A" by (induct rule: finite_induct) (simp_all add: le_SucI card_insert_if)
lemma card_image: "inj_on f A ==> card (f ` A) = card A" proof (induct A rule: infinite_finite_induct) case (infinite A) thenhave"¬ finite (f ` A)"by (auto dest: finite_imageD) with infinite show ?caseby simp qed simp_all
lemma bij_betw_same_card: "bij_betw f A B ==> card A = card B" by (auto simp: card_image bij_betw_def)
lemma endo_inj_surj: "finite A ==> f ` A ⊆ A ==> inj_on f A ==> f ` A = A" by (simp add: card_seteq card_image)
lemma eq_card_imp_inj_on: assumes"finite A""card(f ` A) = card A" shows"inj_on f A" using assms proof (induct rule:finite_induct) case empty show ?caseby simp next case (insert x A) thenshow ?case using card_image_le [of A f] by (simp add: card_insert_if split: if_splits) qed
lemma inj_on_iff_eq_card: "finite A ==> inj_on f A ⟷ card (f ` A) = card A" by (blast intro: card_image eq_card_imp_inj_on)
lemma card_inj_on_le: assumes"inj_on f A""f ` A ⊆ B""finite B" shows"card A ≤ card B" proof - have"finite A" using assms by (blast intro: finite_imageD dest: finite_subset) thenshow ?thesis using assms by (force intro: card_mono simp: card_image [symmetric]) qed
lemma inj_on_iff_card_le: "[ finite A; finite B ]==> (∃f. inj_on f A ∧ f ` A ≤ B) = (card A ≤ card B)" using card_inj_on_le[of _ A B] card_le_inj[of A B] by blast
lemma surj_card_le: "finite A ==> B ⊆ f ` A ==> card B ≤ card A" by (blast intro: card_image_le card_mono le_trans)
lemma card_bij_eq: "inj_on f A ==> f ` A ⊆ B ==> inj_on g B ==> g ` B ⊆ A ==> finite A ==> finite B ==> card A = card B" by (auto intro: le_antisym card_inj_on_le)
lemma bij_betw_finite: "bij_betw f A B ==> finite A ⟷ finite B" unfolding bij_betw_def using finite_imageD [of f A] by auto
lemma inj_on_finite: "inj_on f A ==> f ` A ≤ B ==> finite B ==> finite A" using finite_imageD finite_subset by blast
lemma card_vimage_inj_on_le: assumes"inj_on f D""finite A" shows"card (f-`A ∩ D) ≤ card A" proof (rule card_inj_on_le) show"inj_on f (f -` A ∩ D)" by (blast intro: assms inj_on_subset) qed (use assms in auto)
lemma card_vimage_inj: "inj f ==> A ⊆ range f ==> card (f -` A) = card A" by (auto 43 simp: subset_image_iff inj_vimage_image_eq
intro: card_image[symmetric, OF inj_on_subset])
lemma card_inverse[simp]: "card (R-1) = card R" proof - have *: "∧R. prod.swap ` R = R-1"by auto
{ assume"¬finite R" hence ?thesis by auto
} moreover { assume"finite R" with card_image_le[of R prod.swap] card_image_le[of "R-1" prod.swap] have ?thesis by (auto simp: * )
} ultimatelyshow ?thesis by blast qed
subsubsection‹Pigeonhole Principles›
lemma pigeonhole: "card A > card (f ` A) ==>¬ inj_on f A " by (auto dest: card_image less_irrefl_nat)
lemma pigeonhole_infinite: assumes"¬ finite A"and"finite (f`A)" shows"∃a0∈A. ¬ finite {a∈A. f a = f a0}" using assms(2,1) proof (induct "f`A" arbitrary: A rule: finite_induct) case empty thenshow ?caseby simp next case (insert b F) show ?case proof (cases "finite {a∈A. f a = b}") case True with‹¬ finite A›have"¬ finite (A - {a∈A. f a = b})" by simp alsohave"A - {a∈A. f a = b} = {a∈A. f a ≠ b}" by blast finallyhave"¬ finite {a∈A. f a ≠ b}" . from insert(3)[OF _ this] insert(2,4) show ?thesis by simp (blast intro: rev_finite_subset) next case False thenhave"{a ∈ A. f a = b} ≠ {}"by force with False show ?thesis by blast qed qed
lemma pigeonhole_infinite_rel: assumes"¬ finite A" and"finite B" and"∀a∈A. ∃b∈B. R a b" shows"∃b∈B. ¬ finite {a:A. R a b}" proof - let ?F = "λa. {b∈B. R a b}" from finite_Pow_iff[THEN iffD2, OF ‹finite B›] have"finite (?F ` A)" by (blast intro: rev_finite_subset) from pigeonhole_infinite [where f = ?F, OF assms(1) this] obtain a0 where"a0 ∈ A"and infinite: "¬ finite {a∈A. ?F a = ?F a0}" .. obtain b0 where"b0 ∈ B"and"R a0 b0" using‹a0 ∈ A› assms(3) by blast have"finite {a∈A. ?F a = ?F a0}"if"finite {a∈A. R a b0}" using‹b0 ∈ B›‹R a0 b0› that by (blast intro: rev_finite_subset) with infinite ‹b0 ∈ B›show ?thesis by blast qed
subsubsection‹Cardinality of sums›
lemma card_Plus: assumes"finite A""finite B" shows"card (A <+> B) = card A + card B" proof - have"Inl`A ∩ Inr`B = {}"by fast with assms show ?thesis by (simp add: Plus_def card_Un_disjoint card_image) qed
lemma card_Plus_conv_if: "card (A <+> B) = (if finite A ∧ finite B then card A + card B else 0)" by (auto simp add: card_Plus)
text‹Relates to equivalence classes. Based on a theorem of F. Kammüller.›
lemma dvd_partition: assumes f: "finite (∪C)" and"∀c∈C. k dvd card c""∀c1∈C. ∀c2∈C. c1 ≠ c2 ⟶ c1 ∩ c2 = {}" shows"k dvd card (∪C)" proof - have"finite C" by (rule finite_UnionD [OF f]) thenshow ?thesis using assms proof (induct rule: finite_induct) case empty show ?caseby simp next case (insert c C) thenhave"c ∩∪C = {}" by auto with insert show ?case by (simp add: card_Un_disjoint) qed qed
subsection‹Minimal and maximal elements of finite sets›
contextbegin
qualified lemma assumes"finite A"and"asymp_on A R"and"transp_on A R"and"∃x ∈ A. P x" shows
bex_min_element_with_property: "∃x ∈ A. P x ∧ (∀y ∈ A. R y x ⟶¬ P y)"and
bex_max_element_with_property: "∃x ∈ A. P x ∧ (∀y ∈ A. R x y ⟶¬ P y)" unfolding atomize_conj using assms proof (induction A rule: finite_induct) case empty hence False by simp_all thus ?case .. next case (insert x F)
from insert.prems have "asymp_on F R"
using asymp_on_subset by blast
from insert.prems have "transp_on F R"
using transp_on_subset by blast
show ?case
proof (cases"P x")
case True
show ?thesis
proof (cases"\<exists>a\<in>F. P a")
case True with insert.IH obtain min max where "min \<in> F"and"P min"and"\<forall>z \<in> F. R z min \<longrightarrow> \<not> P z" "max \<in> F"and"P max"and"\<forall>z \<in> F. R max z \<longrightarrow> \<not> P z"
using \<open>asymp_on F R\<close> \<open>transp_on F R\<close> byauto
show ?thesis
proof (rule conjI)
show "\<exists>y \<in> insert x F. P y \<and> (\<forall>z \<in> insert x F. R y z \<longrightarrow> \<not> P z)"
proof (cases"R max x")
case True
show ?thesis
proof (intro bexI conjI ballI impI)
show "x \<in> insert x F" by simp
next
show "P x"
using \<open>P x\<close> by simp
next
fix z assume "z \<in> insert x F"and"R x z"
hence "z = x \<or> z \<in> F" by simp
thus "\<not> P z"
proof (rule disjE)
assume "z = x"
hence "R x x"
using \<open>R x z\<close> by simp
moreover have "\<not> R x x"
using \<open>asymp_on (insert x F) R\<close>[THEN irreflp_on_if_asymp_on, THEN irreflp_onD] by simp
ultimately have False by simp
thus ?thesis ..
next
assume "z \<in> F"
moreover have "R max z"
using \<open>R max x\<close> \<open>R x z\<close>
using \<open>transp_on (insert x F) R\<close>[THEN transp_onD, of max x z]
using \<open>max \<in> F\<close> \<open>z \<in> F\<close> by simp
ultimately show ?thesis
using \<open>\<forall>z \<in> F. R max z \<longrightarrow> \<not> P z\<close> by simp
qed
qed
next
case False
show ?thesis
proof (intro bexI conjI ballI impI)
show "max \<in> insert x F"
using \<open>max \<in> F\<close> by simp
next
show "P max"
using \<open>P max\<close> by simp
next
fix z assume "z \<in> insert x F"and"R max z"
hence "z = x \<or> z \<in> F" by simp
thus "\<not> P z"
proof (rule disjE)
assume "z = x"
hence False
using \<open>\<not> R max x\<close> \<open>R max z\<close> by simp
thus ?thesis ..
next
assume "z \<in> F"
thus ?thesis
using \<open>R max z\<close> \<open>\<forall>z\<in>F. R max z \<longrightarrow> \<not> P z\<close> by simp
qed
qed
qed
next
show "\<exists>y \<in> insert x F. P y \<and> (\<forall>z \<in> insert x F. R z y \<longrightarrow> \<not> P z)"
proof (cases"R x min")
case True
show ?thesis
proof (intro bexI conjI ballI impI)
show "x \<in> insert x F" by simp
next
show "P x"
using \<open>P x\<close> by simp
next
fix z assume "z \<in> insert x F"and"R z x"
hence "z = x \<or> z \<in> F" by simp
thus "\<not> P z"
proof (rule disjE)
assume "z = x"
hence "R x x"
using \<open>R z x\<close> by simp
moreover have "\<not> R x x"
using \<open>asymp_on (insert x F) R\<close>[THEN irreflp_on_if_asymp_on, THEN irreflp_onD] by simp
ultimately have False by simp
thus ?thesis ..
next
assume "z \<in> F"
moreover have "R z min"
using \<open>R z x\<close> \<open>R x min\<close>
using \<open>transp_on (insert x F) R\<close>[THEN transp_onD, of z x min]
using \<open>min \<in> F\<close> \<open>z \<in> F\<close> by simp
ultimately show ?thesis
using \<open>\<forall>z \<in> F. R z min \<longrightarrow> \<not> P z\<close> by simp
qed
qed
next
case False
show ?thesis
proof (intro bexI conjI ballI impI)
show "min \<in> insert x F"
using \<open>min \<in> F\<close> by simp
next
show "P min"
using \<open>P min\<close> by simp
next
fix z assume "z \<in> insert x F"and"R z min"
hence "z = x \<or> z \<in> F" by simp
thus "\<not> P z"
proof (rule disjE)
assume "z = x"
hence False
using \<open>\<not> R x min\<close> \<open>R z min\<close> by simp
thus ?thesis ..
next
assume "z \<in> F"
thus ?thesis
using \<open>R z min\<close> \<open>\<forall>z\<in>F. R z min \<longrightarrow> \<not> P z\<close> by simp
qed
qed
qed
qed
next
case False then show ?thesis
using \<open>\<exists>a\<in>insert x F. P a\<close>
using \<open>asymp_on (insert x F) R\<close>[THEN asymp_onD, of x] insert_iff[of _ x F] by blast
qed
next
case False with insert.prems have "\<exists>x \<in> F. P x" by simp with insert.IH have "\<exists>y \<in> F. P y \<and> (\<forall>z\<in>F. R z y \<longrightarrow> \<not> P z)" "\<exists>y \<in> F. P y \<and> (\<forall>z\<in>F. R y z \<longrightarrow> \<not> P z)"
using \<open>asymp_on F R\<close> \<open>transp_on F R\<close> byauto
thus ?thesis
using Falsebyauto
qed
qed
qualified lemma
assumes "finite A"and"asymp_on A R"and"transp_on A R"and"A \<noteq> {}"
shows
bex_min_element: "\<exists>m \<in> A. \<forall>x \<in> A. x \<noteq> m \<longrightarrow> \<not> R x m"and
bex_max_element: "\<exists>m \<in> A. \<forall>x \<in> A. x \<noteq> m \<longrightarrow> \<not> R m x"
using \<open>A \<noteq> {}\<close>
bex_min_element_with_property[OF assms(1,2,3), of"\<lambda>_. True", simplified]
bex_max_element_with_property[OF assms(1,2,3), of"\<lambda>_. True", simplified] by blast+
end
text \<open>The following alternative form might sometimes be easier to work with.\<close>
lemma is_min_element_in_set_iff: "asymp_on A R \<Longrightarrow> (\<forall>y \<in> A. y \<noteq> x \<longrightarrow> \<not> R y x) \<longleftrightarrow> (\<forall>y. R y x \<longrightarrow> y \<notin> A)" by (auto dest: asymp_onD)
lemma is_max_element_in_set_iff: "asymp_on A R \<Longrightarrow> (\<forall>y \<in> A. y \<noteq> x \<longrightarrow> \<not> R x y) \<longleftrightarrow> (\<forall>y. R x y \<longrightarrow> y \<notin> A)" by (auto dest: asymp_onD)
context begin
qualified lemma
assumes "finite A"and"A \<noteq> {}"and"transp_on A R"and"totalp_on A R"
shows
bex_least_element: "\<exists>l \<in> A. \<forall>x \<in> A. x \<noteq> l \<longrightarrow> R l x"and
bex_greatest_element: "\<exists>g \<in> A. \<forall>x \<in> A. x \<noteq> g \<longrightarrow> R x g"
unfolding atomize_conj
using assms
proof (induction A rule: finite_induct)
case empty
hence Falseby simp
thus ?case ..
next
case (insert a A')
from insert.prems(2) have transp_on_A': "transp_on A' R" by (auto intro: transp_onI dest: transp_onD)
from insert.prems(3) have
totalp_on_a_A'_raw: "\<forall>y \<in> A'. a \<noteq> y \<longrightarrow> R a y \<or> R y a" and
totalp_on_A': "totalp_on A' R" by (simp_all add: totalp_on_def)
show ?case
proof (cases"A' = {}")
case True
thus ?thesis by simp
next
case False then obtain least greatest where "least \<in> A'"and least_of_A': "\<forall>x\<in>A'. x \<noteq> least \<longrightarrow> R least x" and "greatest \<in> A'"and greatest_of_A': "\<forall>x\<in>A'. x \<noteq> greatest \<longrightarrow> R x greatest"
using insert.IH[OF _ transp_on_A' totalp_on_A'] byauto
show ?thesis
proof (rule conjI)
show "\<exists>l\<in>insert a A'. \<forall>x\<in>insert a A'. x \<noteq> l \<longrightarrow> R l x"
proof (cases"R a least")
case True
show ?thesis
proof (intro bexI ballI impI)
show "a \<in> insert a A'" by simp
next
fix x
show "\<And>x. x \<in> insert a A' \<Longrightarrow> x \<noteq> a \<Longrightarrow> R a x"
using True \<open>least \<in> A'\<close> least_of_A'
using insert.prems(2)[THEN transp_onD, of a least] byauto
qed
next
case False
show ?thesis
proof (intro bexI ballI impI)
show "least \<in> insert a A'"
using \<open>least \<in> A'\<close> by simp
next
fix x
show "x \<in> insert a A' \<Longrightarrow> x \<noteq> least \<Longrightarrow> R least x"
using False \<open>least \<in> A'\<close> least_of_A' totalp_on_a_A'_raw by (cases"x = a") auto
qed
qed
next
show "\<exists>g \<in> insert a A'. \<forall>x \<in> insert a A'. x \<noteq> g \<longrightarrow> R x g"
proof (cases"R greatest a")
case True
show ?thesis
proof (intro bexI ballI impI)
show "a \<in> insert a A'" by simp
next
fix x
show "\<And>x. x \<in> insert a A' \<Longrightarrow> x \<noteq> a \<Longrightarrow> R x a"
using True \<open>greatest \<in> A'\<close> greatest_of_A'
using insert.prems(2)[THEN transp_onD, of _ greatest a] byauto
qed
next
case False
show ?thesis
proof (intro bexI ballI impI)
show "greatest \<in> insert a A'"
using \<open>greatest \<in> A'\<close> by simp
next
fix x
show "x \<in> insert a A' \<Longrightarrow> x \<noteq> greatest \<Longrightarrow> R x greatest"
using False \<open>greatest \<in> A'\<close> greatest_of_A' totalp_on_a_A'_raw by (cases"x = a") auto
qed
qed
qed
qed
qed
end
subsubsection \<open>Finite orders\<close>
context order begin
lemma finite_has_maximal:
assumes "finite A"and"A \<noteq> {}"
shows "\<exists> m \<in> A. \<forall> b \<in> A. m \<le> b \<longrightarrow> m = b"
proof -
obtain m where"m \<in> A"and m_is_max: "\<forall>x\<in>A. x \<noteq> m \<longrightarrow> \<not> m < x"
using Finite_Set.bex_max_element[OF \<open>finite A\<close> _ _ \<open>A \<noteq> {}\<close>, of"(<)"] byauto
moreover have "\<forall>b \<in> A. m \<le> b \<longrightarrow> m = b"
using m_is_max by (auto simp: le_less)
ultimately show ?thesis byauto
qed
lemma finite_has_maximal2: "\<lbrakk> finite A; a \<in> A \<rbrakk> \<Longrightarrow> \<exists> m \<in> A. a \<le> m \<and> (\<forall> b \<in> A. m \<le> b \<longrightarrow> m = b)"
using finite_has_maximal[of"{b \<in> A. a \<le> b}"] by fastforce
lemma finite_has_minimal:
assumes "finite A"and"A \<noteq> {}"
shows "\<exists> m \<in> A. \<forall> b \<in> A. b \<le> m \<longrightarrow> m = b"
proof -
obtain m where"m \<in> A"and m_is_min: "\<forall>x\<in>A. x \<noteq> m \<longrightarrow> \<not> x < m"
using Finite_Set.bex_min_element[OF \<open>finite A\<close> _ _ \<open>A \<noteq> {}\<close>, of"(<)"] byauto
moreover have "\<forall>b \<in> A. b \<le> m \<longrightarrow> m = b"
using m_is_min by (auto simp: le_less)
ultimately show ?thesis byauto
qed
lemma finite_has_minimal2: "\<lbrakk> finite A; a \<in> A \<rbrakk> \<Longrightarrow> \<exists> m \<in> A. m \<le> a \<and> (\<forall> b \<in> A. b \<le> m \<longrightarrow> m = b)"
using finite_has_minimal[of"{b \<in> A. b \<le> a}"] by fastforce
end
subsubsection \<open>Relating injectivity and surjectivity\<close>
lemma finite_surj_inj:
assumes "finite A""A \<subseteq> f ` A"
shows "inj_on f A"
proof -
have "f ` A = A" by (rule card_seteq [THEN sym]) (auto simp add: assms card_image_le) then show ?thesis using assms by (simp add: eq_card_imp_inj_on)
qed
lemma finite_UNIV_surj_inj: "finite(UNIV:: 'a set) \<Longrightarrow> surj f \<Longrightarrow> inj f"
for f :: "'a \<Rightarrow> 'a" by (blast intro: finite_surj_inj subset_UNIV)
lemma finite_UNIV_inj_surj: "finite(UNIV:: 'a set) \<Longrightarrow> inj f \<Longrightarrow> surj f"
for f :: "'a \<Rightarrow> 'a" by (fastforce simp:surj_def dest!: endo_inj_surj)
lemma surjective_iff_injective_gen:
assumes fS: "finite S" and fT: "finite T" and c: "card S = card T" and ST: "f ` S \<subseteq> T"
shows "(\<forall>y \<in> T. \<exists>x \<in> S. f x = y) \<longleftrightarrow> inj_on f S"
(is "?lhs \<longleftrightarrow> ?rhs")
proof
assume h: "?lhs"
{
fix x y
assume x: "x \<in> S"
assume y: "y \<in> S"
assume f: "f x = f y" from x fS have S0: "card S \<noteq> 0" byauto
have "x = y"
proof (rule ccontr)
assume xy: "\<not> ?thesis"
have th: "card S \<le> card (f ` (S - {y}))"
unfolding c
proof (rule card_mono)
show "finite (f ` (S - {y}))" by (simp add: fS)
have "\<lbrakk>x \<noteq> y; x \<in> S; z \<in> S; f x = f y\<rbrakk>
\<Longrightarrow> \<exists>x \<in> S. x \<noteq> y \<and> f z = f x" for z by (cases"z = y \<longrightarrow> z = x") auto then show "T \<subseteq> f ` (S - {y})"
using h xy x y f by fastforce
qed
also have " \<dots> \<le> card (S - {y})" by (simp add: card_image_le fS)
also have "\<dots> \<le> card S - 1" using y fS by simp
finally show False using S0 by arith
qed
} then show ?rhs
unfolding inj_on_def by blast
next
assume h: ?rhs
have "f ` S = T" by (simp add: ST c card_image card_subset_eq fT h) then show ?lhs by blast
qed
hide_const (open) Finite_Set.fold
subsection \<open>Infinite Sets\<close>
text \<open>
Some elementary facts about infinite sets, mostly by Stephan Merz.
Beware! Because "infinite" merely abbreviates a negation, these
lemmas may not work well with \<open>blast\<close>.
\<close>
abbreviation infinite :: "'a set \<Rightarrow> bool" where"infinite S \<equiv> \<not> finite S"
text \<open>
Infinite sets are non-empty, andif we remove some elements from an
infinite set, the result is still infinite.
\<close>
lemma infinite_UNIV_nat [iff]: "infinite (UNIV :: nat set)"
proof
assume "finite (UNIV :: nat set)" with finite_UNIV_inj_surj [of Suc] show False by simp (blast dest: Suc_neq_Zero surjD)
qed
lemma infinite_UNIV_char_0: "infinite (UNIV :: 'a::semiring_char_0 set)"
proof
assume "finite (UNIV :: 'a set)" with subset_UNIV have "finite (range of_nat :: 'a set)" by (rule finite_subset)
moreover have "inj (of_nat :: nat \<Rightarrow> 'a)" by (simp add: inj_on_def)
ultimately have "finite (UNIV :: nat set)" by (rule finite_imageD) then show False by simp
qed
lemma infinite_imp_nonempty: "infinite S \<Longrightarrow> S \<noteq> {}" byauto
lemma infinite_remove: "infinite S \<Longrightarrow> infinite (S - {a})" by simp
lemma Diff_infinite_finite:
assumes "finite T""infinite S"
shows "infinite (S - T)"
using \<open>finite T\<close>
proof induct from \<open>infinite S\<close> show "infinite (S - {})" byauto
next
fix T x
assume ih: "infinite (S - T)"
have "S - (insert x T) = (S - T) - {x}" by (rule Diff_insert) with ih show "infinite (S - (insert x T))" by (simp add: infinite_remove)
qed
lemma Un_infinite: "infinite S \<Longrightarrow> infinite (S \<union> T)" by simp
lemma infinite_Un: "infinite (S \<union> T) \<longleftrightarrow> infinite S \<or> infinite T" by simp
lemma infinite_super:
assumes "S \<subseteq> T" and"infinite S"
shows "infinite T"
proof
assume "finite T" with \<open>S \<subseteq> T\<close> have "finite S"by (simp add: finite_subset) with \<open>infinite S\<close> show Falseby simp
qed
proposition infinite_coinduct [consumes 1, case_names infinite]:
assumes "X A" and step: "\<And>A. X A \<Longrightarrow> \<exists>x\<in>A. X (A - {x}) \<or> infinite (A - {x})"
shows "infinite A"
proof
assume "finite A" then show False
using \<open>X A\<close>
proof (induction rule: finite_psubset_induct)
case (psubset A) then obtain x where"x \<in> A""X (A - {x}) \<or> infinite (A - {x})"
using local.step psubset.prems by blast then have "X (A - {x})"
using psubset.hyps by blast
show False
proof (rule psubset.IH [where B = "A - {x}"])
show "A - {x} \<subset> A"
using \<open>x \<in> A\<close> by blast
qed fact
qed
qed
text \<open>
For any functionwith infinite domain and finite range there is some
element that is the image of infinitely many domain elements. In
particular, any infinite sequence of elements from a finite set
contains some element that occurs infinitely often.
\<close>
lemma inf_img_fin_dom':
assumes img: "finite (f ` A)" and dom: "infinite A"
shows "\<exists>y \<in> f ` A. infinite (f -` {y} \<inter> A)"
proof (rule ccontr)
have "A \<subseteq> (\<Union>y\<in>f ` A. f -` {y} \<inter> A)"byauto
moreover assume "\<not> ?thesis" with img have "finite (\<Union>y\<in>f ` A. f -` {y} \<inter> A)"by blast
ultimately have "finite A"by (rule finite_subset) with dom show Falseby contradiction
qed
lemma inf_img_fin_domE':
assumes "finite (f ` A)"and"infinite A"
obtains y where"y \<in> f`A"and"infinite (f -` {y} \<inter> A)"
using assms by (blast dest: inf_img_fin_dom')
lemma inf_img_fin_dom:
assumes img: "finite (f`A)"and dom: "infinite A"
shows "\<exists>y \<in> f`A. infinite (f -` {y})"
using inf_img_fin_dom'[OF assms] by auto
lemma inf_img_fin_domE:
assumes "finite (f`A)"and"infinite A"
obtains y where"y \<in> f`A"and"infinite (f -` {y})"
using assms by (blast dest: inf_img_fin_dom)
proposition finite_image_absD: "finite (abs ` S) \<Longrightarrow> finite S"
for S :: "'a::linordered_ring set" by (rule ccontr) (auto simp: abs_eq_iff vimage_def dest: inf_img_fin_dom)
lemma Fpow_not_empty: "Fpow A \<noteq> {}"
using empty_in_Fpow by blast
lemma Fpow_subset_Pow: "Fpow A \<subseteq> Pow A"
unfolding Fpow_def byauto
lemma Fpow_Pow_finite: "Fpow A = Pow A Int {A. finite A}"
unfolding Fpow_def Pow_def by blast
lemma inj_on_image_Fpow:
assumes "inj_on f A"
shows "inj_on (image f) (Fpow A)"
using assms Fpow_subset_Pow[of A] inj_on_subset[of"image f""Pow A"]
inj_on_image_Pow by blast
lemma image_Fpow_mono:
assumes "f ` A \<subseteq> B"
shows "(image f) ` (Fpow A) \<subseteq> Fpow B"
using assms by(unfold Fpow_def, auto)
end
Messung V0.5 in Prozent
¤ Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.0.122Bemerkung:
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.