Theory Card_Datatype
theory Card_Datatype
imports "HOL-Library.Cardinality"
begin
section ‹Definitions to prove equations about the cardinality of data types›
subsection ‹Specialised @{term range} constants›
definition rangeIt :: "'a ⇒ ('a ⇒ 'a) ⇒ 'a set"
where "rangeIt x f = range (λn. (f ^^ n) x)"
definition rangeC :: "('a ⇒ 'b) set ⇒ 'b set"
where "rangeC F = (⋃f ∈ F. range f)"
lemma infinite_rangeIt:
assumes inj: "inj f"
and x: "∀y. x ≠ f y"
shows "¬ finite (rangeIt x f)"
proof -
have "inj (λn. (f ^^ n) x)"
proof(rule injI)
fix n m
assume "(f ^^ n) x = (f ^^ m) x"
thus "n = m"
proof(induct n arbitrary: m)
case 0
thus ?case using x by(cases m)(auto intro: sym)
next
case (Suc n)
thus ?case using x by(cases m)(auto intro: sym dest: injD[OF inj])
qed
qed
thus ?thesis
by(auto simp add: rangeIt_def dest: finite_imageD)
qed
lemma in_rangeC: "f ∈ A ⟹ f x ∈ rangeC A"
by(auto simp add: rangeC_def)
lemma in_rangeCE: assumes "y ∈ rangeC A"
obtains f x where "f ∈ A" "y = f x"
using assms by(auto simp add: rangeC_def)
lemma in_rangeC_singleton: "f x ∈ rangeC {f}"
by(auto simp add: rangeC_def)
lemma in_rangeC_singleton_const: "x ∈ rangeC {λ_. x}"
by(rule in_rangeC_singleton)
lemma rangeC_rangeC: "f ∈ rangeC A ⟹ f x ∈ rangeC (rangeC A)"
by(auto simp add: rangeC_def)
lemma rangeC_eq_empty: "rangeC A = {} ⟷ A = {}"
by(auto simp add: rangeC_def)
lemma Ball_rangeC_iff:
"(∀x ∈ rangeC A. P x) ⟷ (∀f ∈ A. ∀x. P (f x))"
by(auto intro: in_rangeC elim: in_rangeCE)
lemma Ball_rangeC_singleton:
"(∀x ∈ rangeC {f}. P x) ⟷ (∀x. P (f x))"
by(simp add: Ball_rangeC_iff)
lemma Ball_rangeC_rangeC:
"(∀x ∈ rangeC (rangeC A). P x) ⟷ (∀f ∈ rangeC A. ∀x. P (f x))"
by(simp add: Ball_rangeC_iff)
lemma finite_rangeC:
assumes inj: "∀f ∈ A. inj f"
and disjoint: "∀f ∈ A. ∀g ∈ A. f ≠ g ⟶ (∀x y. f x ≠ g y)"
shows "finite (rangeC (A :: ('a ⇒ 'b) set)) ⟷ finite A ∧ (A ≠ {} ⟶ finite (UNIV :: 'a set))"
(is "?lhs ⟷ ?rhs")
proof
assume ?lhs
thus ?rhs using inj disjoint
proof(induct "rangeC A" arbitrary: A rule: finite_psubset_induct)
case (psubset A)
show ?case
proof(cases "A = {}")
case True thus ?thesis by simp
next
case False
then obtain f A' where A: "A = insert f A'" and f: "f ∈ A" "f ∉ A'"
by(fastforce dest: mk_disjoint_insert)
from A have rA: "rangeC A = rangeC A' ∪ range f"
by(auto simp add: rangeC_def)
have "¬ range f ⊆ rangeC A'"
proof
assume "range f ⊆ rangeC A'"
moreover obtain x where x: "x ∈ range f" by auto
ultimately have "x ∈ rangeC A'" by auto
then obtain g where "g ∈ A'" "x ∈ range g" by(auto simp add: rangeC_def)
with ‹f ∉ A'› A have "g ∈ A" "f ≠ g" by auto
with ‹f ∈ A› have "⋀x y. f x ≠ g y" by(rule psubset.prems[rule_format])
thus False using x ‹x ∈ range g› by auto
qed
hence "rangeC A' ⊂ rangeC A" unfolding rA by auto
hence "finite A' ∧ (A' ≠ {} ⟶ finite (UNIV :: 'a set))"
using psubset.prems
by -(erule psubset.hyps, auto simp add: A)
with A have "finite A" by simp
moreover with ‹finite (rangeC A)› A ‹∀f ∈ A. inj f›
have "finite (UNIV :: 'a set)"
by(auto simp add: rangeC_def dest: finite_imageD)
ultimately show ?thesis by blast
qed
qed
qed(auto simp add: rangeC_def)
lemma finite_rangeC_singleton_const:
"finite (rangeC {λ_. x})"
by(auto simp add: rangeC_def image_def)
lemma card_Un:
"⟦ finite A; finite B ⟧ ⟹ card (A ∪ B) = card (A) + card (B) - card(A ∩ B)"
by(subst card_Un_Int) simp_all
lemma card_rangeC_singleton_const:
"card (rangeC {λ_. f}) = 1"
by(simp add: rangeC_def image_def)
lemma card_rangeC:
assumes inj: "∀f ∈ A. inj f"
and disjoint: "∀f ∈ A. ∀g ∈ A. f ≠ g ⟶ (∀x y. f x ≠ g y)"
shows "card (rangeC (A :: ('a ⇒ 'b) set)) = CARD('a) * card A"
(is "?lhs = ?rhs")
proof(cases "finite (UNIV :: 'a set) ∧ finite A")
case False
thus ?thesis using False finite_rangeC[OF assms]
by(auto simp add: card_eq_0_iff rangeC_eq_empty)
next
case True
{ fix f
assume "f ∈ A"
hence "card (range f) = CARD('a)" using inj by(simp add: card_image) }
thus ?thesis using disjoint True unfolding rangeC_def
by(subst card_UN_disjoint) auto
qed
lemma rangeC_Int_rangeC:
"⟦ ∀f ∈ A. ∀g ∈ B. ∀x y. f x ≠ g y ⟧ ⟹ rangeC A ∩ rangeC B = {}"
by(auto simp add: rangeC_def)
lemmas rangeC_simps =
in_rangeC_singleton
in_rangeC_singleton_const
rangeC_rangeC
rangeC_eq_empty
Ball_rangeC_singleton
Ball_rangeC_rangeC
finite_rangeC
finite_rangeC_singleton_const
card_rangeC_singleton_const
card_rangeC
rangeC_Int_rangeC
bundle card_datatype =
rangeC_simps [simp]
card_Un [simp]
fun_eq_iff [simp]
Int_Un_distrib [simp]
Int_Un_distrib2 [simp]
card_eq_0_iff [simp]
imageI [simp] image_eqI [simp del]
conj_cong [cong]
infinite_rangeIt [simp]
subsection ‹Cardinality primitives for polymorphic HOL types›
ML ‹
structure Card_Simp_Rules = Named_Thms
(
val name = @{binding card_simps}
val description = "Simplification rules for cardinality of types"
)
›
setup ‹Card_Simp_Rules.setup›
definition card_fun :: "nat ⇒ nat ⇒ nat"
where "card_fun a b = (if a ≠ 0 ∧ b ≠ 0 ∨ b = 1 then b ^ a else 0)"
lemma CARD_fun [card_simps]:
"CARD('a ⇒ 'b) = card_fun CARD('a) CARD('b)"
by(simp add: card_fun card_fun_def)
definition card_sum :: "nat ⇒ nat ⇒ nat"
where "card_sum a b = (if a = 0 ∨ b = 0 then 0 else a + b)"
lemma CARD_sum [card_simps]:
"CARD('a + 'b) = card_sum CARD('a) CARD('b)"
by(simp add: card_UNIV_sum card_sum_def)
definition card_option :: "nat ⇒ nat"
where "card_option n = (if n = 0 then 0 else Suc n)"
lemma CARD_option [card_simps]:
"CARD('a option) = card_option CARD('a)"
by(simp add: card_option_def card_UNIV_option)
definition card_prod :: "nat ⇒ nat ⇒ nat"
where "card_prod a b = a * b"
lemma CARD_prod [card_simps]:
"CARD('a * 'b) = card_prod CARD('a) CARD('b)"
by(simp add: card_prod_def)
definition card_list :: "nat ⇒ nat"
where "card_list _ = 0"
lemma CARD_list [card_simps]: "CARD('a list) = card_list CARD('a)"
by(simp add: card_list_def infinite_UNIV_listI)
end