(* (C) Copyright Andreas Viktor Hess, DTU, 2015-2018 All Rights Reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *) (* Title: Messages.thy Author: Andreas Viktor Hess, DTU These theories depend on the IsaFoR library v2.27 available at: http://cl2-informatik.uibk.ac.at/rewriting/mercurial.cgi/IsaFoR/file/23ac5f5c26ed Download into the directory IsaFoR and move it to your Isabelle installation or change the path in the imports. *) section {* Theory: Messages *} theory Messages imports Main "~~/src/HOL/Library/Countable_Set" "~~/IsaFoR/thys/Rewriting/Term" (* Path to IsaFoR *) begin subsection {* Term-related definitions *} instance "term" :: (countable, countable) countable by countable_datatype fun subterms::"('a,'b) term \ ('a,'b) terms" where "subterms (Var x) = {Var x}" | "subterms (Fun f X) = {Fun f X} \ (\x \ (set X). subterms x)" definition subtermeq (infix "\" 50) where "t' \ t \ (t' \ subterms t)" definition subterm (infix "\" 50) where "t' \ t \ (t' \ t \ t' \ t)" abbreviation FV where "FV \ vars_term" lemmas FV_simps = term.simps(17,18) definition FV\<^sub>s\<^sub>e\<^sub>t where "FV\<^sub>s\<^sub>e\<^sub>t M \ (\m \ M. FV m)" definition ground where "ground M \ FV\<^sub>s\<^sub>e\<^sub>t M = {}" declare subtermeq_def[simp] declare subterm_def[simp] declare ground_def[simp] declare FV\<^sub>s\<^sub>e\<^sub>t_def[simp] lemma subtermD[dest]: "s \ t \ s \ t" "s \ t \ s \ t" by (induct t) auto lemma subterm_from_supt: "s \ t \ s \ t" proof (induction s rule: supt.induct) case (arg s S f) thus ?case unfolding subterm_def subtermeq_def by (metis (mono_tags, hide_lams) UN_I UnCI insertCI is_FunE is_VarE subterms.simps(1,2) term_not_arg) next case (subt s S t f) thus ?case using supt_not_sym by fastforce qed lemma subtermeq_from_supteq: "s \ t \ s \ t" proof (induction s rule: supteq.induct) case (refl t) thus ?case by (cases t) auto qed auto subsection {* Lemmas concerning subterms and free variables *} lemma in_subterms_refl[simp]: "t \ subterms t" by (induct t rule: subterms.induct) auto lemma subtermI[intro]: "x \ subterms y \ x \ y \ x \ y" by simp lemma subtermI'[intro]: "x \ set X \ x \ Fun f X" by force lemma subtermeqI[intro]: "x \ subterms y \ x \ y" by simp lemma subtermeqI'[intro]: "x = y \ x \ y" using in_subterms_refl by simp lemma subtermeqI''[intro]: "x \ set X \ x \ Fun f X" by force lemma subtermeqD[dest]: "x \ y \ x \ y \ x \ y" by simp lemma subterms_UnionE: assumes "t \ \(subterms ` M)" obtains t' where "t' \ M" "t \ t'" using assms by auto lemma finite_FV[simp]: "finite (FV t)" by (induct t) simp_all lemma finite_FV_set[intro]: "finite M \ finite (FV\<^sub>s\<^sub>e\<^sub>t M)" by auto lemma finite_fun_symbols[simp]: "finite (funs_term t)" by (induct t) simp_all lemma FV_set_mono: "M \ N \ FV\<^sub>s\<^sub>e\<^sub>t M \ FV\<^sub>s\<^sub>e\<^sub>t N" by auto lemma subterms_Union_mono: "M \ N \ \(subterms ` M) \ \(subterms ` N)" by auto lemma inv_set_fset: "finite M \ set (inv set M) = M" unfolding inv_def by (metis (mono_tags) finite_list someI_ex) lemma FV_map_FV_set: "\set (map FV L) = FV\<^sub>s\<^sub>e\<^sub>t (set L)" by (induct L) auto lemma finite_subset_Union: fixes A::"'a set" and f::"'a \ 'b set" assumes "finite (\a \ A. f a)" shows "\B. finite B \ B \ A \ (\b \ B. f b) = (\a \ A. f a)" by (metis assms eq_iff finite_subset_image finite_UnionD Union_image_eq) lemma inv_set_FV: "finite M \ \set (map FV (inv set M)) = FV\<^sub>s\<^sub>e\<^sub>t M" using FV_map_FV_set[of "inv set M"] inv_set_fset by auto lemma FV_Fun_cons: "FV (Fun f (x#X)) = FV x \ FV (Fun f X)" by auto lemma ground_subterm: "FV t = {} \ t' \ t \ FV t' = {}" by (induct t) auto lemma ground_subterm': "FV t = {} \ t' \ t \ FV t' = {}" by (induct t) auto lemma ground_subterm'': "FV t = {} \ t' \ subterms t \ FV t' = {}" by (induct t) auto lemma empty_FV_not_var: "FV t = {} \ t \ Var x" by auto lemma empty_FV_exists_fun: "FV t = {} \ \f X. t = Fun f X" by (cases t) auto lemma vars_iff_subtermeq: "x \ FV t \ Var x \ t" by (induct t) auto lemma vars_iff_subterm_or_eq: "x \ FV t \ Var x \ t \ Var x = t" by (induct t) (auto simp add: vars_iff_subtermeq) lemma no_var_subterm: "\t \ Var v" by auto lemma fun_if_subterm: "t \ u \ \f X. u = Fun f X" by (induct u) simp_all lemma subtermeq_vars_subset: "M \ N \ FV M \ FV N" by (induct N) auto lemma FV_set_subterms_eq[simp]: "FV\<^sub>s\<^sub>e\<^sub>t M = FV\<^sub>s\<^sub>e\<^sub>t (\(subterms ` M))" using subtermeq_vars_subset by force lemma FV_subset: "t \ M \ FV t \ FV\<^sub>s\<^sub>e\<^sub>t M" by auto lemma FV_subset_subterms: "t \ \(subterms ` M) \ FV t \ FV\<^sub>s\<^sub>e\<^sub>t M" using FV_subset FV_set_subterms_eq by metis lemma subterms_finite[simp]: "finite (subterms t)" by (induction rule: subterms.induct) auto lemma subterms_union_finite: "finite M \ finite (\t \ M. subterms t)" by (induction rule: subterms.induct) auto lemma subterms_subset: "t' \ t \ subterms t' \ subterms t" by (induction rule: subterms.induct) auto lemma subset_subterms_Union[simp]: "M \ \(subterms ` M)" by auto lemma in_subterms_Union: "t \ M \ t \ \(subterms ` M)" using subset_subterms_Union by blast lemma in_subterms_subset: "t \ subterms t' \ subterms t \ subterms t'" by (simp add: subterms_subset) lemma in_subterms_subset': "M \ subterms t \ \(subterms ` M) \ subterms t" by (metis SUP_def SUP_least contra_subsetD in_subterms_subset) lemma in_subterms_subset_Union: "t \ \(subterms ` M) \ subterms t \ \(subterms ` M)" using subterms_subset by auto lemma subtermseq_if_subterms: "t' \ t \ t' \ t" by simp lemma subterm_param_split: assumes "t \ Fun f X" shows "\pre x suf. t \ x \ X = pre@x#suf" proof - obtain x where "t \ x" "x \ set X" using assms by auto then obtain pre suf where "X = pre@x#suf" "x \ set pre \ x \ set suf" by (meson split_list_first split_list_last) thus ?thesis using \t \ x\ by auto qed lemma zip_arg_subterm: assumes "(s,t) \ set (zip X Y)" shows "s \ Fun f X" "t \ Fun g Y" proof - from assms have "s \ set X" "t \ set Y" by (meson in_set_zipE)+ thus "s \ Fun f X" "t \ Fun g Y" by blast+ qed lemma zip_arg_subterm_split: assumes "(x,y) \ set (zip X Y)" obtains X' X'' Y' Y'' where "X = X'@x#X''" "Y = Y'@y#Y''" "length X' = length Y'" proof - from assms have "\X' X'' Y' Y''. X = X'@x#X'' \ Y = Y'@y#Y'' \ length X' = length Y'" proof (induction Y arbitrary: X) case (Cons y' Y' X) then obtain x' X' where "X = x'#X'" by (metis empty_iff list.exhaust list.set(1) set_zip_leftD) show ?case proof (cases "(x, y) \ set (zip X' Y')") case False hence "x = x'" "y = y'" using Cons.prems \X = x'#X'\ by auto hence "X = []@x#X' \ y'#Y' = []@y#Y' \ length [] = length []" using \X = x'#X'\ by auto thus ?thesis by blast qed (metis \X = x'#X'\ Cons.IH[of X'] Cons_eq_appendI list.size(4)) qed simp thus ?thesis using that by blast qed lemma zip_arg_index: assumes "(x,y) \ set (zip X Y)" obtains i where "X ! i = x" "Y ! i = y" "i < length X" "i < length Y" proof - obtain X1 X2 Y1 Y2 where "X = X1@x#X2" "Y = Y1@y#Y2" "length X1 = length Y1" using zip_arg_subterm_split[OF assms] by moura thus ?thesis using nth_append_length[of X1 x X2] nth_append_length[of Y1 y Y2] that by simp qed lemma ground_iff_no_vars: "ground M \ (\v. Var v \ (\m \ M. subterms m))" proof assume "ground M" hence "\v. \m \ M. v \ FV m" by simp hence "\v. \m \ M. Var v \ subterms m" by (simp add: vars_iff_subtermeq) thus "(\v. Var v \ (\m \ M. subterms m))" by simp next assume no_vars: "\v. Var v \ (\m \ M. subterms m)" moreover { assume "\ground M" then obtain v and m::"('a,'b) term" where "m \ M" "FV m \ {}" "v \ FV m" unfolding ground_def FV\<^sub>s\<^sub>e\<^sub>t_def by blast hence "Var v \ (subterms m)" by (simp add: vars_iff_subtermeq) hence "\v. Var v \ (\t \ M. subterms t)" using \m \ M\ by auto hence False using no_vars by simp } ultimately show "ground M" by blast qed lemma index_Fun_subterms_subset[simp]: "i < length T \ subterms (T ! i) \ subterms (Fun f T)" by auto lemma index_Fun_FV_subset[simp]: "i < length T \ FV (T ! i) \ FV (Fun f T)" using subtermeq_vars_subset by fastforce lemma subterms_union_ground: assumes "ground M" shows "ground (\t \ M. subterms t)" proof - { fix t assume "t \ M" hence "FV t = {}" using ground_iff_no_vars[of M] \ground M\ by simp hence "\t' \ subterms t. FV t' = {}" using subtermeq_vars_subset[of _ t] by simp hence "ground (subterms t)" by simp } thus ?thesis by simp qed lemma Var_subtermeq: "t \ Var v \ t = Var v" by simp lemma subtermeq_imp_funs_term_subset: "s \ t \ funs_term s \ funs_term t" using supteq_imp_funs_term_subset[OF subtermD(2)] by metis lemma subterms_const: "subterms (Fun f []) = {Fun f []}" by simp lemma subtermeq_refl[iff]: "t \ t" by (induct t rule: subterms.induct) auto lemma subtermeq_trans[trans]: "x \ y \ y \ z \ x \ z" using subterms_subset by auto lemma subtermeq_antisym: assumes "x \ y" "y \ x" shows "x = y" using assms proof (induction x arbitrary: y rule: subterms.induct[case_names Var Fun]) case (Fun f X) { assume "y \ Fun f X" then obtain t::"('a,'b) term" where "t \ set X" "y \ t" using \y \ Fun f X\ by auto hence "Fun f X \ t" using subtermeq_trans[OF \Fun f X \ y\] by simp have "t \ Fun f X" using \t \ set X\ by fastforce hence "t = Fun f X" using Fun.IH[OF \t \ set X\ _ \Fun f X \ t\] by simp have "t \ y" using subtermeq_trans[OF \t \ Fun f X\ \Fun f X \ y\] by simp hence "t = y" using Fun.IH[OF \t \ set X\ _ \y \ t\] by simp have "y = Fun f X" using \t = Fun f X\ \t = y\ by simp hence False using \y \ Fun f X\ by simp } thus ?case by auto qed simp lemma subterms_antisym: "x \ subterms y \ y \ subterms x \ x = y" by (auto simp add: subtermeq_antisym) lemma subterm_trans[trans]: "x \ y \ y \ z \ x \ z" unfolding subterm_def by (meson subtermeq_def subtermeq_trans subterms_antisym) lemma subterm_irrefl: "\t \ t" by simp lemma subterm_asym: "t \ u \ \u \ t" using subterm_irrefl subterm_trans by blast lemma subterm_subtermeq_neq: "\t \ u; u \ v\ \ t \ v" using subtermeq_antisym by auto lemma subtermeq_subterm_neq: "\t \ u; u \ v\ \ t \ v" using subtermeq_antisym by auto lemma subtermeq_subterm_trans: "\t \ u; u \ v\ \ t \ v" by (metis subtermeqD subterm_trans) lemma subterm_subtermeq_trans: "\t \ u; u \ v\ \ t \ v" by (metis subtermeqD subterm_trans) lemma subterm_size_lt: "x \ y \ size x < size y" using not_less_eq size_list_estimation by (induct y, simp, fastforce) lemma in_subterms_eq: "\x \ subterms y; y \ subterms x\ \ subterms x = subterms y" using subterms_antisym by auto lemma Fun_gt_params: "Fun f X \ (\x \ (set X). subterms x)" proof - have "size_list size X < size (Fun f X)" by simp hence "Fun f X \ set X" by (meson less_not_refl size_list_estimation) hence "\x \ set X. Fun f X \ subterms x \ x \ subterms (Fun f X)" by (metis subterms_antisym[of "Fun f X" _]) moreover have "\x \ set X. x \ subterms (Fun f X)" by fastforce ultimately show ?thesis by auto qed lemma params_subterms[simp]: "set X \ subterms (Fun f X)" by auto lemma params_subterms_Union[simp]: "\(subterms ` set X) \ subterms (Fun f X)" by auto lemma Fun_subterm_inside_params: "t \ Fun f X \ t \ (\x \ (set X). subterms x)" using Fun_gt_params by fastforce lemma Fun_param_is_subterm: "x \ set X \ x \ Fun f X" using Fun_subterm_inside_params by fastforce lemma Fun_not_in_param: "x \ set X \ \Fun f X \ x" using Fun_param_is_subterm[THEN subterm_asym] . lemma subterms_singleton: assumes "(\v. t = Var v) \ (\f. t = Fun f [])" shows "subterms t = {t}" using assms by (cases t) auto lemma subtermeq_Var_const: assumes "s \ t" shows "t = Var v \ s = Var v" "t = Fun f [] \ s = Fun f []" using assms by fastforce+ lemma subterms_singleton': assumes "subterms t = {t}" shows "(\v. t = Var v) \ (\f. t = Fun f [])" proof (cases t) case (Fun f T) { fix s S assume "T = s#S" hence "s \ subterms t" using Fun by auto hence "s = t" using assms by auto hence False using Fun_param_is_subterm[of s "s#S" f] \T = s#S\ Fun unfolding subterm_def subtermeq_def by auto } hence "T = []" by (cases T) auto thus ?thesis using Fun by simp qed (simp add: assms) lemma funs_term_subterms_eq: "\t. \(funs_term ` subterms t) = funs_term t" "\A. \(funs_term ` (\(subterms ` A))) = \(funs_term ` A)" proof - show "\t. \(funs_term ` subterms t) = funs_term t" using in_subterms_refl subtermeq_imp_funs_term_subset unfolding subtermeq_def by blast thus "\A. \(funs_term ` (\(subterms ` A))) = \(funs_term ` A)" by force qed lemma poss_cons_param: "i <# p \ poss t \ p \ poss (t |_ )" by (metis append_Empty append_PCons poss_append_poss) lemma poss_is_subtermeq: assumes "p \ poss t" shows "t |_ p \ t" by (fact subtermeq_from_supteq[OF subt_at_imp_supteq[OF assms]]) lemma poss_is_in_subterms: assumes "p \ poss t" shows "t |_ p \ subterms t" using poss_is_subtermeq[OF assms] by auto lemma poss_subtermeq_sup: "p \ poss t \ s \ t |_ p \ s \ t" by (metis subterm_def subtermeq_subterm_trans poss_is_subtermeq) lemma poss_Fun_param: "t \ set T \ \i. i < length T \ Fun f T |_ = t" proof (induction T) case (Cons t' T) thus ?case by (cases "t = t'") auto qed auto end