primrec
sort_of :: "atom → atom_sort" where "sort_of (Atom s n) = s"
primrec
nat_of :: "atom → nat" where "nat_of (Atom s n) = n"
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 moreoverhave"inj (Atom s)"by (simp add: inj_on_def) ultimatelyshow"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) thenobtain a where"a ∉ X""sort_of a = s" by (auto elim: INFM_E) thenshow ?thesis .. qed
lemma atom_components_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)
section‹Sort-Respecting Permutations›
definition "perm ≡ {f. bij f ∧ finite {a. f a ≠ a} ∧ (∀a. sort_of (f a) = sort_of a)}"
typedef perm = "perm" proof show"id ∈ perm"unfolding perm_def 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
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: 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
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: shows"(a ⇌ b) + (a ⇌ b) = 0" and"(a ⇌ b) + (b ⇌ a) = 0" by (rule_tac [!] Rep_perm_ext)
(simp_all add: Rep_perm_simps fun_eq_iff)
lemma swap_self [simp]: "(a ⇌ a) = 0" by (rule Rep_perm_ext, simp add: Rep_perm_simps fun_eq_iff)
lemma minus_swap [simp]: "- (a ⇌ b) = (a ⇌ b)" by (rule minus_unique [OF swap_cancel(1)])
lemma swap_commute: "(a ⇌ b) = (b ⇌ a)" by (rule Rep_perm_ext)
(simp add: Rep_perm_swap fun_eq_iff)
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: Rep_perm_simps fun_eq_iff)
section‹Permutation Types›
text‹
Infix syntax for ‹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" using permute_plus [of p "- q" x] 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 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 standard 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 perm_eq_iff: fixes p q :: "perm" shows"p = q ⟷ (∀a::atom. p ∙ a = q ∙ a)" unfolding permute_atom_def by (metis Rep_perm_ext ext)
instance apply standard apply (auto simp: permute_set_def) done
end
lemma permute_set_eq: shows"p ∙ X = {x. - p ∙ x ∈ X}" unfolding permute_set_def by (auto) (metis permute_minus_cancel(1))
lemma permute_set_eq_image: shows"p ∙ X = permute p ` X" unfolding permute_set_def by auto
lemma permute_set_eq_vimage: shows"p ∙ X = permute (- p) -` X" unfolding permute_set_eq vimage_def by simp
lemma permute_finite [simp]: shows"finite (p ∙ X) = finite X" unfolding permute_set_eq_vimage using bij_permute by (rule finite_vimage_iff)
lemma swap_set_not_in: assumes a: "a ∉ S""b ∉ S" shows"(a ⇌ b) ∙ S = S" unfolding permute_set_def using a by (auto simp: swap_atom)
lemma swap_set_in: assumes a: "a ∈ S""b ∉ S""sort_of a = sort_of b" shows"(a ⇌ b) ∙ S ≠ S" unfolding permute_set_def using a by (auto simp: swap_atom)
lemma swap_set_in_eq: assumes a: "a ∈ S""b ∉ S""sort_of a = sort_of b" shows"(a ⇌ b) ∙ S = (S - {a}) ∪ {b}" unfolding permute_set_def using a by (auto simp: swap_atom)
lemma swap_set_both_in: assumes a: "a ∈ S""b ∈ S" shows"(a ⇌ b) ∙ S = S" unfolding permute_set_def using a by (auto simp: swap_atom)
lemma mem_permute_iff: shows"(p ∙ x) ∈ (p ∙ X) ⟷ x ∈ X" unfolding permute_set_def by auto
primrec
permute_list where
Nil_eqvt: "p ∙ [] = []"
| Cons_eqvt: "p ∙ (x # xs) = p ∙ x # p ∙ xs"
instance by standard (induct_tac [!] x, simp_all)
end
lemma set_eqvt: shows"p ∙ (set xs) = set (p ∙ xs)" by (induct xs) (simp_all add: empty_eqvt insert_eqvt)
subsection‹Permutations for @{typ "'a option"}›
instantiation option :: (pt) pt begin
primrec
permute_option where
None_eqvt: "p ∙ None = None"
| Some_eqvt: "p ∙ (Some x) = Some (p ∙ x)"
instance by standard (induct_tac [!] x, simp_all)
end
subsection‹Permutations for @{typ "'a multiset"}›
instantiation multiset :: (pt) pt begin
definition "p ∙ M = {# p ∙ x. x :# M #}"
instance proof fix M :: "'a multiset"and p q :: "perm" show"0 ∙ M = M" unfolding permute_multiset_def by (induct_tac M) (simp_all) show"(p + q) ∙ M = p ∙ q ∙ M" unfolding permute_multiset_def by (induct_tac M) (simp_all) qed
end
lemma permute_multiset [simp]: fixes M N::"('a::pt) multiset" shows"(p ∙ {#}) = ({#} ::('a::pt) multiset)" and"(p ∙ add_mset x M) = add_mset (p ∙ x) (p ∙ M)" and"(p ∙ (M + N)) = (p ∙ M) + (p ∙ N)" unfolding permute_multiset_def by (simp_all)
subsection‹Permutations for @{typ "'a fset"}›
instantiation fset :: (pt) pt begin
contextincludes fset.lifting begin
lift_definition "permute_fset" :: "perm → 'a fset → 'a fset" is"permute :: perm → 'a set → 'a set"by simp end
contextincludes fset.lifting begin instance proof fix x :: "'a fset"and p q :: "perm" show"0 ∙ x = x"by transfer simp show"(p + q) ∙ x = p ∙ q ∙ x"by transfer simp qed end
method_setup perm_strict_simp = ‹Nominal_Permeq.args_parser >> Nominal_Permeq.perm_strict_simp_meth› ‹pushes permutations inside, raises an error if it cannot solve all permutations.›
simproc_setup perm_simproc ("p ∙ t") = ‹fn _ => fn ctxt => fn ctrm =>
case Thm.term_of (Thm.dest_arg ctrm) of
Free _ => NONE
| Var _ => NONE
| 🚫‹permute _ for _ _› => NONE
| _ =>
let
val thm = Nominal_Permeq.eqvt_conv ctxt Nominal_Permeq.eqvt_strict_config ctrm
handle ERROR _ => Thm.reflexive ctrm
in
if Thm.is_reflexive thm then NONE else SOME(thm)
end ›
subsubsection‹Equivariance for permutations and swapping›
(* the normal version of this lemma would cause loops *) lemma permute_eqvt_raw [eqvt_raw]: shows"p ∙ permute ≡ permute" apply(simp add: fun_eq_iff permute_fun_def) apply(subst permute_eqvt) apply(simp) done
text‹
In order to prove that lfp is equivariant we need two
auxiliary classes which specify that (<=) and
Inf are equivariant. Instances for bool and fun are
given. ›
lemma finfun_apply_eqvt [eqvt]: shows"(p ∙ (finfun_apply f b)) = finfun_apply (p ∙ f) (p ∙ b)" by (transfer) (simp)
section‹Supp, Freshness and Supports›
context pt begin
definition
supp :: "'a → atom set" where "supp x = {a. infinite {b. (a ⇌ b) ∙ x ≠ x}}"
definition
fresh :: "atom → 'a → bool" (‹_ ♯ _› [55, 55] 55) where "a ♯ x ≡ a ∉ supp x"
end
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 alsohave"(a ⇌ c) + (b ⇌ c) + (a ⇌ c) = (a ⇌ b)" using assms * by (simp add: swap_triple) finallyshow"(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 thenhave"finite ({c. (a ⇌ c) ∙ x ≠ x} ∪ {c. (b ⇌ c) ∙ x ≠ x})"by simp thenobtain c where"(a ⇌ c) ∙ x = x""(b ⇌ c) ∙ x = x""sort_of c = sort_of b" by (rule obtain_atom) (auto) thenshow"(a ⇌ b) ∙ x = x"using asm by (rule_tac swap_rel_trans) (simp_all) next assume"sort_of a ≠ sort_of b" thenshow"(a ⇌ b) ∙ x = x"by simp qed
lemma fresh_eqvt [eqvt]: shows"p ∙ (a ♯ x) = (p ∙ a) ♯ (p ∙ x)" unfolding fresh_def by simp
lemma fresh_permute_iff: shows"(p ∙ a) ♯ (p ∙ x) ⟷ a ♯ x" by (simp only: fresh_eqvt[symmetric] permute_bool_def)
lemma fresh_permute_left: shows"a ♯ p ∙ x ⟷ - p ∙ a ♯ x" proof assume"a ♯ p ∙ x" thenhave"- p ∙ a ♯ - p ∙ p ∙ x"by (simp only: fresh_permute_iff) thenshow"- p ∙ a ♯ x"by simp next assume"- p ∙ a ♯ x" thenhave"p ∙ - p ∙ a ♯ p ∙ x"by (simp only: fresh_permute_iff) thenshow"a ♯ p ∙ x"by simp qed
section‹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)" thenobtain a where b1: "a ∈ supp x"and b2: "a ∉ S"by auto from a1 b2 have"∀b. b ∉ S ⟶ (a ⇌ b) ∙ x = x"unfolding supports_def by auto thenhave"{b. (a ⇌ b) ∙ x ≠ x} ⊆ S"by auto with a2 have"finite {b. (a ⇌ b) ∙ x ≠ x}"by (simp add: finite_subset) thenhave"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) thenshow"finite (supp x)"using a2 by (simp add: finite_subset) qed
lemma supp_supports: fixes x :: "'a::pt" shows"(supp x) supports x" unfolding supports_def proof (intro strip) fix a b assume"a ∉ (supp x) ∧ b ∉ (supp x)" thenhave"a ♯ x"and"b ♯ x"by (simp_all add: fresh_def) thenshow"(a ⇌ b) ∙ x = x"by (simp add: swap_fresh_fresh) qed
lemma supports_fresh: fixes x :: "'a::pt" assumes a1: "S supports x" and a2: "finite S" and a3: "a ∉ S" shows"a ♯ x" unfolding fresh_def proof - have"(supp x) ⊆ S"using a1 a2 by (rule supp_is_subset) thenshow"a ∉ (supp x)"using a3 by auto 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 thenobtain b where"b ∉ S ∪ S'"and"sort_of b = sort_of a" by (rule obtain_atom) thenhave"b ∉ S"and"b ∉ S'"and"sort_of a = sort_of b" by simp_all thenhave"(a ⇌ b) ∙ x = x" using‹a ∉ S'›‹S' supports x›by (simp add: supports_def) moreoverhave"(a ⇌ b) ∙ x ≠ x" using‹a ∈ S›‹b ∉ S›‹sort_of a = sort_of b› by (rule a3) ultimatelyshow"False"by simp qed qed
section‹Support w.r.t. relations›
text‹
This definition is used for unquotient types, where
alpha-equivalence does not coincide with equality. ›
definition "supp_rel R x = {a. infinite {b. ¬(R ((a ⇌ b) ∙ x) x)}}"
section‹Finitely-supported types›
class fs = pt + assumes finite_supp: "finite (supp x)"
lemma pure_supp: fixes x::"'a::pure" shows"supp x = {}" unfolding supp_def by (simp add: permute_pure)
text‹equivariance of a function at a given argument›
definition "eqvt_at f x ≡∀p. p ∙ (f x) = f (p ∙ x)"
lemma eqvtI: shows"(∧p. p ∙ f ≡ f) ==> eqvt f" unfolding eqvt_def by simp
lemma eqvt_at_perm: assumes"eqvt_at f x" shows"eqvt_at f (q ∙ x)" proof -
{ fix p::"perm" have"p ∙ (f (q ∙ x)) = p ∙ q ∙ (f x)" using assms by (simp add: eqvt_at_def) alsohave"… = (p + q) ∙ (f x)"by simp alsohave"… = f ((p + q) ∙ x)" using assms by (simp only: eqvt_at_def) finallyhave"p ∙ (f (q ∙ x)) = f (p ∙ q ∙ x)"by simp } thenshow"eqvt_at f (q ∙ x)"unfolding eqvt_at_def by simp qed
lemma supp_fun_eqvt: assumes a: "eqvt f" shows"supp f = {}" using a unfolding eqvt_def unfolding supp_def by simp
lemma fresh_fun_eqvt: assumes a: "eqvt f" shows"a ♯ f" using a unfolding fresh_def by (simp add: supp_fun_eqvt)
lemma fresh_fun_eqvt_app: assumes a: "eqvt f" shows"a ♯ x ==> a ♯ f x" proof - from a have"supp f = {}"by (simp add: supp_fun_eqvt) thenshow"a ♯ x ==> a ♯ f x" unfolding fresh_def using supp_fun_app by auto qed
lemma supp_fun_app_eqvt: assumes a: "eqvt f" shows"supp (f x) ⊆ supp x" using fresh_fun_eqvt_app[OF a] unfolding fresh_def by auto
lemma fresh_eqvt_at: assumes asm: "eqvt_at f x" and fin: "finite (supp x)" and fresh: "a ♯ x" shows"a ♯ f x" using fresh unfolding fresh_def using supp_eqvt_at[OF asm fin] by auto
text‹for handling of freshness of functions›
simproc_setup fresh_fun_simproc ("a ♯ (f::'a::pt →'b::pt)") = ‹fn _ => fn ctxt => fn ctrm =>
let
val _ $ _ $ f = Thm.term_of ctrm
in
case (Term.add_frees f [], Term.add_vars f []) of
([], []) => SOME(@{thm fresh_fun_eqvt[simplified eqvt_def, THEN Eq_TrueI]})
| (x::_, []) =>
let
val argx = Free x
val absf = absfree x f
val cty_inst =
[SOME (Thm.ctyp_of ctxt (fastype_of argx)), SOME (Thm.ctyp_of ctxt (fastype_of f))]
val ctrm_inst = [NONE, SOME (Thm.cterm_of ctxt absf), SOME (Thm.cterm_of ctxt argx)]
val thm = Thm.instantiate' cty_inst ctrm_inst @{thm fresh_fun_app}
in
SOME(thm RS @{thm Eq_TrueI})
end
| (_, _) => NONE
end ›
subsection‹helper functions for ‹nominal_functions››
lemma THE_defaultI2: assumes"∃!x. P x""∧x. P x ==> Q x" shows"Q (THE_default d P)" by (iprover intro: assms THE_defaultI')
lemma fundef_ex1_eqvt_at: fixes x::"'a::pt" assumes f_def: "f == (λx::'a. THE_default (d x) (G x))" assumes eqvt: "eqvt G" assumes ex1: "∃!y. G x y" shows"eqvt_at f x" unfolding eqvt_at_def using assms by (auto intro: fundef_ex1_eqvt)
lemma fundef_ex1_prop: fixes x::"'a::pt" assumes f_def: "f == (λx::'a. THE_default (d x) (G x))" assumes P_all: "∧x y. G x y ==> P x y" assumes ex1: "∃!y. G x y" shows"P x (f x)" unfolding f_def using ex1 apply(erule_tac ex1E) apply(rule THE_defaultI2) apply(blast) apply(rule P_all) apply(assumption) done
section‹Support of Finite Sets of Finitely Supported Elements›
lemma fresh_finite_atom_set: fixes S::"atom set" assumes"finite S" shows"a ♯ S ⟷ a ∉ S" unfolding fresh_def by (simp add: supp_finite_atom_set[OF assms])
lemma fresh_minus_atom_set: fixes S::"atom set" assumes"finite S" shows"a ♯ S - T ⟷ (a ∉ T ⟶ a ♯ S)" unfolding fresh_def by (auto simp: supp_finite_atom_set assms)
lemma Union_supports_set: shows"(∪x ∈ S. supp x) supports S" proof -
{ fix a b have"∀x ∈ S. (a ⇌ b) ∙ x = x ==> (a ⇌ b) ∙ S = S" unfolding permute_set_def by force
} thenshow"(∪x ∈ S. supp x) supports S" unfolding supports_def by (simp add: fresh_def[symmetric] swap_fresh_fresh) qed
lemma Union_of_finite_supp_sets: fixes S::"('a::fs set)" assumes fin: "finite S" shows"finite (∪x∈S. supp x)" using fin by (induct) (auto simp: finite_supp)
lemma Union_included_in_supp: fixes S::"('a::fs set)" assumes fin: "finite S" shows"(∪x∈S. supp x) ⊆ supp S" proof - have eqvt: "eqvt (λS. ∪x ∈ S. supp x)" unfolding eqvt_def by simp have"(∪x∈S. supp x) = supp (∪x∈S. supp x)" by (rule supp_finite_atom_set[symmetric]) (rule Union_of_finite_supp_sets[OF fin]) alsohave"…⊆ supp S"using eqvt by (rule supp_fun_app_eqvt) finallyshow"(∪x∈S. supp x) ⊆ supp S" . qed
lemma finite_sets_supp: fixes S::"('a::fs set)" assumes"finite S" shows"finite (supp S)" using assms by (simp only: supp_of_finite_sets Union_of_finite_supp_sets)
lemma supp_of_finite_union: fixes S T::"('a::fs) set" assumes fin1: "finite S" and fin2: "finite T" shows"supp (S ∪ T) = supp S ∪ supp T" using fin1 fin2 by (simp add: supp_of_finite_sets)
lemma fresh_finite_union: fixes S T::"('a::fs) set" assumes fin1: "finite S" and fin2: "finite T" shows"a ♯ (S ∪ T) ⟷ a ♯ S ∧ a ♯ T" unfolding fresh_def by (simp add: supp_of_finite_union[OF fin1 fin2])
lemma supp_of_finite_insert: fixes S::"('a::fs) set" assumes fin: "finite S" shows"supp (insert x S) = supp x ∪ supp S" using fin by (simp add: supp_of_finite_sets)
lemma fresh_finite_insert: fixes S::"('a::fs) set" assumes fin: "finite S" shows"a ♯ (insert x S) ⟷ a ♯ x ∧ a ♯ S" using fin unfolding fresh_def by (simp add: supp_of_finite_insert)
lemma Union_finite_multiset: fixes M::"'a::fs multiset" shows"finite (∪{supp x | x. x ∈# M})" proof - have"finite (∪(supp ` {x. x ∈# M}))" by (induct M) (simp_all add: Collect_imp_eq Collect_neg_eq finite_supp) thenshow"finite (∪{supp x | x. x ∈# M})" by (simp only: image_Collect) qed
lemma Union_supports_multiset: shows"∪{supp x | x. x ∈# M} supports M" proof - have sw: "∧a b. ((∧x. x ∈# M ==> (a ⇌ b) ∙ x = x) ==> (a ⇌ b) ∙ M = M)" unfolding permute_multiset_def by (induct M) simp_all have"(∪x∈set_mset M. supp x) supports M" by (auto intro!: sw swap_fresh_fresh simp add: fresh_def supports_def) alsohave"(∪x∈set_mset M. supp x) = (∪{supp x | x. x ∈# M})" by auto finallyshow"(∪{supp x | x. x ∈# M}) supports M" . qed
lemma Union_included_multiset: fixes M::"('a::fs multiset)" shows"(∪{supp x | x. x ∈# M}) ⊆ supp M" proof - have"(∪{supp x | x. x ∈# M}) = (∪x ∈ set_mset M. supp x)"by auto alsohave"... = supp (set_mset M)" by (simp add: supp_of_finite_sets) alsohave" ... ⊆ supp M"by (rule supp_set_mset) finallyshow"(∪{supp x | x. x ∈# M}) ⊆ supp M" . qed
lemma supp_of_multisets: fixes M::"('a::fs multiset)" shows"(supp M) = (∪{supp x | x. x ∈# M})" apply(rule subset_antisym) apply(rule supp_is_subset) apply(rule Union_supports_multiset) apply(rule Union_finite_multiset) apply(rule Union_included_multiset) done
lemma supp_union_fset: fixes S T::"'a::fs fset" shows"supp (S |∪| T) = supp S ∪ supp T" by (induct S) (auto)
lemma fresh_union_fset: fixes S T::"'a::fs fset" shows"a ♯ S |∪| T ⟷ a ♯ S ∧ a ♯ T" unfolding fresh_def by (simp add: supp_union_fset)
instance fset :: (fs) fs by standard (rule fset_finite_supp)
subsection‹Type @{typ "('a, 'b) finfun"} is finitely supported›
lemma fresh_finfun_const: shows"a ♯ (finfun_const b) ⟷ a ♯ b" by (simp add: fresh_def supp_def)
lemma fresh_finfun_update: shows"[a ♯ f; a ♯ x; a ♯ y]==> a ♯ finfun_update f x y" unfolding fresh_conv_MOST unfolding finfun_update_eqvt by (elim MOST_rev_mp) (simp)
lemma supp_finfun_const: shows"supp (finfun_const b) = supp(b)" by (simp add: supp_def)
lemma supp_finfun_update: shows"supp (finfun_update f x y) ⊆ supp(f, x, y)" using fresh_finfun_update by (auto simp: fresh_def supp_Pair)
lemma fresh_Unit_elim: shows"(a ♯ () ==> PROP C) ≡ PROP C" by (simp add: fresh_Unit)
lemma fresh_Pair_elim: shows"(a ♯ (x, y) ==> PROP C) ≡ (a ♯ x ==> a ♯ y ==> PROP C)" by rule (simp_all add: fresh_Pair)
(* this rule needs to be added before the fresh_prodD is *) (* added to the simplifier with mksimps *) lemma [simp]: shows"a ♯ x1 ==> a ♯ x2 ==> a ♯ (x1, x2)" by (simp add: fresh_Pair)
lemma fresh_PairD: shows"a ♯ (x, y) ==> a ♯ x" and"a ♯ (x, y) ==> a ♯ y" by (simp_all add: fresh_Pair)
declaration‹fn _ =>
val mksimps_pairs = (@{const_name Nominal2_Base.fresh}, @{thms fresh_PairD}) :: mksimps_pairs
Simplifier.map_ss (fn ss => Simplifier.set_mksimps (mksimps mksimps_pairs) ss)
›
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_supp_conv: shows"supp x ♯* y ==> supp y ♯* x" by (auto simp: fresh_star_def fresh_def)
lemma fresh_star_perm_set_conv: fixes p::"perm" assumes fresh: "as ♯* p" and fin: "finite as" shows"supp p ♯* as" apply(rule fresh_star_supp_conv) apply(simp add: supp_finite_atom_set fin fresh) done
lemma fresh_star_atom_set_conv: assumes fresh: "as ♯* bs" and fin: "finite as""finite bs" shows"bs ♯* as" using fresh unfolding fresh_star_def fresh_def by (auto simp: supp_finite_atom_set fin)
unfolding fresh_star_def fresh_def by (auto simp: supp_finite_atom_set fin)
lemma fresh_star_Pair: shows"as ♯* (x, y) = (as ♯* x ∧ as ♯* y)" by (auto simp: fresh_star_def fresh_Pair)
lemma fresh_star_list: shows"as ♯* (xs @ ys) ⟷ as ♯* xs ∧ as ♯* ys" and"as ♯* (x # xs) ⟷ as ♯* x ∧ as ♯* xs" and"as ♯* []" by (auto simp: fresh_star_def fresh_Nil fresh_Cons fresh_append)
lemma fresh_star_set: fixes xs::"('a::fs) list" shows"as ♯* set xs ⟷ as ♯* xs" unfolding fresh_star_def by (simp add: fresh_set)
lemma fresh_star_singleton: fixes a::"atom" shows"as ♯* {a} ⟷ as ♯* a" by (simp add: fresh_star_def fresh_finite_insert fresh_set_empty)
lemma fresh_star_fset: fixes xs::"('a::fs) list" shows"as ♯* fset S ⟷ as ♯* S" by (simp add: fresh_star_def fresh_def)
lemma fresh_star_Un: shows"(as ∪ bs) ♯* x = (as ♯* x ∧ bs ♯* x)" by (auto simp: fresh_star_def)
lemma fresh_star_insert: shows"(insert a as) ♯* x = (a ♯ x ∧ as ♯* x)" by (auto simp: 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_Pair_elim: shows"(a ♯* (x, y) ==> PROP C) ≡ (a ♯* x ==> a ♯* y ==> PROP C)" by (rule, simp_all add: fresh_star_Pair)
lemma smaller_supp: assumes a: "a ∈ supp p" shows"supp ((p ∙ a ⇌ a) + p) ⊂ supp p" proof - have"supp ((p ∙ a ⇌ a) + p) ⊆ supp p" unfolding supp_perm by (auto simp: swap_atom) moreover have"a ∉ supp ((p ∙ a ⇌ a) + p)"by (simp add: supp_perm) thenhave"supp ((p ∙ a ⇌ a) + p) ≠ supp p"using a by auto ultimately show"supp ((p ∙ a ⇌ a) + p) ⊂ supp p"by auto qed
lemma perm_struct_induct[consumes 1, case_names zero swap]: assumes S: "supp p ⊆ S" and zero: "P 0" and swap: "∧p a b. [P p; supp p ⊆ S; a ∈ S; b ∈ S; a ≠ b; sort_of a = sort_of b]==> P ((a ⇌ b) + p)" shows"P p" proof - have"finite (supp p)"by (simp add: finite_supp) thenshow"P p"using S proof(induct A≡"supp p" arbitrary: p rule: finite_psubset_induct) case (psubset p) thenhave ih: "∧q. supp q ⊂ supp p ==> P q"by auto have as: "supp p ⊆ S"by fact
{ assume"supp p = {}" thenhave"p = 0"by (simp add: supp_perm perm_eq_iff) thenhave"P p"using zero by simp
} moreover
{ assume"supp p ≠ {}" thenobtain a where a0: "a ∈ supp p"by blast thenhave a1: "p ∙ a ∈ S""a ∈ S""sort_of (p ∙ a) = sort_of a""p ∙ a ≠ a" using as by (auto simp: supp_atom supp_perm swap_atom) let ?q = "(p ∙ a ⇌ a) + p" have a2: "supp ?q ⊂ supp p"using a0 smaller_supp by simp thenhave"P ?q"using ih by simp moreover have"supp ?q ⊆ S"using as a2 by simp ultimatelyhave"P ((p ∙ a ⇌ a) + ?q)"using as a1 swap by simp moreover have"p = (p ∙ a ⇌ a) + ?q"by (simp add: perm_eq_iff) ultimatelyhave"P p"by simp
} ultimatelyshow"P p"by blast qed qed
lemma perm_simple_struct_induct[case_names zero swap]: assumes zero: "P 0" and swap: "∧p a b. [P p; a ≠ b; sort_of a = sort_of b]==> P ((a ⇌ b) + p)" shows"P p" by (rule_tac S="supp p"in perm_struct_induct)
(auto intro: zero swap)
lemma perm_struct_induct2[consumes 1, case_names zero swap plus]: assumes S: "supp p ⊆ S" assumes zero: "P 0" assumes swap: "∧a b. [sort_of a = sort_of b; a ≠ b; a ∈ S; b ∈ S]==> P (a ⇌ b)" assumes plus: "∧p1 p2. [P p1; P p2; supp p1 ⊆ S; supp p2 ⊆ S]==> P (p1 + p2)" shows"P p" using S by (induct p rule: perm_struct_induct)
(auto intro: zero plus swap simp add: supp_swap)
lemma perm_simple_struct_induct2[case_names zero swap plus]: assumes zero: "P 0" assumes swap: "∧a b. [sort_of a = sort_of b; a ≠ b]==> P (a ⇌ b)" assumes plus: "∧p1 p2. [P p1; P p2]==> P (p1 + p2)" shows"P p" by (rule_tac S="supp p"in perm_struct_induct2)
(auto intro: zero swap plus)
lemma supp_perm_singleton: fixes p::"perm" shows"supp p ⊆ {b} ⟷ p = 0" proof -
{ assume"supp p ⊆ {b}" thenhave"p = 0" by (induct p rule: perm_struct_induct) (simp_all)
} thenshow"supp p ⊆ {b} ⟷ p = 0"by (auto simp: supp_zero_perm) qed
lemma supp_perm_pair: fixes p::"perm" shows"supp p ⊆ {a, b} ⟷ p = 0 ∨ p = (b ⇌ a)" proof -
{ assume"supp p ⊆ {a, b}" thenhave"p = 0 ∨ p = (b ⇌ a)" apply (induct p rule: perm_struct_induct) apply (auto simp: swap_cancel supp_zero_perm supp_swap) apply (simp add: swap_commute) done
} thenshow"supp p ⊆ {a, b} ⟷ p = 0 ∨ p = (b ⇌ a)" by (auto simp: supp_zero_perm supp_swap split: if_splits) qed
lemma supp_perm_eq: assumes"(supp x) ♯* p" shows"p ∙ x = x" proof - from assms have"supp p ⊆ {a. a ♯ x}" unfolding supp_perm fresh_star_def fresh_def by auto thenshow"p ∙ x = x" proof (induct p rule: perm_struct_induct) case zero show"0 ∙ x = x"by simp next case (swap p a b) thenhave"a ♯ x""b ♯ x""p ∙ x = x"by simp_all thenshow"((a ⇌ b) + p) ∙ x = x"by (simp add: swap_fresh_fresh) qed qed
text‹same lemma as above, but proved with a different induction principle› lemma supp_perm_eq_test: assumes"(supp x) ♯* p" shows"p ∙ x = x" proof - from assms have"supp p ⊆ {a. a ♯ x}" unfolding supp_perm fresh_star_def fresh_def by auto thenshow"p ∙ x = x" proof (induct p rule: perm_struct_induct2) case zero show"0 ∙ x = x"by simp next case (swap a b) thenhave"a ♯ x""b ♯ x"by simp_all thenshow"(a ⇌ b) ∙ x = x"by (simp add: swap_fresh_fresh) next case (plus p1 p2) have"p1 ∙ x = x""p2 ∙ x = x"by fact+ thenshow"(p1 + p2) ∙ x = x"by simp qed qed
lemma perm_supp_eq: assumes a: "(supp p) ♯* x" shows"p ∙ x = x" proof - from assms have"supp p ⊆ {a. a ♯ x}" unfolding supp_perm fresh_star_def fresh_def by auto thenshow"p ∙ x = x" proof (induct p rule: perm_struct_induct2) case zero show"0 ∙ x = x"by simp next case (swap a b) thenhave"a ♯ x""b ♯ x"by simp_all thenshow"(a ⇌ b) ∙ x = x"by (simp add: swap_fresh_fresh) next case (plus p1 p2) have"p1 ∙ x = x""p2 ∙ x = x"by fact+ thenshow"(p1 + p2) ∙ x = x"by simp qed qed
lemma supp_perm_perm_eq: assumes a: "∀a ∈ supp x. p ∙ a = q ∙ a" shows"p ∙ x = q ∙ x" proof - from a have"∀a ∈ supp x. (-q + p) ∙ a = a"by simp thenhave"∀a ∈ supp x. a ∉ supp (-q + p)" unfolding supp_perm by simp thenhave"supp x ♯* (-q + p)" unfolding fresh_star_def fresh_def by simp thenhave"(-q + p) ∙ x = x"by (simp only: supp_perm_eq) thenshow"p ∙ x = q ∙ x" by (metis permute_minus_cancel permute_plus) qed
text‹disagreement set›
definition
dset :: "perm → perm → atom set" where "dset p q = {a::atom. p ∙ a ≠ q ∙ a}"
lemma ds_fresh: assumes"dset p q ♯* x" shows"p ∙ x = q ∙ x" using assms unfolding dset_def fresh_star_def fresh_def by (auto intro: supp_perm_perm_eq)
lemma atom_set_perm_eq: assumes a: "as ♯* p" shows"p ∙ as = as" proof - from a have"supp p ⊆ {a. a ∉ as}" unfolding supp_perm fresh_star_def fresh_def by auto thenshow"p ∙ as = as" proof (induct p rule: perm_struct_induct) case zero show"0 ∙ as = as"by simp next case (swap p a b) thenhave"a ∉ as""b ∉ as""p ∙ as = as"by simp_all thenshow"((a ⇌ b) + p) ∙ as = as"by (simp add: swap_set_not_in) qed qed
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) thenshow ?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) ultimatelyshow ?caseby blast next case (insert x Xs) thenobtain 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 ∪ supp p)" using‹finite As›‹finite Xs› by (simp add: permute_set_eq_image finite_supp) thenobtain y where"y ∉ (As ∪ p ∙ Xs ∪ supp p)""sort_of y = sort_of x" by (rule obtain_atom) hence y: "y ∉ As""y ∉ p ∙ Xs""y ∉ supp p""sort_of y = sort_of x" by simp_all hence py: "p ∙ y = y""x ≠ y"using‹x ∈ As› by (auto simp: supp_perm) 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 (x ⇌ y) ∩ supp p = {}"using px py ‹sort_of y = sort_of x› unfolding supp_swap by (simp add: supp_perm) thenhave"supp ?q = (supp (x ⇌ y) ∪ supp p)" by (simp add: supp_plus_perm_eq) thenhave"supp ?q = insert x Xs ∪ ?q ∙ insert x Xs" using p2 ‹sort_of y = sort_of x›‹x ≠ y›unfolding q supp_swap by auto ultimatelyshow ?caseby 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
lemma at_set_avoiding2_atom: assumes"finite (supp c)""finite (supp x)" and b: "a ♯ x" shows"∃p. (p ∙ a) ♯ c ∧ supp x ♯* p" proof - have a: "{a} ♯* x"unfolding fresh_star_def by (simp add: b) obtain p where p1: "(p ∙ {a}) ♯* c"and p2: "supp x ♯* p" using at_set_avoiding2[of "{a}""c""x"] assms a by blast have c: "(p ∙ a) ♯ c"using p1 unfolding fresh_star_def Ball_def by(erule_tac x="p ∙ a"in allE) (simp add: permute_set_def) hence"p ∙ a ♯ c ∧ supp x ♯* p"using p2 by blast thenshow"∃p. (p ∙ a) ♯ c ∧ supp x ♯* p"by blast qed
section‹Renaming permutations›
lemma set_renaming_perm: assumes b: "finite bs" shows"∃q. (∀b ∈ bs. q ∙ b = p ∙ b) ∧ supp q ⊆ bs ∪ (p ∙ bs)" using b proof (induct) case empty have"(∀b ∈ {}. 0 ∙ b = p ∙ b) ∧ supp (0::perm) ⊆ {} ∪ p ∙ {}" by (simp add: permute_set_def supp_perm) thenshow"∃q. (∀b ∈ {}. q ∙ b = p ∙ b) ∧ supp q ⊆ {} ∪ p ∙ {}"by blast next case (insert a bs) thenhave" ∃q. (∀b ∈ bs. q ∙ b = p ∙ b) ∧ supp q ⊆ bs ∪ p ∙ bs"by simp thenobtain q where *: "∀b ∈ bs. q ∙ b = p ∙ b"and **: "supp q ⊆ bs ∪ p ∙ bs" by (metis empty_subsetI insert(3) supp_swap)
{ assume1: "q ∙ a = p ∙ a" have"∀b ∈ (insert a bs). q ∙ b = p ∙ b"using1 * by simp moreover have"supp q ⊆ insert a bs ∪ p ∙ insert a bs" using ** by (auto simp: insert_eqvt) ultimately have"∃q. (∀b ∈ insert a bs. q ∙ b = p ∙ b) ∧ supp q ⊆ insert a bs ∪ p ∙ insert a bs"by blast
} moreover
{ assume2: "q ∙ a ≠ p ∙ a" define q' where"q' = ((q ∙ a) ⇌ (p ∙ a)) + q" have"∀b ∈ insert a bs. q' ∙ b = p ∙ b"using2 * ‹a ∉ bs›unfolding q'_def by (auto simp: swap_atom) moreover
{ have"{q ∙ a, p ∙ a} ⊆ insert a bs ∪ p ∙ insert a bs" using ** apply (auto simp: supp_perm insert_eqvt) apply (subgoal_tac "q ∙ a ∈ bs ∪ p ∙ bs") apply(auto)[1] apply(subgoal_tac "q ∙ a ∈ {a. q ∙ a ≠ a}") apply(blast) apply(simp) done thenhave"supp (q ∙ a ⇌ p ∙ a) ⊆ insert a bs ∪ p ∙ insert a bs" unfolding supp_swap by auto moreover have"supp q ⊆ insert a bs ∪ p ∙ insert a bs" using ** by (auto simp: insert_eqvt) ultimately have"supp q' ⊆ insert a bs ∪ p ∙ insert a bs" unfolding q'_defusing supp_plus_perm by blast
} ultimately have"∃q. (∀b ∈ insert a bs. q ∙ b = p ∙ b) ∧ supp q ⊆ insert a bs ∪ p ∙ insert a bs"by blast
} ultimatelyshow"∃q. (∀b ∈ insert a bs. q ∙ b = p ∙ b) ∧ supp q ⊆ insert a bs ∪ p ∙ insert a bs" by blast qed
lemma set_renaming_perm2: shows"∃q. (∀b ∈ bs. q ∙ b = p ∙ b) ∧ supp q ⊆ bs ∪ (p ∙ bs)" proof - have"finite (bs ∩ supp p)"by (simp add: finite_supp) thenobtain q where *: "∀b ∈ bs ∩ supp p. q ∙ b = p ∙ b"and **: "supp q ⊆ (bs ∩ supp p) ∪ (p ∙ (bs∩ supp p))" using set_renaming_perm by blast from ** have"supp q ⊆ bs ∪ (p ∙ bs)"by (auto simp: inter_eqvt) moreover have"∀b ∈ bs - supp p. q ∙ b = p ∙ b" apply(auto) apply(subgoal_tac "b ∉ supp q") apply(simp add: fresh_def[symmetric]) apply(simp add: fresh_perm) apply(clarify) apply(rotate_tac 2) apply(drule subsetD[OF **]) apply(simp add: inter_eqvt supp_eqvt permute_self) done ultimatelyhave"(∀b ∈ bs. q ∙ b = p ∙ b) ∧ supp q ⊆ bs ∪ (p ∙ bs)"using * by auto thenshow"∃q. (∀b ∈ bs. q ∙ b = p ∙ b) ∧ supp q ⊆ bs ∪ (p ∙ bs)"by blast qed
lemma list_renaming_perm: shows"∃q. (∀b ∈ set bs. q ∙ b = p ∙ b) ∧ supp q ⊆ set bs ∪ (p ∙ set bs)" proof (induct bs) case (Cons a bs) thenhave" ∃q. (∀b ∈ set bs. q ∙ b = p ∙ b) ∧ supp q ⊆ set bs ∪ p ∙ (set bs)"by simp thenobtain q where *: "∀b ∈ set bs. q ∙ b = p ∙ b"and **: "supp q ⊆ set bs ∪ p ∙ (set bs)" by (blast)
{ assume1: "a ∈ set bs" have"q ∙ a = p ∙ a"using * 1by (induct bs) (auto) thenhave"∀b ∈ set (a # bs). q ∙ b = p ∙ b"using * by simp moreover have"supp q ⊆ set (a # bs) ∪ p ∙ (set (a # bs))"using ** by (auto simp: insert_eqvt) ultimately have"∃q. (∀b ∈ set (a # bs). q ∙ b = p ∙ b) ∧ supp q ⊆ set (a # bs) ∪ p ∙ (set (a # bs))"by blast
} moreover
{ assume2: "a ∉ set bs" define q' where"q' = ((q ∙ a) ⇌ (p ∙ a)) + q" have"∀b ∈ set (a # bs). q' ∙ b = p ∙ b" unfolding q'_defusing2 * ‹a ∉ set bs›by (auto simp: swap_atom) moreover
{ have"{q ∙ a, p ∙ a} ⊆ set (a # bs) ∪ p ∙ (set (a # bs))" using ** apply (auto simp: supp_perm insert_eqvt) apply (subgoal_tac "q ∙ a ∈ set bs ∪ p ∙ set bs") apply(auto)[1] apply(subgoal_tac "q ∙ a ∈ {a. q ∙ a ≠ a}") apply(blast) apply(simp) done thenhave"supp (q ∙ a ⇌ p ∙ a) ⊆ set (a # bs) ∪ p ∙ set (a # bs)" unfolding supp_swap by auto moreover have"supp q ⊆ set (a # bs) ∪ p ∙ (set (a # bs))" using ** by (auto simp: insert_eqvt) ultimately have"supp q' ⊆ set (a # bs) ∪ p ∙ (set (a # bs))" unfolding q'_defusing supp_plus_perm by blast
} ultimately have"∃q. (∀b ∈ set (a # bs). q ∙ b = p ∙ b) ∧ supp q ⊆ set (a # bs) ∪ p ∙ (set (a # bs))"by blast
} ultimatelyshow"∃q. (∀b ∈ set (a # bs). q ∙ b = p ∙ b) ∧ supp q ⊆ set (a # bs) ∪p ∙ (set (a # bs))" by blast next case Nil have"(∀b ∈ set []. 0 ∙ b = p ∙ b) ∧ supp (0::perm) ⊆ set [] ∪ p ∙ set []" by (simp add: supp_zero_perm) thenshow"∃q. (∀b ∈ set []. q ∙ b = p ∙ b) ∧ supp q ⊆ set [] ∪ p ∙ (set [])"by blast qed
section‹Concrete Atoms Types›
text‹
Class ‹at_base› allows types containing multiple sorts of atoms.
Class ‹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)"
declare atom_eqvt [eqvt]
class at = at_base + assumes sort_of_atom_eq [simp]: "sort_of (atom a) = sort_of (atom b)"
lemma sort_ineq [simp]: assumes"sort_of (atom a) ≠ sort_of (atom b)" shows"atom a ≠ atom b" using assms by metis
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"sort_of a ≠ sort_of (atom b) ==> a ♯ b" and"a ♯ b ⟷ a ≠ atom b" unfolding fresh_def apply(simp_all add: supp_at_base) apply(metis) done
(* solves the freshness only if the inequality can be shown by the
simproc below *) lemma fresh_ineq_at_base [simp]: shows"a ≠ atom b ==> a ♯ b" by (simp add: fresh_at_base)
lemma fresh_atom_at_base [simp]: fixes b::"'a::at_base" shows"a ♯ atom b ⟷ a ♯ b" by (simp add: fresh_def supp_at_base supp_atom)
lemma fresh_star_atom_at_base: fixes b::"'a::at_base" shows"as ♯* atom b ⟷ as ♯* b" by (simp add: fresh_star_def fresh_atom_at_base)
lemma if_fresh_at_base [simp]: shows"atom a ♯ x ==> P (if a = x then t else s) = P s" and"atom a ♯ x ==> P (if x = a then t else s) = P s" by (simp_all add: fresh_at_base)
simproc_setup fresh_ineq ("x ≠ (y::'a::at_base)") = ‹fn _ => fn ctxt => fn ctrm =>
case Thm.term_of ctrm of 🚫‹Not for 🚫‹HOL.eq _ for lhs rhs›› =>
let
fun first_is_neg lhs rhs [] = NONE
| first_is_neg lhs rhs (thm::thms) =
(case Thm.prop_of thm of
_ $ 🚫‹Not for 🚫‹HOL.eq _ for l r›› =>
(if l = lhs andalso r = rhs then SOME(thm)
else if r = lhs andalso l = rhs then SOME(thm RS @{thm not_sym})
else first_is_neg lhs rhs thms)
| _ => first_is_neg lhs rhs thms)
val simp_thms = @{thms fresh_Pair fresh_at_base atom_eq_iff}
val prems = Simplifier.prems_of ctxt
|> filter (fn thm => case Thm.prop_of thm of
_ $ 🚫‹fresh _ for ‹_ $ a› b› =>
(let
val atms = a :: HOLogic.strip_tuple b
in
member (op =) atms lhs andalso member (op =) atms rhs
end)
| _ => false)
|> map (simplify (put_simpset HOL_basic_ss ctxt addsimps simp_thms))
|> map HOLogic.conj_elims
|> flat
in
case first_is_neg lhs rhs prems of
SOME(thm) => SOME(thm RS @{thm Eq_TrueI})
| NONE => NONE
end
| _ => NONE ›
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) thenobtain 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 thenobtain a :: 'a where"atom a ∉ X" by auto thus ?thesis .. qed
lemma obtain_fresh': assumes fin: "finite (supp x)" obtains a::"'a::at_base"where"atom a ♯ x" using obtain_at_base[where X="supp x"] by (auto simp: fresh_def fin)
lemma obtain_fresh: fixes x::"'b::fs" obtains a::"'a::at_base"where"atom a ♯ x" by (rule obtain_fresh') (auto simp: finite_supp)
lemma fresh_finite_set_at_base: fixes a::"'a::at_base" assumes a: "finite S" shows"atom a ♯ S ⟷ a ∉ S" unfolding fresh_def apply(simp add: supp_finite_set_at_base[OF a]) apply(subst inj_image_mem_iff) apply(simp add: inj_on_def) apply(simp) done
lemma fresh_at_base_permute_iff [simp]: fixes a::"'a::at_base" shows"atom (p ∙ a) ♯ p ∙ x ⟷ atom a ♯ x" unfolding atom_eqvt[symmetric] by (simp only: fresh_permute_iff)
lemma fresh_at_base_permI: shows"atom a ♯ p ==> p ∙ a = a" by (simp add: fresh_def supp_perm)
section‹Infrastructure for concrete atom types›
definition
flip :: "'a::at_base → 'a → perm" (‹'(_ ↔ _')›) where "(a ↔ b) = (atom a ⇌ atom b)"
lemma flip_fresh_fresh: assumes"atom a ♯ x""atom b ♯ x" shows"(a ↔ b) ∙ x = x" using assms by (simp add: flip_def swap_fresh_fresh)
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 [eqvt]: 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 flip_triple: fixes a b c::"'a::at" assumes"a ≠ b"and"c ≠ b" shows"(a ↔ c) + (b ↔ c) + (a ↔ c) = (a ↔ b)" unfolding flip_def by (rule swap_triple) (simp_all add: assms)
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
subsection‹Syntax for coercing at-elements to the atom-type›
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 = 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
lemma at_class_sort: fixes s :: atom_sort fixes Rep :: "'a → atom"and Abs :: "atom → 'a" fixes a::"'a" assumes type: "type_definition Rep Abs {a. sort_of a = s}" assumes atom_def: "∧a. atom a = Rep a" shows"sort_of (atom a) = s" using atom_def type unfolding type_definition_def by simp
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‹Library functions for the nominal infrastructure›
ML_file ‹nominal_library.ML›
section‹The freshness lemma according to Andy Pitts›
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: 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_fun_app) 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 alsohave"… = ((atom b ⇌ atom a) ∙ h) ((atom b ⇌ atom a) ∙ b)" by (rule permute_fun_app_eq) alsohave"… = h a" using d2 by simp finallyshow"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: fresh_Pair) qed
text‹packaging the freshness lemma into a function›
definition
Fresh :: "('a::at → 'b::pt) → 'b" where "Fresh h = (THE x. ∀a. atom a ♯ h ⟶ h a = x)"
lemma Fresh_apply: fixes h :: "'a::at → 'b::pt" assumes a: "∃a. atom a ♯ (h, h a)" assumes b: "atom a ♯ h" shows"Fresh h = h a" unfolding Fresh_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_apply': fixes h :: "'a::at → 'b::pt" assumes a: "atom a ♯ h""atom a ♯ h a" shows"Fresh h = h a" apply (rule Fresh_apply) apply (auto simp: fresh_Pair intro: a) done
simproc_setup Fresh_simproc ("Fresh (h::'a::at → 'b::pt)") = ‹fn _ => fn ctxt => fn ctrm =>
let
val _ $ h = Thm.term_of ctrm
val atoms = Simplifier.prems_of ctxt
|> map_filter (fn thm => case Thm.prop_of thm of
_ $ 🚫‹fresh _ for 🚫‹atom _ for atm› _› => SOME atm | _ => NONE)
|> distinct (op =)
fun get_thm atm =
let
val goal1 = HOLogic.mk_Trueprop (mk_fresh (mk_atom atm) h)
val goal2 = HOLogic.mk_Trueprop (mk_fresh (mk_atom atm) (h $ atm))
val thm1 = Goal.prove ctxt [] [] goal1 (fn {context = ctxt', ...} => asm_simp_tac ctxt' 1)
val thm2 = Goal.prove ctxt [] [] goal2 (fn {context = ctxt', ...} => asm_simp_tac ctxt' 1)
in
SOME (@{thm Fresh_apply'} OF [thm1, thm2] RS eq_reflection)
end handle ERROR _ => NONE
in
get_first get_thm atoms
end ›
lemma Fresh_eqvt: fixes h :: "'a::at → 'b::pt" assumes a: "∃a. atom a ♯ (h, h a)" shows"p ∙ (Fresh h) = Fresh (p ∙ h)" proof - from a obtain a::"'a::at"where fr: "atom a ♯ h""atom a ♯ h a" by (metis fresh_Pair) thenhave fr_p: "atom (p ∙ a) ♯ (p ∙ h)""atom (p ∙ a) ♯ (p ∙ h) (p ∙ a)" by (metis atom_eqvt fresh_permute_iff eqvt_apply)+ have"p ∙ (Fresh h) = p ∙ (h a)"using fr by simp alsohave"... = (p ∙ h) (p ∙ a)"by simp alsohave"... = Fresh (p ∙ h)"using fr_p by simp finallyshow"p ∙ (Fresh h) = Fresh (p ∙ h)" . qed
lemma Fresh_supports: fixes h :: "'a::at → 'b::pt" assumes a: "∃a. atom a ♯ (h, h a)" shows"(supp h) supports (Fresh h)" apply (simp add: supports_def fresh_def [symmetric]) apply (simp add: Fresh_eqvt [OF a] swap_fresh_fresh) done
notation Fresh (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 ♯ P"using P by (rule obtain_fresh') thenshow"(FRESH x. f (P x)) = f (FRESH x. P x)" by (simp add: pure_fresh) 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‹Automation for creating concrete atom types›
text‹At the moment only single-sort concrete atoms are supported.›
ML_file ‹nominal_atoms.ML›
section‹Automatic equivariance procedure for inductive definitions›
ML_file ‹nominal_eqvt.ML›
end
Messung V0.5 in Prozent
¤ Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.0.147Angebot
(Wie Sie bei der Firma Beratungs- und Dienstleistungen beauftragen können 2026-09-28)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.