section‹Encoding (almost) everything into natural numbers›
theory Countable imports Old_Datatype HOL.Rat Nat_Bijection begin
subsection‹The class of countable types›
class countable = assumes ex_inj: "∃to_nat :: 'a ==> nat. inj to_nat"
lemma countable_classI: fixes f :: "'a ==> nat" assumes"∧x y. f x = f y ==> x = y" shows"OFCLASS('a, countable_class)" proof (intro_classes, rule exI) show"inj f" by (rule injI [OF assms]) assumption qed
subclass (in finite) countable proof have"finite (UNIV::'a set)"by (rule finite_UNIV) with finite_conv_nat_seg_image [of "UNIV::'a set"] obtain n and f :: "nat ==> 'a" where"UNIV = f ` {i. i < n}"by auto thenhave"surj f"unfolding surj_def by auto thenhave"inj (inv f)"by (rule surj_imp_inj_inv) thenshow"∃to_nat :: 'a ==> nat. inj to_nat"by (rule exI[of inj]) qed
subsection‹Automatically proving countability of old-style datatypes›
qualified function nth_item :: "nat ==> ('a::countable) Old_Datatype.item" where "nth_item 0 = undefined"
| "nth_item (Suc n) = (case sum_decode n of Inl i ==> (case sum_decode i of Inl j ==> Old_Datatype.In0 (nth_item j) | Inr j ==> Old_Datatype.In1 (nth_item j)) | Inr i ==> (case sum_decode i of Inl j ==> Old_Datatype.Leaf (from_nat j) | Inr j ==> (case prod_decode j of (a, b) ==> Old_Datatype.Scons (nth_item a) (nth_item b))))" by pat_completeness auto
lemma le_sum_encode_Inl: "x ≤ y ==> x ≤ sum_encode (Inl y)" unfolding sum_encode_def by simp
lemma le_sum_encode_Inr: "x ≤ y ==> x ≤ sum_encode (Inr y)" unfolding sum_encode_def by simp
lemma nth_item_covers: "finite_item x ==>∃n. nth_item n = x" proof (induct set: finite_item) case undefined have"nth_item 0 = undefined"by simp thus ?case .. next case (In0 x) thenobtain n where"nth_item n = x"by fast hence"nth_item (Suc (sum_encode (Inl (sum_encode (Inl n))))) = Old_Datatype.In0 x"by simp thus ?case .. next case (In1 x) thenobtain n where"nth_item n = x"by fast hence"nth_item (Suc (sum_encode (Inl (sum_encode (Inr n))))) = Old_Datatype.In1 x"by simp thus ?case .. next case (Leaf a) have"nth_item (Suc (sum_encode (Inr (sum_encode (Inl (to_nat a)))))) = Old_Datatype.Leaf a" by simp thus ?case .. next case (Scons x y) thenobtain i j where"nth_item i = x"and"nth_item j = y"by fast hence"nth_item (Suc (sum_encode (Inr (sum_encode (Inr (prod_encode (i, j))))))) = Old_Datatype.Scons x y" by simp thus ?case .. qed
theorem countable_datatype: fixes Rep :: "'b ==> ('a::countable) Old_Datatype.item" fixes Abs :: "('a::countable) Old_Datatype.item ==> 'b" fixes rep_set :: "('a::countable) Old_Datatype.item ==> bool" assumes type: "type_definition Rep Abs (Collect rep_set)" assumes finite_item: "∧x. rep_set x ==> finite_item x" shows"OFCLASS('b, countable_class)" proof
define f where"f y = (LEAST n. nth_item n = Rep y)"for y
{ fix y :: 'b have"rep_set (Rep y)" using type_definition.Rep [OF type] by simp hence"finite_item (Rep y)" by (rule finite_item) hence"∃n. nth_item n = Rep y" by (rule nth_item_covers) hence"nth_item (f y) = Rep y" unfolding f_def by (rule LeastI_ex) hence"Abs (nth_item (f y)) = y" using type_definition.Rep_inverse [OF type] by simp
} hence"inj f" by (rule inj_on_inverseI) thus"∃f::'b ==> nat. inj f" by - (rule exI) qed
ML ‹
fun old_countable_datatype_tac ctxt =
SUBGOAL (fn (goal, _) =>
let
val ty_name =
(case goal of
(_ $ Const (🍋‹Pure.type›, Type (🍋‹itself›, [Type (n, _)]))) => n
| _ => raise Match)
val typedef_info = hd (Typedef.get_info ctxt ty_name)
val typedef_thm = #type_definition (snd typedef_info)
val pred_name =
(case HOLogic.dest_Trueprop (Thm.concl_of typedef_thm) of
(_ $ _ $ _ $ (_ $ Const (n, _))) => n
| _ => raise Match)
val induct_info = Inductive.the_inductive_global ctxt pred_name
val pred_names = #names (fst induct_info)
val induct_thms = #inducts (snd induct_info)
val alist = pred_names ~~ induct_thms
val induct_thm = the (AList.lookup (op =) alist pred_name)
val vars = rev (Term.add_vars (Thm.prop_of induct_thm) [])
val insts = vars |> map (fn (_, T) => try (Thm.cterm_of ctxt)
(Const (🍋‹Countable.finite_item›, T)))
val induct_thm' = Thm.instantiate' [] insts induct_thm
val rules = @{thms finite_item.intros}
in
SOLVED' (fn i => EVERY
[resolve_tac ctxt @{thms countable_datatype} i,
resolve_tac ctxt [typedef_thm] i,
eresolve_tac ctxt [induct_thm'] i,
REPEAT (resolve_tac ctxt rules i ORELSE assume_tac ctxt i)]) 1
end) ›
end
subsection‹Automatically proving countability of datatypes›
ML_file ‹../Tools/BNF/bnf_lfp_countable.ML›
ML ‹
countable_datatype_tac ctxt st =
(case 🍋‹HEADGOAL (old_countable_datatype_tac ctxt) st› of
SOME res => res
| NONE => BNF_LFP_Countable.countable_datatype_tac ctxt st);
instance"fun"::(finite,countable)countable proof obtainxs::"'alist"wherexs:"setxs=UNIV" usingfinite_list[OFfinite_UNIV].. show"\<exists>to_nat::('a\<Rightarrow>'b)\<Rightarrow>nat.injto_nat" proof show"inj(\<lambda>f.to_nat(mapfxs))" by(ruleinjI,simpadd:xsfun_eq_iff) qed qed
instancerat::countable proof show"\<exists>to_nat::rat\<Rightarrow>nat.injto_nat" proof have"surjnat_to_rat_surj" by(rulesurj_nat_to_rat_surj) thenshow"inj(invnat_to_rat_surj)" by(rulesurj_imp_inj_inv) qed qed
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.