thys/FMap.thy
changeset 19 087d82632852
child 20 e04123f4bacc
equal deleted inserted replaced
18:d826899bc424 19:087d82632852
       
     1 theory FMap
       
     2   imports Main "~~/src/HOL/Quotient_Examples/FSet" "~~/src/HOL/Library/DAList"
       
     3 begin
       
     4 
       
     5 subsubsection {* The type of finite maps *}
       
     6 
       
     7 typedef ('a, 'b) fmap  (infixr "f\<rightharpoonup>" 1) = "{x :: 'a \<rightharpoonup> 'b. finite (dom x) }"
       
     8   proof show "empty \<in> {x. finite (dom x)}" by simp qed
       
     9 
       
    10 setup_lifting type_definition_fmap
       
    11 
       
    12 lift_definition fdom :: "'key f\<rightharpoonup> 'value \<Rightarrow> 'key set" is "dom" ..
       
    13 
       
    14 lift_definition fran :: "'key f\<rightharpoonup> 'value \<Rightarrow> 'value set" is "ran" ..
       
    15 
       
    16 lift_definition lookup :: "'key f\<rightharpoonup> 'value \<Rightarrow> 'key \<Rightarrow> 'value option" is "(\<lambda> x. x)" ..
       
    17 
       
    18 abbreviation the_lookup (infix "f!" 55)
       
    19   where "m f! x \<equiv> the (lookup m x)"
       
    20 
       
    21 lift_definition fempty :: "'key f\<rightharpoonup> 'value" ("f\<emptyset>") is Map.empty by simp
       
    22 
       
    23 lemma fempty_fdom[simp]: "fdom f\<emptyset> = {}"
       
    24   by (transfer, auto)
       
    25 
       
    26 lemma fdomIff: "(a : fdom m) = (lookup m a \<noteq> None)"
       
    27  by (transfer, auto)
       
    28 
       
    29 lemma lookup_not_fdom: "x \<notin> fdom m \<Longrightarrow> lookup m x = None"
       
    30   by (auto iff:fdomIff)
       
    31 
       
    32 lemma finite_range:
       
    33   assumes "finite (dom m)"
       
    34   shows "finite (ran m)"
       
    35   apply (rule finite_subset[OF _ finite_imageI[OF assms, of "\<lambda> x . the (m x)"]])
       
    36   by (auto simp add: ran_def dom_def image_def)
       
    37 
       
    38 lemma finite_fdom[simp]: "finite (fdom m)"
       
    39   by transfer
       
    40 
       
    41 lemma finite_fran[simp]: "finite (fran m)"
       
    42   by (transfer, rule finite_range)
       
    43 
       
    44 lemma fmap_eqI[intro]:
       
    45   assumes "fdom a = fdom b"
       
    46   and "\<And> x. x \<in> fdom a \<Longrightarrow> a f! x = b f! x"
       
    47   shows "a = b"
       
    48 using assms
       
    49 proof(transfer)
       
    50   fix a b :: "'a \<rightharpoonup> 'b"
       
    51   assume d: "dom a = dom b"
       
    52   assume eq: "\<And> x. x \<in> dom a \<Longrightarrow> the (a x) = the (b x)"
       
    53   show "a = b"
       
    54   proof
       
    55     fix x
       
    56     show "a x = b x"
       
    57     proof(cases "a x")
       
    58     case None
       
    59       hence "x \<notin> dom a" by (simp add: dom_def)
       
    60       hence "x \<notin> dom b" using d by simp
       
    61       hence " b x = None"  by (simp add: dom_def)
       
    62       thus ?thesis using None by simp
       
    63     next
       
    64     case (Some y)
       
    65       hence d': "x \<in> dom ( a)" by (simp add: dom_def)
       
    66       hence "the ( a x) = the ( b x)" using eq by auto
       
    67       moreover
       
    68       have "x \<in> dom ( b)" using Some d' d by simp
       
    69       then obtain y' where " b x = Some y'" by (auto simp add: dom_def)
       
    70       ultimately
       
    71       show " a x =  b x" using Some by auto
       
    72     qed
       
    73   qed
       
    74 qed
       
    75 
       
    76 subsubsection {* Updates *}
       
    77 
       
    78 lift_definition
       
    79   fmap_upd :: "'key f\<rightharpoonup> 'value \<Rightarrow> 'key \<Rightarrow> 'value \<Rightarrow> 'key f\<rightharpoonup> 'value" ("_'(_ f\<mapsto> _')" [900,900]900)
       
    80   is "\<lambda> m x v. m( x \<mapsto> v)"  by simp
       
    81 
       
    82 lemma fmap_upd_fdom[simp]: "fdom (h (x f\<mapsto> v)) = insert x (fdom h)"
       
    83   by (transfer, auto)
       
    84 
       
    85 lemma the_lookup_fmap_upd[simp]: "lookup (h (x f\<mapsto> v)) x = Some v"
       
    86   by (transfer, auto)
       
    87 
       
    88 lemma the_lookup_fmap_upd_other[simp]: "x' \<noteq> x \<Longrightarrow> lookup (h (x f\<mapsto> v)) x' = lookup h x'"
       
    89   by (transfer, auto)
       
    90 
       
    91 lemma fmap_upd_overwrite[simp]: "f (x f\<mapsto> y) (x f\<mapsto> z) = f (x f\<mapsto> z)"
       
    92   by (transfer, auto) 
       
    93 
       
    94 lemma fmap_upd_twist: "a \<noteq> c \<Longrightarrow> (m(a f\<mapsto> b))(c f\<mapsto> d) = (m(c f\<mapsto> d))(a f\<mapsto> b)"
       
    95   apply (rule fmap_eqI)
       
    96   apply auto[1]
       
    97   apply (case_tac "x = a", auto)
       
    98   apply (case_tac "x = c", auto)
       
    99   done
       
   100 
       
   101 subsubsection {* Restriction *}
       
   102 
       
   103 lift_definition fmap_restr :: "'a set \<Rightarrow> 'a f\<rightharpoonup> 'b \<Rightarrow> 'a f\<rightharpoonup> 'b"
       
   104   is "\<lambda> S m. (if finite S then (restrict_map m S) else empty)" by auto
       
   105 
       
   106 lemma lookup_fmap_restr[simp]: "finite S \<Longrightarrow> x \<in> S \<Longrightarrow> lookup (fmap_restr S m) x = lookup m x"
       
   107   by (transfer, auto)
       
   108 
       
   109 lemma fdom_fmap_restr[simp]: "finite S \<Longrightarrow> fdom (fmap_restr S m) = fdom m \<inter> S"
       
   110   by (transfer, simp)
       
   111 
       
   112 lemma fmap_restr_fmap_restr[simp]:
       
   113  "finite d1 \<Longrightarrow> finite d2 \<Longrightarrow> fmap_restr d1 (fmap_restr d2 x) = fmap_restr (d1 \<inter> d2) x"
       
   114  by (transfer, auto simp add: restrict_map_def)
       
   115 
       
   116 lemma fmap_restr_fmap_restr_subset:
       
   117  "finite d2 \<Longrightarrow> d1 \<subseteq> d2 \<Longrightarrow> fmap_restr d1 (fmap_restr d2 x) = fmap_restr d1 x"
       
   118  by (metis Int_absorb2 finite_subset fmap_restr_fmap_restr)
       
   119 
       
   120 lemma fmap_restr_useless: "finite S \<Longrightarrow> fdom m \<subseteq> S \<Longrightarrow> fmap_restr S m = m"
       
   121   by (rule fmap_eqI, auto)
       
   122 
       
   123 lemma fmap_restr_not_finite:
       
   124   "\<not> finite S \<Longrightarrow> fmap_restr S \<rho> = f\<emptyset>"
       
   125   by (transfer, simp)
       
   126 
       
   127 lemma fmap_restr_fmap_upd: "x \<in> S \<Longrightarrow> finite S \<Longrightarrow> fmap_restr S (m1(x f\<mapsto> v)) = (fmap_restr S m1)(x f\<mapsto> v)"
       
   128   apply (rule fmap_eqI)
       
   129   apply auto[1]
       
   130   apply (case_tac "xa = x")
       
   131   apply auto
       
   132   done
       
   133 
       
   134 subsubsection {* Deleting *}
       
   135 
       
   136 lift_definition fmap_delete :: "'a \<Rightarrow> 'a f\<rightharpoonup> 'b \<Rightarrow> 'a f\<rightharpoonup> 'b"
       
   137   is "\<lambda> x m. m(x := None)" by auto
       
   138 
       
   139 lemma fdom_fmap_delete[simp]:
       
   140   "fdom (fmap_delete x m) = fdom m - {x}"
       
   141   by (transfer, auto)
       
   142 
       
   143 lemma fmap_delete_fmap_upd[simp]:
       
   144   "fmap_delete x (m(x f\<mapsto> v)) = fmap_delete x m"
       
   145   by (transfer, simp)
       
   146 
       
   147 lemma fmap_delete_noop:
       
   148   "x \<notin> fdom m \<Longrightarrow> fmap_delete x m = m"
       
   149   by (transfer, auto)
       
   150 
       
   151 lemma fmap_upd_fmap_delete[simp]: "x \<in> fdom \<Gamma> \<Longrightarrow> (fmap_delete x \<Gamma>)(x f\<mapsto> \<Gamma> f! x) = \<Gamma>"
       
   152   by (transfer, auto)
       
   153 
       
   154 lemma fran_fmap_upd[simp]:
       
   155   "fran (m(x f\<mapsto> v)) = insert v (fran (fmap_delete x m))"
       
   156 by (transfer, auto simp add: ran_def)
       
   157  
       
   158 subsubsection {* Addition (merging) of finite maps *}
       
   159 
       
   160 lift_definition fmap_add :: "'a f\<rightharpoonup> 'b \<Rightarrow> 'a f\<rightharpoonup> 'b \<Rightarrow> 'a f\<rightharpoonup> 'b" (infixl "f++" 100) 
       
   161   is "map_add" by auto
       
   162 
       
   163 lemma fdom_fmap_add[simp]: "fdom (m1 f++ m2) = fdom m1 \<union> fdom m2"
       
   164   by (transfer, auto)
       
   165 
       
   166 lemma lookup_fmap_add1[simp]: "x \<in> fdom m2 \<Longrightarrow> lookup (m1 f++ m2) x = lookup m2 x"
       
   167   by (transfer, auto)
       
   168 
       
   169 lemma lookup_fmap_add2[simp]:  "x \<notin> fdom m2 \<Longrightarrow> lookup (m1 f++ m2) x = lookup m1 x"
       
   170   apply transfer
       
   171   by (metis map_add_dom_app_simps(3))
       
   172 
       
   173 lemma [simp]: "\<rho> f++ f\<emptyset> = \<rho>"
       
   174   by (transfer, auto)
       
   175 
       
   176 lemma fmap_add_overwrite: "fdom m1 \<subseteq> fdom m2 \<Longrightarrow> m1 f++ m2 = m2"
       
   177   apply transfer
       
   178   apply rule
       
   179   apply (case_tac "x \<in> dom m2")
       
   180   apply (auto simp add: map_add_dom_app_simps(1))
       
   181   done
       
   182 
       
   183 lemma fmap_add_upd_swap: 
       
   184   "x \<notin> fdom \<rho>' \<Longrightarrow> \<rho>(x f\<mapsto> z) f++ \<rho>' = (\<rho> f++ \<rho>')(x f\<mapsto> z)"
       
   185   apply transfer
       
   186   by (metis map_add_upd_left)
       
   187 
       
   188 lemma fmap_add_upd: 
       
   189   "\<rho> f++ (\<rho>'(x f\<mapsto> z)) = (\<rho> f++ \<rho>')(x f\<mapsto> z)"
       
   190   apply transfer
       
   191   by (metis map_add_upd)
       
   192 
       
   193 lemma fmap_restr_add: "fmap_restr S (m1 f++ m2) = fmap_restr S m1 f++ fmap_restr S m2"
       
   194   apply (cases "finite S")
       
   195   apply (rule fmap_eqI)
       
   196   apply auto[1]
       
   197   apply (case_tac "x \<in> fdom m2")
       
   198   apply auto
       
   199   apply (simp add: fmap_restr_not_finite)
       
   200   done
       
   201 
       
   202 subsubsection {* Conversion from associative lists *}
       
   203 
       
   204 lift_definition fmap_of :: "('a \<times> 'b) list \<Rightarrow> 'a f\<rightharpoonup> 'b"
       
   205   is map_of by (rule finite_dom_map_of)
       
   206 
       
   207 lemma fmap_of_Nil[simp]: "fmap_of [] = f\<emptyset>"
       
   208  by (transfer, simp)
       
   209 
       
   210 lemma fmap_of_Cons[simp]: "fmap_of (p # l) = (fmap_of l)(fst p f\<mapsto> snd p)" 
       
   211   by (transfer, simp)
       
   212 
       
   213 lemma fmap_of_append[simp]: "fmap_of (l1 @ l2) = fmap_of l2 f++ fmap_of l1"
       
   214   by (transfer, simp)
       
   215 
       
   216 lemma lookup_fmap_of[simp]:
       
   217   "lookup (fmap_of m) x = map_of m x"
       
   218   by (transfer, auto)
       
   219 
       
   220 lemma fmap_delete_fmap_of[simp]:
       
   221   "fmap_delete x (fmap_of m) = fmap_of (AList.delete x m)"
       
   222   by (transfer, metis delete_conv')
       
   223 
       
   224 subsubsection {* Less-than-relation for extending finite maps *}
       
   225 
       
   226 instantiation fmap :: (type,type) order
       
   227 begin
       
   228   definition "\<rho> \<le> \<rho>' = ((fdom \<rho> \<subseteq> fdom \<rho>') \<and> (\<forall>x \<in> fdom \<rho>. lookup \<rho> x = lookup \<rho>' x))"
       
   229   definition "(\<rho>::'a f\<rightharpoonup> 'b) < \<rho>' = (\<rho> \<noteq> \<rho>' \<and> \<rho> \<le> \<rho>')"
       
   230 
       
   231   lemma fmap_less_eqI[intro]:
       
   232     assumes assm1: "fdom \<rho> \<subseteq> fdom \<rho>'"
       
   233       and assm2:  "\<And> x. \<lbrakk> x \<in> fdom \<rho> ; x \<in> fdom \<rho>'  \<rbrakk> \<Longrightarrow> \<rho> f! x = \<rho>' f! x "
       
   234      shows "\<rho> \<le> \<rho>'"
       
   235    unfolding less_eq_fmap_def
       
   236    apply rule
       
   237    apply fact
       
   238    apply rule+
       
   239    apply (frule subsetD[OF `_ \<subseteq> _`])
       
   240    apply (frule  assm2)
       
   241    apply (auto iff: fdomIff)
       
   242    done
       
   243   
       
   244   lemma fmap_less_eqD:
       
   245     assumes "\<rho> \<le> \<rho>'"
       
   246     assumes "x \<in> fdom \<rho>"
       
   247     shows "lookup \<rho> x = lookup \<rho>' x"
       
   248     using assms
       
   249     unfolding less_eq_fmap_def by auto
       
   250   
       
   251   lemma fmap_antisym: assumes  "(x:: 'a f\<rightharpoonup> 'b) \<le> y" and "y \<le> x" shows "x = y "
       
   252   proof(rule fmap_eqI[rule_format])
       
   253       show "fdom x = fdom y" using `x \<le> y` and `y \<le> x` unfolding less_eq_fmap_def by auto
       
   254       
       
   255       fix v
       
   256       assume "v \<in> fdom x"
       
   257       hence "v \<in> fdom y" using `fdom _ = _` by simp
       
   258   
       
   259       thus "x f! v = y f! v"
       
   260         using `x \<le> y` `v \<in> fdom x` unfolding less_eq_fmap_def by simp
       
   261     qed
       
   262   
       
   263   lemma fmap_trans: assumes  "(x:: 'a f\<rightharpoonup> 'b) \<le> y" and "y \<le> z" shows "x \<le> z"
       
   264   proof
       
   265     show "fdom x \<subseteq> fdom z" using `x \<le> y` and `y \<le> z` unfolding less_eq_fmap_def
       
   266       by -(rule order_trans [of _ "fdom y"], auto)
       
   267     
       
   268     fix v
       
   269     assume "v \<in> fdom x" and "v \<in> fdom z"
       
   270     hence "v \<in> fdom y" using `x \<le> y`  unfolding less_eq_fmap_def by auto
       
   271     hence "lookup y v = lookup x v"
       
   272       using `x \<le> y` `v \<in> fdom x` unfolding less_eq_fmap_def by auto
       
   273     moreover
       
   274     have "lookup y v = lookup z v"
       
   275       by (rule fmap_less_eqD[OF `y \<le> z`  `v \<in> fdom y`])
       
   276     ultimately
       
   277     show "x f! v = z f! v" by auto
       
   278   qed
       
   279   
       
   280   instance
       
   281     apply default
       
   282     using fmap_antisym apply (auto simp add: less_fmap_def)[1]
       
   283     apply (auto simp add: less_eq_fmap_def)[1]
       
   284     using fmap_trans apply assumption
       
   285     using fmap_antisym apply assumption
       
   286     done
       
   287 end
       
   288 
       
   289 lemma fmap_less_fdom:
       
   290   "\<rho>1 \<le> \<rho>2 \<Longrightarrow> fdom \<rho>1 \<subseteq> fdom \<rho>2"
       
   291   by (metis less_eq_fmap_def)
       
   292 
       
   293 lemma fmap_less_restrict:
       
   294   "\<rho>1 \<le> \<rho>2 \<longleftrightarrow> \<rho>1 = fmap_restr (fdom \<rho>1) \<rho>2"
       
   295   unfolding less_eq_fmap_def
       
   296   apply transfer
       
   297   apply (auto simp add:restrict_map_def split:option.split_asm)
       
   298   by (metis option.simps(3))+
       
   299 
       
   300 lemma fmap_restr_less:
       
   301   "fmap_restr S \<rho> \<le> \<rho>"
       
   302   unfolding less_eq_fmap_def
       
   303   by (transfer, auto)
       
   304 
       
   305 lemma fmap_upd_less[simp, intro]:
       
   306   "\<rho>1 \<le> \<rho>2 \<Longrightarrow> v1 = v2 \<Longrightarrow> \<rho>1(x f\<mapsto> v1) \<le> \<rho>2(x f\<mapsto> v2)"
       
   307   apply (rule fmap_less_eqI)
       
   308   apply (auto dest: fmap_less_fdom)[1]
       
   309   apply (case_tac "xa = x")
       
   310   apply (auto dest: fmap_less_eqD)
       
   311   done
       
   312 
       
   313 lemma fmap_update_less[simp, intro]:
       
   314   "\<rho>1 \<le> \<rho>1' \<Longrightarrow> \<rho>2 \<le> \<rho>2' \<Longrightarrow>  (fdom \<rho>2' - fdom \<rho>2) \<inter> fdom \<rho>1 = {} \<Longrightarrow> \<rho>1 f++ \<rho>2 \<le> \<rho>1' f++ \<rho>2'"
       
   315   apply (rule fmap_less_eqI)
       
   316   apply (auto dest: fmap_less_fdom)[1]
       
   317   apply (case_tac "x \<in> fdom \<rho>2")
       
   318   apply (auto dest: fmap_less_eqD fmap_less_fdom)
       
   319   apply (metis fmap_less_eqD fmap_less_fdom lookup_fmap_add1 set_mp)
       
   320   by (metis Diff_iff Diff_triv fmap_less_eqD lookup_fmap_add2)
       
   321 
       
   322 lemma fmap_restr_le:
       
   323   assumes "\<rho>1 \<le> \<rho>2"
       
   324   assumes "S1 \<subseteq> S2"
       
   325   assumes [simp]:"finite S2"
       
   326   shows "fmap_restr S1 \<rho>1 \<le> fmap_restr S2 \<rho>2"
       
   327 proof-
       
   328   have [simp]: "finite S1"
       
   329     by (rule finite_subset[OF `S1 \<subseteq> S2` `finite S2`])
       
   330   show ?thesis
       
   331   proof (rule fmap_less_eqI)
       
   332     have "fdom \<rho>1 \<subseteq> fdom \<rho>2"
       
   333       by (metis assms(1) less_eq_fmap_def)
       
   334     thus "fdom (fmap_restr S1 \<rho>1) \<subseteq> fdom (fmap_restr S2 \<rho>2)"
       
   335       using `S1 \<subseteq> S2`
       
   336       by auto
       
   337   next
       
   338     fix x
       
   339     assume "x \<in> fdom (fmap_restr S1 \<rho>1) "
       
   340     hence [simp]:"x \<in> fdom \<rho>1" and [simp]:"x \<in> S1" and [simp]: "x \<in> S2"
       
   341       by (auto intro: set_mp[OF `S1 \<subseteq> S2`])
       
   342     have "\<rho>1 f! x = \<rho>2 f! x"
       
   343       by (metis `x \<in> fdom \<rho>1` assms(1) less_eq_fmap_def)
       
   344     thus "(fmap_restr S1 \<rho>1) f! x = (fmap_restr S2 \<rho>2) f! x"
       
   345       by simp
       
   346   qed
       
   347 qed
       
   348   
       
   349 definition fmapdom_to_list :: "('a :: linorder) f\<rightharpoonup> 'b \<Rightarrow> 'a list"
       
   350 where
       
   351   "fmapdom_to_list f = (THE xs. set xs = fdom f \<and> sorted xs \<and> distinct xs)"
       
   352 
       
   353 definition fmap_to_alist :: "('a :: linorder) f\<rightharpoonup> 'b \<Rightarrow> ('a \<times> 'b) list"
       
   354 where
       
   355   "fmap_to_alist f = [(x, f f! x). x \<leftarrow> fmapdom_to_list f]"
       
   356 
       
   357 
       
   358 end