Closure.thy
changeset 162 e93760534354
parent 5 074d9a4b2bc9
child 166 7743d2ad71d1
equal deleted inserted replaced
161:a8a442ba0dbf 162:e93760534354
     1 theory "RegSet"
     1 theory Closure
     2   imports "Main" 
     2 imports Myhill_2
     3 begin
     3 begin
     4 
     4 
       
     5 section {* Closure properties of regular languages *}
     5 
     6 
     6 text {* Sequential composition of sets *}
     7 abbreviation
     7 
     8   regular :: "lang \<Rightarrow> bool"
     8 definition
     9 where
     9   lang_seq :: "string set \<Rightarrow> string set \<Rightarrow> string set" ("_ ; _" [100,100] 100)
    10   "regular A \<equiv> \<exists>r::rexp. A = L r"
    10 where 
       
    11   "L1 ; L2 = {s1@s2 | s1 s2. s1 \<in> L1 \<and> s2 \<in> L2}"
       
    12 
    11 
    13 
    12 
    14 section {* Kleene star for sets *}
    13 lemma closure_union[intro]:
       
    14   assumes "regular A" "regular B" 
       
    15   shows "regular (A \<union> B)"
       
    16 proof -
       
    17   from assms obtain r1 r2::rexp where "L r1 = A" "L r2 = B" by auto
       
    18   then have "A \<union> B = L (ALT r1 r2)" by simp
       
    19   then show "regular (A \<union> B)" by blast
       
    20 qed
    15 
    21 
    16 inductive_set
    22 lemma closure_seq[intro]:
    17   Star :: "string set \<Rightarrow> string set" ("_\<star>" [101] 102)
    23   assumes "regular A" "regular B" 
    18   for L :: "string set"
    24   shows "regular (A ;; B)"
    19 where
    25 proof -
    20   start[intro]: "[] \<in> L\<star>"
    26   from assms obtain r1 r2::rexp where "L r1 = A" "L r2 = B" by auto
    21 | step[intro]:  "\<lbrakk>s1 \<in> L; s2 \<in> L\<star>\<rbrakk> \<Longrightarrow> s1 @ s2 \<in> L\<star>"
    27   then have "A ;; B = L (SEQ r1 r2)" by simp
       
    28   then show "regular (A ;; B)" by blast
       
    29 qed
    22 
    30 
       
    31 lemma closure_star[intro]:
       
    32   assumes "regular A"
       
    33   shows "regular (A\<star>)"
       
    34 proof -
       
    35   from assms obtain r::rexp where "L r = A" by auto
       
    36   then have "A\<star> = L (STAR r)" by simp
       
    37   then show "regular (A\<star>)" by blast
       
    38 qed
    23 
    39 
    24 text {* A standard property of star *}
    40 lemma closure_complement[intro]:
       
    41   assumes "regular A"
       
    42   shows "regular (- A)"
       
    43 proof -
       
    44   from assms have "finite (UNIV // \<approx>A)" by (simp add: Myhill_Nerode)
       
    45   then have "finite (UNIV // \<approx>(-A))" by (simp add: str_eq_rel_def)
       
    46   then show "regular (- A)" by (simp add: Myhill_Nerode)
       
    47 qed
    25 
    48 
    26 lemma lang_star_cases:
    49 lemma closure_difference[intro]:
    27   shows "L\<star> =  {[]} \<union> L ; L\<star>"
    50   assumes "regular A" "regular B" 
    28 proof
    51   shows "regular (A - B)"
    29   { fix x
    52 proof -
    30     have "x \<in> L\<star> \<Longrightarrow> x \<in> {[]} \<union> L ; L\<star>"
    53   have "A - B = - (- A \<union> B)" by blast
    31       unfolding lang_seq_def
    54   moreover
    32     by (induct rule: Star.induct) (auto)
    55   have "regular (- (- A \<union> B))" 
    33   }
    56     using assms by blast
    34   then show "L\<star> \<subseteq> {[]} \<union> L ; L\<star>" by auto
    57   ultimately show "regular (A - B)" by simp
    35 next
    58 qed
    36   show "{[]} \<union> L ; L\<star> \<subseteq> L\<star>" 
    59 
    37     unfolding lang_seq_def by auto
    60 lemma closure_intersection[intro]:
       
    61   assumes "regular A" "regular B" 
       
    62   shows "regular (A \<inter> B)"
       
    63 proof -
       
    64   have "A \<inter> B = - (- A \<union> - B)" by blast
       
    65   moreover
       
    66   have "regular (- (- A \<union> - B))" 
       
    67     using assms by blast
       
    68   ultimately show "regular (A \<inter> B)" by simp
    38 qed
    69 qed
    39 
    70 
    40 
    71 
    41 lemma lang_star_cases2:
    72 text {* closure under string reversal *}
    42   shows "[] \<notin> L \<Longrightarrow> L\<star> - {[]} =  L ; L\<star>"
       
    43 by (subst lang_star_cases)
       
    44    (simp add: lang_seq_def)
       
    45 
       
    46 
       
    47 section {* Regular Expressions *}
       
    48 
       
    49 datatype rexp =
       
    50   NULL
       
    51 | EMPTY
       
    52 | CHAR char
       
    53 | SEQ rexp rexp
       
    54 | ALT rexp rexp
       
    55 | STAR rexp
       
    56 
       
    57 
       
    58 section {* Semantics of Regular Expressions *}
       
    59 
    73 
    60 fun
    74 fun
    61   L :: "rexp \<Rightarrow> string set"
    75   Rev :: "rexp \<Rightarrow> rexp"
    62 where
    76 where
    63   "L (NULL) = {}"
    77   "Rev NULL = NULL"
    64 | "L (EMPTY) = {[]}"
    78 | "Rev EMPTY = EMPTY"
    65 | "L (CHAR c) = {[c]}"
    79 | "Rev (CHAR c) = CHAR c"
    66 | "L (SEQ r1 r2) = (L r1) ; (L r2)"
    80 | "Rev (ALT r1 r2) = ALT (Rev r1) (Rev r2)"
    67 | "L (ALT r1 r2) = (L r1) \<union> (L r2)"
    81 | "Rev (SEQ r1 r2) = SEQ (Rev r2) (Rev r1)"
    68 | "L (STAR r) = (L r)\<star>"
    82 | "Rev (STAR r) = STAR (Rev r)"
    69 
    83 
    70 abbreviation
    84 lemma rev_Seq:
    71   CUNIV :: "string set"
    85   "(rev ` A) ;; (rev ` B) = rev ` (B ;; A)"
    72 where
    86 unfolding Seq_def image_def
    73   "CUNIV \<equiv> (\<lambda>x. [x]) ` (UNIV::char set)"
    87 apply(auto)
       
    88 apply(rule_tac x="xb @ xa" in exI)
       
    89 apply(auto)
       
    90 done
    74 
    91 
    75 lemma CUNIV_star_minus:
    92 lemma rev_Star1:
    76   "(CUNIV\<star> - {[c]}) = {[]} \<union> (CUNIV - {[c]}; (CUNIV\<star>))"
    93   assumes a: "s \<in> (rev ` A)\<star>"
    77 apply(subst lang_star_cases)
    94   shows "s \<in> rev ` (A\<star>)"
    78 apply(simp add: lang_seq_def)
    95 using a
    79 oops
    96 proof(induct rule: star_induct)
       
    97   case (step s1 s2)
       
    98   have inj: "inj (rev::string \<Rightarrow> string)" unfolding inj_on_def by auto
       
    99   have "s1 \<in> rev ` A" "s2 \<in> rev ` (A\<star>)" by fact+
       
   100   then obtain x1 x2 where "x1 \<in> A" "x2 \<in> A\<star>" and eqs: "s1 = rev x1" "s2 = rev x2" by auto
       
   101   then have "x1 \<in> A\<star>" "x2 \<in> A\<star>" by (auto intro: star_intro2)
       
   102   then have "x2 @ x1 \<in> A\<star>" by (auto intro: star_intro1)
       
   103   then have "rev (x2 @ x1) \<in> rev ` A\<star>" using inj by (simp only: inj_image_mem_iff)
       
   104   then show "s1 @ s2 \<in>  rev ` A\<star>" using eqs by simp
       
   105 qed (auto)
    80 
   106 
       
   107 lemma rev_Star2:
       
   108   assumes a: "s \<in> A\<star>"
       
   109   shows "rev s \<in> (rev ` A)\<star>"
       
   110 using a
       
   111 proof(induct rule: star_induct)
       
   112   case (step s1 s2)
       
   113   have inj: "inj (rev::string \<Rightarrow> string)" unfolding inj_on_def by auto
       
   114   have "s1 \<in> A"by fact
       
   115   then have "rev s1 \<in> rev ` A" using inj by (simp only: inj_image_mem_iff)
       
   116   then have "rev s1 \<in> (rev ` A)\<star>" by (auto intro: star_intro2)
       
   117   moreover
       
   118   have "rev s2 \<in> (rev ` A)\<star>" by fact
       
   119   ultimately show "rev (s1 @ s2) \<in>  (rev ` A)\<star>" by (auto intro: star_intro1)
       
   120 qed (auto)
    81 
   121 
    82 lemma string_in_CUNIV:
   122 lemma rev_Star:
    83   shows "s \<in> CUNIV\<star>"
   123   "(rev ` A)\<star> = rev ` (A\<star>)"
    84 proof (induct s)
   124 using rev_Star1 rev_Star2 by auto
    85   case Nil
       
    86   show "[] \<in> CUNIV\<star>" by (rule start)
       
    87 next
       
    88   case (Cons c s)
       
    89   have "[c] \<in> CUNIV" by simp
       
    90   moreover
       
    91   have "s \<in> CUNIV\<star>" by fact
       
    92   ultimately have "[c] @ s \<in> CUNIV\<star>" by (rule step)
       
    93   then show "c # s \<in> CUNIV\<star>" by simp
       
    94 qed
       
    95 
   125 
    96 lemma UNIV_CUNIV_star: 
   126 lemma rev_lang:
    97   shows "UNIV = CUNIV\<star>"
   127   "L (Rev r) = rev ` (L r)"
    98 using string_in_CUNIV
   128 by (induct r) (simp_all add: rev_Star rev_Seq image_Un)
    99 by (auto)
       
   100 
   129 
   101 abbreviation 
   130 lemma closure_reversal[intro]:
   102   reg :: "string set => bool"
   131   assumes "regular A"
   103 where
   132   shows "regular (rev ` A)"
   104   "reg L1 \<equiv> (\<exists>r. L r = L1)"
   133 proof -
   105 
   134   from assms obtain r::rexp where "L r = A" by auto
   106 lemma reg_null [intro]:
   135   then have "L (Rev r) = rev ` A" by (simp add: rev_lang)
   107   shows "reg {}"
   136   then show "regular (rev` A)" by blast
   108 by (metis L.simps(1))
       
   109 
       
   110 lemma reg_empty [intro]:
       
   111   shows "reg {[]}"
       
   112 by (metis L.simps(2))
       
   113 
       
   114 lemma reg_star [intro]:
       
   115   shows "reg L1 \<Longrightarrow> reg (L1\<star>)"
       
   116 by (metis L.simps(6))
       
   117 
       
   118 lemma reg_seq [intro]:
       
   119   assumes a: "reg L1" "reg L2"
       
   120   shows "reg (L1 ; L2)"
       
   121 using a
       
   122 by (metis L.simps(4)) 
       
   123 
       
   124 lemma reg_union [intro]:
       
   125   assumes a: "reg L1" "reg L2"
       
   126   shows "reg (L1 \<union> L2)"
       
   127 using a
       
   128 by (metis L.simps(5)) 
       
   129 
       
   130 lemma reg_string [intro]:
       
   131   fixes s::string
       
   132   shows "reg {s}"
       
   133 proof (induct s)
       
   134   case Nil
       
   135   show "reg {[]}" by (rule reg_empty)
       
   136 next
       
   137   case (Cons c s)
       
   138   have "reg {s}" by fact
       
   139   then obtain r where "L r = {s}" by auto
       
   140   then have "L (SEQ (CHAR c) r) = {[c]} ; {s}" by simp
       
   141   also have "\<dots> = {c # s}" by (simp add: lang_seq_def)
       
   142   finally show "reg {c # s}" by blast 
       
   143 qed
       
   144 
       
   145 lemma reg_finite [intro]:
       
   146   assumes a: "finite L1"
       
   147   shows "reg L1"
       
   148 using a
       
   149 proof(induct)
       
   150   case empty
       
   151   show "reg {}" by (rule reg_null)
       
   152 next
       
   153   case (insert s S)
       
   154   have "reg {s}" by (rule reg_string)
       
   155   moreover 
       
   156   have "reg S" by fact
       
   157   ultimately have "reg ({s} \<union> S)" by (rule reg_union)
       
   158   then show "reg (insert s S)" by simp
       
   159 qed
   137 qed
   160   
   138   
   161 lemma reg_cuniv [intro]:
       
   162   shows "reg (CUNIV)"
       
   163 by (rule reg_finite) (auto)
       
   164 
   139 
   165 lemma reg_univ:
   140 end
   166   shows "reg (UNIV::string set)"
       
   167 proof -
       
   168   have "reg CUNIV" by (rule reg_cuniv)
       
   169   then have "reg (CUNIV\<star>)" by (rule reg_star)
       
   170   then show "reg UNIV" by (simp add: UNIV_CUNIV_star)
       
   171 qed
       
   172 
       
   173 lemma reg_finite_subset:
       
   174   assumes a: "finite L1"
       
   175   and     b: "reg L1" "L2 \<subseteq> L1"
       
   176   shows "reg L2"
       
   177 using a b
       
   178 apply(induct arbitrary: L2)
       
   179 apply(simp add: reg_empty)
       
   180 oops
       
   181 
       
   182 
       
   183 lemma reg_not:
       
   184   shows "reg (UNIV - L r)"
       
   185 proof (induct r)
       
   186   case NULL
       
   187   have "reg UNIV" by (rule reg_univ)
       
   188   then show "reg (UNIV - L NULL)" by simp
       
   189 next
       
   190   case EMPTY
       
   191   have "[] \<notin> CUNIV" by auto
       
   192   moreover
       
   193   have "reg (CUNIV; CUNIV\<star>)" by auto
       
   194   ultimately have "reg (CUNIV\<star> - {[]})" 
       
   195     using lang_star_cases2 by simp
       
   196   then show "reg (UNIV - L EMPTY)" by (simp add: UNIV_CUNIV_star)
       
   197 next
       
   198   case (CHAR c)
       
   199   then show "?case"
       
   200     apply(simp)
       
   201    
       
   202 using reg_UNIV
       
   203 apply(simp)
       
   204 apply(simp add: char_star2[symmetric])
       
   205 apply(rule reg_seq)
       
   206 apply(rule reg_cuniv)
       
   207 apply(rule reg_star)
       
   208 apply(rule reg_cuniv)
       
   209 oops
       
   210 
       
   211 
       
   212 
       
   213 end    
       
   214    
       
   215 
       
   216 
       
   217 
       
   218   
       
   219 
       
   220   
       
   221   
       
   222 
       
   223