(* Title: HOL/Set.thy Author: Tobias Nipkow Author: Lawrence C Paulson Author: Markus Wenzel
*)
section ‹Set theoryfor higher-order logic›
theory Set imports Lattices Boolean_Algebras begin
subsection ‹Sets as predicates›
typedecl'a set
axiomatization Collect :: "('a \ bool) \ 'a set"🍋‹comprehension› and member :: "'a \ 'a set \ bool"🍋‹membership› where mem_Collect_eq [iff, code_unfold]: "member a (Collect P) = P a" and Collect_mem_eq [simp, code_unfold]: "Collect (\x. member x A) = A"
notation
member (‹'(\')›) and
member (‹(‹notation=‹infix∈››_/ ∈ _)› [51, 51] 50)
abbreviation not_member where"not_member x A \ \ (x \ A)"🍋‹non-membership› notation
not_member (‹'(\')›) and
not_member (‹(‹notation=‹infix∉››_/ ∉ _)› [51, 51] 50)
open_bundle member_ASCII_syntax begin notation (ASCII)
member (‹'(:')›) and
member (‹(‹notation=‹infix :››_/ : _)› [51, 51] 50) and
not_member (‹'(~:')›) and
not_member (‹(‹notation=‹infix ~:››_/ ~: _)› [51, 51] 50) end
syntax (ASCII) "_Collect" :: "pttrn \ 'a set \ bool \ 'a set" (‹(‹indent=1 notation=‹mixfix set comprehension››{(_/: _)./ _})›) syntax "_Collect" :: "pttrn \ 'a set \ bool \ 'a set" (‹(‹indent=1 notation=‹mixfix set comprehension››{(_/ ∈ _)./ _})›) translations "{p:A. P}"⇀"CONST Collect (\p. p \ A \ P)"
ML ‹ fun Collect_binder_tr' c [Abs (x, T, t), Const (\<^const_syntax>\Collect\, _) $ Abs (y, _, P)] = if x = y then let
val x' = Syntax_Trans.mark_bound_body (x, T);
val t' = subst_bound (x', t);
val P' = subst_bound (x', P); inSyntax.const c $ Syntax_Trans.mark_bound_abs (x, T) $ P' $ t'end
else raise Match
| Collect_binder_tr' _ _ = raise Match ›
lemma CollectI: "P a \ a \ {x. P x}" by simp
lemma CollectD: "a \ {x. P x} \ P a" by simp
lemma Collect_cong: "(\x. P x = Q x) \ {x. P x} = {x. Q x}" by simp
text‹
Simproc for pulling ‹x = t›in‹{x. …∧ x = t ∧…}› to the front (and similarly for‹t = x›): ›
simproc_setup defined_Collect ("{x. P x \ Q x}") = ‹
K (Quantifier1.rearrange_Collect
(fn ctxt =>
resolve_tac ctxt @{thms Collect_cong} 1 THEN
resolve_tac ctxt @{thms iffI} 1 THEN
ALLGOALS
(EVERY' [REPEAT_DETERM o eresolve_tac ctxt @{thms conjE},
DEPTH_SOLVE_1 o (assume_tac ctxt ORELSE' resolve_tac ctxt @{thms conjI})]))) ›
lemmas CollectE = CollectD [elim_format]
lemma set_eqI: assumes"\x. x \ A \ x \ B" shows"A = B" proof - from assms have"{x. x \ A} = {x. x \ B}" by simp thenshow ?thesis by simp qed
lemma set_eq_iff: "A = B \ (\x. x \ A \ x \ B)" by (auto intro:set_eqI)
lemma Collect_eqI: assumes"\x. P x = Q x" shows"Collect P = Collect Q" using assms by (auto intro: set_eqI)
text‹Lifting of predicate class instances›
instantiation set :: (type) boolean_algebra begin
definition less_eq_set where"A \ B \ (\x. member x A) \ (\x. member x B)"
definition less_set where"A < B \ (\x. member x A) < (\x. member x B)"
definition inf_set where"A \ B = Collect ((\x. member x A) \ (\x. member x B))"
definition sup_set where"A \ B = Collect ((\x. member x A) \ (\x. member x B))"
definition bot_set where"\ = Collect \"
definition top_set where"\ = Collect \"
definition uminus_set where"- A = Collect (- (\x. member x A))"
definition minus_set where"A - B = Collect ((\x. member x A) - (\x. member x B))"
syntax_consts "_setlessAll""_setleAll"⇌ All and "_setlessEx""_setleEx"⇌ Ex and "_setleEx1"⇌ Ex1
translations "\A\B. P"⇀"\A. A \ B \ P" "\A\B. P"⇀"\A. A \ B \ P" "\A\B. P"⇀"\A. A \ B \ P" "\A\B. P"⇀"\A. A \ B \ P" "\!A\B. P"⇀"\!A. A \ B \ P"
print_translation‹ let
val All_binder = Mixfix.binder_name 🍋‹All›;
val Ex_binder = Mixfix.binder_name 🍋‹Ex›;
val impl = 🍋‹HOL.implies›;
val conj = 🍋‹HOL.conj›;
val sbset = 🍋‹subset›;
val sbset_eq = 🍋‹subset_eq›;
val trans =
[((All_binder, impl, sbset), 🍋‹_setlessAll›),
((All_binder, impl, sbset_eq), 🍋‹_setleAll›),
((Ex_binder, conj, sbset), 🍋‹_setlessEx›),
((Ex_binder, conj, sbset_eq), 🍋‹_setleEx›)];
fun mk v (v', T) c n P = if v = v' andalso not (Term.exists_subterm (fn Free (x, _) => x = v | _ => false) n) thenSyntax.const c $ Syntax_Trans.mark_bound_body (v', T) $ n $ P
else raise Match;
fun tr' q = (q, fn _ =>
(fn [Const (🍋‹_bound›, _) $ Free (v, 🍋‹set _›),
Const (c, _) $
(Const (d, _) $ (Const (🍋‹_bound›, _) $ Free (v', T)) $ n) $ P] =>
(case AList.lookup (=) trans (q, c, d) of
NONE => raise Match
| SOME l => mk v (v', T) l n P)
| _ => raise Match)); in
[tr' All_binder, tr' Ex_binder] end ›
text‹ 🚫
Translate between ‹{e | x1…xn. P}›and‹{u. ∃x1…xn. u = e ∧ P}›; ‹{y. ∃x1…xn. y = e ∧ P}›is only translated if‹[0..n] ⊆ bvs e›. ›
syntax "_Setcompr" :: "'a \ idts \ bool \ 'a set"
(‹(‹indent=1 notation=‹mixfix set comprehension››{_ |/_./ _})›)
syntax_consts "_Setcompr"⇌ Collect
parse_translation‹ let
val ex_tr = snd (Syntax_Trans.mk_binder_tr ("EX ", 🍋‹Ex›));
print_translation‹ let
val ex_tr' = snd (Syntax_Trans.mk_binder_tr' (🍋‹Ex›, "DUMMY"));
fun setcompr_tr' ctxt [Abs (abs as (_, _, P))] = let fun check (Const (🍋‹Ex›, _) $ Abs (_, _, P), n) = check (P, n + 1)
| check (Const (🍋‹HOL.conj›, _) $
(Const (🍋‹HOL.eq›, _) $ Bound m $ e) $ P, n) =
n > 0 andalso m = n andalso not (loose_bvar1 (P, n)) andalso
subset (=) (0 upto (n - 1), add_loose_bnos (e, 0, []))
| check _ = false;
fun tr' (_ $ abs) = let val _ $ idts $ (_ $ (_ $ _ $ e) $ Q) = ex_tr' ctxt [abs] inSyntax.const 🍋‹_Setcompr› $ e $ idts $ Q end; in if check (P, 0) then tr' P
else let
val (x as _ $ Free(xN, _), t) = Syntax_Trans.atomic_abs_tr' ctxt abs;
val M = Syntax.const 🍋‹_Coll› $ x $ t; in case t of
Const (🍋‹HOL.conj›, _) $
(Const (🍋‹Set.member›, _) $
(Const (🍋‹_bound›, _) $ Free (yN, _)) $ A) $ P => if xN = yN thenSyntax.const 🍋‹_Collect› $ x $ A $ P else M
| _ => M end end; in [(🍋‹Collect›, setcompr_tr')] end ›
simproc_setup defined_Bex ("\x\A. P x \ Q x") = ‹
K (Quantifier1.rearrange_Bex (fn ctxt => unfold_tac ctxt @{thms Bex_def})) ›
simproc_setup defined_All ("\x\A. P x \ Q x") = ‹
K (Quantifier1.rearrange_Ball (fn ctxt => unfold_tac ctxt @{thms Ball_def})) ›
lemma ballI [intro!]: "(\x. x \ A \ P x) \ \x\A. P x" by (simp add: Ball_def)
lemmas strip = impI allI ballI
lemma bspec [dest?]: "\x\A. P x \ x \ A \ P x" by (simp add: Ball_def)
lemma ballE [elim]: "\x\A. P x \ (P x \ Q) \ (x \ A \ Q) \ Q" unfolding Ball_def by blast
lemma bexI [intro]: "P x \ x \ A \ \x\A. P x" 🍋‹Normally the best argument order: ‹P x›constrains the choice of ‹x ∈ A›.› unfolding Bex_def by blast
lemma rev_bexI [intro?]: "x \ A \ P x \ \x\A. P x" 🍋‹The best argument order when there is only one ‹x ∈ A›.› unfolding Bex_def by blast
lemma bexCI: "(\x\A. \ P x \ P a) \ a \ A \ \x\A. P x" unfolding Bex_def by blast
lemma bexE [elim!]: "\x\A. P x \ (\x. x \ A \ P x \ Q) \ Q" unfolding Bex_def by blast
lemma ball_triv [simp]: "(\x\A. P) \ ((\x. x \ A) \ P)" 🍋‹trivial rewrite rule.› by (simp add: Ball_def)
lemma bex_triv [simp]: "(\x\A. P) \ ((\x. x \ A) \ P)" 🍋‹Dual form for existentials.› by (simp add: Bex_def)
lemma bex_triv_one_point1 [simp]: "(\x\A. x = a) \ a \ A" by blast
lemma bex_triv_one_point2 [simp]: "(\x\A. a = x) \ a \ A" by blast
lemma bex_one_point1 [simp]: "(\x\A. x = a \ P x) \ a \ A \ P a" by blast
lemma bex_one_point2 [simp]: "(\x\A. a = x \ P x) \ a \ A \ P a" by blast
lemma ball_one_point1 [simp]: "(\x\A. x = a \ P x) \ (a \ A \ P a)" by blast
lemma ball_one_point2 [simp]: "(\x\A. a = x \ P x) \ (a \ A \ P a)" by blast
lemma ball_conj_distrib: "(\x\A. P x \ Q x) \ (\x\A. P x) \ (\x\A. Q x)" by blast
lemma bex_disj_distrib: "(\x\A. P x \ Q x) \ (\x\A. P x) \ (\x\A. Q x)" by blast
text‹Congruence rules›
lemma ball_cong: "\ A = B; \x. x \ B \ P x \ Q x \ \
(∀x∈A. P x) ⟷ (∀x∈B. Q x)" by (simp add: Ball_def)
lemma ball_cong_simp [cong]: "\ A = B; \x. x \ B =simp=> P x \ Q x \ \
(∀x∈A. P x) ⟷ (∀x∈B. Q x)" by (simp add: simp_implies_def Ball_def)
lemma bex_cong: "\ A = B; \x. x \ B \ P x \ Q x \ \
(∃x∈A. P x) ⟷ (∃x∈B. Q x)" by (simp add: Bex_def cong: conj_cong)
lemma bex_cong_simp [cong]: "\ A = B; \x. x \ B =simp=> P x \ Q x \ \
(∃x∈A. P x) ⟷ (∃x∈B. Q x)" by (simp add: simp_implies_def Bex_def cong: conj_cong)
lemma bex1_def: "(\!x\X. P x) \ (\x\X. P x) \ (\x\X. \y\X. P x \ P y \ x = y)" by auto
subsection ‹Basic operations›
subsubsection ‹Subsets›
lemma subsetI [intro!]: "(\x. x \ A \ x \ B) \ A \ B" by (simp add: less_eq_set_def le_fun_def)
text‹ 🚫
Map the type ‹'a set \ anything\ to just \'a›; foroverloading constants
whose first argument has type ‹'a set\. ›
lemma subsetD [elim, intro?]: "A \ B \ c \ A \ c \ B" by (simp add: less_eq_set_def le_fun_def) 🍋‹Rule in Modus Ponens style.›
lemma rev_subsetD [intro?,no_atp]: "c \ A \ A \ B \ c \ B" 🍋‹The same, with reversed premises forusewith @{method erule} -- cf. @{thm rev_mp}.› by (rule subsetD)
lemma subsetCE [elim,no_atp]: "A \ B \ (c \ A \ P) \ (c \ B \ P) \ P" 🍋‹Classical elimination rule.› by (auto simp add: less_eq_set_def le_fun_def)
lemma subset_eq: "A \ B \ (\x\A. x \ B)" by blast
lemma contra_subsetD [no_atp]: "A \ B \ c \ B \ c \ A" by blast
lemma subset_refl: "A \ A" by (fact order_refl) (* already [iff] *)
lemma subset_trans: "A \ B \ B \ C \ A \ C" by (fact order_trans)
lemma subset_not_subset_eq [code]: "A \ B \ A \ B \ \ B \ A" by (fact less_le_not_le)
lemma eq_mem_trans: "a = b \ b \ A \ a \ A" by simp
lemma UNIV_I [simp]: "x \ UNIV" by (simp add: UNIV_def)
declare UNIV_I [intro] 🍋‹unsafe makes it less likely to cause problems›
lemma UNIV_witness [intro?]: "\x. x \ UNIV" by simp
lemma subset_UNIV: "A \ UNIV" by (fact top_greatest) (* already simp *)
text‹ 🚫
Eta-contracting these two rules (to remove ‹P›) causes them to be ignored because of their interaction with congruence rules. ›
lemma ball_UNIV [simp]: "Ball UNIV P \ All P" by (simp add: Ball_def)
lemma bex_UNIV [simp]: "Bex UNIV P \ Ex P" by (simp add: Bex_def)
lemma UNIV_eq_I: "(\x. x \ A) \ UNIV = A" by auto
lemma UNIV_not_empty [iff]: "UNIV \ {}" by (blast elim: equalityE)
lemma empty_not_UNIV[simp]: "{} \ UNIV" by blast
subsubsection ‹The Powerset operator -- Pow›
definition Pow :: "'a set \ 'a set set" where Pow_def: "Pow A = {B. B \ A}"
lemma Pow_iff [iff]: "A \ Pow B \ A \ B" by (simp add: Pow_def)
lemma PowI: "A \ B \ A \ Pow B" by (simp add: Pow_def)
lemma PowD: "A \ Pow B \ A \ B" by (simp add: Pow_def)
lemma Pow_bottom: "{} \ Pow B" by simp
lemma Pow_top: "A \ Pow A" by simp
lemma Pow_not_empty: "Pow A \ {}" using Pow_top by blast
subsubsection ‹Set complement›
lemma Compl_iff [simp]: "c \ - A \ c \ A" by (simp add: fun_Compl_def uminus_set_def)
lemma ComplI [intro!]: "(c \ A \ False) \ c \ - A" by (simp add: fun_Compl_def uminus_set_def) blast
text‹ 🚫
This form, with negated conclusion, works well with the Classical prover.
Negated assumptions behave like formulae on the right side of the
notional turnstile \dots ›
lemma ComplD [dest!]: "c \ - A \ c \ A" by simp
lemmas ComplE = ComplD [elim_format]
lemma Compl_eq: "- A = {x. \ x \ A}" by blast
subsubsection ‹Binary intersection›
abbreviation inter :: "'a set \ 'a set \ 'a set" (infixl‹∩› 70) where"(\) \ inf"
notation (ASCII)
inter (infixl‹Int› 70)
lemma Int_def: "A \ B = {x. x \ A \ x \ B}" by (simp add: inf_set_def inf_fun_def)
lemma Int_iff [simp]: "c \ A \ B \ c \ A \ c \ B" unfolding Int_def by blast
lemma IntI [intro!]: "c \ A \ c \ B \ c \ A \ B" by simp
lemma IntD1: "c \ A \ B \ c \ A" by simp
lemma IntD2: "c \ A \ B \ c \ B" by simp
lemma IntE [elim!]: "c \ A \ B \ (c \ A \ c \ B \ P) \ P" by simp
subsubsection ‹Binary union›
abbreviation union :: "'a set \ 'a set \ 'a set" (infixl‹∪› 65) where"union \ sup"
notation (ASCII)
union (infixl‹Un› 65)
lemma Un_def: "A \ B = {x. x \ A \ x \ B}" by (simp add: sup_set_def sup_fun_def)
lemma Un_iff [simp]: "c \ A \ B \ c \ A \ c \ B" unfolding Un_def by blast
lemma UnI1 [elim?]: "c \ A \ c \ A \ B" by simp
lemma UnI2 [elim?]: "c \ B \ c \ A \ B" by simp
text‹🚫 Classical introduction rule: no commitment to‹A› vs. ‹B›.› lemma UnCI [intro!]: "(c \ B \ c \ A) \ c \ A \ B" by auto
lemma UnE [elim!]: "c \ A \ B \ (c \ A \ P) \ (c \ B \ P) \ P" unfolding Un_def by blast
lemma insert_def: "insert a B = {x. x = a} \ B" by (simp add: insert_compr Un_def)
subsubsection ‹Set difference›
lemma Diff_iff [simp]: "c \ A - B \ c \ A \ c \ B" by (simp add: minus_set_def fun_diff_def)
lemma DiffI [intro!]: "c \ A \ c \ B \ c \ A - B" by simp
lemma DiffD1: "c \ A - B \ c \ A" by simp
lemma DiffD2: "c \ A - B \ c \ B \ P" by simp
lemma DiffE [elim!]: "c \ A - B \ (c \ A \ c \ B \ P) \ P" by simp
lemma set_diff_eq: "A - B = {x. x \ A \ x \ B}" by blast
lemma Compl_eq_Diff_UNIV: "- A = (UNIV - A)" by blast
abbreviation sym_diff :: "'a set \ 'a set \ 'a set"where "sym_diff A B \ ((A - B) \ (B-A))"
subsubsection ‹Augmenting a set -- 🍋‹insert››
lemma insert_iff [simp]: "a \ insert b A \ a = b \ a \ A" unfolding insert_def by blast
lemma insertI1: "a \ insert a B" by simp
lemma insertI2: "a \ B \ a \ insert b B" by simp
lemma insertE [elim!]: "a \ insert b A \ (a = b \ P) \ (a \ A \ P) \ P" unfolding insert_def by blast
lemma insertCI [intro!]: "(a \ B \ a = b) \ a \ insert b B" 🍋‹Classical introduction rule.› by auto
lemma subset_insert_iff: "A \ insert x B \ (if x \ A then A - {x} \ B else A \ B)" by auto
lemma set_insert: assumes"x \ A" obtains B where"A = insert x B"and"x \ B" proof show"A = insert x (A - {x})"using assms by blast show"x \ A - {x}"by blast qed
lemma insert_ident: "x \ A \ x \ B \ insert x A = insert x B \ A = B" by auto
lemma insert_eq_iff: assumes"a \ A""b \ B" shows"insert a A = insert b B \
(if a = b then A = B else ∃C. A = insert b C ∧ b ∉ C ∧ B = insert a C ∧ a ∉ C)"
(is"?L \ ?R") proof show ?R if ?L proof (cases "a = b") case True with assms ‹?L›show ?R by (simp add: insert_ident) next case False let ?C = "A - {b}" have"A = insert b ?C \ b \ ?C \ B = insert a ?C \ a \ ?C" using assms ‹?L›‹a ≠ b›by auto thenshow ?R using‹a ≠ b›by auto qed show ?L if ?R using that by (auto split: if_splits) qed
lemma insert_UNIV[simp]: "insert x UNIV = UNIV" by auto
subsubsection ‹Singletons, using insert›
lemma singletonI [intro!]: "a \ {a}" 🍋‹Redundant? But unlike ‹insertCI›, it proves the subgoal immediately!› by (rule insertI1)
lemma singletonD [dest!]: "b \ {a} \ b = a" by blast
lemmas singletonE = singletonD [elim_format]
lemma singleton_iff: "b \ {a} \ b = a" by blast
lemma singleton_inject [dest!]: "{a} = {b} \ a = b" by blast
lemma singleton_insert_inj_eq [iff]: "{b} = insert a A \ a = b \ A \ {b}" by blast
lemma singleton_insert_inj_eq' [iff]: "insert a A = {b} \ a = b \ A \ {b}" by blast
lemma subset_singletonD: "A \ {x} \ A = {} \ A = {x}" by fast
lemma subset_singleton_iff: "X \ {a} \ X = {} \ X = {a}" by blast
lemma subset_singleton_iff_Uniq: "(\a. A \ {a}) \ (\\<^sub>\\<^sub>1x. x \ A)" unfolding Uniq_def by blast
lemma singleton_conv [simp]: "{x. x = a} = {a}" by blast
lemma singleton_conv2 [simp]: "{x. a = x} = {a}" by blast
lemma Diff_single_insert: "A - {x} \ B \ A \ insert x B" by blast
lemma subset_Diff_insert: "A \ B - insert x C \ A \ B - C \ x \ A" by blast
lemma doubleton_eq_iff: "{a, b} = {c, d} \ a = c \ b = d \ a = d \ b = c" by (blast elim: equalityE)
lemma Un_singleton_iff: "A \ B = {x} \ A = {} \ B = {x} \ A = {x} \ B = {} \ A = {x} \ B = {x}" by auto
lemma singleton_Un_iff: "{x} = A \ B \ A = {} \ B = {x} \ A = {x} \ B = {} \ A = {x} \ B = {x}" by auto
subsubsection ‹Image of a set under a function›
text‹Frequently ‹b› does not have the syntactic form of ‹f x›.›
definition image :: "('a \ 'b) \ 'a set \ 'b set" (infixr‹`› 90) where"f ` A = {y. \x\A. y = f x}"
lemma image_eqI [simp, intro]: "b = f x \ x \ A \ b \ f ` A" unfolding image_def by blast
lemma imageI: "x \ A \ f x \ f ` A" by (rule image_eqI) (rule refl)
lemma rev_image_eqI: "x \ A \ b = f x \ b \ f ` A" 🍋‹This version's more effective when we already have the required \x\.\ by (rule image_eqI)
lemma imageE [elim!]: assumes"b \ (\x. f x) ` A"🍋‹The eta-expansion gives variable-name preservation.› obtains x where"b = f x"and"x \ A" using assms unfolding image_def by blast
lemma Compr_image_eq: "{x \ f ` A. P x} = f ` {x \ A. P (f x)}" by auto
lemma image_Un: "f ` (A \ B) = f ` A \ f ` B" by blast
lemma image_iff: "z \ f ` A \ (\x\A. z = f x)" by blast
lemma image_subsetI: "(\x. x \ A \ f x \ B) \ f ` A \ B" 🍋‹Replaces the three steps ‹subsetI›, ‹imageE›, ‹hypsubst›, but breaks too many existing proofs.› by blast
lemma image_subset_iff: "f ` A \ B \ (\x\A. f x \ B)" 🍋‹This rewrite rule would confuse users if made default.› by blast
lemma subset_imageE: assumes"B \ f ` A" obtains C where"C \ A"and"B = f ` C" proof - from assms have"B = f ` {a \ A. f a \ B}"by fast moreoverhave"{a \ A. f a \ B} \ A"by blast ultimatelyshow thesis by (blast intro: that) qed
lemma subset_image_iff: "B \ f ` A \ (\AA\A. B = f ` AA)" by (blast elim: subset_imageE)
lemma image_ident [simp]: "(\x. x) ` Y = Y" by blast
lemma image_empty [simp]: "f ` {} = {}" by blast
lemma image_insert [simp]: "f ` insert a B = insert (f a) (f ` B)" by blast
lemma image_constant: "x \ A \ (\x. c) ` A = {c}" by auto
lemma image_constant_conv: "(\x. c) ` A = (if A = {} then {} else {c})" by auto
lemma image_image: "f ` (g ` A) = (\x. f (g x)) ` A" by blast
lemma insert_image [simp]: "x \ A \ insert (f x) (f ` A) = f ` A" by blast
lemma image_is_empty [iff]: "f ` A = {} \ A = {}" by blast
lemma empty_is_image [iff]: "{} = f ` A \ A = {}" by blast
lemma image_Collect: "f ` {x. P x} = {f x | x. P x}" 🍋‹NOT suitable as a default simp rule: the RHS isn't simpler than the LHS, with its implicit quantifier and conjunction. Also image enjoys better
equational properties than does the RHS.› by blast
lemma if_image_distrib [simp]: "(\x. if P x then f x else g x) ` S = f ` (S \ {x. P x}) \ g ` (S \ {x. \ P x})" by auto
lemma image_cong: "f ` M = g ` N"if"M = N""\x. x \ N \ f x = g x" using that by (simp add: image_def)
lemma image_cong_simp [cong]: "f ` M = g ` N"if"M = N""\x. x \ N =simp=> f x = g x" using that image_cong [of M N f g] by (simp add: simp_implies_def)
lemma image_Int_subset: "f ` (A \ B) \ f ` A \ f ` B" by blast
lemma image_diff_subset: "f ` A - f ` B \ f ` (A - B)" by blast
lemma Setcompr_eq_image: "{f x |x. x \ A} = f ` A" by blast
lemma setcompr_eq_image: "{f x |x. P x} = f ` {x. P x}" by auto
lemma ball_imageD: "\x\f ` A. P x \ \x\A. P (f x)" by simp
lemma bex_imageD: "\x\f ` A. P x \ \x\A. P (f x)" by auto
lemma image_add_0 [simp]: "(+) (0::'a::comm_monoid_add) ` S = S" by auto
theorem Cantors_theorem: "\f. f ` A = Pow A" proof assume"\f. f ` A = Pow A" thenobtain f where f: "f ` A = Pow A" .. let ?X = "{a \ A. a \ f a}" have"?X \ Pow A"by blast thenhave"?X \ f ` A"by (simp only: f) thenobtain x where"x \ A"and"f x = ?X"by blast thenshow False by blast qed
text‹🚫 Range of a function -- just an abbreviationfor image!›
abbreviation range :: "('a \ 'b) \ 'b set"🍋‹of function› where"range f \ f ` UNIV"
lemma range_eqI: "b = f x \ b \ range f" by simp
lemma rangeI: "f x \ range f" by simp
lemma rangeE [elim?]: "b \ range (\x. f x) \ (\x. b = f x \ P) \ P" by (rule imageE)
lemma range_subsetD: "range f \ B \ f i \ B" by blast
lemma full_SetCompr_eq: "{u. \x. u = f x} = range f" by auto
lemma range_composition: "range (\x. f (g x)) = f ` range g" by auto
(*Would like to add these, but the existing code only searches for the outer-level constant, which in this case is just Set.member; we instead need to use term-nets to associate patterns with rules. Also, if a rule fails to apply, then the formula should be kept. [("uminus", Compl_iff RS iffD1), ("minus", [Diff_iff RS iffD1]), ("Int", [IntD1,IntD2]), ("Collect", [CollectD]), ("Inter", [InterD]), ("INTER", [INT_D])]
*)
subsection ‹Further operations andlemmas›
subsubsection ‹The ``proper subset'' relation›
lemma psubsetI [intro!]: "A \ B \ A \ B \ A \ B" unfolding less_le by blast
lemma psubsetE [elim!]: "A \ B \ (A \ B \ \ B \ A \ R) \ R" unfolding less_le by blast
lemma psubset_insert_iff: "A \ insert x B \ (if x \ B then A \ B else if x \ A then A - {x} \ B else A \ B)" by (auto simp add: less_le subset_insert_iff)
lemma psubset_eq: "A \ B \ A \ B \ A \ B" by (simp only: less_le)
lemma psubset_imp_subset: "A \ B \ A \ B" by (simp add: psubset_eq)
lemma psubset_trans: "A \ B \ B \ C \ A \ C" unfolding less_le by (auto dest: subset_antisym)
lemma psubsetD: "A \ B \ c \ A \ c \ B" unfolding less_le by (auto dest: subsetD)
lemma psubset_subset_trans: "A \ B \ B \ C \ A \ C" by (auto simp add: psubset_eq)
lemma subset_psubset_trans: "A \ B \ B \ C \ A \ C" by (auto simp add: psubset_eq)
lemma psubset_imp_ex_mem: "A \ B \ \b. b \ B - A" unfolding less_le by blast
lemma atomize_ball: "(\x. x \ A \ P x) \ Trueprop (\x\A. P x)" by (simp only: Ball_def atomize_all atomize_imp)
lemmas [symmetric, rulify] = atomize_ball and [symmetric, defn] = atomize_ball
lemma image_Pow_mono: "f ` A \ B \ image f ` Pow A \ Pow B" by blast
lemma image_Pow_surj: "f ` A = B \ image f ` Pow A = Pow B" by (blast elim: subset_imageE)
subsubsection ‹Derived rules involving subsets.›
text‹‹insert›.›
lemma subset_insertI: "B \ insert a B" by (rule subsetI) (erule insertI2)
lemma subset_insertI2: "A \ B \ A \ insert b B" by blast
lemma subset_insert: "x \ A \ A \ insert x B \ A \ B" by blast
text‹🚫 Finite Union -- the least upper bound of two sets.›
lemma Un_upper1: "A \ A \ B" by (fact sup_ge1)
lemma Un_upper2: "B \ A \ B" by (fact sup_ge2)
lemma Un_least: "A \ C \ B \ C \ A \ B \ C" by (fact sup_least)
text‹🚫 Finite Intersection -- the greatest lower bound of two sets.›
lemma Int_lower1: "A \ B \ A" by (fact inf_le1)
lemma Int_lower2: "A \ B \ B" by (fact inf_le2)
lemma Int_greatest: "C \ A \ C \ B \ C \ A \ B" by (fact inf_greatest)
text‹🚫 Set difference.›
lemma Diff_subset[simp]: "A - B \ A" by blast
lemma Diff_subset_conv: "A - B \ C \ A \ B \ C" by blast
lemma Collect_const [simp]: "{s. P} = (if P then UNIV else {})" 🍋‹supersedes ‹Collect_False_empty›› by auto
lemma subset_empty [simp]: "A \ {} \ A = {}" by (fact bot_unique)
lemma not_psubset_empty [iff]: "\ (A < {})" by (fact not_less_bot) (*already simp *)
lemma Collect_subset [simp]: "{x\A. P x} \ A"by auto
lemma Collect_empty_eq [simp]: "Collect P = {} \ (\x. \ P x)" by blast
lemma empty_Collect_eq [simp]: "{} = Collect P \ (\x. \ P x)" by blast
lemma Collect_neg_eq: "{x. \ P x} = - {x. P x}" by blast
lemma Collect_disj_eq: "{x. P x \ Q x} = {x. P x} \ {x. Q x}" by blast
lemma Collect_imp_eq: "{x. P x \ Q x} = - {x. P x} \ {x. Q x}" by blast
lemma Collect_conj_eq: "{x. P x \ Q x} = {x. P x} \ {x. Q x}" by blast
lemma Collect_conj_eq2: "{x \ A. P x \ Q x} = {x \ A. P x} \ {x \ A. Q x}" by blast
lemma Collect_mono_iff: "Collect P \ Collect Q \ (\x. P x \ Q x)" by blast
text‹🚫‹insert›.›
lemma insert_is_Un: "insert a A = {a} \ A" 🍋‹NOT SUITABLE FOR REWRITING since ‹{a} ≡ insert a {}›› by blast
lemma insert_not_empty [simp]: "insert a A \ {}" and empty_not_insert [simp]: "{} \ insert a A" by blast+
lemma insert_absorb: "a \ A \ insert a A = A" 🍋‹‹[simp]› causes recursive calls when there are nested inserts› 🍋‹with🚫‹quadratic› running time› by blast
lemma insert_absorb2 [simp]: "insert x (insert x A) = insert x A" by blast
lemma insert_commute: "insert x (insert y A) = insert y (insert x A)" by blast
lemma insert_subset [simp]: "insert x A \ B \ x \ B \ A \ B" by blast
lemma mk_disjoint_insert: "a \ A \ \B. A = insert a B \ a \ B" 🍋‹use new ‹B› rather than ‹A - {a}›to avoid infinite unfolding› by (rule exI [where x = "A - {a}"]) blast
lemma insert_Collect: "insert a (Collect P) = {u. u \ a \ P u}" by auto
lemma insert_inter_insert [simp]: "insert a A \ insert a B = insert a (A \ B)" by blast
lemma insert_disjoint [simp]: "insert a A \ B = {} \ a \ B \ A \ B = {}" "{} = insert a A \ B \ a \ B \ {} = A \ B" by auto
lemma disjoint_insert [simp]: "B \ insert a A = {} \ a \ B \ B \ A = {}" "{} = A \ insert b B \ b \ A \ {} = A \ B" by auto
text‹🚫‹Int››
lemma Int_absorb: "A \ A = A" by (fact inf_idem) (* already simp *)
lemma Int_left_absorb: "A \ (A \ B) = A \ B" by (fact inf_left_idem)
lemma Int_commute: "A \ B = B \ A" by (fact inf_commute)
lemma Int_left_commute: "A \ (B \ C) = B \ (A \ C)" by (fact inf_left_commute)
lemma Int_assoc: "(A \ B) \ C = A \ (B \ C)" by (fact inf_assoc)
lemmas Int_ac = Int_assoc Int_left_absorb Int_commute Int_left_commute 🍋‹Intersection is an AC-operator›
lemma Int_absorb1: "B \ A \ A \ B = B" by (fact inf_absorb2)
lemma Int_absorb2: "A \ B \ A \ B = A" by (fact inf_absorb1)
lemma Int_empty_left: "{} \ B = {}" by (fact inf_bot_left) (* already simp *)
lemma Int_empty_right: "A \ {} = {}" by (fact inf_bot_right) (* already simp *)
lemma disjoint_eq_subset_Compl: "A \ B = {} \ A \ - B" by blast
lemma disjoint_iff: "A \ B = {} \ (\x. x\A \ x \ B)" by blast
lemma disjoint_iff_not_equal: "A \ B = {} \ (\x\A. \y\B. x \ y)" by blast
lemma Int_UNIV_left: "UNIV \ B = B" by (fact inf_top_left) (* already simp *)
lemma Int_UNIV_right: "A \ UNIV = A" by (fact inf_top_right) (* already simp *)
lemma Int_Un_distrib: "A \ (B \ C) = (A \ B) \ (A \ C)" by (fact inf_sup_distrib1)
lemma Int_Un_distrib2: "(B \ C) \ A = (B \ A) \ (C \ A)" by (fact inf_sup_distrib2)
lemma Int_UNIV: "A \ B = UNIV \ A = UNIV \ B = UNIV" by (fact inf_eq_top_iff) (* already simp *)
lemma Int_subset_iff: "C \ A \ B \ C \ A \ C \ B" by (fact le_inf_iff) (* already simp *)
lemma Int_Collect: "x \ A \ {x. P x} \ x \ A \ P x" by blast
text‹🚫‹Un›.›
lemma Un_absorb: "A \ A = A" by (fact sup_idem) (* already simp *)
lemma Un_left_absorb: "A \ (A \ B) = A \ B" by (fact sup_left_idem)
lemma Un_commute: "A \ B = B \ A" by (fact sup_commute)
lemma Un_left_commute: "A \ (B \ C) = B \ (A \ C)" by (fact sup_left_commute)
lemma Un_assoc: "(A \ B) \ C = A \ (B \ C)" by (fact sup_assoc)
lemmas Un_ac = Un_assoc Un_left_absorb Un_commute Un_left_commute 🍋‹Union is an AC-operator›
lemma Un_absorb1: "A \ B \ A \ B = B" by (fact sup_absorb2)
lemma Un_absorb2: "B \ A \ A \ B = A" by (fact sup_absorb1)
lemma Un_empty_left: "{} \ B = B" by (fact sup_bot_left) (* already simp *)
lemma Un_empty_right: "A \ {} = A" by (fact sup_bot_right) (* already simp *)
lemma Un_UNIV_left: "UNIV \ B = UNIV" by (fact sup_top_left) (* already simp *)
lemma Un_UNIV_right: "A \ UNIV = UNIV" by (fact sup_top_right) (* already simp *)
lemma Un_insert_left [simp]: "(insert a B) \ C = insert a (B \ C)" by blast
lemma Un_insert_right [simp]: "A \ (insert a B) = insert a (A \ B)" by blast
lemma Int_insert_left: "(insert a B) \ C = (if a \ C then insert a (B \ C) else B \ C)" by auto
lemma Int_insert_left_if0 [simp]: "a \ C \ (insert a B) \ C = B \ C" by auto
lemma Int_insert_left_if1 [simp]: "a \ C \ (insert a B) \ C = insert a (B \ C)" by auto
lemma Int_insert_right: "A \ (insert a B) = (if a \ A then insert a (A \ B) else A \ B)" by auto
lemma Int_insert_right_if0 [simp]: "a \ A \ A \ (insert a B) = A \ B" by auto
lemma Int_insert_right_if1 [simp]: "a \ A \ A \ (insert a B) = insert a (A \ B)" by auto
lemma Un_Int_distrib: "A \ (B \ C) = (A \ B) \ (A \ C)" by (fact sup_inf_distrib1)
lemma Un_Int_distrib2: "(B \ C) \ A = (B \ A) \ (C \ A)" by (fact sup_inf_distrib2)
lemma Un_Int_crazy: "(A \ B) \ (B \ C) \ (C \ A) = (A \ B) \ (B \ C) \ (C \ A)" by blast
lemma subset_Un_eq: "A \ B \ A \ B = B" by (fact le_iff_sup)
lemma Un_empty [iff]: "A \ B = {} \ A = {} \ B = {}" by (fact sup_eq_bot_iff) (* FIXME: already simp *)
lemma Un_subset_iff: "A \ B \ C \ A \ C \ B \ C" by (fact le_sup_iff) (* already simp *)
lemma Un_Diff_Int: "(A - B) \ (A \ B) = A" by blast
lemma Diff_Int2: "A \ C - B \ C = A \ C - B" by blast
lemma subset_UnE: assumes"C \ A \ B" obtains A' B'where"A' \ A""B' \ B""C = A' \ B'" proof show"C \ A \ A""C \ B \ B""C = (C \ A) \ (C \ B)" using assms by blast+ qed
lemma Un_Int_eq [simp]: "(S \ T) \ S = S""(S \ T) \ T = T""S \ (S \ T) = S""T \ (S \ T) = T" by auto
lemma Int_Un_eq [simp]: "(S \ T) \ S = S""(S \ T) \ T = T""S \ (S \ T) = S""T \ (S \ T) = T" by auto
text‹🚫 Set complement›
lemma Compl_disjoint [simp]: "A \ - A = {}" by (fact inf_compl_bot)
lemma Compl_disjoint2 [simp]: "- A \ A = {}" by (fact compl_inf_bot)
lemma Compl_partition: "A \ - A = UNIV" by (fact sup_compl_top)
lemma Compl_partition2: "- A \ A = UNIV" by (fact compl_sup_top)
lemma double_complement: "- (-A) = A"for A :: "'a set" by (fact double_compl) (* already simp *)
lemma Compl_Un: "- (A \ B) = (- A) \ (- B)" by (fact compl_sup) (* already simp *)
lemma Compl_Int: "- (A \ B) = (- A) \ (- B)" by (fact compl_inf) (* already simp *)
lemma subset_Compl_self_eq: "A \ - A \ A = {}" by blast
lemma Un_Int_assoc_eq: "(A \ B) \ C = A \ (B \ C) \ C \ A" 🍋‹Halmos, Naive Set Theory, page 16.› by blast
lemma Pow_singleton_iff [simp]: "Pow X = {Y} \ X = {} \ Y = {}" by blast (* somewhat slow *)
lemma Pow_insert: "Pow (insert a A) = Pow A \ (insert a ` Pow A)" by (blast intro: image_eqI [where ?x = "u - {a}"for u])
lemma Pow_Compl: "Pow (- A) = {- B | B. A \ Pow B}" by (blast intro: exI [where ?x = "- u"for u])
lemma Pow_UNIV [simp]: "Pow UNIV = UNIV" by blast
lemma Un_Pow_subset: "Pow A \ Pow B \ Pow (A \ B)" by blast
lemma Pow_Int_eq [simp]: "Pow (A \ B) = Pow A \ Pow B" by blast
text‹🚫 Miscellany.›
lemma Int_Diff_disjoint: "A \ B \ (A - B) = {}" by blast
lemma Int_Diff_Un: "A \ B \ (A - B) = A" by blast
lemma set_eq_subset: "A = B \ A \ B \ B \ A" by blast
lemma subset_iff: "A \ B \ (\t. t \ A \ t \ B)" by blast
lemma subset_iff_psubset_eq: "A \ B \ A \ B \ A = B" unfolding less_le by blast
lemma all_not_in_conv [simp]: "(\x. x \ A) \ A = {}" by blast
lemma ex_in_conv: "(\x. x \ A) \ A \ {}" by blast
lemma ball_simps [simp, no_atp]: "\A P Q. (\x\A. P x \ Q) \ ((\x\A. P x) \ Q)" "\A P Q. (\x\A. P \ Q x) \ (P \ (\x\A. Q x))" "\A P Q. (\x\A. P \ Q x) \ (P \ (\x\A. Q x))" "\A P Q. (\x\A. P x \ Q) \ ((\x\A. P x) \ Q)" "\P. (\x\{}. P x) \ True" "\P. (\x\UNIV. P x) \ (\x. P x)" "\a B P. (\x\insert a B. P x) \ (P a \ (\x\B. P x))" "\P Q. (\x\Collect Q. P x) \ (\x. Q x \ P x)" "\A P f. (\x\f`A. P x) \ (\x\A. P (f x))" "\A P. (\ (\x\A. P x)) \ (\x\A. \ P x)" by auto
lemma bex_simps [simp, no_atp]: "\A P Q. (\x\A. P x \ Q) \ ((\x\A. P x) \ Q)" "\A P Q. (\x\A. P \ Q x) \ (P \ (\x\A. Q x))" "\P. (\x\{}. P x) \ False" "\P. (\x\UNIV. P x) \ (\x. P x)" "\a B P. (\x\insert a B. P x) \ (P a \ (\x\B. P x))" "\P Q. (\x\Collect Q. P x) \ (\x. Q x \ P x)" "\A P f. (\x\f`A. P x) \ (\x\A. P (f x))" "\A P. (\(\x\A. P x)) \ (\x\A. \ P x)" by auto
lemma ex_image_cong_iff [simp, no_atp]: "(\x. x\f`A) \ A \ {}""(\x. x\f`A \ P x) \ (\x\A. P (f x))" by auto
subsubsection ‹Monotonicity of various operations›
lemma image_mono: "A \ B \ f ` A \ f ` B" by blast
lemma Pow_mono: "A \ B \ Pow A \ Pow B" by blast
lemma insert_mono: "C \ D \ insert a C \ insert a D" by blast
lemma Un_mono: "A \ C \ B \ D \ A \ B \ C \ D" by (fact sup_mono)
lemma Int_mono: "A \ C \ B \ D \ A \ B \ C \ D" by (fact inf_mono)
lemma Diff_mono: "A \ C \ D \ B \ A - B \ C - D" by blast
lemma Compl_anti_mono: "A \ B \ - B \ - A" by (fact compl_mono)
text‹🚫 Monotonicity of implications.›
lemma in_mono: "A \ B \ x \ A \ x \ B" by (rule impI) (erule subsetD)
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.