src/HOL/ex/FinFunPred.thy
changeset 48028 a5377f6d9f14
child 48029 9d9c9069abbc
equal deleted inserted replaced
48013:44de84112a67 48028:a5377f6d9f14
       
     1 (*  Author:     Andreas Lochbihler *)
       
     2 
       
     3 header {*
       
     4   Predicates modelled as FinFuns
       
     5 *}
       
     6 
       
     7 theory FinFunPred imports "~~/src/HOL/Library/FinFun" begin
       
     8 
       
     9 text {* Instantiate FinFun predicates just like predicates *}
       
    10 
       
    11 type_synonym 'a pred\<^isub>f = "'a \<Rightarrow>\<^isub>f bool"
       
    12 
       
    13 instantiation "finfun" :: (type, ord) ord
       
    14 begin
       
    15 
       
    16 definition le_finfun_def [code del]: "f \<le> g \<longleftrightarrow> (\<forall>x. f\<^sub>f x \<le> g\<^sub>f x)"
       
    17 
       
    18 definition [code del]: "(f\<Colon>'a \<Rightarrow>\<^isub>f 'b) < g \<longleftrightarrow> f \<le> g \<and> \<not> f \<ge> g"
       
    19 
       
    20 instance ..
       
    21 
       
    22 lemma le_finfun_code [code]:
       
    23   "f \<le> g \<longleftrightarrow> finfun_All ((\<lambda>(x, y). x \<le> y) \<circ>\<^isub>f (f, g)\<^sup>f)"
       
    24 by(simp add: le_finfun_def finfun_All_All o_def)
       
    25 
       
    26 end
       
    27 
       
    28 instance "finfun" :: (type, preorder) preorder
       
    29   by(intro_classes)(auto simp add: less_finfun_def le_finfun_def intro: order_trans)
       
    30 
       
    31 instance "finfun" :: (type, order) order
       
    32 by(intro_classes)(auto simp add: le_finfun_def order_antisym_conv intro: finfun_ext)
       
    33 
       
    34 instantiation "finfun" :: (type, bot) bot begin
       
    35 definition "bot = finfun_const bot"
       
    36 instance by(intro_classes)(simp add: bot_finfun_def le_finfun_def)
       
    37 end
       
    38 
       
    39 lemma bot_finfun_apply [simp]: "bot\<^sub>f = (\<lambda>_. bot)"
       
    40 by(auto simp add: bot_finfun_def)
       
    41 
       
    42 instantiation "finfun" :: (type, top) top begin
       
    43 definition "top = finfun_const top"
       
    44 instance by(intro_classes)(simp add: top_finfun_def le_finfun_def)
       
    45 end
       
    46 
       
    47 lemma top_finfun_apply [simp]: "top\<^sub>f = (\<lambda>_. top)"
       
    48 by(auto simp add: top_finfun_def)
       
    49 
       
    50 instantiation "finfun" :: (type, inf) inf begin
       
    51 definition [code]: "inf f g = (\<lambda>(x, y). inf x y) \<circ>\<^isub>f (f, g)\<^sup>f"
       
    52 instance ..
       
    53 end
       
    54 
       
    55 lemma inf_finfun_apply [simp]: "(inf f g)\<^sub>f = inf f\<^sub>f g\<^sub>f"
       
    56 by(auto simp add: inf_finfun_def o_def inf_fun_def)
       
    57 
       
    58 instantiation "finfun" :: (type, sup) sup begin
       
    59 definition [code]: "sup f g = (\<lambda>(x, y). sup x y) \<circ>\<^isub>f (f, g)\<^sup>f"
       
    60 instance ..
       
    61 end
       
    62 
       
    63 lemma sup_finfun_apply [simp]: "(sup f g)\<^sub>f = sup f\<^sub>f g\<^sub>f"
       
    64 by(auto simp add: sup_finfun_def o_def sup_fun_def)
       
    65 
       
    66 instance "finfun" :: (type, semilattice_inf) semilattice_inf
       
    67 by(intro_classes)(simp_all add: inf_finfun_def le_finfun_def)
       
    68 
       
    69 instance "finfun" :: (type, semilattice_sup) semilattice_sup
       
    70 by(intro_classes)(simp_all add: sup_finfun_def le_finfun_def)
       
    71 
       
    72 instance "finfun" :: (type, lattice) lattice ..
       
    73 
       
    74 instance "finfun" :: (type, bounded_lattice) bounded_lattice
       
    75 by(intro_classes)
       
    76 
       
    77 instance "finfun" :: (type, distrib_lattice) distrib_lattice
       
    78 by(intro_classes)(simp add: sup_finfun_def inf_finfun_def expand_finfun_eq o_def sup_inf_distrib1)
       
    79 
       
    80 instantiation "finfun" :: (type, minus) minus begin
       
    81 definition "f - g = split (op -) \<circ>\<^isub>f (f, g)\<^sup>f"
       
    82 instance ..
       
    83 end
       
    84 
       
    85 lemma minus_finfun_apply [simp]: "(f - g)\<^sub>f = f\<^sub>f - g\<^sub>f"
       
    86 by(simp add: minus_finfun_def o_def fun_diff_def)
       
    87 
       
    88 instantiation "finfun" :: (type, uminus) uminus begin
       
    89 definition "- A = uminus \<circ>\<^isub>f A"
       
    90 instance ..
       
    91 end
       
    92 
       
    93 lemma uminus_finfun_apply [simp]: "(- g)\<^sub>f = - g\<^sub>f"
       
    94 by(simp add: uminus_finfun_def o_def fun_Compl_def)
       
    95 
       
    96 instance "finfun" :: (type, boolean_algebra) boolean_algebra
       
    97 by(intro_classes)
       
    98   (simp_all add: uminus_finfun_def inf_finfun_def expand_finfun_eq sup_fun_def inf_fun_def fun_Compl_def o_def inf_compl_bot sup_compl_top diff_eq)
       
    99 
       
   100 text {*
       
   101   Replicate predicate operations for FinFuns
       
   102 *}
       
   103 
       
   104 abbreviation finfun_empty :: "'a pred\<^isub>f" ("{}\<^isub>f")
       
   105 where "{}\<^isub>f \<equiv> bot"
       
   106 
       
   107 abbreviation finfun_UNIV :: "'a pred\<^isub>f" 
       
   108 where "finfun_UNIV \<equiv> top"
       
   109 
       
   110 definition finfun_single :: "'a \<Rightarrow> 'a pred\<^isub>f"
       
   111 where [code]: "finfun_single x = finfun_empty(\<^sup>f x := True)"
       
   112 
       
   113 lemma finfun_single_apply [simp]:
       
   114   "(finfun_single x)\<^sub>f y \<longleftrightarrow> x = y"
       
   115 by(simp add: finfun_single_def finfun_upd_apply)
       
   116 
       
   117 lemma [iff]:
       
   118   shows finfun_single_neq_bot: "finfun_single x \<noteq> bot" 
       
   119   and bot_neq_finfun_single: "bot \<noteq> finfun_single x"
       
   120 by(simp_all add: expand_finfun_eq fun_eq_iff)
       
   121 
       
   122 lemma finfun_leI [intro!]: "(!!x. A\<^sub>f x \<Longrightarrow> B\<^sub>f x) \<Longrightarrow> A \<le> B"
       
   123 by(simp add: le_finfun_def)
       
   124 
       
   125 lemma finfun_leD [elim]: "\<lbrakk> A \<le> B; A\<^sub>f x \<rbrakk> \<Longrightarrow> B\<^sub>f x"
       
   126 by(simp add: le_finfun_def)
       
   127 
       
   128 text {* Bounded quantification.
       
   129   Warning: @{text "finfun_Ball"} and @{text "finfun_Ex"} may raise an exception, they should not be used for quickcheck
       
   130 *}
       
   131 
       
   132 definition finfun_Ball_except :: "'a list \<Rightarrow> 'a pred\<^isub>f \<Rightarrow> ('a \<Rightarrow> bool) \<Rightarrow> bool"
       
   133 where [code del]: "finfun_Ball_except xs A P = (\<forall>a. A\<^sub>f a \<longrightarrow> a \<in> set xs \<or> P a)"
       
   134 
       
   135 lemma finfun_Ball_except_const:
       
   136   "finfun_Ball_except xs (\<lambda>\<^isup>f b) P \<longleftrightarrow> \<not> b \<or> set xs = UNIV \<or> FinFun.code_abort (\<lambda>u. finfun_Ball_except xs (\<lambda>\<^isup>f b) P)"
       
   137 by(auto simp add: finfun_Ball_except_def)
       
   138 
       
   139 lemma finfun_Ball_except_const_finfun_UNIV_code [code]:
       
   140   "finfun_Ball_except xs (\<lambda>\<^isup>f b) P \<longleftrightarrow> \<not> b \<or> is_list_UNIV xs \<or> FinFun.code_abort (\<lambda>u. finfun_Ball_except xs (\<lambda>\<^isup>f b) P)"
       
   141 by(auto simp add: finfun_Ball_except_def is_list_UNIV_iff)
       
   142 
       
   143 lemma finfun_Ball_except_update:
       
   144   "finfun_Ball_except xs (A(\<^sup>f a := b)) P = ((a \<in> set xs \<or> (b \<longrightarrow> P a)) \<and> finfun_Ball_except (a # xs) A P)"
       
   145 by(fastforce simp add: finfun_Ball_except_def finfun_upd_apply split: split_if_asm)
       
   146 
       
   147 lemma finfun_Ball_except_update_code [code]:
       
   148   fixes a :: "'a :: card_UNIV"
       
   149   shows "finfun_Ball_except xs (finfun_update_code f a b) P = ((a \<in> set xs \<or> (b \<longrightarrow> P a)) \<and> finfun_Ball_except (a # xs) f P)"
       
   150 by(simp add: finfun_Ball_except_update)
       
   151 
       
   152 definition finfun_Ball :: "'a pred\<^isub>f \<Rightarrow> ('a \<Rightarrow> bool) \<Rightarrow> bool"
       
   153 where [code del]: "finfun_Ball A P = Ball {x. A\<^sub>f x} P"
       
   154 
       
   155 lemma finfun_Ball_code [code]: "finfun_Ball = finfun_Ball_except []"
       
   156 by(auto intro!: ext simp add: finfun_Ball_except_def finfun_Ball_def)
       
   157 
       
   158 
       
   159 definition finfun_Bex_except :: "'a list \<Rightarrow> 'a pred\<^isub>f \<Rightarrow> ('a \<Rightarrow> bool) \<Rightarrow> bool"
       
   160 where [code del]: "finfun_Bex_except xs A P = (\<exists>a. A\<^sub>f a \<and> a \<notin> set xs \<and> P a)"
       
   161 
       
   162 lemma finfun_Bex_except_const:
       
   163   "finfun_Bex_except xs (\<lambda>\<^isup>f b) P \<longleftrightarrow> b \<and> set xs \<noteq> UNIV \<and> FinFun.code_abort (\<lambda>u. finfun_Bex_except xs (\<lambda>\<^isup>f b) P)"
       
   164 by(auto simp add: finfun_Bex_except_def)
       
   165 
       
   166 lemma finfun_Bex_except_const_finfun_UNIV_code [code]:
       
   167   "finfun_Bex_except xs (\<lambda>\<^isup>f b) P \<longleftrightarrow> b \<and> \<not> is_list_UNIV xs \<and> FinFun.code_abort (\<lambda>u. finfun_Bex_except xs (\<lambda>\<^isup>f b) P)"
       
   168 by(auto simp add: finfun_Bex_except_def is_list_UNIV_iff)
       
   169 
       
   170 lemma finfun_Bex_except_update: 
       
   171   "finfun_Bex_except xs (A(\<^sup>f a := b)) P \<longleftrightarrow> (a \<notin> set xs \<and> b \<and> P a) \<or> finfun_Bex_except (a # xs) A P"
       
   172 by(fastforce simp add: finfun_Bex_except_def finfun_upd_apply dest: bspec split: split_if_asm)
       
   173 
       
   174 lemma finfun_Bex_except_update_code [code]:
       
   175   fixes a :: "'a :: card_UNIV"
       
   176   shows "finfun_Bex_except xs (finfun_update_code f a b) P \<longleftrightarrow> ((a \<notin> set xs \<and> b \<and> P a) \<or> finfun_Bex_except (a # xs) f P)"
       
   177 by(simp add: finfun_Bex_except_update)
       
   178 
       
   179 definition finfun_Bex :: "'a pred\<^isub>f \<Rightarrow> ('a \<Rightarrow> bool) \<Rightarrow> bool"
       
   180 where [code del]: "finfun_Bex A P = Bex {x. A\<^sub>f x} P"
       
   181 
       
   182 lemma finfun_Bex_code [code]: "finfun_Bex = finfun_Bex_except []"
       
   183 by(auto intro!: ext simp add: finfun_Bex_except_def finfun_Bex_def)
       
   184 
       
   185 
       
   186 text {* Automatically replace predicate operations by finfun predicate operations where possible *}
       
   187 
       
   188 lemma iso_finfun_le [code_unfold]:
       
   189   "A\<^sub>f \<le> B\<^sub>f \<longleftrightarrow> A \<le> B"
       
   190 by (metis le_finfun_def le_funD le_funI)
       
   191 
       
   192 lemma iso_finfun_less [code_unfold]:
       
   193   "A\<^sub>f < B\<^sub>f \<longleftrightarrow> A < B"
       
   194 by (metis iso_finfun_le less_finfun_def less_fun_def)
       
   195 
       
   196 lemma iso_finfun_eq [code_unfold]:
       
   197   "A\<^sub>f = B\<^sub>f \<longleftrightarrow> A = B"
       
   198 by(simp add: expand_finfun_eq)
       
   199 
       
   200 lemma iso_finfun_sup [code_unfold]:
       
   201   "sup A\<^sub>f B\<^sub>f = (sup A B)\<^sub>f"
       
   202 by(simp)
       
   203 
       
   204 lemma iso_finfun_disj [code_unfold]:
       
   205   "A\<^sub>f x \<or> B\<^sub>f x \<longleftrightarrow> (sup A B)\<^sub>f x"
       
   206 by(simp add: sup_fun_def)
       
   207 
       
   208 lemma iso_finfun_inf [code_unfold]:
       
   209   "inf A\<^sub>f B\<^sub>f = (inf A B)\<^sub>f"
       
   210 by(simp)
       
   211 
       
   212 lemma iso_finfun_conj [code_unfold]:
       
   213   "A\<^sub>f x \<and> B\<^sub>f x \<longleftrightarrow> (inf A B)\<^sub>f x"
       
   214 by(simp add: inf_fun_def)
       
   215 
       
   216 lemma iso_finfun_empty_conv [code_unfold]:
       
   217   "(\<lambda>_. False) = {}\<^isub>f\<^sub>f"
       
   218 by simp
       
   219 
       
   220 lemma iso_finfun_UNIV_conv [code_unfold]:
       
   221   "(\<lambda>_. True) = finfun_UNIV\<^sub>f"
       
   222 by simp
       
   223 
       
   224 lemma iso_finfun_upd [code_unfold]:
       
   225   fixes A :: "'a pred\<^isub>f"
       
   226   shows "A\<^sub>f(x := b) = (A(\<^sup>f x := b))\<^sub>f"
       
   227 by(simp add: fun_eq_iff)
       
   228 
       
   229 lemma iso_finfun_uminus [code_unfold]:
       
   230   fixes A :: "'a pred\<^isub>f"
       
   231   shows "- A\<^sub>f = (- A)\<^sub>f"
       
   232 by(simp)
       
   233 
       
   234 lemma iso_finfun_minus [code_unfold]:
       
   235   fixes A :: "'a pred\<^isub>f"
       
   236   shows "A\<^sub>f - B\<^sub>f = (A - B)\<^sub>f"
       
   237 by(simp)
       
   238 
       
   239 text {*
       
   240   Do not declare the following two theorems as @{text "[code_unfold]"},
       
   241   because this causes quickcheck to fail frequently when bounded quantification is used which raises an exception.
       
   242   For code generation, the same problems occur, but then, no randomly generated FinFun is usually around.
       
   243 *}
       
   244 
       
   245 lemma iso_finfun_Ball_Ball:
       
   246   "(\<forall>x. A\<^sub>f x \<longrightarrow> P x) \<longleftrightarrow> finfun_Ball A P"
       
   247 by(simp add: finfun_Ball_def)
       
   248 
       
   249 lemma iso_finfun_Bex_Bex:
       
   250   "(\<exists>x. A\<^sub>f x \<and> P x) \<longleftrightarrow> finfun_Bex A P"
       
   251 by(simp add: finfun_Bex_def)
       
   252 
       
   253 text {* Test replacement setup *}
       
   254 
       
   255 notepad begin
       
   256 have "inf ((\<lambda>_ :: nat. False)(1 := True, 2 := True)) ((\<lambda>_. True)(3 := False)) \<le> 
       
   257       sup ((\<lambda>_. False)(1 := True, 5 := True)) (- ((\<lambda>_. True)(2 := False, 3 := False)))"
       
   258   by eval
       
   259 end
       
   260 
       
   261 end