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)
(uto intro: zero swap)
perm_struct_induct2 assumes assumes zero: "P 0" assumes swapAnd b. [sort_of a = sort_of b; a <noteq S] <Longrightarrow
Tangle_Moves
sp using Sjava.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
_lencen(domain_blockhave.s
(autoproof
lemmaperm_simple_struct_induct2 zero assumes zero " "
>f<oteq b] <Longrightarrow by auto 0 shows by ule_tac p"inp) (auto intro: zero swap plus)
lemma supp_perm_singleton: fixes p::" shows"supp \ubseteq {b} ⟷ proof - { assume "supp[ sic "p = 0" bytruleinduct
}
e_diagram_defjava.lang.StringIndexOutOfBoundsException: Index 61 out of bounds for length 61 qeded
lemma:
java.lang.StringIndexOutOfBoundsException: Index 49 out of bounds for length 17 shows(cup#[])))∘(vert#vert#[])))" proof { assume "using then[>c##)
(usingl_right_tensor apply (auto simp: swap_cancel supp_zero_perm supp_swap apply (simp add: swap_commute) done
java.lang.StringIndexOutOfBoundsException: Index 6 out of bounds for length 3 thenshow"supp \subseteq {a, b} ⟷🚫(enhn mcm s auto sip:spp_ero_prm sppwppi: fpts qed
lemma_e: assumes "(ake_vert_block_def shows proof -
assms" p ⊆ x}" unfolding supp_perm fresh_star_def fresh_def by auto thenshow"p ∙ (?w)) = (b~ (basic [cu) ∘ = c?m) case zero "0\ x = x" by simp next moreovereaeiga(?z" thenhave"a ♯ then show "((a ⇌ b) Longrightarrow ?thesis" qed qed
text ‹codomain_walli#p#]) <> ?ep)=oial(a u, u <>basic [vert, over, vert])› emmatest assumes "(circ (basic (cap[)
bullet proof - fromassms \ x}" unfolding supp_perm fresh_st = make_ve(nat (domain_w(ba (ca#[]))))"
pbullet x = x" proof (induct p rule: perm_struct_induct2) case zero show "0 java.lang.NullPointerException: Cannot invoke "String.equals(Object)" because "brackoff" is null next case (swap a b) thenhave"a ♯ x""b ♯ then shac(b (cap[)))~ ?cc next case (plus p1 p2) have "p1 ∙ x = x" "p2 ∙ x = x" by fact+ then show "(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 then show "p ∙ x = x" proof (induct p rule: perm_struct_induct2) case zero show "0∙ x = x" by simp next case (swap a b) then have "a ♯ x" "b ♯ x" by simp_all then show "(a ⇌ b) ∙ x = x" by (simp add: swap_fresh_fresh) next case (plus p1 p2) have "p1 ∙ x = x" "p2 ∙ x = x" by fact+ then show "(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 then have "∀a ∈ supp x. a ∉ supp (-q + p)" unfolding supp_perm by simp then have "supp x ♯* (-q + p)" unfolding fresh_star_def fresh_def by simp then have "(-q + p) ∙ x = x" by (simp only: supp_perm_eq) then show "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 then show "p ∙ as = as" proof (induct p rule: perm_struct_induct) case zero show "0∙ as = as" by simp next case (swap p a b) then have "a ∉ as" "b ∉ as" "p ∙ as = as" by simp_all then show "((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. \<close>
lemma at_set_avoiding_aux: fixes Xs::" set"
and As::"atom set"
assumes b: "Xs ⊆ As"
and c: "finite As"
shows "∃p. (p ∙ Xs) ∩ As = {} ∧ (supp p) = (Xs ∪ (p ∙ Xs))"
-
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 ∪ supp p)"
using ‹finite As›‹finite Xs›
by (simp add: permute_set_eq_image finite_supp)
then obtain 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)
then have "supp ?q = (supp (x ⇌ y) ∪ supp p)"
by (simp add: supp_plus_perm_eq)
then have "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
ultimately show ?case by blast
qed
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
at_set_avoiding2:
assumes "finite xs"
and "finite (supp c)" "finite (supp x)"
and "xs ♯* x"
shows "∃p. (p ∙ xs) ♯* c ∧ supp x ♯* p"
assms
(erule_tac c="(c, x)" in at_set_avoiding)
(simp add: supp_Pair)
(rule_tac x="p" in exI)
(simp add: fresh_star_Pair)
(rule fresh_star_supp_conv)
(auto simp: fresh_star_def)
at_set_avoiding3:
assumes "finite xs"
and "finite (supp c)" "finite (supp x)"
and "xs ♯* x"
shows "∃p. (p ∙ xs) ♯* c ∧ supp x ♯* p ∧ supp p = xs ∪ (p ∙ xs)"
assms
(erule_tac c="(c, x)" in at_set_avoiding)
(simp add: supp_Pair)
(rule_tac x="p" in exI)
(simp add: fresh_star_Pair)
(rule fresh_star_supp_conv)
(auto simp: fresh_star_def)
at_set_avoiding2_atom:
assumes "finite (supp c)" "finite (supp x)"
and b: "a ♯ x"
shows "∃p. (p ∙ a) ♯ c ∧ supp x ♯* p"
-
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
then show "∃p. (p ∙ a) ♯ c ∧ supp x ♯* p" by blast
‹Renaming permutations›
set_renaming_perm:
assumes b: "finite bs"
shows "∃q. (∀b ∈ bs. q ∙ b = p ∙ b) ∧ supp q ⊆ bs ∪ (p ∙ bs)"
b
(induct)
case empty
have "(∀b ∈ {}. 0 ∙ b = p ∙ b) ∧ supp (0::perm) ⊆ {} ∪ p ∙ {}"
by (simp add: permute_set_def supp_perm)
then show "∃q. (∀b ∈ {}. q ∙ b = p ∙ b) ∧ supp q ⊆ {} ∪ p ∙ {}" by blast
case (insert a bs)
then have " ∃q. (∀b ∈ bs. q ∙ b = p ∙ b) ∧ supp q ⊆ bs ∪ p ∙ bs" by simp
then obtain q where *: "∀b ∈ bs. q ∙ b = p ∙ b" and **: "supp q ⊆ bs ∪ p ∙ bs"
by (metis empty_subsetI insert(3) supp_swap)
{ assume 1: "q ∙ a = p ∙ a"
have "∀b ∈ (insert a bs). q ∙ b = p ∙ b" using 1 * 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
{ assume 2: "q ∙ a ≠ p ∙ a"
define q' where "q' = ((q ∙ a) ⇌ (p ∙ a)) + q"
have "∀b ∈ insert a bs. q' ∙ b = p ∙ b" using 2 * ‹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
then have "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'_def using 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
}
ultimately show "∃q. (∀b ∈ insert a bs. q ∙ b = p ∙ b) ∧ supp q ⊆ insert a bs ∪p ∙ insert a bs"
by blast
set_renaming_perm2:
shows "∃q. (∀b ∈ bs. q ∙ b = p ∙ b) ∧ supp q ⊆ bs ∪ (p ∙ bs)"
-
have "finite (bs ∩ supp p)" by (simp add: finite_supp)
then obtain 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
ultimately have "(∀b ∈ bs. q ∙ b = p ∙ b) ∧ supp q ⊆ bs ∪ (p ∙ bs)" using * by auto
then show "∃q. (∀b ∈ bs. q ∙ b = p ∙ b) ∧ supp q ⊆ bs ∪ (p ∙ bs)" by blast
list_renaming_perm:
shows "∃q. (∀b ∈ set bs. q ∙ b = p ∙ b) ∧ supp q ⊆ set bs ∪ (p ∙ set bs)"
(induct bs)
case (Cons a bs)
then have " ∃q. (∀b ∈ set bs. q ∙ b = p ∙ b) ∧ supp q ⊆ set bs ∪ p ∙ (set bs)" by simp
then obtain q where *: "∀b ∈ set bs. q ∙ b = p ∙ b" and **: "supp q ⊆ set bs ∪ p∙ (set bs)"
by (blast)
{ assume 1: "a ∈ set bs"
have "q ∙ a = p ∙ a" using * 1 by (induct bs) (auto)
then have "∀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
{ assume 2: "a ∉ set bs"
define q' where "q' = ((q ∙ a) ⇌ (p ∙ a)) + q"
have "∀b ∈ set (a # bs). q' ∙ b = p ∙ b"
unfolding q'_def using 2 * ‹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
then have "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'_def using 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
}
ultimately show "∃q. (∀b ∈ set (a # bs). q ∙ b = p ∙ b) ∧ supp q ⊆ set (a # bs) ∪ p ∙ (set (a # bs))"
by blast
case Nil
have "(∀b ∈ set []. 0 ∙ b = p ∙ b) ∧ supp (0::perm) ⊆ set [] ∪ p ∙ set []"
by (simp add: supp_zero_perm)
then show "∃q. (∀b ∈ set []. q ∙ b = p ∙ b) ∧ supp q ⊆ set [] ∪ p ∙ (set [])" by blast
‹Concrete Atoms Types›
‹
Class ‹at_base› allows types containing multiple sorts of atoms.
Class ‹at› only allows types with a single sort. ›
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)"
atom_eqvt [eqvt]
at = at_base +
assumes sort_of_atom_eq [simp]: "sort_of (atom a) = sort_of (atom b)"
sort_ineq [simp]:
assumes "sort_of (atom a) ≠ sort_of (atom b)"
shows "atom a ≠ atom b"
assms by metis
supp_at_base:
fixes a::"'a::at_base"
shows "supp a = {atom a}"
by (simp add: supp_atom [symmetric] supp_def atom_eqvt)
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
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 🍋‹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.99Bemerkung:
(vorverarbeitet am 2026-06-10)
¤
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.