# HG changeset patch # User Christian Urban # Date 1270409968 -7200 # Node ID c34347ec7ab3d10b99769739ec1ca26d0d27fdf2 # Parent c0eac04ae3b467f361eba434b7bbff95e39c372a separated general nominal theory into separate folder diff -r c0eac04ae3b4 -r c34347ec7ab3 IsaMakefile --- a/IsaMakefile Sat Apr 03 22:31:11 2010 +0200 +++ b/IsaMakefile Sun Apr 04 21:39:28 2010 +0200 @@ -36,7 +36,7 @@ pearl: $(LOG)/HOL-Pearl.gz -$(LOG)/HOL-Pearl.gz: Nominal/Nominal*.thy Pearl/ROOT.ML Pearl/document/root.* Pearl/*.thy +$(LOG)/HOL-Pearl.gz: Nominal-General/Nominal*.thy Pearl/ROOT.ML Pearl/document/root.* Pearl/*.thy @$(USEDIR) -D generated HOL Pearl $(ISABELLE_TOOL) document -o pdf Pearl/generated @cp Pearl/document.pdf pearl.pdf diff -r c0eac04ae3b4 -r c34347ec7ab3 Nominal-General/Atoms.thy --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Nominal-General/Atoms.thy Sun Apr 04 21:39:28 2010 +0200 @@ -0,0 +1,164 @@ +(* Title: Atoms + Authors: Brian Huffman, Christian Urban + + Instantiations of concrete atoms +*) +theory Atoms +imports Nominal2_Atoms +begin + +section {* Manual instantiation of class @{text at}. *} + +typedef (open) name = "{a. sort_of a = Sort ''name'' []}" +by (rule exists_eq_simple_sort) + +instantiation name :: at +begin + +definition + "p \ a = Abs_name (p \ Rep_name a)" + +definition + "atom a = Rep_name a" + +instance +apply (rule at_class) +apply (rule type_definition_name) +apply (rule atom_name_def) +apply (rule permute_name_def) +done + +end + +lemma sort_of_atom_name: + shows "sort_of (atom (a::name)) = Sort ''name'' []" + unfolding atom_name_def using Rep_name by simp + +text {* Custom syntax for concrete atoms of type at *} + +term "a:::name" + +text {* + a:::name stands for (atom a) with a being of concrete atom + type name. The above lemma can therefore also be stated as + + "sort_of (a:::name) = Sort ''name'' []" + + This does not work for multi-sorted atoms. +*} + + +section {* Automatic instantiation of class @{text at}. *} + +atom_decl name2 + +lemma sort_of_atom_name2: + "sort_of (atom (a::name2)) = Sort ''Atoms.name2'' []" +unfolding atom_name2_def +using Rep_name2 +by simp + +text {* example swappings *} +lemma + fixes a b::"atom" + assumes "sort_of a = sort_of b" + shows "(a \ b) \ (a, b) = (b, a)" +using assms +by simp + +lemma + fixes a b::"name2" + shows "(a \ b) \ (a, b) = (b, a)" +by simp + +section {* An example for multiple-sort atoms *} + +datatype ty = + TVar string +| Fun ty ty ("_ \ _") + +primrec + sort_of_ty::"ty \ atom_sort" +where + "sort_of_ty (TVar s) = Sort ''TVar'' [Sort s []]" +| "sort_of_ty (Fun ty1 ty2) = Sort ''Fun'' [sort_of_ty ty1, sort_of_ty ty2]" + +lemma sort_of_ty_eq_iff: + shows "sort_of_ty x = sort_of_ty y \ x = y" +apply(induct x arbitrary: y) +apply(case_tac [!] y) +apply(simp_all) +done + +declare sort_of_ty.simps [simp del] + +typedef (open) var = "{a. sort_of a \ range sort_of_ty}" + by (rule_tac x="Atom (sort_of_ty x) y" in exI, simp) + +instantiation var :: at_base +begin + +definition + "p \ a = Abs_var (p \ Rep_var a)" + +definition + "atom a = Rep_var a" + +instance +apply (rule at_base_class) +apply (rule type_definition_var) +apply (rule atom_var_def) +apply (rule permute_var_def) +done + +end + +text {* Constructor for variables. *} + +definition + Var :: "nat \ ty \ var" +where + "Var x t = Abs_var (Atom (sort_of_ty t) x)" + +lemma Var_eq_iff [simp]: + shows "Var x s = Var y t \ x = y \ s = t" + unfolding Var_def + by (auto simp add: Abs_var_inject sort_of_ty_eq_iff) + +lemma sort_of_atom_var [simp]: + "sort_of (atom (Var n ty)) = sort_of_ty ty" + unfolding atom_var_def Var_def + by (simp add: Abs_var_inverse) + +lemma + assumes "\ \ \" + shows "(Var x \ \ Var y \) \ (Var x \, Var x \) = (Var y \, Var x \)" + using assms by simp + +text {* Projecting out the type component of a variable. *} + +definition + ty_of :: "var \ ty" +where + "ty_of x = inv sort_of_ty (sort_of (atom x))" + +text {* + Functions @{term Var}/@{term ty_of} satisfy many of the same + properties as @{term Atom}/@{term sort_of}. +*} + +lemma ty_of_Var [simp]: + shows "ty_of (Var x t) = t" + unfolding ty_of_def + unfolding sort_of_atom_var + apply (rule inv_f_f) + apply (simp add: inj_on_def sort_of_ty_eq_iff) + done + +lemma ty_of_permute [simp]: + shows "ty_of (p \ x) = ty_of x" + unfolding ty_of_def + unfolding atom_eqvt [symmetric] + by simp + +end diff -r c0eac04ae3b4 -r c34347ec7ab3 Nominal-General/Nominal2_Atoms.thy --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Nominal-General/Nominal2_Atoms.thy Sun Apr 04 21:39:28 2010 +0200 @@ -0,0 +1,255 @@ +(* Title: Nominal2_Atoms + Authors: Brian Huffman, Christian Urban + + Definitions for concrete atom types. +*) +theory Nominal2_Atoms +imports Nominal2_Base +uses ("nominal_atoms.ML") +begin + +section {* Concrete atom types *} + +text {* + Class @{text at_base} allows types containing multiple sorts of atoms. + Class @{text at} only allows types with a single sort. +*} + +class at_base = pt + + fixes atom :: "'a \ atom" + assumes atom_eq_iff [simp]: "atom a = atom b \ a = b" + assumes atom_eqvt: "p \ (atom a) = atom (p \ a)" + +class at = at_base + + assumes sort_of_atom_eq [simp]: "sort_of (atom a) = sort_of (atom b)" + +lemma supp_at_base: + fixes a::"'a::at_base" + shows "supp a = {atom a}" + by (simp add: supp_atom [symmetric] supp_def atom_eqvt) + +lemma fresh_at_base: + shows "a \ b \ a \ atom b" + unfolding fresh_def by (simp add: supp_at_base) + +instance at_base < fs +proof qed (simp add: supp_at_base) + +lemma at_base_infinite [simp]: + shows "infinite (UNIV :: 'a::at_base set)" (is "infinite ?U") +proof + obtain a :: 'a where "True" by auto + assume "finite ?U" + hence "finite (atom ` ?U)" + by (rule finite_imageI) + then obtain b where b: "b \ atom ` ?U" "sort_of b = sort_of (atom a)" + by (rule obtain_atom) + from b(2) have "b = atom ((atom a \ b) \ a)" + unfolding atom_eqvt [symmetric] + by (simp add: swap_atom) + hence "b \ atom ` ?U" by simp + with b(1) show "False" by simp +qed + +lemma swap_at_base_simps [simp]: + fixes x y::"'a::at_base" + shows "sort_of (atom x) = sort_of (atom y) \ (atom x \ atom y) \ x = y" + and "sort_of (atom x) = sort_of (atom y) \ (atom x \ atom y) \ y = x" + and "atom x \ a \ atom x \ b \ (a \ b) \ x = x" + unfolding atom_eq_iff [symmetric] + unfolding atom_eqvt [symmetric] + by simp_all + +lemma obtain_at_base: + assumes X: "finite X" + obtains a::"'a::at_base" where "atom a \ X" +proof - + have "inj (atom :: 'a \ atom)" + by (simp add: inj_on_def) + with X have "finite (atom -` X :: 'a set)" + by (rule finite_vimageI) + with at_base_infinite have "atom -` X \ (UNIV :: 'a set)" + by auto + then obtain a :: 'a where "atom a \ X" + by auto + thus ?thesis .. +qed + + +section {* A swapping operation for concrete atoms *} + +definition + flip :: "'a::at_base \ 'a \ perm" ("'(_ \ _')") +where + "(a \ b) = (atom a \ atom b)" + +lemma flip_self [simp]: "(a \ a) = 0" + unfolding flip_def by (rule swap_self) + +lemma flip_commute: "(a \ b) = (b \ a)" + unfolding flip_def by (rule swap_commute) + +lemma minus_flip [simp]: "- (a \ b) = (a \ b)" + unfolding flip_def by (rule minus_swap) + +lemma add_flip_cancel: "(a \ b) + (a \ b) = 0" + unfolding flip_def by (rule swap_cancel) + +lemma permute_flip_cancel [simp]: "(a \ b) \ (a \ b) \ x = x" + unfolding permute_plus [symmetric] add_flip_cancel by simp + +lemma permute_flip_cancel2 [simp]: "(a \ b) \ (b \ a) \ x = x" + by (simp add: flip_commute) + +lemma flip_eqvt: + fixes a b c::"'a::at_base" + shows "p \ (a \ b) = (p \ a \ p \ b)" + unfolding flip_def + by (simp add: swap_eqvt atom_eqvt) + +lemma flip_at_base_simps [simp]: + shows "sort_of (atom a) = sort_of (atom b) \ (a \ b) \ a = b" + and "sort_of (atom a) = sort_of (atom b) \ (a \ b) \ b = a" + and "\a \ c; b \ c\ \ (a \ b) \ c = c" + and "sort_of (atom a) \ sort_of (atom b) \ (a \ b) \ x = x" + unfolding flip_def + unfolding atom_eq_iff [symmetric] + unfolding atom_eqvt [symmetric] + by simp_all + +text {* the following two lemmas do not hold for at_base, + only for single sort atoms from at *} + +lemma permute_flip_at: + fixes a b c::"'a::at" + shows "(a \ b) \ c = (if c = a then b else if c = b then a else c)" + unfolding flip_def + apply (rule atom_eq_iff [THEN iffD1]) + apply (subst atom_eqvt [symmetric]) + apply (simp add: swap_atom) + done + +lemma flip_at_simps [simp]: + fixes a b::"'a::at" + shows "(a \ b) \ a = b" + and "(a \ b) \ b = a" + unfolding permute_flip_at by simp_all + +lemma flip_fresh_fresh: + fixes a b::"'a::at_base" + assumes "atom a \ x" "atom b \ x" + shows "(a \ b) \ x = x" +using assms +by (simp add: flip_def swap_fresh_fresh) + +subsection {* Syntax for coercing at-elements to the atom-type *} + +syntax + "_atom_constrain" :: "logic \ type \ logic" ("_:::_" [4, 0] 3) + +translations + "_atom_constrain a t" => "CONST atom (_constrain a t)" + + +subsection {* A lemma for proving instances of class @{text at}. *} + +setup {* Sign.add_const_constraint (@{const_name "permute"}, NONE) *} +setup {* Sign.add_const_constraint (@{const_name "atom"}, NONE) *} + +text {* + New atom types are defined as subtypes of @{typ atom}. +*} + +lemma exists_eq_simple_sort: + shows "\a. a \ {a. sort_of a = s}" + by (rule_tac x="Atom s 0" in exI, simp) + +lemma exists_eq_sort: + shows "\a. a \ {a. sort_of a \ range sort_fun}" + by (rule_tac x="Atom (sort_fun x) y" in exI, simp) + +lemma at_base_class: + fixes sort_fun :: "'b \atom_sort" + fixes Rep :: "'a \ atom" and Abs :: "atom \ 'a" + assumes type: "type_definition Rep Abs {a. sort_of a \ range sort_fun}" + assumes atom_def: "\a. atom a = Rep a" + assumes permute_def: "\p a. p \ a = Abs (p \ Rep a)" + shows "OFCLASS('a, at_base_class)" +proof + interpret type_definition Rep Abs "{a. sort_of a \ range sort_fun}" by (rule type) + have sort_of_Rep: "\a. sort_of (Rep a) \ range sort_fun" using Rep by simp + fix a b :: 'a and p p1 p2 :: perm + show "0 \ a = a" + unfolding permute_def by (simp add: Rep_inverse) + show "(p1 + p2) \ a = p1 \ p2 \ a" + unfolding permute_def by (simp add: Abs_inverse sort_of_Rep) + show "atom a = atom b \ a = b" + unfolding atom_def by (simp add: Rep_inject) + show "p \ atom a = atom (p \ a)" + unfolding permute_def atom_def by (simp add: Abs_inverse sort_of_Rep) +qed + +(* +lemma at_class: + fixes s :: atom_sort + fixes Rep :: "'a \ atom" and Abs :: "atom \ 'a" + assumes type: "type_definition Rep Abs {a. sort_of a \ range (\x::unit. s)}" + assumes atom_def: "\a. atom a = Rep a" + assumes permute_def: "\p a. p \ a = Abs (p \ Rep a)" + shows "OFCLASS('a, at_class)" +proof + interpret type_definition Rep Abs "{a. sort_of a \ range (\x::unit. s)}" by (rule type) + have sort_of_Rep: "\a. sort_of (Rep a) = s" using Rep by (simp add: image_def) + fix a b :: 'a and p p1 p2 :: perm + show "0 \ a = a" + unfolding permute_def by (simp add: Rep_inverse) + show "(p1 + p2) \ a = p1 \ p2 \ a" + unfolding permute_def by (simp add: Abs_inverse sort_of_Rep) + show "sort_of (atom a) = sort_of (atom b)" + unfolding atom_def by (simp add: sort_of_Rep) + show "atom a = atom b \ a = b" + unfolding atom_def by (simp add: Rep_inject) + show "p \ atom a = atom (p \ a)" + unfolding permute_def atom_def by (simp add: Abs_inverse sort_of_Rep) +qed +*) + +lemma at_class: + fixes s :: atom_sort + fixes Rep :: "'a \ atom" and Abs :: "atom \ 'a" + assumes type: "type_definition Rep Abs {a. sort_of a = s}" + assumes atom_def: "\a. atom a = Rep a" + assumes permute_def: "\p a. p \ a = Abs (p \ Rep a)" + shows "OFCLASS('a, at_class)" +proof + interpret type_definition Rep Abs "{a. sort_of a = s}" by (rule type) + have sort_of_Rep: "\a. sort_of (Rep a) = s" using Rep by (simp add: image_def) + fix a b :: 'a and p p1 p2 :: perm + show "0 \ a = a" + unfolding permute_def by (simp add: Rep_inverse) + show "(p1 + p2) \ a = p1 \ p2 \ a" + unfolding permute_def by (simp add: Abs_inverse sort_of_Rep) + show "sort_of (atom a) = sort_of (atom b)" + unfolding atom_def by (simp add: sort_of_Rep) + show "atom a = atom b \ a = b" + unfolding atom_def by (simp add: Rep_inject) + show "p \ atom a = atom (p \ a)" + unfolding permute_def atom_def by (simp add: Abs_inverse sort_of_Rep) +qed + +setup {* Sign.add_const_constraint + (@{const_name "permute"}, SOME @{typ "perm \ 'a::pt \ 'a"}) *} +setup {* Sign.add_const_constraint + (@{const_name "atom"}, SOME @{typ "'a::at_base \ atom"}) *} + + +section {* Automation for creating concrete atom types *} + +text {* at the moment only single-sort concrete atoms are supported *} + +use "nominal_atoms.ML" + + + + +end diff -r c0eac04ae3b4 -r c34347ec7ab3 Nominal-General/Nominal2_Base.thy --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Nominal-General/Nominal2_Base.thy Sun Apr 04 21:39:28 2010 +0200 @@ -0,0 +1,1062 @@ +(* Title: Nominal2_Base + Authors: Brian Huffman, Christian Urban + + Basic definitions and lemma infrastructure for + Nominal Isabelle. +*) +theory Nominal2_Base +imports Main Infinite_Set +begin + +section {* Atoms and Sorts *} + +text {* A simple implementation for atom_sorts is strings. *} +(* types atom_sort = string *) + +text {* To deal with Church-like binding we use trees of + strings as sorts. *} + +datatype atom_sort = Sort "string" "atom_sort list" + +datatype atom = Atom atom_sort nat + + +text {* Basic projection function. *} + +primrec + sort_of :: "atom \ atom_sort" +where + "sort_of (Atom s i) = s" + + +text {* There are infinitely many atoms of each sort. *} +lemma INFM_sort_of_eq: + shows "INFM a. sort_of a = s" +proof - + have "INFM i. sort_of (Atom s i) = s" by simp + moreover have "inj (Atom s)" by (simp add: inj_on_def) + ultimately show "INFM a. sort_of a = s" by (rule INFM_inj) +qed + +lemma infinite_sort_of_eq: + shows "infinite {a. sort_of a = s}" + using INFM_sort_of_eq unfolding INFM_iff_infinite . + +lemma atom_infinite [simp]: + shows "infinite (UNIV :: atom set)" + using subset_UNIV infinite_sort_of_eq + by (rule infinite_super) + +lemma obtain_atom: + fixes X :: "atom set" + assumes X: "finite X" + obtains a where "a \ X" "sort_of a = s" +proof - + from X have "MOST a. a \ X" + unfolding MOST_iff_cofinite by simp + with INFM_sort_of_eq + have "INFM a. sort_of a = s \ a \ X" + by (rule INFM_conjI) + then obtain a where "a \ X" "sort_of a = s" + by (auto elim: INFM_E) + then show ?thesis .. +qed + +section {* Sort-Respecting Permutations *} + +typedef perm = + "{f. bij f \ finite {a. f a \ a} \ (\a. sort_of (f a) = sort_of a)}" +proof + show "id \ ?perm" by simp +qed + +lemma permI: + assumes "bij f" and "MOST x. f x = x" and "\a. sort_of (f a) = sort_of a" + shows "f \ perm" + using assms unfolding perm_def MOST_iff_cofinite by simp + +lemma perm_is_bij: "f \ perm \ bij f" + unfolding perm_def by simp + +lemma perm_is_finite: "f \ perm \ finite {a. f a \ a}" + unfolding perm_def by simp + +lemma perm_is_sort_respecting: "f \ perm \ sort_of (f a) = sort_of a" + unfolding perm_def by simp + +lemma perm_MOST: "f \ perm \ MOST x. f x = x" + unfolding perm_def MOST_iff_cofinite by simp + +lemma perm_id: "id \ perm" + unfolding perm_def by simp + +lemma perm_comp: + assumes f: "f \ perm" and g: "g \ perm" + shows "(f \ g) \ perm" +apply (rule permI) +apply (rule bij_comp) +apply (rule perm_is_bij [OF g]) +apply (rule perm_is_bij [OF f]) +apply (rule MOST_rev_mp [OF perm_MOST [OF g]]) +apply (rule MOST_rev_mp [OF perm_MOST [OF f]]) +apply (simp) +apply (simp add: perm_is_sort_respecting [OF f]) +apply (simp add: perm_is_sort_respecting [OF g]) +done + +lemma perm_inv: + assumes f: "f \ perm" + shows "(inv f) \ perm" +apply (rule permI) +apply (rule bij_imp_bij_inv) +apply (rule perm_is_bij [OF f]) +apply (rule MOST_mono [OF perm_MOST [OF f]]) +apply (erule subst, rule inv_f_f) +apply (rule bij_is_inj [OF perm_is_bij [OF f]]) +apply (rule perm_is_sort_respecting [OF f, THEN sym, THEN trans]) +apply (simp add: surj_f_inv_f [OF bij_is_surj [OF perm_is_bij [OF f]]]) +done + +lemma bij_Rep_perm: "bij (Rep_perm p)" + using Rep_perm [of p] unfolding perm_def by simp + +lemma finite_Rep_perm: "finite {a. Rep_perm p a \ a}" + using Rep_perm [of p] unfolding perm_def by simp + +lemma sort_of_Rep_perm: "sort_of (Rep_perm p a) = sort_of a" + using Rep_perm [of p] unfolding perm_def by simp + +lemma Rep_perm_ext: + "Rep_perm p1 = Rep_perm p2 \ p1 = p2" + by (simp add: expand_fun_eq Rep_perm_inject [symmetric]) + + +subsection {* Permutations form a group *} + +instantiation perm :: group_add +begin + +definition + "0 = Abs_perm id" + +definition + "- p = Abs_perm (inv (Rep_perm p))" + +definition + "p + q = Abs_perm (Rep_perm p \ Rep_perm q)" + +definition + "(p1::perm) - p2 = p1 + - p2" + +lemma Rep_perm_0: "Rep_perm 0 = id" + unfolding zero_perm_def + by (simp add: Abs_perm_inverse perm_id) + +lemma Rep_perm_add: + "Rep_perm (p1 + p2) = Rep_perm p1 \ Rep_perm p2" + unfolding plus_perm_def + by (simp add: Abs_perm_inverse perm_comp Rep_perm) + +lemma Rep_perm_uminus: + "Rep_perm (- p) = inv (Rep_perm p)" + unfolding uminus_perm_def + by (simp add: Abs_perm_inverse perm_inv Rep_perm) + +instance +apply default +unfolding Rep_perm_inject [symmetric] +unfolding minus_perm_def +unfolding Rep_perm_add +unfolding Rep_perm_uminus +unfolding Rep_perm_0 +by (simp_all add: o_assoc inv_o_cancel [OF bij_is_inj [OF bij_Rep_perm]]) + +end + + +section {* Implementation of swappings *} + +definition + swap :: "atom \ atom \ perm" ("'(_ \ _')") +where + "(a \ b) = + Abs_perm (if sort_of a = sort_of b + then (\c. if a = c then b else if b = c then a else c) + else id)" + +lemma Rep_perm_swap: + "Rep_perm (a \ b) = + (if sort_of a = sort_of b + then (\c. if a = c then b else if b = c then a else c) + else id)" +unfolding swap_def +apply (rule Abs_perm_inverse) +apply (rule permI) +apply (auto simp add: bij_def inj_on_def surj_def)[1] +apply (rule MOST_rev_mp [OF MOST_neq(1) [of a]]) +apply (rule MOST_rev_mp [OF MOST_neq(1) [of b]]) +apply (simp) +apply (simp) +done + +lemmas Rep_perm_simps = + Rep_perm_0 + Rep_perm_add + Rep_perm_uminus + Rep_perm_swap + +lemma swap_different_sorts [simp]: + "sort_of a \ sort_of b \ (a \ b) = 0" + by (rule Rep_perm_ext) (simp add: Rep_perm_simps) + +lemma swap_cancel: + "(a \ b) + (a \ b) = 0" +by (rule Rep_perm_ext) + (simp add: Rep_perm_simps expand_fun_eq) + +lemma swap_self [simp]: + "(a \ a) = 0" + by (rule Rep_perm_ext, simp add: Rep_perm_simps expand_fun_eq) + +lemma minus_swap [simp]: + "- (a \ b) = (a \ b)" + by (rule minus_unique [OF swap_cancel]) + +lemma swap_commute: + "(a \ b) = (b \ a)" + by (rule Rep_perm_ext) + (simp add: Rep_perm_swap expand_fun_eq) + +lemma swap_triple: + assumes "a \ b" and "c \ b" + assumes "sort_of a = sort_of b" "sort_of b = sort_of c" + shows "(a \ c) + (b \ c) + (a \ c) = (a \ b)" + using assms + by (rule_tac Rep_perm_ext) + (auto simp add: Rep_perm_simps expand_fun_eq) + + +section {* Permutation Types *} + +text {* + Infix syntax for @{text permute} has higher precedence than + addition, but lower than unary minus. +*} + +class pt = + fixes permute :: "perm \ 'a \ 'a" ("_ \ _" [76, 75] 75) + assumes permute_zero [simp]: "0 \ x = x" + assumes permute_plus [simp]: "(p + q) \ x = p \ (q \ x)" +begin + +lemma permute_diff [simp]: + shows "(p - q) \ x = p \ - q \ x" + unfolding diff_minus by simp + +lemma permute_minus_cancel [simp]: + shows "p \ - p \ x = x" + and "- p \ p \ x = x" + unfolding permute_plus [symmetric] by simp_all + +lemma permute_swap_cancel [simp]: + shows "(a \ b) \ (a \ b) \ x = x" + unfolding permute_plus [symmetric] + by (simp add: swap_cancel) + +lemma permute_swap_cancel2 [simp]: + shows "(a \ b) \ (b \ a) \ x = x" + unfolding permute_plus [symmetric] + by (simp add: swap_commute) + +lemma inj_permute [simp]: + shows "inj (permute p)" + by (rule inj_on_inverseI) + (rule permute_minus_cancel) + +lemma surj_permute [simp]: + shows "surj (permute p)" + by (rule surjI, rule permute_minus_cancel) + +lemma bij_permute [simp]: + shows "bij (permute p)" + by (rule bijI [OF inj_permute surj_permute]) + +lemma inv_permute: + shows "inv (permute p) = permute (- p)" + by (rule inv_equality) (simp_all) + +lemma permute_minus: + shows "permute (- p) = inv (permute p)" + by (simp add: inv_permute) + +lemma permute_eq_iff [simp]: + shows "p \ x = p \ y \ x = y" + by (rule inj_permute [THEN inj_eq]) + +end + +subsection {* Permutations for atoms *} + +instantiation atom :: pt +begin + +definition + "p \ a = Rep_perm p a" + +instance +apply(default) +apply(simp_all add: permute_atom_def Rep_perm_simps) +done + +end + +lemma sort_of_permute [simp]: + shows "sort_of (p \ a) = sort_of a" + unfolding permute_atom_def by (rule sort_of_Rep_perm) + +lemma swap_atom: + shows "(a \ b) \ c = + (if sort_of a = sort_of b + then (if c = a then b else if c = b then a else c) else c)" + unfolding permute_atom_def + by (simp add: Rep_perm_swap) + +lemma swap_atom_simps [simp]: + "sort_of a = sort_of b \ (a \ b) \ a = b" + "sort_of a = sort_of b \ (a \ b) \ b = a" + "c \ a \ c \ b \ (a \ b) \ c = c" + unfolding swap_atom by simp_all + +lemma expand_perm_eq: + fixes p q :: "perm" + shows "p = q \ (\a::atom. p \ a = q \ a)" + unfolding permute_atom_def + by (metis Rep_perm_ext ext) + + +subsection {* Permutations for permutations *} + +instantiation perm :: pt +begin + +definition + "p \ q = p + q - p" + +instance +apply default +apply (simp add: permute_perm_def) +apply (simp add: permute_perm_def diff_minus minus_add add_assoc) +done + +end + +lemma permute_self: "p \ p = p" +unfolding permute_perm_def by (simp add: diff_minus add_assoc) + +lemma permute_eqvt: + shows "p \ (q \ x) = (p \ q) \ (p \ x)" + unfolding permute_perm_def by simp + +lemma zero_perm_eqvt: + shows "p \ (0::perm) = 0" + unfolding permute_perm_def by simp + +lemma add_perm_eqvt: + fixes p p1 p2 :: perm + shows "p \ (p1 + p2) = p \ p1 + p \ p2" + unfolding permute_perm_def + by (simp add: expand_perm_eq) + +lemma swap_eqvt: + shows "p \ (a \ b) = (p \ a \ p \ b)" + unfolding permute_perm_def + by (auto simp add: swap_atom expand_perm_eq) + + +subsection {* Permutations for functions *} + +instantiation "fun" :: (pt, pt) pt +begin + +definition + "p \ f = (\x. p \ (f (- p \ x)))" + +instance +apply default +apply (simp add: permute_fun_def) +apply (simp add: permute_fun_def minus_add) +done + +end + +lemma permute_fun_app_eq: + shows "p \ (f x) = (p \ f) (p \ x)" +unfolding permute_fun_def by simp + + +subsection {* Permutations for booleans *} + +instantiation bool :: pt +begin + +definition "p \ (b::bool) = b" + +instance +apply(default) +apply(simp_all add: permute_bool_def) +done + +end + +lemma Not_eqvt: + shows "p \ (\ A) = (\ (p \ A))" +by (simp add: permute_bool_def) + +lemma permute_boolE: + fixes P::"bool" + shows "p \ P \ P" + by (simp add: permute_bool_def) + +lemma permute_boolI: + fixes P::"bool" + shows "P \ p \ P" + by(simp add: permute_bool_def) + +subsection {* Permutations for sets *} + +lemma permute_set_eq: + fixes x::"'a::pt" + and p::"perm" + shows "(p \ X) = {p \ x | x. x \ X}" + apply(auto simp add: permute_fun_def permute_bool_def mem_def) + apply(rule_tac x="- p \ x" in exI) + apply(simp) + done + +lemma permute_set_eq_image: + shows "p \ X = permute p ` X" +unfolding permute_set_eq by auto + +lemma permute_set_eq_vimage: + shows "p \ X = permute (- p) -` X" +unfolding permute_fun_def permute_bool_def +unfolding vimage_def Collect_def mem_def .. + +lemma swap_set_not_in: + assumes a: "a \ S" "b \ S" + shows "(a \ b) \ S = S" + using a by (auto simp add: permute_set_eq swap_atom) + +lemma swap_set_in: + assumes a: "a \ S" "b \ S" "sort_of a = sort_of b" + shows "(a \ b) \ S \ S" + using a by (auto simp add: permute_set_eq swap_atom) + + +subsection {* Permutations for units *} + +instantiation unit :: pt +begin + +definition "p \ (u::unit) = u" + +instance proof +qed (simp_all add: permute_unit_def) + +end + + +subsection {* Permutations for products *} + +instantiation "*" :: (pt, pt) pt +begin + +primrec + permute_prod +where + Pair_eqvt: "p \ (x, y) = (p \ x, p \ y)" + +instance +by default auto + +end + +subsection {* Permutations for sums *} + +instantiation "+" :: (pt, pt) pt +begin + +primrec + permute_sum +where + "p \ (Inl x) = Inl (p \ x)" +| "p \ (Inr y) = Inr (p \ y)" + +instance proof +qed (case_tac [!] x, simp_all) + +end + +subsection {* Permutations for lists *} + +instantiation list :: (pt) pt +begin + +primrec + permute_list +where + "p \ [] = []" +| "p \ (x # xs) = p \ x # p \ xs" + +instance proof +qed (induct_tac [!] x, simp_all) + +end + +subsection {* Permutations for options *} + +instantiation option :: (pt) pt +begin + +primrec + permute_option +where + "p \ None = None" +| "p \ (Some x) = Some (p \ x)" + +instance proof +qed (induct_tac [!] x, simp_all) + +end + +subsection {* Permutations for @{typ char}, @{typ nat}, and @{typ int} *} + +instantiation char :: pt +begin + +definition "p \ (c::char) = c" + +instance proof +qed (simp_all add: permute_char_def) + +end + +instantiation nat :: pt +begin + +definition "p \ (n::nat) = n" + +instance proof +qed (simp_all add: permute_nat_def) + +end + +instantiation int :: pt +begin + +definition "p \ (i::int) = i" + +instance proof +qed (simp_all add: permute_int_def) + +end + + +section {* Pure types *} + +text {* Pure types will have always empty support. *} + +class pure = pt + + assumes permute_pure: "p \ x = x" + +text {* Types @{typ unit} and @{typ bool} are pure. *} + +instance unit :: pure +proof qed (rule permute_unit_def) + +instance bool :: pure +proof qed (rule permute_bool_def) + +text {* Other type constructors preserve purity. *} + +instance "fun" :: (pure, pure) pure +by default (simp add: permute_fun_def permute_pure) + +instance "*" :: (pure, pure) pure +by default (induct_tac x, simp add: permute_pure) + +instance "+" :: (pure, pure) pure +by default (induct_tac x, simp_all add: permute_pure) + +instance list :: (pure) pure +by default (induct_tac x, simp_all add: permute_pure) + +instance option :: (pure) pure +by default (induct_tac x, simp_all add: permute_pure) + + +subsection {* Types @{typ char}, @{typ nat}, and @{typ int} *} + +instance char :: pure +proof qed (rule permute_char_def) + +instance nat :: pure +proof qed (rule permute_nat_def) + +instance int :: pure +proof qed (rule permute_int_def) + + +subsection {* Supp, Freshness and Supports *} + +context pt +begin + +definition + supp :: "'a \ atom set" +where + "supp x = {a. infinite {b. (a \ b) \ x \ x}}" + +end + +definition + fresh :: "atom \ 'a::pt \ bool" ("_ \ _" [55, 55] 55) +where + "a \ x \ a \ supp x" + +lemma supp_conv_fresh: + shows "supp x = {a. \ a \ x}" + unfolding fresh_def by simp + +lemma swap_rel_trans: + assumes "sort_of a = sort_of b" + assumes "sort_of b = sort_of c" + assumes "(a \ c) \ x = x" + assumes "(b \ c) \ x = x" + shows "(a \ b) \ x = x" +proof (cases) + assume "a = b \ c = b" + with assms show "(a \ b) \ x = x" by auto +next + assume *: "\ (a = b \ c = b)" + have "((a \ c) + (b \ c) + (a \ c)) \ x = x" + using assms by simp + also have "(a \ c) + (b \ c) + (a \ c) = (a \ b)" + using assms * by (simp add: swap_triple) + finally show "(a \ b) \ x = x" . +qed + +lemma swap_fresh_fresh: + assumes a: "a \ x" + and b: "b \ x" + shows "(a \ b) \ x = x" +proof (cases) + assume asm: "sort_of a = sort_of b" + have "finite {c. (a \ c) \ x \ x}" "finite {c. (b \ c) \ x \ x}" + using a b unfolding fresh_def supp_def by simp_all + then have "finite ({c. (a \ c) \ x \ x} \ {c. (b \ c) \ x \ x})" by simp + then obtain c + where "(a \ c) \ x = x" "(b \ c) \ x = x" "sort_of c = sort_of b" + by (rule obtain_atom) (auto) + then show "(a \ b) \ x = x" using asm by (rule_tac swap_rel_trans) (simp_all) +next + assume "sort_of a \ sort_of b" + then show "(a \ b) \ x = x" by simp +qed + + +subsection {* supp and fresh are equivariant *} + +lemma finite_Collect_bij: + assumes a: "bij f" + shows "finite {x. P (f x)} = finite {x. P x}" +by (metis a finite_vimage_iff vimage_Collect_eq) + +lemma fresh_permute_iff: + shows "(p \ a) \ (p \ x) \ a \ x" +proof - + have "(p \ a) \ (p \ x) \ finite {b. (p \ a \ b) \ p \ x \ p \ x}" + unfolding fresh_def supp_def by simp + also have "\ \ finite {b. (p \ a \ p \ b) \ p \ x \ p \ x}" + using bij_permute by (rule finite_Collect_bij [symmetric]) + also have "\ \ finite {b. p \ (a \ b) \ x \ p \ x}" + by (simp only: permute_eqvt [of p] swap_eqvt) + also have "\ \ finite {b. (a \ b) \ x \ x}" + by (simp only: permute_eq_iff) + also have "\ \ a \ x" + unfolding fresh_def supp_def by simp + finally show ?thesis . +qed + +lemma fresh_eqvt: + shows "p \ (a \ x) = (p \ a) \ (p \ x)" + by (simp add: permute_bool_def fresh_permute_iff) + +lemma supp_eqvt: + fixes p :: "perm" + and x :: "'a::pt" + shows "p \ (supp x) = supp (p \ x)" + unfolding supp_conv_fresh + unfolding permute_fun_def Collect_def + by (simp add: Not_eqvt fresh_eqvt) + +subsection {* supports *} + +definition + supports :: "atom set \ 'a::pt \ bool" (infixl "supports" 80) +where + "S supports x \ \a b. (a \ S \ b \ S \ (a \ b) \ x = x)" + +lemma supp_is_subset: + fixes S :: "atom set" + and x :: "'a::pt" + assumes a1: "S supports x" + and a2: "finite S" + shows "(supp x) \ S" +proof (rule ccontr) + assume "\(supp x \ S)" + then obtain a where b1: "a \ supp x" and b2: "a \ S" by auto + from a1 b2 have "\b. b \ S \ (a \ b) \ x = x" by (unfold supports_def) (auto) + hence "{b. (a \ b) \ x \ x} \ S" by auto + with a2 have "finite {b. (a \ b)\x \ x}" by (simp add: finite_subset) + then have "a \ (supp x)" unfolding supp_def by simp + with b1 show False by simp +qed + +lemma supports_finite: + fixes S :: "atom set" + and x :: "'a::pt" + assumes a1: "S supports x" + and a2: "finite S" + shows "finite (supp x)" +proof - + have "(supp x) \ S" using a1 a2 by (rule supp_is_subset) + then show "finite (supp x)" using a2 by (simp add: finite_subset) +qed + +lemma supp_supports: + fixes x :: "'a::pt" + shows "(supp x) supports x" +proof (unfold supports_def, intro strip) + fix a b + assume "a \ (supp x) \ b \ (supp x)" + then have "a \ x" and "b \ x" by (simp_all add: fresh_def) + then show "(a \ b) \ x = x" by (rule swap_fresh_fresh) +qed + +lemma supp_is_least_supports: + fixes S :: "atom set" + and x :: "'a::pt" + assumes a1: "S supports x" + and a2: "finite S" + and a3: "\S'. finite S' \ (S' supports x) \ S \ S'" + shows "(supp x) = S" +proof (rule equalityI) + show "(supp x) \ S" using a1 a2 by (rule supp_is_subset) + with a2 have fin: "finite (supp x)" by (rule rev_finite_subset) + have "(supp x) supports x" by (rule supp_supports) + with fin a3 show "S \ supp x" by blast +qed + +lemma subsetCI: + shows "(\x. x \ A \ x \ B \ False) \ A \ B" + by auto + +lemma finite_supp_unique: + assumes a1: "S supports x" + assumes a2: "finite S" + assumes a3: "\a b. \a \ S; b \ S; sort_of a = sort_of b\ \ (a \ b) \ x \ x" + shows "(supp x) = S" + using a1 a2 +proof (rule supp_is_least_supports) + fix S' + assume "finite S'" and "S' supports x" + show "S \ S'" + proof (rule subsetCI) + fix a + assume "a \ S" and "a \ S'" + have "finite (S \ S')" + using `finite S` `finite S'` by simp + then obtain b where "b \ S \ S'" and "sort_of b = sort_of a" + by (rule obtain_atom) + then have "b \ S" and "b \ S'" and "sort_of a = sort_of b" + by simp_all + then have "(a \ b) \ x = x" + using `a \ S'` `S' supports x` by (simp add: supports_def) + moreover have "(a \ b) \ x \ x" + using `a \ S` `b \ S` `sort_of a = sort_of b` + by (rule a3) + ultimately show "False" by simp + qed +qed + +section {* Finitely-supported types *} + +class fs = pt + + assumes finite_supp: "finite (supp x)" + +lemma pure_supp: + shows "supp (x::'a::pure) = {}" + unfolding supp_def by (simp add: permute_pure) + +lemma pure_fresh: + fixes x::"'a::pure" + shows "a \ x" + unfolding fresh_def by (simp add: pure_supp) + +instance pure < fs +by default (simp add: pure_supp) + + +subsection {* Type @{typ atom} is finitely-supported. *} + +lemma supp_atom: + shows "supp a = {a}" +apply (rule finite_supp_unique) +apply (clarsimp simp add: supports_def) +apply simp +apply simp +done + +lemma fresh_atom: + shows "a \ b \ a \ b" + unfolding fresh_def supp_atom by simp + +instance atom :: fs +by default (simp add: supp_atom) + + +section {* Type @{typ perm} is finitely-supported. *} + +lemma perm_swap_eq: + shows "(a \ b) \ p = p \ (p \ (a \ b)) = (a \ b)" +unfolding permute_perm_def +by (metis add_diff_cancel minus_perm_def) + +lemma supports_perm: + shows "{a. p \ a \ a} supports p" + unfolding supports_def + by (simp add: perm_swap_eq swap_eqvt) + +lemma finite_perm_lemma: + shows "finite {a::atom. p \ a \ a}" + using finite_Rep_perm [of p] + unfolding permute_atom_def . + +lemma supp_perm: + shows "supp p = {a. p \ a \ a}" +apply (rule finite_supp_unique) +apply (rule supports_perm) +apply (rule finite_perm_lemma) +apply (simp add: perm_swap_eq swap_eqvt) +apply (auto simp add: expand_perm_eq swap_atom) +done + +lemma fresh_perm: + shows "a \ p \ p \ a = a" +unfolding fresh_def by (simp add: supp_perm) + +lemma supp_swap: + shows "supp (a \ b) = (if a = b \ sort_of a \ sort_of b then {} else {a, b})" + by (auto simp add: supp_perm swap_atom) + +lemma fresh_zero_perm: + shows "a \ (0::perm)" + unfolding fresh_perm by simp + +lemma supp_zero_perm: + shows "supp (0::perm) = {}" + unfolding supp_perm by simp + +lemma fresh_plus_perm: + fixes p q::perm + assumes "a \ p" "a \ q" + shows "a \ (p + q)" + using assms + unfolding fresh_def + by (auto simp add: supp_perm) + +lemma supp_plus_perm: + fixes p q::perm + shows "supp (p + q) \ supp p \ supp q" + by (auto simp add: supp_perm) + +lemma fresh_minus_perm: + fixes p::perm + shows "a \ (- p) \ a \ p" + unfolding fresh_def + apply(auto simp add: supp_perm) + apply(metis permute_minus_cancel)+ + done + +lemma supp_minus_perm: + fixes p::perm + shows "supp (- p) = supp p" + unfolding supp_conv_fresh + by (simp add: fresh_minus_perm) + +instance perm :: fs +by default (simp add: supp_perm finite_perm_lemma) + +lemma plus_perm_eq: + fixes p q::"perm" + assumes asm: "supp p \ supp q = {}" + shows "p + q = q + p" +unfolding expand_perm_eq +proof + fix a::"atom" + show "(p + q) \ a = (q + p) \ a" + proof - + { assume "a \ supp p" "a \ supp q" + then have "(p + q) \ a = (q + p) \ a" + by (simp add: supp_perm) + } + moreover + { assume a: "a \ supp p" "a \ supp q" + then have "p \ a \ supp p" by (simp add: supp_perm) + then have "p \ a \ supp q" using asm by auto + with a have "(p + q) \ a = (q + p) \ a" + by (simp add: supp_perm) + } + moreover + { assume a: "a \ supp p" "a \ supp q" + then have "q \ a \ supp q" by (simp add: supp_perm) + then have "q \ a \ supp p" using asm by auto + with a have "(p + q) \ a = (q + p) \ a" + by (simp add: supp_perm) + } + ultimately show "(p + q) \ a = (q + p) \ a" + using asm by blast + qed +qed + +section {* Finite Support instances for other types *} + +subsection {* Type @{typ "'a \ 'b"} is finitely-supported. *} + +lemma supp_Pair: + shows "supp (x, y) = supp x \ supp y" + by (simp add: supp_def Collect_imp_eq Collect_neg_eq) + +lemma fresh_Pair: + shows "a \ (x, y) \ a \ x \ a \ y" + by (simp add: fresh_def supp_Pair) + +instance "*" :: (fs, fs) fs +apply default +apply (induct_tac x) +apply (simp add: supp_Pair finite_supp) +done + +subsection {* Type @{typ "'a + 'b"} is finitely supported *} + +lemma supp_Inl: + shows "supp (Inl x) = supp x" + by (simp add: supp_def) + +lemma supp_Inr: + shows "supp (Inr x) = supp x" + by (simp add: supp_def) + +lemma fresh_Inl: + shows "a \ Inl x \ a \ x" + by (simp add: fresh_def supp_Inl) + +lemma fresh_Inr: + shows "a \ Inr y \ a \ y" + by (simp add: fresh_def supp_Inr) + +instance "+" :: (fs, fs) fs +apply default +apply (induct_tac x) +apply (simp_all add: supp_Inl supp_Inr finite_supp) +done + +subsection {* Type @{typ "'a option"} is finitely supported *} + +lemma supp_None: + shows "supp None = {}" +by (simp add: supp_def) + +lemma supp_Some: + shows "supp (Some x) = supp x" + by (simp add: supp_def) + +lemma fresh_None: + shows "a \ None" + by (simp add: fresh_def supp_None) + +lemma fresh_Some: + shows "a \ Some x \ a \ x" + by (simp add: fresh_def supp_Some) + +instance option :: (fs) fs +apply default +apply (induct_tac x) +apply (simp_all add: supp_None supp_Some finite_supp) +done + +subsubsection {* Type @{typ "'a list"} is finitely supported *} + +lemma supp_Nil: + shows "supp [] = {}" + by (simp add: supp_def) + +lemma supp_Cons: + shows "supp (x # xs) = supp x \ supp xs" +by (simp add: supp_def Collect_imp_eq Collect_neg_eq) + +lemma fresh_Nil: + shows "a \ []" + by (simp add: fresh_def supp_Nil) + +lemma fresh_Cons: + shows "a \ (x # xs) \ a \ x \ a \ xs" + by (simp add: fresh_def supp_Cons) + +instance list :: (fs) fs +apply default +apply (induct_tac x) +apply (simp_all add: supp_Nil supp_Cons finite_supp) +done + +section {* Support and freshness for applications *} + +lemma supp_fun_app: + shows "supp (f x) \ (supp f) \ (supp x)" +proof (rule subsetCI) + fix a::"atom" + assume a: "a \ supp (f x)" + assume b: "a \ supp f \ supp x" + then have "finite {b. (a \ b) \ f \ f}" "finite {b. (a \ b) \ x \ x}" + unfolding supp_def by auto + then have "finite ({b. (a \ b) \ f \ f} \ {b. (a \ b) \ x \ x})" by simp + moreover + have "{b. ((a \ b) \ f) ((a \ b) \ x) \ f x} \ ({b. (a \ b) \ f \ f} \ {b. (a \ b) \ x \ x})" + by auto + ultimately have "finite {b. ((a \ b) \ f) ((a \ b) \ x) \ f x}" + using finite_subset by auto + then have "a \ supp (f x)" unfolding supp_def + by (simp add: permute_fun_app_eq) + with a show "False" by simp +qed + +lemma fresh_fun_app: + shows "a \ (f, x) \ a \ f x" +unfolding fresh_def +using supp_fun_app +by (auto simp add: supp_Pair) + +lemma fresh_fun_eqvt_app: + assumes a: "\p. p \ f = f" + shows "a \ x \ a \ f x" +proof - + from a have b: "supp f = {}" + unfolding supp_def by simp + show "a \ x \ a \ f x" + unfolding fresh_def + using supp_fun_app b + by auto +qed + +end diff -r c0eac04ae3b4 -r c34347ec7ab3 Nominal-General/Nominal2_Eqvt.thy --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Nominal-General/Nominal2_Eqvt.thy Sun Apr 04 21:39:28 2010 +0200 @@ -0,0 +1,305 @@ +(* Title: Nominal2_Eqvt + Authors: Brian Huffman, Christian Urban + + Equivariance, Supp and Fresh Lemmas for Operators. + (Contains most, but not all such lemmas.) +*) +theory Nominal2_Eqvt +imports Nominal2_Base Nominal2_Atoms +uses ("nominal_thmdecls.ML") + ("nominal_permeq.ML") +begin + +section {* Logical Operators *} + +lemma eq_eqvt: + shows "p \ (x = y) \ (p \ x) = (p \ y)" + unfolding permute_eq_iff permute_bool_def .. + +lemma if_eqvt: + shows "p \ (if b then x else y) = (if p \ b then p \ x else p \ y)" + by (simp add: permute_fun_def permute_bool_def) + +lemma True_eqvt: + shows "p \ True = True" + unfolding permute_bool_def .. + +lemma False_eqvt: + shows "p \ False = False" + unfolding permute_bool_def .. + +lemma imp_eqvt: + shows "p \ (A \ B) = ((p \ A) \ (p \ B))" + by (simp add: permute_bool_def) + +lemma conj_eqvt: + shows "p \ (A \ B) = ((p \ A) \ (p \ B))" + by (simp add: permute_bool_def) + +lemma disj_eqvt: + shows "p \ (A \ B) = ((p \ A) \ (p \ B))" + by (simp add: permute_bool_def) + +lemma Not_eqvt: + shows "p \ (\ A) = (\ (p \ A))" + by (simp add: permute_bool_def) + +lemma all_eqvt: + shows "p \ (\x. P x) = (\x. (p \ P) x)" + unfolding permute_fun_def permute_bool_def + by (auto, drule_tac x="p \ x" in spec, simp) + +lemma all_eqvt2: + shows "p \ (\x. P x) = (\x. p \ P (- p \ x))" + unfolding permute_fun_def permute_bool_def + by (auto, drule_tac x="p \ x" in spec, simp) + +lemma ex_eqvt: + shows "p \ (\x. P x) = (\x. (p \ P) x)" + unfolding permute_fun_def permute_bool_def + by (auto, rule_tac x="p \ x" in exI, simp) + +lemma ex_eqvt2: + shows "p \ (\x. P x) = (\x. p \ P (- p \ x))" + unfolding permute_fun_def permute_bool_def + by (auto, rule_tac x="p \ x" in exI, simp) + +lemma ex1_eqvt: + shows "p \ (\!x. P x) = (\!x. (p \ P) x)" + unfolding Ex1_def + by (simp add: ex_eqvt permute_fun_def conj_eqvt all_eqvt imp_eqvt eq_eqvt) + +lemma ex1_eqvt2: + shows "p \ (\!x. P x) = (\!x. p \ P (- p \ x))" + unfolding Ex1_def ex_eqvt2 conj_eqvt all_eqvt2 imp_eqvt eq_eqvt + by simp + +lemma the_eqvt: + assumes unique: "\!x. P x" + shows "(p \ (THE x. P x)) = (THE x. p \ P (- p \ x))" + apply(rule the1_equality [symmetric]) + apply(simp add: ex1_eqvt2[symmetric]) + apply(simp add: permute_bool_def unique) + apply(simp add: permute_bool_def) + apply(rule theI'[OF unique]) + done + +section {* Set Operations *} + +lemma mem_permute_iff: + shows "(p \ x) \ (p \ X) \ x \ X" +unfolding mem_def permute_fun_def permute_bool_def +by simp + +lemma mem_eqvt: + shows "p \ (x \ A) \ (p \ x) \ (p \ A)" + unfolding mem_permute_iff permute_bool_def by simp + +lemma not_mem_eqvt: + shows "p \ (x \ A) \ (p \ x) \ (p \ A)" + unfolding mem_def permute_fun_def by (simp add: Not_eqvt) + +lemma Collect_eqvt: + shows "p \ {x. P x} = {x. (p \ P) x}" + unfolding Collect_def permute_fun_def .. + +lemma Collect_eqvt2: + shows "p \ {x. P x} = {x. p \ (P (-p \ x))}" + unfolding Collect_def permute_fun_def .. + +lemma empty_eqvt: + shows "p \ {} = {}" + unfolding empty_def Collect_eqvt2 False_eqvt .. + +lemma supp_set_empty: + shows "supp {} = {}" + by (simp add: supp_def empty_eqvt) + +lemma fresh_set_empty: + shows "a \ {}" + by (simp add: fresh_def supp_set_empty) + +lemma UNIV_eqvt: + shows "p \ UNIV = UNIV" + unfolding UNIV_def Collect_eqvt2 True_eqvt .. + +lemma union_eqvt: + shows "p \ (A \ B) = (p \ A) \ (p \ B)" + unfolding Un_def Collect_eqvt2 disj_eqvt mem_eqvt by simp + +lemma inter_eqvt: + shows "p \ (A \ B) = (p \ A) \ (p \ B)" + unfolding Int_def Collect_eqvt2 conj_eqvt mem_eqvt by simp + +lemma Diff_eqvt: + fixes A B :: "'a::pt set" + shows "p \ (A - B) = p \ A - p \ B" + unfolding set_diff_eq Collect_eqvt2 conj_eqvt Not_eqvt mem_eqvt by simp + +lemma Compl_eqvt: + fixes A :: "'a::pt set" + shows "p \ (- A) = - (p \ A)" + unfolding Compl_eq_Diff_UNIV Diff_eqvt UNIV_eqvt .. + +lemma insert_eqvt: + shows "p \ (insert x A) = insert (p \ x) (p \ A)" + unfolding permute_set_eq_image image_insert .. + +lemma vimage_eqvt: + shows "p \ (f -` A) = (p \ f) -` (p \ A)" + unfolding vimage_def permute_fun_def [where f=f] + unfolding Collect_eqvt2 mem_eqvt .. + +lemma image_eqvt: + shows "p \ (f ` A) = (p \ f) ` (p \ A)" + unfolding permute_set_eq_image + unfolding permute_fun_def [where f=f] + by (simp add: image_image) + +lemma finite_permute_iff: + shows "finite (p \ A) \ finite A" + unfolding permute_set_eq_vimage + using bij_permute by (rule finite_vimage_iff) + +lemma finite_eqvt: + shows "p \ finite A = finite (p \ A)" + unfolding finite_permute_iff permute_bool_def .. + + +section {* List Operations *} + +lemma append_eqvt: + shows "p \ (xs @ ys) = (p \ xs) @ (p \ ys)" + by (induct xs) auto + +lemma supp_append: + shows "supp (xs @ ys) = supp xs \ supp ys" + by (induct xs) (auto simp add: supp_Nil supp_Cons) + +lemma fresh_append: + shows "a \ (xs @ ys) \ a \ xs \ a \ ys" + by (induct xs) (simp_all add: fresh_Nil fresh_Cons) + +lemma rev_eqvt: + shows "p \ (rev xs) = rev (p \ xs)" + by (induct xs) (simp_all add: append_eqvt) + +lemma supp_rev: + shows "supp (rev xs) = supp xs" + by (induct xs) (auto simp add: supp_append supp_Cons supp_Nil) + +lemma fresh_rev: + shows "a \ rev xs \ a \ xs" + by (induct xs) (auto simp add: fresh_append fresh_Cons fresh_Nil) + +lemma set_eqvt: + shows "p \ (set xs) = set (p \ xs)" + by (induct xs) (simp_all add: empty_eqvt insert_eqvt) + +(* needs finite support premise +lemma supp_set: + fixes x :: "'a::pt" + shows "supp (set xs) = supp xs" +*) + + +section {* Product Operations *} + +lemma fst_eqvt: + "p \ (fst x) = fst (p \ x)" + by (cases x) simp + +lemma snd_eqvt: + "p \ (snd x) = snd (p \ x)" + by (cases x) simp + +section {* Units *} + +lemma supp_unit: + shows "supp () = {}" + by (simp add: supp_def) + +lemma fresh_unit: + shows "a \ ()" + by (simp add: fresh_def supp_unit) + +section {* Equivariance automation *} + +text {* Setup of the theorem attributes @{text eqvt} and @{text eqvt_force} *} + +use "nominal_thmdecls.ML" +setup "Nominal_ThmDecls.setup" + +lemmas [eqvt] = + (* connectives *) + eq_eqvt if_eqvt imp_eqvt disj_eqvt conj_eqvt Not_eqvt + True_eqvt False_eqvt ex_eqvt all_eqvt ex1_eqvt + imp_eqvt [folded induct_implies_def] + + (* nominal *) + (*permute_eqvt commented out since it loops *) + supp_eqvt fresh_eqvt + permute_pure + + (* datatypes *) + permute_prod.simps append_eqvt rev_eqvt set_eqvt + fst_eqvt snd_eqvt Pair_eqvt + + (* sets *) + empty_eqvt UNIV_eqvt union_eqvt inter_eqvt mem_eqvt + Diff_eqvt Compl_eqvt insert_eqvt Collect_eqvt image_eqvt + + atom_eqvt add_perm_eqvt + +thm eqvts +thm eqvts_raw + +text {* helper lemmas for the eqvt_tac *} + +definition + "unpermute p = permute (- p)" + +lemma eqvt_apply: + fixes f :: "'a::pt \ 'b::pt" + and x :: "'a::pt" + shows "p \ (f x) \ (p \ f) (p \ x)" + unfolding permute_fun_def by simp + +lemma eqvt_lambda: + fixes f :: "'a::pt \ 'b::pt" + shows "p \ (\x. f x) \ (\x. p \ (f (unpermute p x)))" + unfolding permute_fun_def unpermute_def by simp + +lemma eqvt_bound: + shows "p \ unpermute p x \ x" + unfolding unpermute_def by simp + +use "nominal_permeq.ML" + + +lemma "p \ (A \ B = C)" +apply (tactic {* Nominal_Permeq.eqvt_tac @{context} 1 *}) +oops + +lemma "p \ (\(x::'a::pt). A \ (B::'a \ bool) x = C) = foo" +apply (tactic {* Nominal_Permeq.eqvt_tac @{context} 1 *}) +oops + +lemma "p \ (\x y. \z. x = z \ x = y \ z \ x) = foo" +apply (tactic {* Nominal_Permeq.eqvt_tac @{context} 1 *}) +oops + +lemma "p \ (\f x. f (g (f x))) = foo" +apply (tactic {* Nominal_Permeq.eqvt_tac @{context} 1 *}) +oops + +lemma "p \ (\q. q \ (r \ x)) = foo" +apply (tactic {* Nominal_Permeq.eqvt_tac @{context} 1 *}) +oops + +lemma "p \ (q \ r \ x) = foo" +apply (tactic {* Nominal_Permeq.eqvt_tac @{context} 1 *}) +oops + + +end diff -r c0eac04ae3b4 -r c34347ec7ab3 Nominal-General/Nominal2_Supp.thy --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Nominal-General/Nominal2_Supp.thy Sun Apr 04 21:39:28 2010 +0200 @@ -0,0 +1,501 @@ +(* Title: Nominal2_Supp + Authors: Brian Huffman, Christian Urban + + Supplementary Lemmas and Definitions for + Nominal Isabelle. +*) +theory Nominal2_Supp +imports Nominal2_Base Nominal2_Eqvt Nominal2_Atoms +begin + + +section {* Fresh-Star *} + +text {* The fresh-star generalisation of fresh is used in strong + induction principles. *} + +definition + fresh_star :: "atom set \ 'a::pt \ bool" ("_ \* _" [80,80] 80) +where + "as \* x \ \a \ as. a \ x" + +lemma fresh_star_prod: + fixes as::"atom set" + shows "as \* (x, y) = (as \* x \ as \* y)" + by (auto simp add: fresh_star_def fresh_Pair) + +lemma fresh_star_union: + shows "(as \ bs) \* x = (as \* x \ bs \* x)" + by (auto simp add: fresh_star_def) + +lemma fresh_star_insert: + shows "(insert a as) \* x = (a \ x \ as \* x)" + by (auto simp add: fresh_star_def) + +lemma fresh_star_Un_elim: + "((as \ bs) \* x \ PROP C) \ (as \* x \ bs \* x \ PROP C)" + unfolding fresh_star_def + apply(rule) + apply(erule meta_mp) + apply(auto) + done + +lemma fresh_star_insert_elim: + "(insert a as \* x \ PROP C) \ (a \ x \ as \* x \ PROP C)" + unfolding fresh_star_def + by rule (simp_all add: fresh_star_def) + +lemma fresh_star_empty_elim: + "({} \* x \ PROP C) \ PROP C" + by (simp add: fresh_star_def) + +lemma fresh_star_unit_elim: + shows "(a \* () \ PROP C) \ PROP C" + by (simp add: fresh_star_def fresh_unit) + +lemma fresh_star_prod_elim: + shows "(a \* (x, y) \ PROP C) \ (a \* x \ a \* y \ PROP C)" + by (rule, simp_all add: fresh_star_prod) + +lemma fresh_star_plus: + fixes p q::perm + shows "\a \* p; a \* q\ \ a \* (p + q)" + unfolding fresh_star_def + by (simp add: fresh_plus_perm) + +lemma fresh_star_permute_iff: + shows "(p \ a) \* (p \ x) \ a \* x" + unfolding fresh_star_def + by (metis mem_permute_iff permute_minus_cancel fresh_permute_iff) + +lemma fresh_star_eqvt: + shows "(p \ (as \* x)) = (p \ as) \* (p \ x)" +unfolding fresh_star_def +unfolding Ball_def +apply(simp add: all_eqvt) +apply(subst permute_fun_def) +apply(simp add: imp_eqvt fresh_eqvt mem_eqvt) +done + +section {* Avoiding of atom sets *} + +text {* + For every set of atoms, there is another set of atoms + avoiding a finitely supported c and there is a permutation + which 'translates' between both sets. +*} + +lemma at_set_avoiding_aux: + fixes Xs::"atom set" + and As::"atom set" + assumes b: "Xs \ As" + and c: "finite As" + shows "\p. (p \ Xs) \ As = {} \ (supp p) \ (Xs \ (p \ Xs))" +proof - + from b c have "finite Xs" by (rule finite_subset) + then show ?thesis using b + proof (induct rule: finite_subset_induct) + case empty + have "0 \ {} \ As = {}" by simp + moreover + have "supp (0::perm) \ {} \ 0 \ {}" by (simp add: supp_zero_perm) + ultimately show ?case by blast + next + case (insert x Xs) + then obtain p where + p1: "(p \ Xs) \ As = {}" and + p2: "supp p \ (Xs \ (p \ Xs))" by blast + from `x \ As` p1 have "x \ p \ Xs" by fast + with `x \ Xs` p2 have "x \ supp p" by fast + hence px: "p \ x = x" unfolding supp_perm by simp + have "finite (As \ p \ Xs)" + using `finite As` `finite Xs` + by (simp add: permute_set_eq_image) + then obtain y where "y \ (As \ p \ Xs)" "sort_of y = sort_of x" + by (rule obtain_atom) + hence y: "y \ As" "y \ p \ Xs" "sort_of y = sort_of x" + by simp_all + let ?q = "(x \ y) + p" + have q: "?q \ insert x Xs = insert y (p \ Xs)" + unfolding insert_eqvt + using `p \ x = x` `sort_of y = sort_of x` + using `x \ p \ Xs` `y \ p \ Xs` + by (simp add: swap_atom swap_set_not_in) + have "?q \ insert x Xs \ As = {}" + using `y \ As` `p \ Xs \ As = {}` + unfolding q by simp + moreover + have "supp ?q \ insert x Xs \ ?q \ insert x Xs" + using p2 unfolding q + apply (intro subset_trans [OF supp_plus_perm]) + apply (auto simp add: supp_swap) + done + ultimately show ?case by blast + qed +qed + +lemma at_set_avoiding: + assumes a: "finite Xs" + and b: "finite (supp c)" + obtains p::"perm" where "(p \ Xs)\*c" and "(supp p) \ (Xs \ (p \ Xs))" + using a b at_set_avoiding_aux [where Xs="Xs" and As="Xs \ supp c"] + unfolding fresh_star_def fresh_def by blast + + +section {* The freshness lemma according to Andrew Pitts *} + +lemma fresh_conv_MOST: + shows "a \ x \ (MOST b. (a \ b) \ x = x)" + unfolding fresh_def supp_def MOST_iff_cofinite by simp + +lemma fresh_apply: + assumes "a \ f" and "a \ x" + shows "a \ f x" + using assms unfolding fresh_conv_MOST + unfolding permute_fun_app_eq [where f=f] + by (elim MOST_rev_mp, simp) + +lemma freshness_lemma: + fixes h :: "'a::at \ 'b::pt" + assumes a: "\a. atom a \ (h, h a)" + shows "\x. \a. atom a \ h \ h a = x" +proof - + from a obtain b where a1: "atom b \ h" and a2: "atom b \ h b" + by (auto simp add: fresh_Pair) + show "\x. \a. atom a \ h \ h a = x" + proof (intro exI allI impI) + fix a :: 'a + assume a3: "atom a \ h" + show "h a = h b" + proof (cases "a = b") + assume "a = b" + thus "h a = h b" by simp + next + assume "a \ b" + hence "atom a \ b" by (simp add: fresh_at_base) + with a3 have "atom a \ h b" by (rule fresh_apply) + with a2 have d1: "(atom b \ atom a) \ (h b) = (h b)" + by (rule swap_fresh_fresh) + from a1 a3 have d2: "(atom b \ atom a) \ h = h" + by (rule swap_fresh_fresh) + from d1 have "h b = (atom b \ atom a) \ (h b)" by simp + also have "\ = ((atom b \ atom a) \ h) ((atom b \ atom a) \ b)" + by (rule permute_fun_app_eq) + also have "\ = h a" + using d2 by simp + finally show "h a = h b" by simp + qed + qed +qed + +lemma freshness_lemma_unique: + fixes h :: "'a::at \ 'b::pt" + assumes a: "\a. atom a \ (h, h a)" + shows "\!x. \a. atom a \ h \ h a = x" +proof (rule ex_ex1I) + from a show "\x. \a. atom a \ h \ h a = x" + by (rule freshness_lemma) +next + fix x y + assume x: "\a. atom a \ h \ h a = x" + assume y: "\a. atom a \ h \ h a = y" + from a x y show "x = y" + by (auto simp add: fresh_Pair) +qed + +text {* packaging the freshness lemma into a function *} + +definition + fresh_fun :: "('a::at \ 'b::pt) \ 'b" +where + "fresh_fun h = (THE x. \a. atom a \ h \ h a = x)" + +lemma fresh_fun_app: + fixes h :: "'a::at \ 'b::pt" + assumes a: "\a. atom a \ (h, h a)" + assumes b: "atom a \ h" + shows "fresh_fun h = h a" +unfolding fresh_fun_def +proof (rule the_equality) + show "\a'. atom a' \ h \ h a' = h a" + proof (intro strip) + fix a':: 'a + assume c: "atom a' \ h" + from a have "\x. \a. atom a \ h \ h a = x" by (rule freshness_lemma) + with b c show "h a' = h a" by auto + qed +next + fix fr :: 'b + assume "\a. atom a \ h \ h a = fr" + with b show "fr = h a" by auto +qed + +lemma fresh_fun_app': + fixes h :: "'a::at \ 'b::pt" + assumes a: "atom a \ h" "atom a \ h a" + shows "fresh_fun h = h a" + apply (rule fresh_fun_app) + apply (auto simp add: fresh_Pair intro: a) + done + +lemma fresh_fun_eqvt: + fixes h :: "'a::at \ 'b::pt" + assumes a: "\a. atom a \ (h, h a)" + shows "p \ (fresh_fun h) = fresh_fun (p \ h)" + using a + apply (clarsimp simp add: fresh_Pair) + apply (subst fresh_fun_app', assumption+) + apply (drule fresh_permute_iff [where p=p, THEN iffD2]) + apply (drule fresh_permute_iff [where p=p, THEN iffD2]) + apply (simp add: atom_eqvt permute_fun_app_eq [where f=h]) + apply (erule (1) fresh_fun_app' [symmetric]) + done + +lemma fresh_fun_supports: + fixes h :: "'a::at \ 'b::pt" + assumes a: "\a. atom a \ (h, h a)" + shows "(supp h) supports (fresh_fun h)" + apply (simp add: supports_def fresh_def [symmetric]) + apply (simp add: fresh_fun_eqvt [OF a] swap_fresh_fresh) + done + +notation fresh_fun (binder "FRESH " 10) + +lemma FRESH_f_iff: + fixes P :: "'a::at \ 'b::pure" + fixes f :: "'b \ 'c::pure" + assumes P: "finite (supp P)" + shows "(FRESH x. f (P x)) = f (FRESH x. P x)" +proof - + obtain a::'a where "atom a \ supp P" + using P by (rule obtain_at_base) + hence "atom a \ P" + by (simp add: fresh_def) + show "(FRESH x. f (P x)) = f (FRESH x. P x)" + apply (subst fresh_fun_app' [where a=a, OF _ pure_fresh]) + apply (cut_tac `atom a \ P`) + apply (simp add: fresh_conv_MOST) + apply (elim MOST_rev_mp, rule MOST_I, clarify) + apply (simp add: permute_fun_def permute_pure expand_fun_eq) + apply (subst fresh_fun_app' [where a=a, OF `atom a \ P` pure_fresh]) + apply (rule refl) + done +qed + +lemma FRESH_binop_iff: + fixes P :: "'a::at \ 'b::pure" + fixes Q :: "'a::at \ 'c::pure" + fixes binop :: "'b \ 'c \ 'd::pure" + assumes P: "finite (supp P)" + and Q: "finite (supp Q)" + shows "(FRESH x. binop (P x) (Q x)) = binop (FRESH x. P x) (FRESH x. Q x)" +proof - + from assms have "finite (supp P \ supp Q)" by simp + then obtain a::'a where "atom a \ (supp P \ supp Q)" + by (rule obtain_at_base) + hence "atom a \ P" and "atom a \ Q" + by (simp_all add: fresh_def) + show ?thesis + apply (subst fresh_fun_app' [where a=a, OF _ pure_fresh]) + apply (cut_tac `atom a \ P` `atom a \ Q`) + apply (simp add: fresh_conv_MOST) + apply (elim MOST_rev_mp, rule MOST_I, clarify) + apply (simp add: permute_fun_def permute_pure expand_fun_eq) + apply (subst fresh_fun_app' [where a=a, OF `atom a \ P` pure_fresh]) + apply (subst fresh_fun_app' [where a=a, OF `atom a \ Q` pure_fresh]) + apply (rule refl) + done +qed + +lemma FRESH_conj_iff: + fixes P Q :: "'a::at \ bool" + assumes P: "finite (supp P)" and Q: "finite (supp Q)" + shows "(FRESH x. P x \ Q x) \ (FRESH x. P x) \ (FRESH x. Q x)" +using P Q by (rule FRESH_binop_iff) + +lemma FRESH_disj_iff: + fixes P Q :: "'a::at \ bool" + assumes P: "finite (supp P)" and Q: "finite (supp Q)" + shows "(FRESH x. P x \ Q x) \ (FRESH x. P x) \ (FRESH x. Q x)" +using P Q by (rule FRESH_binop_iff) + + +section {* An example of a function without finite support *} + +primrec + nat_of :: "atom \ nat" +where + "nat_of (Atom s n) = n" + +lemma atom_eq_iff: + fixes a b :: atom + shows "a = b \ sort_of a = sort_of b \ nat_of a = nat_of b" + by (induct a, induct b, simp) + +lemma not_fresh_nat_of: + shows "\ a \ nat_of" +unfolding fresh_def supp_def +proof (clarsimp) + assume "finite {b. (a \ b) \ nat_of \ nat_of}" + hence "finite ({a} \ {b. (a \ b) \ nat_of \ nat_of})" + by simp + then obtain b where + b1: "b \ a" and + b2: "sort_of b = sort_of a" and + b3: "(a \ b) \ nat_of = nat_of" + by (rule obtain_atom) auto + have "nat_of a = (a \ b) \ (nat_of a)" by (simp add: permute_nat_def) + also have "\ = ((a \ b) \ nat_of) ((a \ b) \ a)" by (simp add: permute_fun_app_eq) + also have "\ = nat_of ((a \ b) \ a)" using b3 by simp + also have "\ = nat_of b" using b2 by simp + finally have "nat_of a = nat_of b" by simp + with b2 have "a = b" by (simp add: atom_eq_iff) + with b1 show "False" by simp +qed + +lemma supp_nat_of: + shows "supp nat_of = UNIV" + using not_fresh_nat_of [unfolded fresh_def] by auto + + +section {* Support for sets of atoms *} + +lemma supp_finite_atom_set: + fixes S::"atom set" + assumes "finite S" + shows "supp S = S" + apply(rule finite_supp_unique) + apply(simp add: supports_def) + apply(simp add: swap_set_not_in) + apply(rule assms) + apply(simp add: swap_set_in) +done + + +section {* transpositions of permutations *} + +fun + add_perm +where + "add_perm [] = 0" +| "add_perm ((a, b) # xs) = (a \ b) + add_perm xs" + +lemma add_perm_append: + shows "add_perm (xs @ ys) = add_perm xs + add_perm ys" +by (induct xs arbitrary: ys) + (auto simp add: add_assoc) + +lemma perm_list_exists: + fixes p::perm + shows "\xs. p = add_perm xs \ supp xs \ supp p" +apply(induct p taking: "\p::perm. card (supp p)" rule: measure_induct) +apply(rename_tac p) +apply(case_tac "supp p = {}") +apply(simp) +apply(simp add: supp_perm) +apply(rule_tac x="[]" in exI) +apply(simp add: supp_Nil) +apply(simp add: expand_perm_eq) +apply(subgoal_tac "\x. x \ supp p") +defer +apply(auto)[1] +apply(erule exE) +apply(drule_tac x="p + (((- p) \ x) \ x)" in spec) +apply(drule mp) +defer +apply(erule exE) +apply(rule_tac x="xs @ [((- p) \ x, x)]" in exI) +apply(simp add: add_perm_append) +apply(erule conjE) +apply(drule sym) +apply(simp) +apply(simp add: expand_perm_eq) +apply(simp add: supp_append) +apply(simp add: supp_perm supp_Cons supp_Nil supp_Pair supp_atom) +apply(rule conjI) +prefer 2 +apply(auto)[1] +apply (metis permute_atom_def_raw permute_minus_cancel(2)) +defer +apply(rule psubset_card_mono) +apply(simp add: finite_supp) +apply(rule psubsetI) +defer +apply(subgoal_tac "x \ supp (p + (- p \ x \ x))") +apply(blast) +apply(simp add: supp_perm) +defer +apply(auto simp add: supp_perm)[1] +apply(case_tac "x = xa") +apply(simp) +apply(case_tac "((- p) \ x) = xa") +apply(simp) +apply(case_tac "sort_of xa = sort_of x") +apply(simp) +apply(auto)[1] +apply(simp) +apply(simp) +apply(subgoal_tac "{a. p \ (- p \ x \ x) \ a \ a} \ {a. p \ a \ a}") +apply(blast) +apply(auto simp add: supp_perm)[1] +apply(case_tac "x = xa") +apply(simp) +apply(case_tac "((- p) \ x) = xa") +apply(simp) +apply(case_tac "sort_of xa = sort_of x") +apply(simp) +apply(auto)[1] +apply(simp) +apply(simp) +done + +section {* Lemma about support and permutations *} + +lemma supp_perm_eq: + assumes a: "(supp x) \* p" + shows "p \ x = x" +proof - + obtain xs where eq: "p = add_perm xs" and sub: "supp xs \ supp p" + using perm_list_exists by blast + from a have "\a \ supp p. a \ x" + by (auto simp add: fresh_star_def fresh_def supp_perm) + with eq sub have "\a \ supp xs. a \ x" by auto + then have "add_perm xs \ x = x" + by (induct xs rule: add_perm.induct) + (simp_all add: supp_Cons supp_Pair supp_atom swap_fresh_fresh) + then show "p \ x = x" using eq by simp +qed + +section {* at_set_avoiding2 *} + +lemma at_set_avoiding2: + assumes "finite xs" + and "finite (supp c)" "finite (supp x)" + and "xs \* x" + shows "\p. (p \ xs) \* c \ supp x \* p" +using assms +apply(erule_tac c="(c, x)" in at_set_avoiding) +apply(simp add: supp_Pair) +apply(rule_tac x="p" in exI) +apply(simp add: fresh_star_prod) +apply(subgoal_tac "\a \ supp p. a \ x") +apply(auto simp add: fresh_star_def fresh_def supp_perm)[1] +apply(auto simp add: fresh_star_def fresh_def) +done + +lemma at_set_avoiding2_atom: + assumes "finite (supp c)" "finite (supp x)" + and b: "xa \ x" + shows "\p. (p \ xa) \ c \ supp x \* p" +proof - + have a: "{xa} \* x" unfolding fresh_star_def by (simp add: b) + obtain p where p1: "(p \ {xa}) \* c" and p2: "supp x \* p" + using at_set_avoiding2[of "{xa}" "c" "x"] assms a by blast + have c: "(p \ xa) \ c" using p1 + unfolding fresh_star_def Ball_def + by (erule_tac x="p \ xa" in allE) (simp add: eqvts) + hence "p \ xa \ c \ supp x \* p" using p2 by blast + then show ?thesis by blast +qed + +end diff -r c0eac04ae3b4 -r c34347ec7ab3 Nominal-General/ROOT.ML --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Nominal-General/ROOT.ML Sun Apr 04 21:39:28 2010 +0200 @@ -0,0 +1,7 @@ + +no_document use_thys + ["Nominal2_Base", + "Nominal2_Eqvt", + "Nominal2_Atoms", + "Nominal2_Supp", + "Atoms"]; diff -r c0eac04ae3b4 -r c34347ec7ab3 Nominal-General/nominal_atoms.ML --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Nominal-General/nominal_atoms.ML Sun Apr 04 21:39:28 2010 +0200 @@ -0,0 +1,94 @@ +(* Title: nominal_atoms/ML + Authors: Brian Huffman, Christian Urban + + Command for defining concrete atom types. + + At the moment, only single-sorted atom types + are supported. +*) + +signature ATOM_DECL = +sig + val add_atom_decl: (binding * (binding option)) -> theory -> theory +end; + +structure Atom_Decl :> ATOM_DECL = +struct + +val atomT = @{typ atom}; +val permT = @{typ perm}; + +val sort_of_const = @{term sort_of}; +fun atom_const T = Const (@{const_name atom}, T --> atomT); +fun permute_const T = Const (@{const_name permute}, permT --> T --> T); + +fun mk_sort_of t = sort_of_const $ t; +fun mk_atom t = atom_const (fastype_of t) $ t; +fun mk_permute (p, t) = permute_const (fastype_of t) $ p $ t; + +fun atom_decl_set (str : string) : term = + let + val a = Free ("a", atomT); + val s = Const (@{const_name "Sort"}, @{typ "string => atom_sort list => atom_sort"}) + $ HOLogic.mk_string str $ HOLogic.nil_const @{typ "atom_sort"}; + in + HOLogic.mk_Collect ("a", atomT, HOLogic.mk_eq (mk_sort_of a, s)) + end + +fun add_atom_decl (name : binding, arg : binding option) (thy : theory) = + let + val _ = Theory.requires thy "Nominal2_Atoms" "nominal logic"; + val str = Sign.full_name thy name; + + (* typedef *) + val set = atom_decl_set str; + val tac = rtac @{thm exists_eq_simple_sort} 1; + val ((full_tname, info as ({Rep_name, Abs_name, ...}, {type_definition, ...})), thy) = + Typedef.add_typedef_global false NONE (name, [], NoSyn) set NONE tac thy; + + (* definition of atom and permute *) + val newT = #abs_type (fst info); + val RepC = Const (Rep_name, newT --> atomT); + val AbsC = Const (Abs_name, atomT --> newT); + val a = Free ("a", newT); + val p = Free ("p", permT); + val atom_eqn = + HOLogic.mk_Trueprop (HOLogic.mk_eq (mk_atom a, RepC $ a)); + val permute_eqn = + HOLogic.mk_Trueprop (HOLogic.mk_eq + (mk_permute (p, a), AbsC $ (mk_permute (p, RepC $ a)))); + val atom_def_name = + Binding.prefix_name "atom_" (Binding.suffix_name "_def" name); + val permute_def_name = + Binding.prefix_name "permute_" (Binding.suffix_name "_def" name); + + (* at class instance *) + val lthy = + Theory_Target.instantiation ([full_tname], [], @{sort at}) thy; + val ((_, (_, permute_ldef)), lthy) = + Specification.definition (NONE, ((permute_def_name, []), permute_eqn)) lthy; + val ((_, (_, atom_ldef)), lthy) = + Specification.definition (NONE, ((atom_def_name, []), atom_eqn)) lthy; + val ctxt_thy = ProofContext.init (ProofContext.theory_of lthy); + val permute_def = singleton (ProofContext.export lthy ctxt_thy) permute_ldef; + val atom_def = singleton (ProofContext.export lthy ctxt_thy) atom_ldef; + val class_thm = @{thm at_class} OF [type_definition, atom_def, permute_def]; + val thy = lthy + |> Class.prove_instantiation_instance (K (Tactic.rtac class_thm 1)) + |> Local_Theory.exit_global; + in + thy + end; + +(** outer syntax **) + +local structure P = OuterParse and K = OuterKeyword in + +val _ = + OuterSyntax.command "atom_decl" "declaration of a concrete atom type" K.thy_decl + ((P.binding -- Scan.option (Args.parens (P.binding))) >> + (Toplevel.print oo (Toplevel.theory o add_atom_decl))); + +end; + +end; diff -r c0eac04ae3b4 -r c34347ec7ab3 Nominal-General/nominal_permeq.ML --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Nominal-General/nominal_permeq.ML Sun Apr 04 21:39:28 2010 +0200 @@ -0,0 +1,71 @@ +(* Title: nominal_thmdecls.ML + Author: Brian Huffman, Christian Urban +*) + +signature NOMINAL_PERMEQ = +sig + val eqvt_tac: Proof.context -> int -> tactic + +end; + +(* TODO: + + - provide a method interface with the usual add and del options + + - print a warning if for a constant no eqvt lemma is stored + + - there seems to be too much simplified in case of multiple + permutations, like + + p o q o r o x + + we usually only want the outermost permutation to "float" in +*) + + +structure Nominal_Permeq: NOMINAL_PERMEQ = +struct + +local + +fun eqvt_apply_conv ctxt ct = + case (term_of ct) of + (Const (@{const_name "permute"}, _) $ _ $ (_ $ _)) => + let + val (perm, t) = Thm.dest_comb ct + val (_, p) = Thm.dest_comb perm + val (f, x) = Thm.dest_comb t + val a = ctyp_of_term x; + val b = ctyp_of_term t; + val ty_insts = map SOME [b, a] + val term_insts = map SOME [p, f, x] + in + Drule.instantiate' ty_insts term_insts @{thm eqvt_apply} + end + | _ => Conv.no_conv ct + +fun eqvt_lambda_conv ctxt ct = + case (term_of ct) of + (Const (@{const_name "permute"}, _) $ _ $ Abs _) => + Conv.rewr_conv @{thm eqvt_lambda} ct + | _ => Conv.no_conv ct + +in + +fun eqvt_conv ctxt ct = + Conv.first_conv + [ Conv.rewr_conv @{thm eqvt_bound}, + eqvt_apply_conv ctxt + then_conv Conv.comb_conv (eqvt_conv ctxt), + eqvt_lambda_conv ctxt + then_conv Conv.abs_conv (fn (v, ctxt) => eqvt_conv ctxt) ctxt, + More_Conv.rewrs_conv (Nominal_ThmDecls.get_eqvts_raw_thms ctxt), + Conv.all_conv + ] ct + +fun eqvt_tac ctxt = + CONVERSION (More_Conv.bottom_conv (fn ctxt => eqvt_conv ctxt) ctxt) + +end + +end; (* structure *) \ No newline at end of file diff -r c0eac04ae3b4 -r c34347ec7ab3 Nominal-General/nominal_thmdecls.ML --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Nominal-General/nominal_thmdecls.ML Sun Apr 04 21:39:28 2010 +0200 @@ -0,0 +1,134 @@ +(* Title: nominal_thmdecls.ML + Author: Christian Urban + + Infrastructure for the lemma collection "eqvts". + + Provides the attributes [eqvt] and [eqvt_raw], and the theorem + lists eqvts and eqvts_raw. The first attribute will store the + theorem in the eqvts list and also in the eqvts_raw list. For + the latter the theorem is expected to be of the form + + p o (c x1 x2 ...) = c (p o x1) (p o x2) ... + + and it is stored in the form + + p o c == c + + The [eqvt_raw] attribute just adds the theorem to eqvts_raw. + + TODO: + + - deal with eqvt-lemmas of the form + + c x1 x2 ... ==> c (p o x1) (p o x2) .. +*) + +signature NOMINAL_THMDECLS = +sig + val eqvt_add: attribute + val eqvt_del: attribute + val eqvt_raw_add: attribute + val eqvt_raw_del: attribute + val setup: theory -> theory + val get_eqvts_thms: Proof.context -> thm list + val get_eqvts_raw_thms: Proof.context -> thm list + +end; + +structure Nominal_ThmDecls: NOMINAL_THMDECLS = +struct + + +structure EqvtData = Generic_Data +( type T = thm Item_Net.T; + val empty = Thm.full_rules; + val extend = I; + val merge = Item_Net.merge ); + +structure EqvtRawData = Generic_Data +( type T = thm Item_Net.T; + val empty = Thm.full_rules; + val extend = I; + val merge = Item_Net.merge ); + +val eqvts = Item_Net.content o EqvtData.get; +val eqvts_raw = Item_Net.content o EqvtRawData.get; + +val get_eqvts_thms = eqvts o Context.Proof; +val get_eqvts_raw_thms = eqvts_raw o Context.Proof; + +val add_thm = EqvtData.map o Item_Net.update; +val del_thm = EqvtData.map o Item_Net.remove; + +val add_raw_thm = EqvtRawData.map o Item_Net.update; +val del_raw_thm = EqvtRawData.map o Item_Net.remove; + +fun dest_perm (Const (@{const_name "permute"}, _) $ p $ t) = (p, t) + | dest_perm t = raise TERM("dest_perm", [t]) + +fun mk_perm p trm = +let + val ty = fastype_of trm +in + Const (@{const_name "permute"}, @{typ "perm"} --> ty --> ty) $ p $ trm +end + +fun eqvt_transform_tac thm = REPEAT o FIRST' + [CHANGED o simp_tac (HOL_basic_ss addsimps @{thms permute_minus_cancel}), + rtac (thm RS @{thm trans}), + rtac @{thm trans[OF permute_fun_def]} THEN' rtac @{thm ext}] + +(* transform equations into the required form *) +fun transform_eq ctxt thm lhs rhs = +let + val (p, t) = dest_perm lhs + val (c, args) = strip_comb t + val (c', args') = strip_comb rhs + val eargs = map Envir.eta_contract args + val eargs' = map Envir.eta_contract args' + val p_str = fst (fst (dest_Var p)) + val goal = HOLogic.mk_Trueprop (HOLogic.mk_eq (mk_perm p c, c)) +in + if c <> c' + then error "eqvt lemma is not of the right form (constants do not agree)" + else if eargs' <> map (mk_perm p) eargs + then error "eqvt lemma is not of the right form (arguments do not agree)" + else if args = [] + then thm + else Goal.prove ctxt [p_str] [] goal + (fn _ => eqvt_transform_tac thm 1) +end + +fun transform addel_fun thm context = +let + val ctxt = Context.proof_of context + val trm = HOLogic.dest_Trueprop (prop_of thm) +in + case trm of + Const (@{const_name "op ="}, _) $ lhs $ rhs => + let + val thm' = transform_eq ctxt thm lhs rhs RS @{thm eq_reflection} + in + addel_fun thm' context + end + | _ => raise (error "only (op=) case implemented yet") +end + +val eqvt_add = Thm.declaration_attribute (fn thm => (add_thm thm) o (transform add_raw_thm thm)); +val eqvt_del = Thm.declaration_attribute (fn thm => (del_thm thm) o (transform del_raw_thm thm)); + +val eqvt_raw_add = Thm.declaration_attribute add_raw_thm; +val eqvt_raw_del = Thm.declaration_attribute del_raw_thm; + +val setup = + Attrib.setup @{binding "eqvt"} (Attrib.add_del eqvt_add eqvt_del) + (cat_lines ["declaration of equivariance lemmas - they will automtically be", + "brought into the form p o c = c"]) #> + Attrib.setup @{binding "eqvt_raw"} (Attrib.add_del eqvt_raw_add eqvt_raw_del) + (cat_lines ["declaration of equivariance lemmas - no", + "transformation is performed"]) #> + PureThy.add_thms_dynamic (@{binding "eqvts"}, eqvts) #> + PureThy.add_thms_dynamic (@{binding "eqvts_raw"}, eqvts_raw); + + +end; diff -r c0eac04ae3b4 -r c34347ec7ab3 Nominal/Atoms.thy --- a/Nominal/Atoms.thy Sat Apr 03 22:31:11 2010 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,164 +0,0 @@ -(* Title: Atoms - Authors: Brian Huffman, Christian Urban - - Instantiations of concrete atoms -*) -theory Atoms -imports Nominal2_Atoms -begin - -section {* Manual instantiation of class @{text at}. *} - -typedef (open) name = "{a. sort_of a = Sort ''name'' []}" -by (rule exists_eq_simple_sort) - -instantiation name :: at -begin - -definition - "p \ a = Abs_name (p \ Rep_name a)" - -definition - "atom a = Rep_name a" - -instance -apply (rule at_class) -apply (rule type_definition_name) -apply (rule atom_name_def) -apply (rule permute_name_def) -done - -end - -lemma sort_of_atom_name: - shows "sort_of (atom (a::name)) = Sort ''name'' []" - unfolding atom_name_def using Rep_name by simp - -text {* Custom syntax for concrete atoms of type at *} - -term "a:::name" - -text {* - a:::name stands for (atom a) with a being of concrete atom - type name. The above lemma can therefore also be stated as - - "sort_of (a:::name) = Sort ''name'' []" - - This does not work for multi-sorted atoms. -*} - - -section {* Automatic instantiation of class @{text at}. *} - -atom_decl name2 - -lemma sort_of_atom_name2: - "sort_of (atom (a::name2)) = Sort ''Atoms.name2'' []" -unfolding atom_name2_def -using Rep_name2 -by simp - -text {* example swappings *} -lemma - fixes a b::"atom" - assumes "sort_of a = sort_of b" - shows "(a \ b) \ (a, b) = (b, a)" -using assms -by simp - -lemma - fixes a b::"name2" - shows "(a \ b) \ (a, b) = (b, a)" -by simp - -section {* An example for multiple-sort atoms *} - -datatype ty = - TVar string -| Fun ty ty ("_ \ _") - -primrec - sort_of_ty::"ty \ atom_sort" -where - "sort_of_ty (TVar s) = Sort ''TVar'' [Sort s []]" -| "sort_of_ty (Fun ty1 ty2) = Sort ''Fun'' [sort_of_ty ty1, sort_of_ty ty2]" - -lemma sort_of_ty_eq_iff: - shows "sort_of_ty x = sort_of_ty y \ x = y" -apply(induct x arbitrary: y) -apply(case_tac [!] y) -apply(simp_all) -done - -declare sort_of_ty.simps [simp del] - -typedef (open) var = "{a. sort_of a \ range sort_of_ty}" - by (rule_tac x="Atom (sort_of_ty x) y" in exI, simp) - -instantiation var :: at_base -begin - -definition - "p \ a = Abs_var (p \ Rep_var a)" - -definition - "atom a = Rep_var a" - -instance -apply (rule at_base_class) -apply (rule type_definition_var) -apply (rule atom_var_def) -apply (rule permute_var_def) -done - -end - -text {* Constructor for variables. *} - -definition - Var :: "nat \ ty \ var" -where - "Var x t = Abs_var (Atom (sort_of_ty t) x)" - -lemma Var_eq_iff [simp]: - shows "Var x s = Var y t \ x = y \ s = t" - unfolding Var_def - by (auto simp add: Abs_var_inject sort_of_ty_eq_iff) - -lemma sort_of_atom_var [simp]: - "sort_of (atom (Var n ty)) = sort_of_ty ty" - unfolding atom_var_def Var_def - by (simp add: Abs_var_inverse) - -lemma - assumes "\ \ \" - shows "(Var x \ \ Var y \) \ (Var x \, Var x \) = (Var y \, Var x \)" - using assms by simp - -text {* Projecting out the type component of a variable. *} - -definition - ty_of :: "var \ ty" -where - "ty_of x = inv sort_of_ty (sort_of (atom x))" - -text {* - Functions @{term Var}/@{term ty_of} satisfy many of the same - properties as @{term Atom}/@{term sort_of}. -*} - -lemma ty_of_Var [simp]: - shows "ty_of (Var x t) = t" - unfolding ty_of_def - unfolding sort_of_atom_var - apply (rule inv_f_f) - apply (simp add: inj_on_def sort_of_ty_eq_iff) - done - -lemma ty_of_permute [simp]: - shows "ty_of (p \ x) = ty_of x" - unfolding ty_of_def - unfolding atom_eqvt [symmetric] - by simp - -end diff -r c0eac04ae3b4 -r c34347ec7ab3 Nominal/Ex/ExLet.thy --- a/Nominal/Ex/ExLet.thy Sat Apr 03 22:31:11 2010 +0200 +++ b/Nominal/Ex/ExLet.thy Sun Apr 04 21:39:28 2010 +0200 @@ -167,6 +167,7 @@ apply(subgoal_tac "\q. (q \ set (bn (p \ lts))) \* c \ supp (Abs_lst (bn (p \ lts)) (p \ trm)) \* q") apply(erule exE) apply(erule conjE) + thm Lt_subst apply(subst Lt_subst) apply assumption apply(rule a4) diff -r c0eac04ae3b4 -r c34347ec7ab3 Nominal/Fv.thy --- a/Nominal/Fv.thy Sat Apr 03 22:31:11 2010 +0200 +++ b/Nominal/Fv.thy Sun Apr 04 21:39:28 2010 +0200 @@ -1,5 +1,5 @@ theory Fv -imports "Nominal2_Atoms" "Abs" "Perm" "Rsp" "Nominal2_FSet" +imports "../Nominal-General/Nominal2_Atoms" "Abs" "Perm" "Rsp" "Nominal2_FSet" begin (* The bindings data structure: diff -r c0eac04ae3b4 -r c34347ec7ab3 Nominal/Lift.thy --- a/Nominal/Lift.thy Sat Apr 03 22:31:11 2010 +0200 +++ b/Nominal/Lift.thy Sun Apr 04 21:39:28 2010 +0200 @@ -1,5 +1,8 @@ theory Lift -imports "Nominal2_Atoms" "Nominal2_Eqvt" "Nominal2_Supp" "Abs" "Perm" "Fv" "Rsp" +imports "../Nominal-General/Nominal2_Atoms" + "../Nominal-General/Nominal2_Eqvt" + "../Nominal_General/Nominal2_Supp" + "Abs" "Perm" "Fv" "Rsp" begin diff -r c0eac04ae3b4 -r c34347ec7ab3 Nominal/Nominal2_Atoms.thy --- a/Nominal/Nominal2_Atoms.thy Sat Apr 03 22:31:11 2010 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,255 +0,0 @@ -(* Title: Nominal2_Atoms - Authors: Brian Huffman, Christian Urban - - Definitions for concrete atom types. -*) -theory Nominal2_Atoms -imports Nominal2_Base -uses ("nominal_atoms.ML") -begin - -section {* Concrete atom types *} - -text {* - Class @{text at_base} allows types containing multiple sorts of atoms. - Class @{text at} only allows types with a single sort. -*} - -class at_base = pt + - fixes atom :: "'a \ atom" - assumes atom_eq_iff [simp]: "atom a = atom b \ a = b" - assumes atom_eqvt: "p \ (atom a) = atom (p \ a)" - -class at = at_base + - assumes sort_of_atom_eq [simp]: "sort_of (atom a) = sort_of (atom b)" - -lemma supp_at_base: - fixes a::"'a::at_base" - shows "supp a = {atom a}" - by (simp add: supp_atom [symmetric] supp_def atom_eqvt) - -lemma fresh_at_base: - shows "a \ b \ a \ atom b" - unfolding fresh_def by (simp add: supp_at_base) - -instance at_base < fs -proof qed (simp add: supp_at_base) - -lemma at_base_infinite [simp]: - shows "infinite (UNIV :: 'a::at_base set)" (is "infinite ?U") -proof - obtain a :: 'a where "True" by auto - assume "finite ?U" - hence "finite (atom ` ?U)" - by (rule finite_imageI) - then obtain b where b: "b \ atom ` ?U" "sort_of b = sort_of (atom a)" - by (rule obtain_atom) - from b(2) have "b = atom ((atom a \ b) \ a)" - unfolding atom_eqvt [symmetric] - by (simp add: swap_atom) - hence "b \ atom ` ?U" by simp - with b(1) show "False" by simp -qed - -lemma swap_at_base_simps [simp]: - fixes x y::"'a::at_base" - shows "sort_of (atom x) = sort_of (atom y) \ (atom x \ atom y) \ x = y" - and "sort_of (atom x) = sort_of (atom y) \ (atom x \ atom y) \ y = x" - and "atom x \ a \ atom x \ b \ (a \ b) \ x = x" - unfolding atom_eq_iff [symmetric] - unfolding atom_eqvt [symmetric] - by simp_all - -lemma obtain_at_base: - assumes X: "finite X" - obtains a::"'a::at_base" where "atom a \ X" -proof - - have "inj (atom :: 'a \ atom)" - by (simp add: inj_on_def) - with X have "finite (atom -` X :: 'a set)" - by (rule finite_vimageI) - with at_base_infinite have "atom -` X \ (UNIV :: 'a set)" - by auto - then obtain a :: 'a where "atom a \ X" - by auto - thus ?thesis .. -qed - - -section {* A swapping operation for concrete atoms *} - -definition - flip :: "'a::at_base \ 'a \ perm" ("'(_ \ _')") -where - "(a \ b) = (atom a \ atom b)" - -lemma flip_self [simp]: "(a \ a) = 0" - unfolding flip_def by (rule swap_self) - -lemma flip_commute: "(a \ b) = (b \ a)" - unfolding flip_def by (rule swap_commute) - -lemma minus_flip [simp]: "- (a \ b) = (a \ b)" - unfolding flip_def by (rule minus_swap) - -lemma add_flip_cancel: "(a \ b) + (a \ b) = 0" - unfolding flip_def by (rule swap_cancel) - -lemma permute_flip_cancel [simp]: "(a \ b) \ (a \ b) \ x = x" - unfolding permute_plus [symmetric] add_flip_cancel by simp - -lemma permute_flip_cancel2 [simp]: "(a \ b) \ (b \ a) \ x = x" - by (simp add: flip_commute) - -lemma flip_eqvt: - fixes a b c::"'a::at_base" - shows "p \ (a \ b) = (p \ a \ p \ b)" - unfolding flip_def - by (simp add: swap_eqvt atom_eqvt) - -lemma flip_at_base_simps [simp]: - shows "sort_of (atom a) = sort_of (atom b) \ (a \ b) \ a = b" - and "sort_of (atom a) = sort_of (atom b) \ (a \ b) \ b = a" - and "\a \ c; b \ c\ \ (a \ b) \ c = c" - and "sort_of (atom a) \ sort_of (atom b) \ (a \ b) \ x = x" - unfolding flip_def - unfolding atom_eq_iff [symmetric] - unfolding atom_eqvt [symmetric] - by simp_all - -text {* the following two lemmas do not hold for at_base, - only for single sort atoms from at *} - -lemma permute_flip_at: - fixes a b c::"'a::at" - shows "(a \ b) \ c = (if c = a then b else if c = b then a else c)" - unfolding flip_def - apply (rule atom_eq_iff [THEN iffD1]) - apply (subst atom_eqvt [symmetric]) - apply (simp add: swap_atom) - done - -lemma flip_at_simps [simp]: - fixes a b::"'a::at" - shows "(a \ b) \ a = b" - and "(a \ b) \ b = a" - unfolding permute_flip_at by simp_all - -lemma flip_fresh_fresh: - fixes a b::"'a::at_base" - assumes "atom a \ x" "atom b \ x" - shows "(a \ b) \ x = x" -using assms -by (simp add: flip_def swap_fresh_fresh) - -subsection {* Syntax for coercing at-elements to the atom-type *} - -syntax - "_atom_constrain" :: "logic \ type \ logic" ("_:::_" [4, 0] 3) - -translations - "_atom_constrain a t" => "CONST atom (_constrain a t)" - - -subsection {* A lemma for proving instances of class @{text at}. *} - -setup {* Sign.add_const_constraint (@{const_name "permute"}, NONE) *} -setup {* Sign.add_const_constraint (@{const_name "atom"}, NONE) *} - -text {* - New atom types are defined as subtypes of @{typ atom}. -*} - -lemma exists_eq_simple_sort: - shows "\a. a \ {a. sort_of a = s}" - by (rule_tac x="Atom s 0" in exI, simp) - -lemma exists_eq_sort: - shows "\a. a \ {a. sort_of a \ range sort_fun}" - by (rule_tac x="Atom (sort_fun x) y" in exI, simp) - -lemma at_base_class: - fixes sort_fun :: "'b \atom_sort" - fixes Rep :: "'a \ atom" and Abs :: "atom \ 'a" - assumes type: "type_definition Rep Abs {a. sort_of a \ range sort_fun}" - assumes atom_def: "\a. atom a = Rep a" - assumes permute_def: "\p a. p \ a = Abs (p \ Rep a)" - shows "OFCLASS('a, at_base_class)" -proof - interpret type_definition Rep Abs "{a. sort_of a \ range sort_fun}" by (rule type) - have sort_of_Rep: "\a. sort_of (Rep a) \ range sort_fun" using Rep by simp - fix a b :: 'a and p p1 p2 :: perm - show "0 \ a = a" - unfolding permute_def by (simp add: Rep_inverse) - show "(p1 + p2) \ a = p1 \ p2 \ a" - unfolding permute_def by (simp add: Abs_inverse sort_of_Rep) - show "atom a = atom b \ a = b" - unfolding atom_def by (simp add: Rep_inject) - show "p \ atom a = atom (p \ a)" - unfolding permute_def atom_def by (simp add: Abs_inverse sort_of_Rep) -qed - -(* -lemma at_class: - fixes s :: atom_sort - fixes Rep :: "'a \ atom" and Abs :: "atom \ 'a" - assumes type: "type_definition Rep Abs {a. sort_of a \ range (\x::unit. s)}" - assumes atom_def: "\a. atom a = Rep a" - assumes permute_def: "\p a. p \ a = Abs (p \ Rep a)" - shows "OFCLASS('a, at_class)" -proof - interpret type_definition Rep Abs "{a. sort_of a \ range (\x::unit. s)}" by (rule type) - have sort_of_Rep: "\a. sort_of (Rep a) = s" using Rep by (simp add: image_def) - fix a b :: 'a and p p1 p2 :: perm - show "0 \ a = a" - unfolding permute_def by (simp add: Rep_inverse) - show "(p1 + p2) \ a = p1 \ p2 \ a" - unfolding permute_def by (simp add: Abs_inverse sort_of_Rep) - show "sort_of (atom a) = sort_of (atom b)" - unfolding atom_def by (simp add: sort_of_Rep) - show "atom a = atom b \ a = b" - unfolding atom_def by (simp add: Rep_inject) - show "p \ atom a = atom (p \ a)" - unfolding permute_def atom_def by (simp add: Abs_inverse sort_of_Rep) -qed -*) - -lemma at_class: - fixes s :: atom_sort - fixes Rep :: "'a \ atom" and Abs :: "atom \ 'a" - assumes type: "type_definition Rep Abs {a. sort_of a = s}" - assumes atom_def: "\a. atom a = Rep a" - assumes permute_def: "\p a. p \ a = Abs (p \ Rep a)" - shows "OFCLASS('a, at_class)" -proof - interpret type_definition Rep Abs "{a. sort_of a = s}" by (rule type) - have sort_of_Rep: "\a. sort_of (Rep a) = s" using Rep by (simp add: image_def) - fix a b :: 'a and p p1 p2 :: perm - show "0 \ a = a" - unfolding permute_def by (simp add: Rep_inverse) - show "(p1 + p2) \ a = p1 \ p2 \ a" - unfolding permute_def by (simp add: Abs_inverse sort_of_Rep) - show "sort_of (atom a) = sort_of (atom b)" - unfolding atom_def by (simp add: sort_of_Rep) - show "atom a = atom b \ a = b" - unfolding atom_def by (simp add: Rep_inject) - show "p \ atom a = atom (p \ a)" - unfolding permute_def atom_def by (simp add: Abs_inverse sort_of_Rep) -qed - -setup {* Sign.add_const_constraint - (@{const_name "permute"}, SOME @{typ "perm \ 'a::pt \ 'a"}) *} -setup {* Sign.add_const_constraint - (@{const_name "atom"}, SOME @{typ "'a::at_base \ atom"}) *} - - -section {* Automation for creating concrete atom types *} - -text {* at the moment only single-sort concrete atoms are supported *} - -use "nominal_atoms.ML" - - - - -end diff -r c0eac04ae3b4 -r c34347ec7ab3 Nominal/Nominal2_Base.thy --- a/Nominal/Nominal2_Base.thy Sat Apr 03 22:31:11 2010 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1062 +0,0 @@ -(* Title: Nominal2_Base - Authors: Brian Huffman, Christian Urban - - Basic definitions and lemma infrastructure for - Nominal Isabelle. -*) -theory Nominal2_Base -imports Main Infinite_Set -begin - -section {* Atoms and Sorts *} - -text {* A simple implementation for atom_sorts is strings. *} -(* types atom_sort = string *) - -text {* To deal with Church-like binding we use trees of - strings as sorts. *} - -datatype atom_sort = Sort "string" "atom_sort list" - -datatype atom = Atom atom_sort nat - - -text {* Basic projection function. *} - -primrec - sort_of :: "atom \ atom_sort" -where - "sort_of (Atom s i) = s" - - -text {* There are infinitely many atoms of each sort. *} -lemma INFM_sort_of_eq: - shows "INFM a. sort_of a = s" -proof - - have "INFM i. sort_of (Atom s i) = s" by simp - moreover have "inj (Atom s)" by (simp add: inj_on_def) - ultimately show "INFM a. sort_of a = s" by (rule INFM_inj) -qed - -lemma infinite_sort_of_eq: - shows "infinite {a. sort_of a = s}" - using INFM_sort_of_eq unfolding INFM_iff_infinite . - -lemma atom_infinite [simp]: - shows "infinite (UNIV :: atom set)" - using subset_UNIV infinite_sort_of_eq - by (rule infinite_super) - -lemma obtain_atom: - fixes X :: "atom set" - assumes X: "finite X" - obtains a where "a \ X" "sort_of a = s" -proof - - from X have "MOST a. a \ X" - unfolding MOST_iff_cofinite by simp - with INFM_sort_of_eq - have "INFM a. sort_of a = s \ a \ X" - by (rule INFM_conjI) - then obtain a where "a \ X" "sort_of a = s" - by (auto elim: INFM_E) - then show ?thesis .. -qed - -section {* Sort-Respecting Permutations *} - -typedef perm = - "{f. bij f \ finite {a. f a \ a} \ (\a. sort_of (f a) = sort_of a)}" -proof - show "id \ ?perm" by simp -qed - -lemma permI: - assumes "bij f" and "MOST x. f x = x" and "\a. sort_of (f a) = sort_of a" - shows "f \ perm" - using assms unfolding perm_def MOST_iff_cofinite by simp - -lemma perm_is_bij: "f \ perm \ bij f" - unfolding perm_def by simp - -lemma perm_is_finite: "f \ perm \ finite {a. f a \ a}" - unfolding perm_def by simp - -lemma perm_is_sort_respecting: "f \ perm \ sort_of (f a) = sort_of a" - unfolding perm_def by simp - -lemma perm_MOST: "f \ perm \ MOST x. f x = x" - unfolding perm_def MOST_iff_cofinite by simp - -lemma perm_id: "id \ perm" - unfolding perm_def by simp - -lemma perm_comp: - assumes f: "f \ perm" and g: "g \ perm" - shows "(f \ g) \ perm" -apply (rule permI) -apply (rule bij_comp) -apply (rule perm_is_bij [OF g]) -apply (rule perm_is_bij [OF f]) -apply (rule MOST_rev_mp [OF perm_MOST [OF g]]) -apply (rule MOST_rev_mp [OF perm_MOST [OF f]]) -apply (simp) -apply (simp add: perm_is_sort_respecting [OF f]) -apply (simp add: perm_is_sort_respecting [OF g]) -done - -lemma perm_inv: - assumes f: "f \ perm" - shows "(inv f) \ perm" -apply (rule permI) -apply (rule bij_imp_bij_inv) -apply (rule perm_is_bij [OF f]) -apply (rule MOST_mono [OF perm_MOST [OF f]]) -apply (erule subst, rule inv_f_f) -apply (rule bij_is_inj [OF perm_is_bij [OF f]]) -apply (rule perm_is_sort_respecting [OF f, THEN sym, THEN trans]) -apply (simp add: surj_f_inv_f [OF bij_is_surj [OF perm_is_bij [OF f]]]) -done - -lemma bij_Rep_perm: "bij (Rep_perm p)" - using Rep_perm [of p] unfolding perm_def by simp - -lemma finite_Rep_perm: "finite {a. Rep_perm p a \ a}" - using Rep_perm [of p] unfolding perm_def by simp - -lemma sort_of_Rep_perm: "sort_of (Rep_perm p a) = sort_of a" - using Rep_perm [of p] unfolding perm_def by simp - -lemma Rep_perm_ext: - "Rep_perm p1 = Rep_perm p2 \ p1 = p2" - by (simp add: expand_fun_eq Rep_perm_inject [symmetric]) - - -subsection {* Permutations form a group *} - -instantiation perm :: group_add -begin - -definition - "0 = Abs_perm id" - -definition - "- p = Abs_perm (inv (Rep_perm p))" - -definition - "p + q = Abs_perm (Rep_perm p \ Rep_perm q)" - -definition - "(p1::perm) - p2 = p1 + - p2" - -lemma Rep_perm_0: "Rep_perm 0 = id" - unfolding zero_perm_def - by (simp add: Abs_perm_inverse perm_id) - -lemma Rep_perm_add: - "Rep_perm (p1 + p2) = Rep_perm p1 \ Rep_perm p2" - unfolding plus_perm_def - by (simp add: Abs_perm_inverse perm_comp Rep_perm) - -lemma Rep_perm_uminus: - "Rep_perm (- p) = inv (Rep_perm p)" - unfolding uminus_perm_def - by (simp add: Abs_perm_inverse perm_inv Rep_perm) - -instance -apply default -unfolding Rep_perm_inject [symmetric] -unfolding minus_perm_def -unfolding Rep_perm_add -unfolding Rep_perm_uminus -unfolding Rep_perm_0 -by (simp_all add: o_assoc inv_o_cancel [OF bij_is_inj [OF bij_Rep_perm]]) - -end - - -section {* Implementation of swappings *} - -definition - swap :: "atom \ atom \ perm" ("'(_ \ _')") -where - "(a \ b) = - Abs_perm (if sort_of a = sort_of b - then (\c. if a = c then b else if b = c then a else c) - else id)" - -lemma Rep_perm_swap: - "Rep_perm (a \ b) = - (if sort_of a = sort_of b - then (\c. if a = c then b else if b = c then a else c) - else id)" -unfolding swap_def -apply (rule Abs_perm_inverse) -apply (rule permI) -apply (auto simp add: bij_def inj_on_def surj_def)[1] -apply (rule MOST_rev_mp [OF MOST_neq(1) [of a]]) -apply (rule MOST_rev_mp [OF MOST_neq(1) [of b]]) -apply (simp) -apply (simp) -done - -lemmas Rep_perm_simps = - Rep_perm_0 - Rep_perm_add - Rep_perm_uminus - Rep_perm_swap - -lemma swap_different_sorts [simp]: - "sort_of a \ sort_of b \ (a \ b) = 0" - by (rule Rep_perm_ext) (simp add: Rep_perm_simps) - -lemma swap_cancel: - "(a \ b) + (a \ b) = 0" -by (rule Rep_perm_ext) - (simp add: Rep_perm_simps expand_fun_eq) - -lemma swap_self [simp]: - "(a \ a) = 0" - by (rule Rep_perm_ext, simp add: Rep_perm_simps expand_fun_eq) - -lemma minus_swap [simp]: - "- (a \ b) = (a \ b)" - by (rule minus_unique [OF swap_cancel]) - -lemma swap_commute: - "(a \ b) = (b \ a)" - by (rule Rep_perm_ext) - (simp add: Rep_perm_swap expand_fun_eq) - -lemma swap_triple: - assumes "a \ b" and "c \ b" - assumes "sort_of a = sort_of b" "sort_of b = sort_of c" - shows "(a \ c) + (b \ c) + (a \ c) = (a \ b)" - using assms - by (rule_tac Rep_perm_ext) - (auto simp add: Rep_perm_simps expand_fun_eq) - - -section {* Permutation Types *} - -text {* - Infix syntax for @{text permute} has higher precedence than - addition, but lower than unary minus. -*} - -class pt = - fixes permute :: "perm \ 'a \ 'a" ("_ \ _" [76, 75] 75) - assumes permute_zero [simp]: "0 \ x = x" - assumes permute_plus [simp]: "(p + q) \ x = p \ (q \ x)" -begin - -lemma permute_diff [simp]: - shows "(p - q) \ x = p \ - q \ x" - unfolding diff_minus by simp - -lemma permute_minus_cancel [simp]: - shows "p \ - p \ x = x" - and "- p \ p \ x = x" - unfolding permute_plus [symmetric] by simp_all - -lemma permute_swap_cancel [simp]: - shows "(a \ b) \ (a \ b) \ x = x" - unfolding permute_plus [symmetric] - by (simp add: swap_cancel) - -lemma permute_swap_cancel2 [simp]: - shows "(a \ b) \ (b \ a) \ x = x" - unfolding permute_plus [symmetric] - by (simp add: swap_commute) - -lemma inj_permute [simp]: - shows "inj (permute p)" - by (rule inj_on_inverseI) - (rule permute_minus_cancel) - -lemma surj_permute [simp]: - shows "surj (permute p)" - by (rule surjI, rule permute_minus_cancel) - -lemma bij_permute [simp]: - shows "bij (permute p)" - by (rule bijI [OF inj_permute surj_permute]) - -lemma inv_permute: - shows "inv (permute p) = permute (- p)" - by (rule inv_equality) (simp_all) - -lemma permute_minus: - shows "permute (- p) = inv (permute p)" - by (simp add: inv_permute) - -lemma permute_eq_iff [simp]: - shows "p \ x = p \ y \ x = y" - by (rule inj_permute [THEN inj_eq]) - -end - -subsection {* Permutations for atoms *} - -instantiation atom :: pt -begin - -definition - "p \ a = Rep_perm p a" - -instance -apply(default) -apply(simp_all add: permute_atom_def Rep_perm_simps) -done - -end - -lemma sort_of_permute [simp]: - shows "sort_of (p \ a) = sort_of a" - unfolding permute_atom_def by (rule sort_of_Rep_perm) - -lemma swap_atom: - shows "(a \ b) \ c = - (if sort_of a = sort_of b - then (if c = a then b else if c = b then a else c) else c)" - unfolding permute_atom_def - by (simp add: Rep_perm_swap) - -lemma swap_atom_simps [simp]: - "sort_of a = sort_of b \ (a \ b) \ a = b" - "sort_of a = sort_of b \ (a \ b) \ b = a" - "c \ a \ c \ b \ (a \ b) \ c = c" - unfolding swap_atom by simp_all - -lemma expand_perm_eq: - fixes p q :: "perm" - shows "p = q \ (\a::atom. p \ a = q \ a)" - unfolding permute_atom_def - by (metis Rep_perm_ext ext) - - -subsection {* Permutations for permutations *} - -instantiation perm :: pt -begin - -definition - "p \ q = p + q - p" - -instance -apply default -apply (simp add: permute_perm_def) -apply (simp add: permute_perm_def diff_minus minus_add add_assoc) -done - -end - -lemma permute_self: "p \ p = p" -unfolding permute_perm_def by (simp add: diff_minus add_assoc) - -lemma permute_eqvt: - shows "p \ (q \ x) = (p \ q) \ (p \ x)" - unfolding permute_perm_def by simp - -lemma zero_perm_eqvt: - shows "p \ (0::perm) = 0" - unfolding permute_perm_def by simp - -lemma add_perm_eqvt: - fixes p p1 p2 :: perm - shows "p \ (p1 + p2) = p \ p1 + p \ p2" - unfolding permute_perm_def - by (simp add: expand_perm_eq) - -lemma swap_eqvt: - shows "p \ (a \ b) = (p \ a \ p \ b)" - unfolding permute_perm_def - by (auto simp add: swap_atom expand_perm_eq) - - -subsection {* Permutations for functions *} - -instantiation "fun" :: (pt, pt) pt -begin - -definition - "p \ f = (\x. p \ (f (- p \ x)))" - -instance -apply default -apply (simp add: permute_fun_def) -apply (simp add: permute_fun_def minus_add) -done - -end - -lemma permute_fun_app_eq: - shows "p \ (f x) = (p \ f) (p \ x)" -unfolding permute_fun_def by simp - - -subsection {* Permutations for booleans *} - -instantiation bool :: pt -begin - -definition "p \ (b::bool) = b" - -instance -apply(default) -apply(simp_all add: permute_bool_def) -done - -end - -lemma Not_eqvt: - shows "p \ (\ A) = (\ (p \ A))" -by (simp add: permute_bool_def) - -lemma permute_boolE: - fixes P::"bool" - shows "p \ P \ P" - by (simp add: permute_bool_def) - -lemma permute_boolI: - fixes P::"bool" - shows "P \ p \ P" - by(simp add: permute_bool_def) - -subsection {* Permutations for sets *} - -lemma permute_set_eq: - fixes x::"'a::pt" - and p::"perm" - shows "(p \ X) = {p \ x | x. x \ X}" - apply(auto simp add: permute_fun_def permute_bool_def mem_def) - apply(rule_tac x="- p \ x" in exI) - apply(simp) - done - -lemma permute_set_eq_image: - shows "p \ X = permute p ` X" -unfolding permute_set_eq by auto - -lemma permute_set_eq_vimage: - shows "p \ X = permute (- p) -` X" -unfolding permute_fun_def permute_bool_def -unfolding vimage_def Collect_def mem_def .. - -lemma swap_set_not_in: - assumes a: "a \ S" "b \ S" - shows "(a \ b) \ S = S" - using a by (auto simp add: permute_set_eq swap_atom) - -lemma swap_set_in: - assumes a: "a \ S" "b \ S" "sort_of a = sort_of b" - shows "(a \ b) \ S \ S" - using a by (auto simp add: permute_set_eq swap_atom) - - -subsection {* Permutations for units *} - -instantiation unit :: pt -begin - -definition "p \ (u::unit) = u" - -instance proof -qed (simp_all add: permute_unit_def) - -end - - -subsection {* Permutations for products *} - -instantiation "*" :: (pt, pt) pt -begin - -primrec - permute_prod -where - Pair_eqvt: "p \ (x, y) = (p \ x, p \ y)" - -instance -by default auto - -end - -subsection {* Permutations for sums *} - -instantiation "+" :: (pt, pt) pt -begin - -primrec - permute_sum -where - "p \ (Inl x) = Inl (p \ x)" -| "p \ (Inr y) = Inr (p \ y)" - -instance proof -qed (case_tac [!] x, simp_all) - -end - -subsection {* Permutations for lists *} - -instantiation list :: (pt) pt -begin - -primrec - permute_list -where - "p \ [] = []" -| "p \ (x # xs) = p \ x # p \ xs" - -instance proof -qed (induct_tac [!] x, simp_all) - -end - -subsection {* Permutations for options *} - -instantiation option :: (pt) pt -begin - -primrec - permute_option -where - "p \ None = None" -| "p \ (Some x) = Some (p \ x)" - -instance proof -qed (induct_tac [!] x, simp_all) - -end - -subsection {* Permutations for @{typ char}, @{typ nat}, and @{typ int} *} - -instantiation char :: pt -begin - -definition "p \ (c::char) = c" - -instance proof -qed (simp_all add: permute_char_def) - -end - -instantiation nat :: pt -begin - -definition "p \ (n::nat) = n" - -instance proof -qed (simp_all add: permute_nat_def) - -end - -instantiation int :: pt -begin - -definition "p \ (i::int) = i" - -instance proof -qed (simp_all add: permute_int_def) - -end - - -section {* Pure types *} - -text {* Pure types will have always empty support. *} - -class pure = pt + - assumes permute_pure: "p \ x = x" - -text {* Types @{typ unit} and @{typ bool} are pure. *} - -instance unit :: pure -proof qed (rule permute_unit_def) - -instance bool :: pure -proof qed (rule permute_bool_def) - -text {* Other type constructors preserve purity. *} - -instance "fun" :: (pure, pure) pure -by default (simp add: permute_fun_def permute_pure) - -instance "*" :: (pure, pure) pure -by default (induct_tac x, simp add: permute_pure) - -instance "+" :: (pure, pure) pure -by default (induct_tac x, simp_all add: permute_pure) - -instance list :: (pure) pure -by default (induct_tac x, simp_all add: permute_pure) - -instance option :: (pure) pure -by default (induct_tac x, simp_all add: permute_pure) - - -subsection {* Types @{typ char}, @{typ nat}, and @{typ int} *} - -instance char :: pure -proof qed (rule permute_char_def) - -instance nat :: pure -proof qed (rule permute_nat_def) - -instance int :: pure -proof qed (rule permute_int_def) - - -subsection {* Supp, Freshness and Supports *} - -context pt -begin - -definition - supp :: "'a \ atom set" -where - "supp x = {a. infinite {b. (a \ b) \ x \ x}}" - -end - -definition - fresh :: "atom \ 'a::pt \ bool" ("_ \ _" [55, 55] 55) -where - "a \ x \ a \ supp x" - -lemma supp_conv_fresh: - shows "supp x = {a. \ a \ x}" - unfolding fresh_def by simp - -lemma swap_rel_trans: - assumes "sort_of a = sort_of b" - assumes "sort_of b = sort_of c" - assumes "(a \ c) \ x = x" - assumes "(b \ c) \ x = x" - shows "(a \ b) \ x = x" -proof (cases) - assume "a = b \ c = b" - with assms show "(a \ b) \ x = x" by auto -next - assume *: "\ (a = b \ c = b)" - have "((a \ c) + (b \ c) + (a \ c)) \ x = x" - using assms by simp - also have "(a \ c) + (b \ c) + (a \ c) = (a \ b)" - using assms * by (simp add: swap_triple) - finally show "(a \ b) \ x = x" . -qed - -lemma swap_fresh_fresh: - assumes a: "a \ x" - and b: "b \ x" - shows "(a \ b) \ x = x" -proof (cases) - assume asm: "sort_of a = sort_of b" - have "finite {c. (a \ c) \ x \ x}" "finite {c. (b \ c) \ x \ x}" - using a b unfolding fresh_def supp_def by simp_all - then have "finite ({c. (a \ c) \ x \ x} \ {c. (b \ c) \ x \ x})" by simp - then obtain c - where "(a \ c) \ x = x" "(b \ c) \ x = x" "sort_of c = sort_of b" - by (rule obtain_atom) (auto) - then show "(a \ b) \ x = x" using asm by (rule_tac swap_rel_trans) (simp_all) -next - assume "sort_of a \ sort_of b" - then show "(a \ b) \ x = x" by simp -qed - - -subsection {* supp and fresh are equivariant *} - -lemma finite_Collect_bij: - assumes a: "bij f" - shows "finite {x. P (f x)} = finite {x. P x}" -by (metis a finite_vimage_iff vimage_Collect_eq) - -lemma fresh_permute_iff: - shows "(p \ a) \ (p \ x) \ a \ x" -proof - - have "(p \ a) \ (p \ x) \ finite {b. (p \ a \ b) \ p \ x \ p \ x}" - unfolding fresh_def supp_def by simp - also have "\ \ finite {b. (p \ a \ p \ b) \ p \ x \ p \ x}" - using bij_permute by (rule finite_Collect_bij [symmetric]) - also have "\ \ finite {b. p \ (a \ b) \ x \ p \ x}" - by (simp only: permute_eqvt [of p] swap_eqvt) - also have "\ \ finite {b. (a \ b) \ x \ x}" - by (simp only: permute_eq_iff) - also have "\ \ a \ x" - unfolding fresh_def supp_def by simp - finally show ?thesis . -qed - -lemma fresh_eqvt: - shows "p \ (a \ x) = (p \ a) \ (p \ x)" - by (simp add: permute_bool_def fresh_permute_iff) - -lemma supp_eqvt: - fixes p :: "perm" - and x :: "'a::pt" - shows "p \ (supp x) = supp (p \ x)" - unfolding supp_conv_fresh - unfolding permute_fun_def Collect_def - by (simp add: Not_eqvt fresh_eqvt) - -subsection {* supports *} - -definition - supports :: "atom set \ 'a::pt \ bool" (infixl "supports" 80) -where - "S supports x \ \a b. (a \ S \ b \ S \ (a \ b) \ x = x)" - -lemma supp_is_subset: - fixes S :: "atom set" - and x :: "'a::pt" - assumes a1: "S supports x" - and a2: "finite S" - shows "(supp x) \ S" -proof (rule ccontr) - assume "\(supp x \ S)" - then obtain a where b1: "a \ supp x" and b2: "a \ S" by auto - from a1 b2 have "\b. b \ S \ (a \ b) \ x = x" by (unfold supports_def) (auto) - hence "{b. (a \ b) \ x \ x} \ S" by auto - with a2 have "finite {b. (a \ b)\x \ x}" by (simp add: finite_subset) - then have "a \ (supp x)" unfolding supp_def by simp - with b1 show False by simp -qed - -lemma supports_finite: - fixes S :: "atom set" - and x :: "'a::pt" - assumes a1: "S supports x" - and a2: "finite S" - shows "finite (supp x)" -proof - - have "(supp x) \ S" using a1 a2 by (rule supp_is_subset) - then show "finite (supp x)" using a2 by (simp add: finite_subset) -qed - -lemma supp_supports: - fixes x :: "'a::pt" - shows "(supp x) supports x" -proof (unfold supports_def, intro strip) - fix a b - assume "a \ (supp x) \ b \ (supp x)" - then have "a \ x" and "b \ x" by (simp_all add: fresh_def) - then show "(a \ b) \ x = x" by (rule swap_fresh_fresh) -qed - -lemma supp_is_least_supports: - fixes S :: "atom set" - and x :: "'a::pt" - assumes a1: "S supports x" - and a2: "finite S" - and a3: "\S'. finite S' \ (S' supports x) \ S \ S'" - shows "(supp x) = S" -proof (rule equalityI) - show "(supp x) \ S" using a1 a2 by (rule supp_is_subset) - with a2 have fin: "finite (supp x)" by (rule rev_finite_subset) - have "(supp x) supports x" by (rule supp_supports) - with fin a3 show "S \ supp x" by blast -qed - -lemma subsetCI: - shows "(\x. x \ A \ x \ B \ False) \ A \ B" - by auto - -lemma finite_supp_unique: - assumes a1: "S supports x" - assumes a2: "finite S" - assumes a3: "\a b. \a \ S; b \ S; sort_of a = sort_of b\ \ (a \ b) \ x \ x" - shows "(supp x) = S" - using a1 a2 -proof (rule supp_is_least_supports) - fix S' - assume "finite S'" and "S' supports x" - show "S \ S'" - proof (rule subsetCI) - fix a - assume "a \ S" and "a \ S'" - have "finite (S \ S')" - using `finite S` `finite S'` by simp - then obtain b where "b \ S \ S'" and "sort_of b = sort_of a" - by (rule obtain_atom) - then have "b \ S" and "b \ S'" and "sort_of a = sort_of b" - by simp_all - then have "(a \ b) \ x = x" - using `a \ S'` `S' supports x` by (simp add: supports_def) - moreover have "(a \ b) \ x \ x" - using `a \ S` `b \ S` `sort_of a = sort_of b` - by (rule a3) - ultimately show "False" by simp - qed -qed - -section {* Finitely-supported types *} - -class fs = pt + - assumes finite_supp: "finite (supp x)" - -lemma pure_supp: - shows "supp (x::'a::pure) = {}" - unfolding supp_def by (simp add: permute_pure) - -lemma pure_fresh: - fixes x::"'a::pure" - shows "a \ x" - unfolding fresh_def by (simp add: pure_supp) - -instance pure < fs -by default (simp add: pure_supp) - - -subsection {* Type @{typ atom} is finitely-supported. *} - -lemma supp_atom: - shows "supp a = {a}" -apply (rule finite_supp_unique) -apply (clarsimp simp add: supports_def) -apply simp -apply simp -done - -lemma fresh_atom: - shows "a \ b \ a \ b" - unfolding fresh_def supp_atom by simp - -instance atom :: fs -by default (simp add: supp_atom) - - -section {* Type @{typ perm} is finitely-supported. *} - -lemma perm_swap_eq: - shows "(a \ b) \ p = p \ (p \ (a \ b)) = (a \ b)" -unfolding permute_perm_def -by (metis add_diff_cancel minus_perm_def) - -lemma supports_perm: - shows "{a. p \ a \ a} supports p" - unfolding supports_def - by (simp add: perm_swap_eq swap_eqvt) - -lemma finite_perm_lemma: - shows "finite {a::atom. p \ a \ a}" - using finite_Rep_perm [of p] - unfolding permute_atom_def . - -lemma supp_perm: - shows "supp p = {a. p \ a \ a}" -apply (rule finite_supp_unique) -apply (rule supports_perm) -apply (rule finite_perm_lemma) -apply (simp add: perm_swap_eq swap_eqvt) -apply (auto simp add: expand_perm_eq swap_atom) -done - -lemma fresh_perm: - shows "a \ p \ p \ a = a" -unfolding fresh_def by (simp add: supp_perm) - -lemma supp_swap: - shows "supp (a \ b) = (if a = b \ sort_of a \ sort_of b then {} else {a, b})" - by (auto simp add: supp_perm swap_atom) - -lemma fresh_zero_perm: - shows "a \ (0::perm)" - unfolding fresh_perm by simp - -lemma supp_zero_perm: - shows "supp (0::perm) = {}" - unfolding supp_perm by simp - -lemma fresh_plus_perm: - fixes p q::perm - assumes "a \ p" "a \ q" - shows "a \ (p + q)" - using assms - unfolding fresh_def - by (auto simp add: supp_perm) - -lemma supp_plus_perm: - fixes p q::perm - shows "supp (p + q) \ supp p \ supp q" - by (auto simp add: supp_perm) - -lemma fresh_minus_perm: - fixes p::perm - shows "a \ (- p) \ a \ p" - unfolding fresh_def - apply(auto simp add: supp_perm) - apply(metis permute_minus_cancel)+ - done - -lemma supp_minus_perm: - fixes p::perm - shows "supp (- p) = supp p" - unfolding supp_conv_fresh - by (simp add: fresh_minus_perm) - -instance perm :: fs -by default (simp add: supp_perm finite_perm_lemma) - -lemma plus_perm_eq: - fixes p q::"perm" - assumes asm: "supp p \ supp q = {}" - shows "p + q = q + p" -unfolding expand_perm_eq -proof - fix a::"atom" - show "(p + q) \ a = (q + p) \ a" - proof - - { assume "a \ supp p" "a \ supp q" - then have "(p + q) \ a = (q + p) \ a" - by (simp add: supp_perm) - } - moreover - { assume a: "a \ supp p" "a \ supp q" - then have "p \ a \ supp p" by (simp add: supp_perm) - then have "p \ a \ supp q" using asm by auto - with a have "(p + q) \ a = (q + p) \ a" - by (simp add: supp_perm) - } - moreover - { assume a: "a \ supp p" "a \ supp q" - then have "q \ a \ supp q" by (simp add: supp_perm) - then have "q \ a \ supp p" using asm by auto - with a have "(p + q) \ a = (q + p) \ a" - by (simp add: supp_perm) - } - ultimately show "(p + q) \ a = (q + p) \ a" - using asm by blast - qed -qed - -section {* Finite Support instances for other types *} - -subsection {* Type @{typ "'a \ 'b"} is finitely-supported. *} - -lemma supp_Pair: - shows "supp (x, y) = supp x \ supp y" - by (simp add: supp_def Collect_imp_eq Collect_neg_eq) - -lemma fresh_Pair: - shows "a \ (x, y) \ a \ x \ a \ y" - by (simp add: fresh_def supp_Pair) - -instance "*" :: (fs, fs) fs -apply default -apply (induct_tac x) -apply (simp add: supp_Pair finite_supp) -done - -subsection {* Type @{typ "'a + 'b"} is finitely supported *} - -lemma supp_Inl: - shows "supp (Inl x) = supp x" - by (simp add: supp_def) - -lemma supp_Inr: - shows "supp (Inr x) = supp x" - by (simp add: supp_def) - -lemma fresh_Inl: - shows "a \ Inl x \ a \ x" - by (simp add: fresh_def supp_Inl) - -lemma fresh_Inr: - shows "a \ Inr y \ a \ y" - by (simp add: fresh_def supp_Inr) - -instance "+" :: (fs, fs) fs -apply default -apply (induct_tac x) -apply (simp_all add: supp_Inl supp_Inr finite_supp) -done - -subsection {* Type @{typ "'a option"} is finitely supported *} - -lemma supp_None: - shows "supp None = {}" -by (simp add: supp_def) - -lemma supp_Some: - shows "supp (Some x) = supp x" - by (simp add: supp_def) - -lemma fresh_None: - shows "a \ None" - by (simp add: fresh_def supp_None) - -lemma fresh_Some: - shows "a \ Some x \ a \ x" - by (simp add: fresh_def supp_Some) - -instance option :: (fs) fs -apply default -apply (induct_tac x) -apply (simp_all add: supp_None supp_Some finite_supp) -done - -subsubsection {* Type @{typ "'a list"} is finitely supported *} - -lemma supp_Nil: - shows "supp [] = {}" - by (simp add: supp_def) - -lemma supp_Cons: - shows "supp (x # xs) = supp x \ supp xs" -by (simp add: supp_def Collect_imp_eq Collect_neg_eq) - -lemma fresh_Nil: - shows "a \ []" - by (simp add: fresh_def supp_Nil) - -lemma fresh_Cons: - shows "a \ (x # xs) \ a \ x \ a \ xs" - by (simp add: fresh_def supp_Cons) - -instance list :: (fs) fs -apply default -apply (induct_tac x) -apply (simp_all add: supp_Nil supp_Cons finite_supp) -done - -section {* Support and freshness for applications *} - -lemma supp_fun_app: - shows "supp (f x) \ (supp f) \ (supp x)" -proof (rule subsetCI) - fix a::"atom" - assume a: "a \ supp (f x)" - assume b: "a \ supp f \ supp x" - then have "finite {b. (a \ b) \ f \ f}" "finite {b. (a \ b) \ x \ x}" - unfolding supp_def by auto - then have "finite ({b. (a \ b) \ f \ f} \ {b. (a \ b) \ x \ x})" by simp - moreover - have "{b. ((a \ b) \ f) ((a \ b) \ x) \ f x} \ ({b. (a \ b) \ f \ f} \ {b. (a \ b) \ x \ x})" - by auto - ultimately have "finite {b. ((a \ b) \ f) ((a \ b) \ x) \ f x}" - using finite_subset by auto - then have "a \ supp (f x)" unfolding supp_def - by (simp add: permute_fun_app_eq) - with a show "False" by simp -qed - -lemma fresh_fun_app: - shows "a \ (f, x) \ a \ f x" -unfolding fresh_def -using supp_fun_app -by (auto simp add: supp_Pair) - -lemma fresh_fun_eqvt_app: - assumes a: "\p. p \ f = f" - shows "a \ x \ a \ f x" -proof - - from a have b: "supp f = {}" - unfolding supp_def by simp - show "a \ x \ a \ f x" - unfolding fresh_def - using supp_fun_app b - by auto -qed - -end diff -r c0eac04ae3b4 -r c34347ec7ab3 Nominal/Nominal2_Eqvt.thy --- a/Nominal/Nominal2_Eqvt.thy Sat Apr 03 22:31:11 2010 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,305 +0,0 @@ -(* Title: Nominal2_Eqvt - Authors: Brian Huffman, Christian Urban - - Equivariance, Supp and Fresh Lemmas for Operators. - (Contains most, but not all such lemmas.) -*) -theory Nominal2_Eqvt -imports Nominal2_Base Nominal2_Atoms -uses ("nominal_thmdecls.ML") - ("nominal_permeq.ML") -begin - -section {* Logical Operators *} - -lemma eq_eqvt: - shows "p \ (x = y) \ (p \ x) = (p \ y)" - unfolding permute_eq_iff permute_bool_def .. - -lemma if_eqvt: - shows "p \ (if b then x else y) = (if p \ b then p \ x else p \ y)" - by (simp add: permute_fun_def permute_bool_def) - -lemma True_eqvt: - shows "p \ True = True" - unfolding permute_bool_def .. - -lemma False_eqvt: - shows "p \ False = False" - unfolding permute_bool_def .. - -lemma imp_eqvt: - shows "p \ (A \ B) = ((p \ A) \ (p \ B))" - by (simp add: permute_bool_def) - -lemma conj_eqvt: - shows "p \ (A \ B) = ((p \ A) \ (p \ B))" - by (simp add: permute_bool_def) - -lemma disj_eqvt: - shows "p \ (A \ B) = ((p \ A) \ (p \ B))" - by (simp add: permute_bool_def) - -lemma Not_eqvt: - shows "p \ (\ A) = (\ (p \ A))" - by (simp add: permute_bool_def) - -lemma all_eqvt: - shows "p \ (\x. P x) = (\x. (p \ P) x)" - unfolding permute_fun_def permute_bool_def - by (auto, drule_tac x="p \ x" in spec, simp) - -lemma all_eqvt2: - shows "p \ (\x. P x) = (\x. p \ P (- p \ x))" - unfolding permute_fun_def permute_bool_def - by (auto, drule_tac x="p \ x" in spec, simp) - -lemma ex_eqvt: - shows "p \ (\x. P x) = (\x. (p \ P) x)" - unfolding permute_fun_def permute_bool_def - by (auto, rule_tac x="p \ x" in exI, simp) - -lemma ex_eqvt2: - shows "p \ (\x. P x) = (\x. p \ P (- p \ x))" - unfolding permute_fun_def permute_bool_def - by (auto, rule_tac x="p \ x" in exI, simp) - -lemma ex1_eqvt: - shows "p \ (\!x. P x) = (\!x. (p \ P) x)" - unfolding Ex1_def - by (simp add: ex_eqvt permute_fun_def conj_eqvt all_eqvt imp_eqvt eq_eqvt) - -lemma ex1_eqvt2: - shows "p \ (\!x. P x) = (\!x. p \ P (- p \ x))" - unfolding Ex1_def ex_eqvt2 conj_eqvt all_eqvt2 imp_eqvt eq_eqvt - by simp - -lemma the_eqvt: - assumes unique: "\!x. P x" - shows "(p \ (THE x. P x)) = (THE x. p \ P (- p \ x))" - apply(rule the1_equality [symmetric]) - apply(simp add: ex1_eqvt2[symmetric]) - apply(simp add: permute_bool_def unique) - apply(simp add: permute_bool_def) - apply(rule theI'[OF unique]) - done - -section {* Set Operations *} - -lemma mem_permute_iff: - shows "(p \ x) \ (p \ X) \ x \ X" -unfolding mem_def permute_fun_def permute_bool_def -by simp - -lemma mem_eqvt: - shows "p \ (x \ A) \ (p \ x) \ (p \ A)" - unfolding mem_permute_iff permute_bool_def by simp - -lemma not_mem_eqvt: - shows "p \ (x \ A) \ (p \ x) \ (p \ A)" - unfolding mem_def permute_fun_def by (simp add: Not_eqvt) - -lemma Collect_eqvt: - shows "p \ {x. P x} = {x. (p \ P) x}" - unfolding Collect_def permute_fun_def .. - -lemma Collect_eqvt2: - shows "p \ {x. P x} = {x. p \ (P (-p \ x))}" - unfolding Collect_def permute_fun_def .. - -lemma empty_eqvt: - shows "p \ {} = {}" - unfolding empty_def Collect_eqvt2 False_eqvt .. - -lemma supp_set_empty: - shows "supp {} = {}" - by (simp add: supp_def empty_eqvt) - -lemma fresh_set_empty: - shows "a \ {}" - by (simp add: fresh_def supp_set_empty) - -lemma UNIV_eqvt: - shows "p \ UNIV = UNIV" - unfolding UNIV_def Collect_eqvt2 True_eqvt .. - -lemma union_eqvt: - shows "p \ (A \ B) = (p \ A) \ (p \ B)" - unfolding Un_def Collect_eqvt2 disj_eqvt mem_eqvt by simp - -lemma inter_eqvt: - shows "p \ (A \ B) = (p \ A) \ (p \ B)" - unfolding Int_def Collect_eqvt2 conj_eqvt mem_eqvt by simp - -lemma Diff_eqvt: - fixes A B :: "'a::pt set" - shows "p \ (A - B) = p \ A - p \ B" - unfolding set_diff_eq Collect_eqvt2 conj_eqvt Not_eqvt mem_eqvt by simp - -lemma Compl_eqvt: - fixes A :: "'a::pt set" - shows "p \ (- A) = - (p \ A)" - unfolding Compl_eq_Diff_UNIV Diff_eqvt UNIV_eqvt .. - -lemma insert_eqvt: - shows "p \ (insert x A) = insert (p \ x) (p \ A)" - unfolding permute_set_eq_image image_insert .. - -lemma vimage_eqvt: - shows "p \ (f -` A) = (p \ f) -` (p \ A)" - unfolding vimage_def permute_fun_def [where f=f] - unfolding Collect_eqvt2 mem_eqvt .. - -lemma image_eqvt: - shows "p \ (f ` A) = (p \ f) ` (p \ A)" - unfolding permute_set_eq_image - unfolding permute_fun_def [where f=f] - by (simp add: image_image) - -lemma finite_permute_iff: - shows "finite (p \ A) \ finite A" - unfolding permute_set_eq_vimage - using bij_permute by (rule finite_vimage_iff) - -lemma finite_eqvt: - shows "p \ finite A = finite (p \ A)" - unfolding finite_permute_iff permute_bool_def .. - - -section {* List Operations *} - -lemma append_eqvt: - shows "p \ (xs @ ys) = (p \ xs) @ (p \ ys)" - by (induct xs) auto - -lemma supp_append: - shows "supp (xs @ ys) = supp xs \ supp ys" - by (induct xs) (auto simp add: supp_Nil supp_Cons) - -lemma fresh_append: - shows "a \ (xs @ ys) \ a \ xs \ a \ ys" - by (induct xs) (simp_all add: fresh_Nil fresh_Cons) - -lemma rev_eqvt: - shows "p \ (rev xs) = rev (p \ xs)" - by (induct xs) (simp_all add: append_eqvt) - -lemma supp_rev: - shows "supp (rev xs) = supp xs" - by (induct xs) (auto simp add: supp_append supp_Cons supp_Nil) - -lemma fresh_rev: - shows "a \ rev xs \ a \ xs" - by (induct xs) (auto simp add: fresh_append fresh_Cons fresh_Nil) - -lemma set_eqvt: - shows "p \ (set xs) = set (p \ xs)" - by (induct xs) (simp_all add: empty_eqvt insert_eqvt) - -(* needs finite support premise -lemma supp_set: - fixes x :: "'a::pt" - shows "supp (set xs) = supp xs" -*) - - -section {* Product Operations *} - -lemma fst_eqvt: - "p \ (fst x) = fst (p \ x)" - by (cases x) simp - -lemma snd_eqvt: - "p \ (snd x) = snd (p \ x)" - by (cases x) simp - -section {* Units *} - -lemma supp_unit: - shows "supp () = {}" - by (simp add: supp_def) - -lemma fresh_unit: - shows "a \ ()" - by (simp add: fresh_def supp_unit) - -section {* Equivariance automation *} - -text {* Setup of the theorem attributes @{text eqvt} and @{text eqvt_force} *} - -use "nominal_thmdecls.ML" -setup "Nominal_ThmDecls.setup" - -lemmas [eqvt] = - (* connectives *) - eq_eqvt if_eqvt imp_eqvt disj_eqvt conj_eqvt Not_eqvt - True_eqvt False_eqvt ex_eqvt all_eqvt ex1_eqvt - imp_eqvt [folded induct_implies_def] - - (* nominal *) - (*permute_eqvt commented out since it loops *) - supp_eqvt fresh_eqvt - permute_pure - - (* datatypes *) - permute_prod.simps append_eqvt rev_eqvt set_eqvt - fst_eqvt snd_eqvt Pair_eqvt - - (* sets *) - empty_eqvt UNIV_eqvt union_eqvt inter_eqvt mem_eqvt - Diff_eqvt Compl_eqvt insert_eqvt Collect_eqvt image_eqvt - - atom_eqvt add_perm_eqvt - -thm eqvts -thm eqvts_raw - -text {* helper lemmas for the eqvt_tac *} - -definition - "unpermute p = permute (- p)" - -lemma eqvt_apply: - fixes f :: "'a::pt \ 'b::pt" - and x :: "'a::pt" - shows "p \ (f x) \ (p \ f) (p \ x)" - unfolding permute_fun_def by simp - -lemma eqvt_lambda: - fixes f :: "'a::pt \ 'b::pt" - shows "p \ (\x. f x) \ (\x. p \ (f (unpermute p x)))" - unfolding permute_fun_def unpermute_def by simp - -lemma eqvt_bound: - shows "p \ unpermute p x \ x" - unfolding unpermute_def by simp - -use "nominal_permeq.ML" - - -lemma "p \ (A \ B = C)" -apply (tactic {* Nominal_Permeq.eqvt_tac @{context} 1 *}) -oops - -lemma "p \ (\(x::'a::pt). A \ (B::'a \ bool) x = C) = foo" -apply (tactic {* Nominal_Permeq.eqvt_tac @{context} 1 *}) -oops - -lemma "p \ (\x y. \z. x = z \ x = y \ z \ x) = foo" -apply (tactic {* Nominal_Permeq.eqvt_tac @{context} 1 *}) -oops - -lemma "p \ (\f x. f (g (f x))) = foo" -apply (tactic {* Nominal_Permeq.eqvt_tac @{context} 1 *}) -oops - -lemma "p \ (\q. q \ (r \ x)) = foo" -apply (tactic {* Nominal_Permeq.eqvt_tac @{context} 1 *}) -oops - -lemma "p \ (q \ r \ x) = foo" -apply (tactic {* Nominal_Permeq.eqvt_tac @{context} 1 *}) -oops - - -end diff -r c0eac04ae3b4 -r c34347ec7ab3 Nominal/Nominal2_FSet.thy --- a/Nominal/Nominal2_FSet.thy Sat Apr 03 22:31:11 2010 +0200 +++ b/Nominal/Nominal2_FSet.thy Sun Apr 04 21:39:28 2010 +0200 @@ -1,5 +1,5 @@ theory Nominal2_FSet -imports FSet Nominal2_Supp +imports FSet "../Nominal-General/Nominal2_Supp" begin lemma permute_rsp_fset[quot_respect]: diff -r c0eac04ae3b4 -r c34347ec7ab3 Nominal/Nominal2_Supp.thy --- a/Nominal/Nominal2_Supp.thy Sat Apr 03 22:31:11 2010 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,501 +0,0 @@ -(* Title: Nominal2_Supp - Authors: Brian Huffman, Christian Urban - - Supplementary Lemmas and Definitions for - Nominal Isabelle. -*) -theory Nominal2_Supp -imports Nominal2_Base Nominal2_Eqvt Nominal2_Atoms -begin - - -section {* Fresh-Star *} - -text {* The fresh-star generalisation of fresh is used in strong - induction principles. *} - -definition - fresh_star :: "atom set \ 'a::pt \ bool" ("_ \* _" [80,80] 80) -where - "as \* x \ \a \ as. a \ x" - -lemma fresh_star_prod: - fixes as::"atom set" - shows "as \* (x, y) = (as \* x \ as \* y)" - by (auto simp add: fresh_star_def fresh_Pair) - -lemma fresh_star_union: - shows "(as \ bs) \* x = (as \* x \ bs \* x)" - by (auto simp add: fresh_star_def) - -lemma fresh_star_insert: - shows "(insert a as) \* x = (a \ x \ as \* x)" - by (auto simp add: fresh_star_def) - -lemma fresh_star_Un_elim: - "((as \ bs) \* x \ PROP C) \ (as \* x \ bs \* x \ PROP C)" - unfolding fresh_star_def - apply(rule) - apply(erule meta_mp) - apply(auto) - done - -lemma fresh_star_insert_elim: - "(insert a as \* x \ PROP C) \ (a \ x \ as \* x \ PROP C)" - unfolding fresh_star_def - by rule (simp_all add: fresh_star_def) - -lemma fresh_star_empty_elim: - "({} \* x \ PROP C) \ PROP C" - by (simp add: fresh_star_def) - -lemma fresh_star_unit_elim: - shows "(a \* () \ PROP C) \ PROP C" - by (simp add: fresh_star_def fresh_unit) - -lemma fresh_star_prod_elim: - shows "(a \* (x, y) \ PROP C) \ (a \* x \ a \* y \ PROP C)" - by (rule, simp_all add: fresh_star_prod) - -lemma fresh_star_plus: - fixes p q::perm - shows "\a \* p; a \* q\ \ a \* (p + q)" - unfolding fresh_star_def - by (simp add: fresh_plus_perm) - -lemma fresh_star_permute_iff: - shows "(p \ a) \* (p \ x) \ a \* x" - unfolding fresh_star_def - by (metis mem_permute_iff permute_minus_cancel fresh_permute_iff) - -lemma fresh_star_eqvt: - shows "(p \ (as \* x)) = (p \ as) \* (p \ x)" -unfolding fresh_star_def -unfolding Ball_def -apply(simp add: all_eqvt) -apply(subst permute_fun_def) -apply(simp add: imp_eqvt fresh_eqvt mem_eqvt) -done - -section {* Avoiding of atom sets *} - -text {* - For every set of atoms, there is another set of atoms - avoiding a finitely supported c and there is a permutation - which 'translates' between both sets. -*} - -lemma at_set_avoiding_aux: - fixes Xs::"atom set" - and As::"atom set" - assumes b: "Xs \ As" - and c: "finite As" - shows "\p. (p \ Xs) \ As = {} \ (supp p) \ (Xs \ (p \ Xs))" -proof - - from b c have "finite Xs" by (rule finite_subset) - then show ?thesis using b - proof (induct rule: finite_subset_induct) - case empty - have "0 \ {} \ As = {}" by simp - moreover - have "supp (0::perm) \ {} \ 0 \ {}" by (simp add: supp_zero_perm) - ultimately show ?case by blast - next - case (insert x Xs) - then obtain p where - p1: "(p \ Xs) \ As = {}" and - p2: "supp p \ (Xs \ (p \ Xs))" by blast - from `x \ As` p1 have "x \ p \ Xs" by fast - with `x \ Xs` p2 have "x \ supp p" by fast - hence px: "p \ x = x" unfolding supp_perm by simp - have "finite (As \ p \ Xs)" - using `finite As` `finite Xs` - by (simp add: permute_set_eq_image) - then obtain y where "y \ (As \ p \ Xs)" "sort_of y = sort_of x" - by (rule obtain_atom) - hence y: "y \ As" "y \ p \ Xs" "sort_of y = sort_of x" - by simp_all - let ?q = "(x \ y) + p" - have q: "?q \ insert x Xs = insert y (p \ Xs)" - unfolding insert_eqvt - using `p \ x = x` `sort_of y = sort_of x` - using `x \ p \ Xs` `y \ p \ Xs` - by (simp add: swap_atom swap_set_not_in) - have "?q \ insert x Xs \ As = {}" - using `y \ As` `p \ Xs \ As = {}` - unfolding q by simp - moreover - have "supp ?q \ insert x Xs \ ?q \ insert x Xs" - using p2 unfolding q - apply (intro subset_trans [OF supp_plus_perm]) - apply (auto simp add: supp_swap) - done - ultimately show ?case by blast - qed -qed - -lemma at_set_avoiding: - assumes a: "finite Xs" - and b: "finite (supp c)" - obtains p::"perm" where "(p \ Xs)\*c" and "(supp p) \ (Xs \ (p \ Xs))" - using a b at_set_avoiding_aux [where Xs="Xs" and As="Xs \ supp c"] - unfolding fresh_star_def fresh_def by blast - - -section {* The freshness lemma according to Andrew Pitts *} - -lemma fresh_conv_MOST: - shows "a \ x \ (MOST b. (a \ b) \ x = x)" - unfolding fresh_def supp_def MOST_iff_cofinite by simp - -lemma fresh_apply: - assumes "a \ f" and "a \ x" - shows "a \ f x" - using assms unfolding fresh_conv_MOST - unfolding permute_fun_app_eq [where f=f] - by (elim MOST_rev_mp, simp) - -lemma freshness_lemma: - fixes h :: "'a::at \ 'b::pt" - assumes a: "\a. atom a \ (h, h a)" - shows "\x. \a. atom a \ h \ h a = x" -proof - - from a obtain b where a1: "atom b \ h" and a2: "atom b \ h b" - by (auto simp add: fresh_Pair) - show "\x. \a. atom a \ h \ h a = x" - proof (intro exI allI impI) - fix a :: 'a - assume a3: "atom a \ h" - show "h a = h b" - proof (cases "a = b") - assume "a = b" - thus "h a = h b" by simp - next - assume "a \ b" - hence "atom a \ b" by (simp add: fresh_at_base) - with a3 have "atom a \ h b" by (rule fresh_apply) - with a2 have d1: "(atom b \ atom a) \ (h b) = (h b)" - by (rule swap_fresh_fresh) - from a1 a3 have d2: "(atom b \ atom a) \ h = h" - by (rule swap_fresh_fresh) - from d1 have "h b = (atom b \ atom a) \ (h b)" by simp - also have "\ = ((atom b \ atom a) \ h) ((atom b \ atom a) \ b)" - by (rule permute_fun_app_eq) - also have "\ = h a" - using d2 by simp - finally show "h a = h b" by simp - qed - qed -qed - -lemma freshness_lemma_unique: - fixes h :: "'a::at \ 'b::pt" - assumes a: "\a. atom a \ (h, h a)" - shows "\!x. \a. atom a \ h \ h a = x" -proof (rule ex_ex1I) - from a show "\x. \a. atom a \ h \ h a = x" - by (rule freshness_lemma) -next - fix x y - assume x: "\a. atom a \ h \ h a = x" - assume y: "\a. atom a \ h \ h a = y" - from a x y show "x = y" - by (auto simp add: fresh_Pair) -qed - -text {* packaging the freshness lemma into a function *} - -definition - fresh_fun :: "('a::at \ 'b::pt) \ 'b" -where - "fresh_fun h = (THE x. \a. atom a \ h \ h a = x)" - -lemma fresh_fun_app: - fixes h :: "'a::at \ 'b::pt" - assumes a: "\a. atom a \ (h, h a)" - assumes b: "atom a \ h" - shows "fresh_fun h = h a" -unfolding fresh_fun_def -proof (rule the_equality) - show "\a'. atom a' \ h \ h a' = h a" - proof (intro strip) - fix a':: 'a - assume c: "atom a' \ h" - from a have "\x. \a. atom a \ h \ h a = x" by (rule freshness_lemma) - with b c show "h a' = h a" by auto - qed -next - fix fr :: 'b - assume "\a. atom a \ h \ h a = fr" - with b show "fr = h a" by auto -qed - -lemma fresh_fun_app': - fixes h :: "'a::at \ 'b::pt" - assumes a: "atom a \ h" "atom a \ h a" - shows "fresh_fun h = h a" - apply (rule fresh_fun_app) - apply (auto simp add: fresh_Pair intro: a) - done - -lemma fresh_fun_eqvt: - fixes h :: "'a::at \ 'b::pt" - assumes a: "\a. atom a \ (h, h a)" - shows "p \ (fresh_fun h) = fresh_fun (p \ h)" - using a - apply (clarsimp simp add: fresh_Pair) - apply (subst fresh_fun_app', assumption+) - apply (drule fresh_permute_iff [where p=p, THEN iffD2]) - apply (drule fresh_permute_iff [where p=p, THEN iffD2]) - apply (simp add: atom_eqvt permute_fun_app_eq [where f=h]) - apply (erule (1) fresh_fun_app' [symmetric]) - done - -lemma fresh_fun_supports: - fixes h :: "'a::at \ 'b::pt" - assumes a: "\a. atom a \ (h, h a)" - shows "(supp h) supports (fresh_fun h)" - apply (simp add: supports_def fresh_def [symmetric]) - apply (simp add: fresh_fun_eqvt [OF a] swap_fresh_fresh) - done - -notation fresh_fun (binder "FRESH " 10) - -lemma FRESH_f_iff: - fixes P :: "'a::at \ 'b::pure" - fixes f :: "'b \ 'c::pure" - assumes P: "finite (supp P)" - shows "(FRESH x. f (P x)) = f (FRESH x. P x)" -proof - - obtain a::'a where "atom a \ supp P" - using P by (rule obtain_at_base) - hence "atom a \ P" - by (simp add: fresh_def) - show "(FRESH x. f (P x)) = f (FRESH x. P x)" - apply (subst fresh_fun_app' [where a=a, OF _ pure_fresh]) - apply (cut_tac `atom a \ P`) - apply (simp add: fresh_conv_MOST) - apply (elim MOST_rev_mp, rule MOST_I, clarify) - apply (simp add: permute_fun_def permute_pure expand_fun_eq) - apply (subst fresh_fun_app' [where a=a, OF `atom a \ P` pure_fresh]) - apply (rule refl) - done -qed - -lemma FRESH_binop_iff: - fixes P :: "'a::at \ 'b::pure" - fixes Q :: "'a::at \ 'c::pure" - fixes binop :: "'b \ 'c \ 'd::pure" - assumes P: "finite (supp P)" - and Q: "finite (supp Q)" - shows "(FRESH x. binop (P x) (Q x)) = binop (FRESH x. P x) (FRESH x. Q x)" -proof - - from assms have "finite (supp P \ supp Q)" by simp - then obtain a::'a where "atom a \ (supp P \ supp Q)" - by (rule obtain_at_base) - hence "atom a \ P" and "atom a \ Q" - by (simp_all add: fresh_def) - show ?thesis - apply (subst fresh_fun_app' [where a=a, OF _ pure_fresh]) - apply (cut_tac `atom a \ P` `atom a \ Q`) - apply (simp add: fresh_conv_MOST) - apply (elim MOST_rev_mp, rule MOST_I, clarify) - apply (simp add: permute_fun_def permute_pure expand_fun_eq) - apply (subst fresh_fun_app' [where a=a, OF `atom a \ P` pure_fresh]) - apply (subst fresh_fun_app' [where a=a, OF `atom a \ Q` pure_fresh]) - apply (rule refl) - done -qed - -lemma FRESH_conj_iff: - fixes P Q :: "'a::at \ bool" - assumes P: "finite (supp P)" and Q: "finite (supp Q)" - shows "(FRESH x. P x \ Q x) \ (FRESH x. P x) \ (FRESH x. Q x)" -using P Q by (rule FRESH_binop_iff) - -lemma FRESH_disj_iff: - fixes P Q :: "'a::at \ bool" - assumes P: "finite (supp P)" and Q: "finite (supp Q)" - shows "(FRESH x. P x \ Q x) \ (FRESH x. P x) \ (FRESH x. Q x)" -using P Q by (rule FRESH_binop_iff) - - -section {* An example of a function without finite support *} - -primrec - nat_of :: "atom \ nat" -where - "nat_of (Atom s n) = n" - -lemma atom_eq_iff: - fixes a b :: atom - shows "a = b \ sort_of a = sort_of b \ nat_of a = nat_of b" - by (induct a, induct b, simp) - -lemma not_fresh_nat_of: - shows "\ a \ nat_of" -unfolding fresh_def supp_def -proof (clarsimp) - assume "finite {b. (a \ b) \ nat_of \ nat_of}" - hence "finite ({a} \ {b. (a \ b) \ nat_of \ nat_of})" - by simp - then obtain b where - b1: "b \ a" and - b2: "sort_of b = sort_of a" and - b3: "(a \ b) \ nat_of = nat_of" - by (rule obtain_atom) auto - have "nat_of a = (a \ b) \ (nat_of a)" by (simp add: permute_nat_def) - also have "\ = ((a \ b) \ nat_of) ((a \ b) \ a)" by (simp add: permute_fun_app_eq) - also have "\ = nat_of ((a \ b) \ a)" using b3 by simp - also have "\ = nat_of b" using b2 by simp - finally have "nat_of a = nat_of b" by simp - with b2 have "a = b" by (simp add: atom_eq_iff) - with b1 show "False" by simp -qed - -lemma supp_nat_of: - shows "supp nat_of = UNIV" - using not_fresh_nat_of [unfolded fresh_def] by auto - - -section {* Support for sets of atoms *} - -lemma supp_finite_atom_set: - fixes S::"atom set" - assumes "finite S" - shows "supp S = S" - apply(rule finite_supp_unique) - apply(simp add: supports_def) - apply(simp add: swap_set_not_in) - apply(rule assms) - apply(simp add: swap_set_in) -done - - -section {* transpositions of permutations *} - -fun - add_perm -where - "add_perm [] = 0" -| "add_perm ((a, b) # xs) = (a \ b) + add_perm xs" - -lemma add_perm_append: - shows "add_perm (xs @ ys) = add_perm xs + add_perm ys" -by (induct xs arbitrary: ys) - (auto simp add: add_assoc) - -lemma perm_list_exists: - fixes p::perm - shows "\xs. p = add_perm xs \ supp xs \ supp p" -apply(induct p taking: "\p::perm. card (supp p)" rule: measure_induct) -apply(rename_tac p) -apply(case_tac "supp p = {}") -apply(simp) -apply(simp add: supp_perm) -apply(rule_tac x="[]" in exI) -apply(simp add: supp_Nil) -apply(simp add: expand_perm_eq) -apply(subgoal_tac "\x. x \ supp p") -defer -apply(auto)[1] -apply(erule exE) -apply(drule_tac x="p + (((- p) \ x) \ x)" in spec) -apply(drule mp) -defer -apply(erule exE) -apply(rule_tac x="xs @ [((- p) \ x, x)]" in exI) -apply(simp add: add_perm_append) -apply(erule conjE) -apply(drule sym) -apply(simp) -apply(simp add: expand_perm_eq) -apply(simp add: supp_append) -apply(simp add: supp_perm supp_Cons supp_Nil supp_Pair supp_atom) -apply(rule conjI) -prefer 2 -apply(auto)[1] -apply (metis permute_atom_def_raw permute_minus_cancel(2)) -defer -apply(rule psubset_card_mono) -apply(simp add: finite_supp) -apply(rule psubsetI) -defer -apply(subgoal_tac "x \ supp (p + (- p \ x \ x))") -apply(blast) -apply(simp add: supp_perm) -defer -apply(auto simp add: supp_perm)[1] -apply(case_tac "x = xa") -apply(simp) -apply(case_tac "((- p) \ x) = xa") -apply(simp) -apply(case_tac "sort_of xa = sort_of x") -apply(simp) -apply(auto)[1] -apply(simp) -apply(simp) -apply(subgoal_tac "{a. p \ (- p \ x \ x) \ a \ a} \ {a. p \ a \ a}") -apply(blast) -apply(auto simp add: supp_perm)[1] -apply(case_tac "x = xa") -apply(simp) -apply(case_tac "((- p) \ x) = xa") -apply(simp) -apply(case_tac "sort_of xa = sort_of x") -apply(simp) -apply(auto)[1] -apply(simp) -apply(simp) -done - -section {* Lemma about support and permutations *} - -lemma supp_perm_eq: - assumes a: "(supp x) \* p" - shows "p \ x = x" -proof - - obtain xs where eq: "p = add_perm xs" and sub: "supp xs \ supp p" - using perm_list_exists by blast - from a have "\a \ supp p. a \ x" - by (auto simp add: fresh_star_def fresh_def supp_perm) - with eq sub have "\a \ supp xs. a \ x" by auto - then have "add_perm xs \ x = x" - by (induct xs rule: add_perm.induct) - (simp_all add: supp_Cons supp_Pair supp_atom swap_fresh_fresh) - then show "p \ x = x" using eq by simp -qed - -section {* at_set_avoiding2 *} - -lemma at_set_avoiding2: - assumes "finite xs" - and "finite (supp c)" "finite (supp x)" - and "xs \* x" - shows "\p. (p \ xs) \* c \ supp x \* p" -using assms -apply(erule_tac c="(c, x)" in at_set_avoiding) -apply(simp add: supp_Pair) -apply(rule_tac x="p" in exI) -apply(simp add: fresh_star_prod) -apply(subgoal_tac "\a \ supp p. a \ x") -apply(auto simp add: fresh_star_def fresh_def supp_perm)[1] -apply(auto simp add: fresh_star_def fresh_def) -done - -lemma at_set_avoiding2_atom: - assumes "finite (supp c)" "finite (supp x)" - and b: "xa \ x" - shows "\p. (p \ xa) \ c \ supp x \* p" -proof - - have a: "{xa} \* x" unfolding fresh_star_def by (simp add: b) - obtain p where p1: "(p \ {xa}) \* c" and p2: "supp x \* p" - using at_set_avoiding2[of "{xa}" "c" "x"] assms a by blast - have c: "(p \ xa) \ c" using p1 - unfolding fresh_star_def Ball_def - by (erule_tac x="p \ xa" in allE) (simp add: eqvts) - hence "p \ xa \ c \ supp x \* p" using p2 by blast - then show ?thesis by blast -qed - -end diff -r c0eac04ae3b4 -r c34347ec7ab3 Nominal/Parser.thy --- a/Nominal/Parser.thy Sat Apr 03 22:31:11 2010 +0200 +++ b/Nominal/Parser.thy Sun Apr 04 21:39:28 2010 +0200 @@ -1,5 +1,7 @@ theory Parser -imports "Nominal2_Atoms" "Nominal2_Eqvt" "Nominal2_Supp" "Perm" "Fv" "Rsp" "Lift" +imports "../Nominal-General/Nominal2_Atoms" + "../Nominal-General/Nominal2_Eqvt" + "../Nominal-General/Nominal2_Supp" "Perm" "Fv" "Rsp" "Lift" begin section{* Interface for nominal_datatype *} diff -r c0eac04ae3b4 -r c34347ec7ab3 Nominal/Perm.thy --- a/Nominal/Perm.thy Sat Apr 03 22:31:11 2010 +0200 +++ b/Nominal/Perm.thy Sun Apr 04 21:39:28 2010 +0200 @@ -1,5 +1,5 @@ theory Perm -imports "Nominal2_Atoms" +imports "../Nominal-General/Nominal2_Atoms" begin ML {* diff -r c0eac04ae3b4 -r c34347ec7ab3 Nominal/ROOT.ML --- a/Nominal/ROOT.ML Sat Apr 03 22:31:11 2010 +0200 +++ b/Nominal/ROOT.ML Sun Apr 04 21:39:28 2010 +0200 @@ -1,11 +1,7 @@ quick_and_dirty := true; no_document use_thys - ["Nominal2_Base", - "Nominal2_Eqvt", - "Nominal2_Atoms", - "Nominal2_Supp", - "Ex/ExLam", + ["Ex/ExLam", "Ex/ExLF", "Ex/Ex1", "Ex/Ex1rec", diff -r c0eac04ae3b4 -r c34347ec7ab3 Nominal/nominal_atoms.ML --- a/Nominal/nominal_atoms.ML Sat Apr 03 22:31:11 2010 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,94 +0,0 @@ -(* Title: nominal_atoms/ML - Authors: Brian Huffman, Christian Urban - - Command for defining concrete atom types. - - At the moment, only single-sorted atom types - are supported. -*) - -signature ATOM_DECL = -sig - val add_atom_decl: (binding * (binding option)) -> theory -> theory -end; - -structure Atom_Decl :> ATOM_DECL = -struct - -val atomT = @{typ atom}; -val permT = @{typ perm}; - -val sort_of_const = @{term sort_of}; -fun atom_const T = Const (@{const_name atom}, T --> atomT); -fun permute_const T = Const (@{const_name permute}, permT --> T --> T); - -fun mk_sort_of t = sort_of_const $ t; -fun mk_atom t = atom_const (fastype_of t) $ t; -fun mk_permute (p, t) = permute_const (fastype_of t) $ p $ t; - -fun atom_decl_set (str : string) : term = - let - val a = Free ("a", atomT); - val s = Const (@{const_name "Sort"}, @{typ "string => atom_sort list => atom_sort"}) - $ HOLogic.mk_string str $ HOLogic.nil_const @{typ "atom_sort"}; - in - HOLogic.mk_Collect ("a", atomT, HOLogic.mk_eq (mk_sort_of a, s)) - end - -fun add_atom_decl (name : binding, arg : binding option) (thy : theory) = - let - val _ = Theory.requires thy "Nominal2_Atoms" "nominal logic"; - val str = Sign.full_name thy name; - - (* typedef *) - val set = atom_decl_set str; - val tac = rtac @{thm exists_eq_simple_sort} 1; - val ((full_tname, info as ({Rep_name, Abs_name, ...}, {type_definition, ...})), thy) = - Typedef.add_typedef_global false NONE (name, [], NoSyn) set NONE tac thy; - - (* definition of atom and permute *) - val newT = #abs_type (fst info); - val RepC = Const (Rep_name, newT --> atomT); - val AbsC = Const (Abs_name, atomT --> newT); - val a = Free ("a", newT); - val p = Free ("p", permT); - val atom_eqn = - HOLogic.mk_Trueprop (HOLogic.mk_eq (mk_atom a, RepC $ a)); - val permute_eqn = - HOLogic.mk_Trueprop (HOLogic.mk_eq - (mk_permute (p, a), AbsC $ (mk_permute (p, RepC $ a)))); - val atom_def_name = - Binding.prefix_name "atom_" (Binding.suffix_name "_def" name); - val permute_def_name = - Binding.prefix_name "permute_" (Binding.suffix_name "_def" name); - - (* at class instance *) - val lthy = - Theory_Target.instantiation ([full_tname], [], @{sort at}) thy; - val ((_, (_, permute_ldef)), lthy) = - Specification.definition (NONE, ((permute_def_name, []), permute_eqn)) lthy; - val ((_, (_, atom_ldef)), lthy) = - Specification.definition (NONE, ((atom_def_name, []), atom_eqn)) lthy; - val ctxt_thy = ProofContext.init (ProofContext.theory_of lthy); - val permute_def = singleton (ProofContext.export lthy ctxt_thy) permute_ldef; - val atom_def = singleton (ProofContext.export lthy ctxt_thy) atom_ldef; - val class_thm = @{thm at_class} OF [type_definition, atom_def, permute_def]; - val thy = lthy - |> Class.prove_instantiation_instance (K (Tactic.rtac class_thm 1)) - |> Local_Theory.exit_global; - in - thy - end; - -(** outer syntax **) - -local structure P = OuterParse and K = OuterKeyword in - -val _ = - OuterSyntax.command "atom_decl" "declaration of a concrete atom type" K.thy_decl - ((P.binding -- Scan.option (Args.parens (P.binding))) >> - (Toplevel.print oo (Toplevel.theory o add_atom_decl))); - -end; - -end; diff -r c0eac04ae3b4 -r c34347ec7ab3 Nominal/nominal_permeq.ML --- a/Nominal/nominal_permeq.ML Sat Apr 03 22:31:11 2010 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,71 +0,0 @@ -(* Title: nominal_thmdecls.ML - Author: Brian Huffman, Christian Urban -*) - -signature NOMINAL_PERMEQ = -sig - val eqvt_tac: Proof.context -> int -> tactic - -end; - -(* TODO: - - - provide a method interface with the usual add and del options - - - print a warning if for a constant no eqvt lemma is stored - - - there seems to be too much simplified in case of multiple - permutations, like - - p o q o r o x - - we usually only want the outermost permutation to "float" in -*) - - -structure Nominal_Permeq: NOMINAL_PERMEQ = -struct - -local - -fun eqvt_apply_conv ctxt ct = - case (term_of ct) of - (Const (@{const_name "permute"}, _) $ _ $ (_ $ _)) => - let - val (perm, t) = Thm.dest_comb ct - val (_, p) = Thm.dest_comb perm - val (f, x) = Thm.dest_comb t - val a = ctyp_of_term x; - val b = ctyp_of_term t; - val ty_insts = map SOME [b, a] - val term_insts = map SOME [p, f, x] - in - Drule.instantiate' ty_insts term_insts @{thm eqvt_apply} - end - | _ => Conv.no_conv ct - -fun eqvt_lambda_conv ctxt ct = - case (term_of ct) of - (Const (@{const_name "permute"}, _) $ _ $ Abs _) => - Conv.rewr_conv @{thm eqvt_lambda} ct - | _ => Conv.no_conv ct - -in - -fun eqvt_conv ctxt ct = - Conv.first_conv - [ Conv.rewr_conv @{thm eqvt_bound}, - eqvt_apply_conv ctxt - then_conv Conv.comb_conv (eqvt_conv ctxt), - eqvt_lambda_conv ctxt - then_conv Conv.abs_conv (fn (v, ctxt) => eqvt_conv ctxt) ctxt, - More_Conv.rewrs_conv (Nominal_ThmDecls.get_eqvts_raw_thms ctxt), - Conv.all_conv - ] ct - -fun eqvt_tac ctxt = - CONVERSION (More_Conv.bottom_conv (fn ctxt => eqvt_conv ctxt) ctxt) - -end - -end; (* structure *) \ No newline at end of file diff -r c0eac04ae3b4 -r c34347ec7ab3 Nominal/nominal_thmdecls.ML --- a/Nominal/nominal_thmdecls.ML Sat Apr 03 22:31:11 2010 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,134 +0,0 @@ -(* Title: nominal_thmdecls.ML - Author: Christian Urban - - Infrastructure for the lemma collection "eqvts". - - Provides the attributes [eqvt] and [eqvt_raw], and the theorem - lists eqvts and eqvts_raw. The first attribute will store the - theorem in the eqvts list and also in the eqvts_raw list. For - the latter the theorem is expected to be of the form - - p o (c x1 x2 ...) = c (p o x1) (p o x2) ... - - and it is stored in the form - - p o c == c - - The [eqvt_raw] attribute just adds the theorem to eqvts_raw. - - TODO: - - - deal with eqvt-lemmas of the form - - c x1 x2 ... ==> c (p o x1) (p o x2) .. -*) - -signature NOMINAL_THMDECLS = -sig - val eqvt_add: attribute - val eqvt_del: attribute - val eqvt_raw_add: attribute - val eqvt_raw_del: attribute - val setup: theory -> theory - val get_eqvts_thms: Proof.context -> thm list - val get_eqvts_raw_thms: Proof.context -> thm list - -end; - -structure Nominal_ThmDecls: NOMINAL_THMDECLS = -struct - - -structure EqvtData = Generic_Data -( type T = thm Item_Net.T; - val empty = Thm.full_rules; - val extend = I; - val merge = Item_Net.merge ); - -structure EqvtRawData = Generic_Data -( type T = thm Item_Net.T; - val empty = Thm.full_rules; - val extend = I; - val merge = Item_Net.merge ); - -val eqvts = Item_Net.content o EqvtData.get; -val eqvts_raw = Item_Net.content o EqvtRawData.get; - -val get_eqvts_thms = eqvts o Context.Proof; -val get_eqvts_raw_thms = eqvts_raw o Context.Proof; - -val add_thm = EqvtData.map o Item_Net.update; -val del_thm = EqvtData.map o Item_Net.remove; - -val add_raw_thm = EqvtRawData.map o Item_Net.update; -val del_raw_thm = EqvtRawData.map o Item_Net.remove; - -fun dest_perm (Const (@{const_name "permute"}, _) $ p $ t) = (p, t) - | dest_perm t = raise TERM("dest_perm", [t]) - -fun mk_perm p trm = -let - val ty = fastype_of trm -in - Const (@{const_name "permute"}, @{typ "perm"} --> ty --> ty) $ p $ trm -end - -fun eqvt_transform_tac thm = REPEAT o FIRST' - [CHANGED o simp_tac (HOL_basic_ss addsimps @{thms permute_minus_cancel}), - rtac (thm RS @{thm trans}), - rtac @{thm trans[OF permute_fun_def]} THEN' rtac @{thm ext}] - -(* transform equations into the required form *) -fun transform_eq ctxt thm lhs rhs = -let - val (p, t) = dest_perm lhs - val (c, args) = strip_comb t - val (c', args') = strip_comb rhs - val eargs = map Envir.eta_contract args - val eargs' = map Envir.eta_contract args' - val p_str = fst (fst (dest_Var p)) - val goal = HOLogic.mk_Trueprop (HOLogic.mk_eq (mk_perm p c, c)) -in - if c <> c' - then error "eqvt lemma is not of the right form (constants do not agree)" - else if eargs' <> map (mk_perm p) eargs - then error "eqvt lemma is not of the right form (arguments do not agree)" - else if args = [] - then thm - else Goal.prove ctxt [p_str] [] goal - (fn _ => eqvt_transform_tac thm 1) -end - -fun transform addel_fun thm context = -let - val ctxt = Context.proof_of context - val trm = HOLogic.dest_Trueprop (prop_of thm) -in - case trm of - Const (@{const_name "op ="}, _) $ lhs $ rhs => - let - val thm' = transform_eq ctxt thm lhs rhs RS @{thm eq_reflection} - in - addel_fun thm' context - end - | _ => raise (error "only (op=) case implemented yet") -end - -val eqvt_add = Thm.declaration_attribute (fn thm => (add_thm thm) o (transform add_raw_thm thm)); -val eqvt_del = Thm.declaration_attribute (fn thm => (del_thm thm) o (transform del_raw_thm thm)); - -val eqvt_raw_add = Thm.declaration_attribute add_raw_thm; -val eqvt_raw_del = Thm.declaration_attribute del_raw_thm; - -val setup = - Attrib.setup @{binding "eqvt"} (Attrib.add_del eqvt_add eqvt_del) - (cat_lines ["declaration of equivariance lemmas - they will automtically be", - "brought into the form p o c = c"]) #> - Attrib.setup @{binding "eqvt_raw"} (Attrib.add_del eqvt_raw_add eqvt_raw_del) - (cat_lines ["declaration of equivariance lemmas - no", - "transformation is performed"]) #> - PureThy.add_thms_dynamic (@{binding "eqvts"}, eqvts) #> - PureThy.add_thms_dynamic (@{binding "eqvts_raw"}, eqvts_raw); - - -end; diff -r c0eac04ae3b4 -r c34347ec7ab3 Pearl/Paper.thy --- a/Pearl/Paper.thy Sat Apr 03 22:31:11 2010 +0200 +++ b/Pearl/Paper.thy Sun Apr 04 21:39:28 2010 +0200 @@ -1,9 +1,9 @@ (*<*) theory Paper -imports "../Nominal/Nominal2_Base" - "../Nominal/Nominal2_Atoms" - "../Nominal/Nominal2_Eqvt" - "../Nominal/Atoms" +imports "../Nominal-General/Nominal2_Base" + "../Nominal-General/Nominal2_Atoms" + "../Nominal-General/Nominal2_Eqvt" + "../Nominal-General/Atoms" "LaTeXsugar" begin diff -r c0eac04ae3b4 -r c34347ec7ab3 Pearl/ROOT.ML --- a/Pearl/ROOT.ML Sat Apr 03 22:31:11 2010 +0200 +++ b/Pearl/ROOT.ML Sun Apr 04 21:39:28 2010 +0200 @@ -1,7 +1,7 @@ -no_document use_thys ["../Nominal/Nominal2_Base", - "../Nominal/Nominal2_Atoms", - "../Nominal/Nominal2_Eqvt", - "../Nominal/Atoms", +no_document use_thys ["../Nominal-General/Nominal2_Base", + "../Nominal-General/Nominal2_Atoms", + "../Nominal-General/Nominal2_Eqvt", + "../Nominal-General/Atoms", "LaTeXsugar"]; use_thys ["Paper"]; \ No newline at end of file diff -r c0eac04ae3b4 -r c34347ec7ab3 README --- a/README Sat Apr 03 22:31:11 2010 +0200 +++ b/README Sun Apr 04 21:39:28 2010 +0200 @@ -3,16 +3,18 @@ Subdirectories: -Attic ... old version of the quotient package (is now - part of the Isabelle distribution) +Attic ... old version of the quotient package (is now + part of the Isabelle distribution) -Literature ... some relevant papers bout binders and - Core-Haskell +Literature ... some relevant papers about binders and + Core-Haskell + +Nominal-General . implementation of the abstract nominal theory -Nominal ... main files for Nominal Isabelle +Nominal ... main files for new Nominal Isabelle -Nominal/Ex ... examples for new implementation +Nominal/Ex ... examples for new implementation -Paper ... submitted +Paper ... submitted to ICFP -Pearl ... paper accepted at ITP \ No newline at end of file +Pearl ... paper accepted at ITP \ No newline at end of file