merged
authorChristian Urban <urbanc@in.tum.de>
Thu, 18 Mar 2010 18:43:21 +0100
changeset 1521 b2d4ebff3bc9
parent 1520 6ac75fd979d4 (current diff)
parent 1519 de8cbeac0624 (diff)
child 1522 4f8bab472a83
merged
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Nominal/FSet.thy	Thu Mar 18 18:43:21 2010 +0100
@@ -0,0 +1,376 @@
+theory FSet
+imports Quotient Quotient_List List
+begin
+
+fun
+  list_eq :: "'a list \<Rightarrow> 'a list \<Rightarrow> bool" (infix "\<approx>" 50)
+where
+  "list_eq xs ys = (\<forall>x. x \<in> set xs \<longleftrightarrow> x \<in> set ys)"
+
+lemma list_eq_equivp:
+  shows "equivp list_eq"
+unfolding equivp_reflp_symp_transp reflp_def symp_def transp_def
+by auto
+
+quotient_type
+  'a fset = "'a list" / "list_eq"
+by (rule list_eq_equivp)
+
+section {* empty fset, finsert and membership *}
+
+quotient_definition
+  fempty  ("{||}")
+where
+  "fempty :: 'a fset"
+is "[]::'a list"
+
+quotient_definition
+  "finsert :: 'a \<Rightarrow> 'a fset \<Rightarrow> 'a fset" 
+is "op #"
+
+syntax
+  "@Finset"     :: "args => 'a fset"  ("{|(_)|}")
+
+translations
+  "{|x, xs|}" == "CONST finsert x {|xs|}"
+  "{|x|}"     == "CONST finsert x {||}"
+
+definition
+  memb :: "'a \<Rightarrow> 'a list \<Rightarrow> bool"
+where
+  "memb x xs \<equiv> x \<in> set xs"
+
+quotient_definition
+  fin ("_ |\<in>| _" [50, 51] 50)
+where
+  "fin :: 'a \<Rightarrow> 'a fset \<Rightarrow> bool"
+is "memb"
+
+abbreviation
+  fnotin :: "'a \<Rightarrow> 'a fset \<Rightarrow> bool" ("_ |\<notin>| _" [50, 51] 50)
+where
+  "a |\<notin>| S \<equiv> \<not>(a |\<in>| S)"
+
+lemma memb_rsp[quot_respect]:
+  shows "(op = ===> op \<approx> ===> op =) memb memb"
+by (auto simp add: memb_def)
+
+lemma nil_rsp[quot_respect]:
+  shows "[] \<approx> []"
+by simp
+
+lemma cons_rsp[quot_respect]:
+  shows "(op = ===> op \<approx> ===> op \<approx>) op # op #"
+by simp
+
+section {* Augmenting a set -- @{const finsert} *}
+
+lemma nil_not_cons:
+  shows "\<not>[] \<approx> x # xs"
+  by auto
+
+lemma memb_cons_iff:
+  shows "memb x (y # xs) = (x = y \<or> memb x xs)"
+  by (induct xs) (auto simp add: memb_def)
+
+lemma memb_consI1:
+  shows "memb x (x # xs)"
+  by (simp add: memb_def)
+
+lemma memb_consI2:
+  shows "memb x xs \<Longrightarrow> memb x (y # xs)"
+  by (simp add: memb_def)
+
+lemma memb_absorb:
+  shows "memb x xs \<Longrightarrow> x # xs \<approx> xs"
+  by (induct xs) (auto simp add: memb_def id_simps)
+
+section {* Singletons *}
+
+lemma singleton_list_eq:
+  shows "[x] \<approx> [y] \<longleftrightarrow> x = y"
+  by (simp add: id_simps) auto
+
+section {* Union *}
+
+quotient_definition
+  funion  (infixl "|\<union>|" 65)
+where
+  "funion :: 'a fset \<Rightarrow> 'a fset \<Rightarrow> 'a fset"
+is
+  "op @"
+
+section {* Cardinality of finite sets *}
+
+fun
+  fcard_raw :: "'a list \<Rightarrow> nat"
+where
+  fcard_raw_nil:  "fcard_raw [] = 0"
+| fcard_raw_cons: "fcard_raw (x # xs) = (if memb x xs then fcard_raw xs else Suc (fcard_raw xs))"
+
+quotient_definition
+  "fcard :: 'a fset \<Rightarrow> nat" 
+is
+  "fcard_raw"
+
+lemma fcard_raw_gt_0:
+  assumes a: "x \<in> set xs"
+  shows "0 < fcard_raw xs"
+  using a
+  by (induct xs) (auto simp add: memb_def)
+
+lemma fcard_raw_delete_one:
+  "fcard_raw ([x \<leftarrow> xs. x \<noteq> y]) = (if memb y xs then fcard_raw xs - 1 else fcard_raw xs)"
+  by (induct xs) (auto dest: fcard_raw_gt_0 simp add: memb_def)
+
+lemma fcard_raw_rsp_aux:
+  assumes a: "a \<approx> b"
+  shows "fcard_raw a = fcard_raw b"
+  using a
+  apply(induct a arbitrary: b)
+  apply(auto simp add: memb_def)
+  apply(metis)
+  apply(drule_tac x="[x \<leftarrow> b. x \<noteq> a1]" in meta_spec)
+  apply(simp add: fcard_raw_delete_one)
+  apply(metis Suc_pred' fcard_raw_gt_0 fcard_raw_delete_one memb_def)
+  done
+
+lemma fcard_raw_rsp[quot_respect]:
+  "(op \<approx> ===> op =) fcard_raw fcard_raw"
+  by (simp add: fcard_raw_rsp_aux)
+
+
+section {* fmap and fset comprehension *}
+
+quotient_definition
+  "fmap :: ('a \<Rightarrow> 'b) \<Rightarrow> 'a fset \<Rightarrow> 'b fset"
+is
+ "map"
+
+text {* raw section *}
+
+lemma map_rsp_aux:
+  assumes a: "a \<approx> b"
+  shows "map f a \<approx> map f b"
+  using a
+  apply(induct a arbitrary: b)
+  apply(auto)
+  apply(metis rev_image_eqI)
+  done
+
+lemma map_rsp[quot_respect]:
+  shows "(op = ===> op \<approx> ===> op \<approx>) map map"
+  by (auto simp add: map_rsp_aux)
+
+lemma cons_left_comm:
+  "x # y # A \<approx> y # x # A"
+  by (auto simp add: id_simps)
+
+lemma cons_left_idem:
+  "x # x # A \<approx> x # A"
+  by (auto simp add: id_simps)
+
+lemma none_mem_nil:
+  "(\<forall>a. a \<notin> set A) = (A \<approx> [])"
+  by simp
+
+lemma finite_set_raw_strong_cases:
+  "(X = []) \<or> (\<exists>a Y. ((a \<notin> set Y) \<and> (X \<approx> a # Y)))"
+  apply (induct X)
+  apply (simp)
+  apply (rule disjI2)
+  apply (erule disjE)
+  apply (rule_tac x="a" in exI)
+  apply (rule_tac x="[]" in exI)
+  apply (simp)
+  apply (erule exE)+
+  apply (case_tac "a = aa")
+  apply (rule_tac x="a" in exI)
+  apply (rule_tac x="Y" in exI)
+  apply (simp)
+  apply (rule_tac x="aa" in exI)
+  apply (rule_tac x="a # Y" in exI)
+  apply (auto)
+  done
+
+fun
+  delete_raw :: "'a list \<Rightarrow> 'a \<Rightarrow> 'a list"
+where
+  "delete_raw [] x = []"
+| "delete_raw (a # A) x = (if (a = x) then delete_raw A x else a # (delete_raw A x))"
+
+lemma mem_delete_raw:
+  "x \<in> set (delete_raw A a) = (x \<in> set A \<and> \<not>(x = a))"
+  by (induct A arbitrary: x a) (auto)
+
+lemma mem_delete_raw_ident:
+  "\<not>(a \<in> set (delete_raw A a))"
+  by (induct A) (auto)
+
+lemma not_mem_delete_raw_ident:
+  "b \<notin> set A \<Longrightarrow> (delete_raw A b = A)"
+  by (induct A) (auto)
+
+lemma finite_set_raw_delete_raw_cases:
+  "X = [] \<or> (\<exists>a. a mem X \<and> X \<approx> a # delete_raw X a)"
+  by (induct X) (auto)
+
+lemma list2set_thm:
+  shows "set [] = {}"
+  and "set (h # t) = insert h (set t)"
+  by (auto)
+
+lemma list2set_rsp[quot_respect]:
+  "(op \<approx> ===> op =) set set"
+  by auto
+
+definition
+  rsp_fold
+where
+  "rsp_fold f = (\<forall>u v w. (f u (f v w) = f v (f u w)))"
+
+primrec
+  fold_raw :: "('a \<Rightarrow> 'b \<Rightarrow> 'b) \<Rightarrow> 'b \<Rightarrow> 'a list \<Rightarrow> 'b"
+where
+  "fold_raw f z [] = z"
+| "fold_raw f z (a # A) =
+     (if (rsp_fold f) then
+       if a mem A then fold_raw f z A
+       else f a (fold_raw f z A)
+     else z)"
+
+section {* Constants on the Quotient Type *} 
+
+quotient_definition
+  "fdelete :: 'a fset \<Rightarrow> 'a \<Rightarrow> 'a fset" 
+  is "delete_raw"
+
+quotient_definition
+  "fset_to_set :: 'a fset \<Rightarrow> 'a set" 
+  is "set"
+
+lemma funion_sym_pre:
+  "a @ b \<approx> b @ a"
+  by auto
+
+
+lemma append_rsp[quot_respect]:
+  shows "(op \<approx> ===> op \<approx> ===> op \<approx>) op @ op @"
+  by (auto)
+
+
+
+section {* lifted part *}
+
+
+lemma fin_finsert_iff[simp]:
+  "x |\<in>| finsert y S = (x = y \<or> x |\<in>| S)"
+  by (lifting memb_cons_iff)
+
+lemma
+  shows finsertI1: "x |\<in>| finsert x S"
+  and   finsertI2: "x |\<in>| S \<Longrightarrow> x |\<in>| finsert y S"
+  by (lifting memb_consI1, lifting memb_consI2)
+
+lemma finsert_absorb[simp]:
+  shows "x |\<in>| S \<Longrightarrow> finsert x S = S"
+  by (lifting memb_absorb)
+
+lemma fempty_not_finsert[simp]:
+  shows "{||} \<noteq> finsert x S"
+  by (lifting nil_not_cons)
+
+lemma finsert_left_comm:
+  "finsert a (finsert b S) = finsert b (finsert a S)"
+  by (lifting cons_left_comm)
+
+lemma finsert_left_idem:
+  "finsert a (finsert a S) = finsert a S"
+  by (lifting cons_left_idem)
+
+lemma fsingleton_eq[simp]:
+  shows "{|x|} = {|y|} \<longleftrightarrow> x = y"
+  by (lifting singleton_list_eq)
+
+text {* fset_to_set *}
+
+lemma fset_to_set_simps:
+  "fset_to_set {||} = {}"
+  "fset_to_set (finsert (h :: 'b) t) = insert h (fset_to_set t)"
+  by (lifting list2set_thm)
+
+lemma in_fset_to_set:
+  "x \<in> fset_to_set xs \<equiv> x |\<in>| xs"
+  by (lifting memb_def[symmetric])
+
+lemma none_in_fempty:
+  "(\<forall>a. a \<notin> fset_to_set A) = (A = {||})"
+  by (lifting none_mem_nil)
+
+text {* fcard *}
+
+lemma fcard_fempty [simp]:
+  shows "fcard {||} = 0"
+  by (lifting fcard_raw_nil)
+
+lemma fcard_finsert_if [simp]:
+  shows "fcard (finsert x S) = (if x |\<in>| S then fcard S else Suc (fcard S))"
+  by (lifting fcard_raw_cons)
+
+lemma fcard_gt_0: "x \<in> fset_to_set xs \<Longrightarrow> 0 < fcard xs"
+  by (lifting fcard_raw_gt_0)
+
+text {* funion *}
+
+lemma funion_simps[simp]:
+  "{||} |\<union>| ys = ys"
+  "finsert x xs |\<union>| ys = finsert x (xs |\<union>| ys)"
+  by (lifting append.simps)
+
+lemma funion_sym:
+  "a |\<union>| b = b |\<union>| a"
+  by (lifting funion_sym_pre)
+
+lemma funion_assoc:
+ "x |\<union>| xa |\<union>| xb = x |\<union>| (xa |\<union>| xb)"
+  by (lifting append_assoc)
+
+section {* Induction and Cases rules for finite sets *}
+
+lemma fset_strong_cases:
+  "X = {||} \<or> (\<exists>a Y. a \<notin> fset_to_set Y \<and> X = finsert a Y)"
+  by (lifting finite_set_raw_strong_cases)
+
+lemma fset_exhaust[case_names fempty finsert, cases type: fset]:
+  shows "\<lbrakk>S = {||} \<Longrightarrow> P; \<And>x S'. S = finsert x S' \<Longrightarrow> P\<rbrakk> \<Longrightarrow> P"
+  by (lifting list.exhaust)
+
+lemma fset_induct[case_names fempty finsert]:
+  shows "\<lbrakk>P {||}; \<And>x S. P S \<Longrightarrow> P (finsert x S)\<rbrakk> \<Longrightarrow> P S"
+  by (lifting list.induct)
+
+lemma fset_induct2[case_names fempty finsert, induct type: fset]:
+  assumes prem1: "P {||}" 
+  and     prem2: "\<And>x S. \<lbrakk>x |\<notin>| S; P S\<rbrakk> \<Longrightarrow> P (finsert x S)"
+  shows "P S"
+proof(induct S rule: fset_induct)
+  case fempty
+  show "P {||}" by (rule prem1)
+next
+  case (finsert x S)
+  have asm: "P S" by fact
+  show "P (finsert x S)"
+  proof(cases "x |\<in>| S")
+    case True
+    have "x |\<in>| S" by fact
+    then show "P (finsert x S)" using asm by simp
+  next
+    case False
+    have "x |\<notin>| S" by fact
+    then show "P (finsert x S)" using prem2 asm by simp
+  qed
+qed
+
+
+
+end