progs/Matcher2.thy
author Christian Urban <christian.urban@kcl.ac.uk>
Sun, 19 Oct 2025 09:51:35 +0200
changeset 1012 c01dfa3ff177
parent 1011 31e011ce66e3
permissions -rw-r--r--
updated

theory Matcher2
  imports "Main" 
begin



section \<open>Regular Expressions\<close>

datatype rexp =
  ZERO
| ONE
| CH char
| SEQ rexp rexp
| ALT rexp rexp
| STAR rexp

| NOT rexp
| PLUS rexp
| OPT rexp
| NTIMES rexp nat
| BETWEEN rexp nat nat
| UPTO rexp nat


section \<open>Sequential Composition of Sets\<close>

definition
  Seq :: "string set \<Rightarrow> string set \<Rightarrow> string set" ("_ ;; _" [100,100] 100)
where 
  "A ;; B = {s1 @ s2 | s1 s2. s1 \<in> A \<and> s2 \<in> B}"

text \<open>Two Simple Properties about Sequential Composition\<close>

lemma seq_empty [simp]:
  shows "A ;; {[]} = A"
  and   "{[]} ;; A = A"
by (simp_all add: Seq_def)

lemma seq_null [simp]:
  shows "A ;; {} = {}"
  and   "{} ;; A = {}"
by (simp_all add: Seq_def)

lemma seq_union:
  shows "A ;; (B \<union> C) = A ;; B \<union> A ;; C"
  and   "(B \<union> C) ;; A = B ;; A \<union> C ;; A"
by (auto simp add: Seq_def)

lemma seq_Union:
  shows "A ;; (\<Union>x\<in>B. C x) = (\<Union>x\<in>B. A ;; C x)"
by (auto simp add: Seq_def)

lemma seq_empty_in [simp]:
  "[] \<in> A ;; B \<longleftrightarrow> ([] \<in> A \<and> [] \<in> B)"
by (simp add: Seq_def)

lemma seq_assoc: 
  shows "A ;; (B ;; C) = (A ;; B) ;; C" 
apply(auto simp add: Seq_def)
apply(metis append_assoc)
apply(metis)
done


section \<open>Power for Sets\<close>

fun 
  pow :: "string set \<Rightarrow> nat \<Rightarrow> string set" ("_ \<up> _" [101, 102] 101)
where
   "A \<up> 0 = {[]}"
|  "A \<up> (Suc n) = A ;; (A \<up> n)"

lemma pow_empty [simp]:
  shows "[] \<in> A \<up> n \<longleftrightarrow> (n = 0 \<or> [] \<in> A)"
by (induct n) (auto)

lemma pow_plus:
  "A \<up> (n + m) = A \<up> n ;; A \<up> m"
by (induct n) (simp_all add: seq_assoc)

section \<open>Kleene Star for Sets\<close>

inductive_set
  Star :: "string set \<Rightarrow> string set" ("_\<star>" [101] 102)
  for A :: "string set"
where
  start[intro]: "[] \<in> A\<star>"
| step[intro]:  "\<lbrakk>s1 \<in> A; s2 \<in> A\<star>\<rbrakk> \<Longrightarrow> s1 @ s2 \<in> A\<star>"

text \<open>A Standard Property of Star\<close>

lemma star_decomp: 
  assumes a: "c # x \<in> A\<star>" 
  shows "\<exists>a b. x = a @ b \<and> c # a \<in> A \<and> b \<in> A\<star>"
using a 
using a
by (induct x\<equiv>"c # x" rule: Star.induct) 
   (auto simp add: append_eq_Cons_conv)

lemma star_cases:
  shows "A\<star> = {[]} \<union> A ;; A\<star>"
unfolding Seq_def 
by (auto) (metis Star.simps)

lemma Star_in_Pow:
  assumes a: "s \<in> A\<star>"
  shows "\<exists>n. s \<in> A \<up> n"
using a
apply(induct)
apply(auto)
apply(rule_tac x="Suc n" in exI)
apply(auto simp add: Seq_def)
done

lemma Pow_in_Star:
  assumes a: "s \<in> A \<up> n"
  shows "s \<in> A\<star>"
using a
by (induct n arbitrary: s) (auto simp add: Seq_def)


lemma Star_def2: 
  shows "A\<star> = (\<Union>n. A \<up> n)"
using Star_in_Pow Pow_in_Star
by (auto)


section \<open>Semantics of Regular Expressions\<close>
 
fun
  L :: "rexp \<Rightarrow> string set"
where
  "L (ZERO) = {}"
| "L (ONE) = {[]}"
| "L (CH c) = {[c]}"
| "L (SEQ r1 r2) = (L r1) ;; (L r2)"
| "L (ALT r1 r2) = (L r1) \<union> (L r2)"
| "L (STAR r) = (L r)\<star>"
| "L (NOT r) = UNIV - (L r)"
| "L (PLUS r) = (L r) ;; ((L r)\<star>)"
| "L (OPT r) = (L r) \<union> {[]}"
| "L (NTIMES r n) = (L r) \<up> n"
| "L (BETWEEN r n m) = (\<Union>i\<in> {n..m} . ((L r) \<up> i))" 
| "L (UPTO r n) = (\<Union>i\<in> {..n} . ((L r) \<up> i))"

lemma "L (NOT ZERO) = UNIV"
apply(simp)
done

section \<open>The Matcher\<close>

fun
 nullable :: "rexp \<Rightarrow> bool"
where
  "nullable (ZERO) = False"
| "nullable (ONE) = True"
| "nullable (CH c) = False"
| "nullable (ALT r1 r2) = (nullable r1 \<or> nullable r2)"
| "nullable (SEQ r1 r2) = (nullable r1 \<and> nullable r2)"
| "nullable (STAR r) = True"
| "nullable (NOT r) = (\<not>(nullable r))"
| "nullable (PLUS r) = (nullable r)"
| "nullable (OPT r) = True"
| "nullable (NTIMES r n) = (if n = 0 then True else nullable r)"
| "nullable (BETWEEN r n m) = (if m < n then False else (if n = 0 then True else nullable r))"
| "nullable (UPTO r n) = True"


fun der :: "char \<Rightarrow> rexp \<Rightarrow> rexp"
where
  "der c (ZERO) = ZERO"
| "der c (ONE) = ZERO"
| "der c (CH d) = (if c = d then ONE else ZERO)"
| "der c (ALT r1 r2) = ALT (der c r1) (der c r2)"
| "der c (SEQ r1 r2) = ALT (SEQ (der c r1) r2) (if nullable r1 then der c r2 else ZERO)"
| "der c (STAR r) = SEQ (der c r) (STAR r)"
| "der c (NOT r) = NOT(der c r)"
| "der c (PLUS r) = SEQ (der c r) (STAR r)"
| "der c (OPT r) = der c r"
| "der c (NTIMES r n) = (if n = 0 then ZERO else (SEQ (der c r) (NTIMES r (n - 1))))"
| "der c (BETWEEN r n m) = 
        (if m = 0 then ZERO else 
        (if n = 0 then SEQ (der c r) (UPTO r (m - 1))
         else SEQ (der c r) (BETWEEN r (n - 1) (m - 1))))"
| "der c (UPTO r n) = (if n = 0 then ZERO else SEQ (der c r) (UPTO r (n - 1)))"

fun 
 ders :: "string \<Rightarrow> rexp \<Rightarrow> rexp"
where
  "ders [] r = r"
| "ders (c # s) r = ders s (der c r)"

fun
  matcher :: "rexp \<Rightarrow> string \<Rightarrow> bool"
where
  "matcher r s = nullable (ders s r)"


section \<open>Correctness Proof of the Matcher\<close>

lemma nullable_correctness:
  shows "nullable r  \<longleftrightarrow> [] \<in> (L r)"
apply(induct r) 
apply(auto simp add: Seq_def) 
done

section \<open>Left-Quotient of a Set\<close>

definition
  Der :: "char \<Rightarrow> string set \<Rightarrow> string set"
where
  "Der c A \<equiv> {s. [c] @ s \<in> A}"

lemma Der_null [simp]:
  shows "Der c {} = {}"
unfolding Der_def
by auto

lemma Der_empty [simp]:
  shows "Der c {[]} = {}"
unfolding Der_def
by auto

lemma Der_char [simp]:
  shows "Der c {[d]} = (if c = d then {[]} else {})"
unfolding Der_def
by auto

lemma Der_union [simp]:
  shows "Der c (A \<union> B) = Der c A \<union> Der c B"
unfolding Der_def
by auto

lemma Der_insert_nil [simp]:
  shows "Der c (insert [] A) = Der c A"
unfolding Der_def 
by auto 

lemma Der_seq [simp]:
  shows "Der c (A ;; B) = (Der c A) ;; B \<union> (if [] \<in> A then Der c B else {})"
unfolding Der_def Seq_def
by (auto simp add: Cons_eq_append_conv)

lemma Der_star [simp]:
  shows "Der c (A\<star>) = (Der c A) ;; A\<star>"
proof -    
  have "Der c (A\<star>) = Der c ({[]} \<union> A ;; A\<star>)"
    by (simp only: star_cases[symmetric])
  also have "... = Der c (A ;; A\<star>)"
    by (simp only: Der_union Der_empty) (simp)
  also have "... = (Der c A) ;; A\<star> \<union> (if [] \<in> A then Der c (A\<star>) else {})"
    by simp
  also have "... =  (Der c A) ;; A\<star>"
    unfolding Seq_def Der_def
    by (auto dest: star_decomp)
  finally show "Der c (A\<star>) = (Der c A) ;; A\<star>" .
qed

lemma test:
  assumes "[] \<in> A"
  shows "Der c (A \<up> n) \<subseteq> (Der c A) ;; (A \<up> n)"
  using assms
  apply(induct n)
   apply(simp)
  apply(simp)
  apply(auto simp add: Der_def Seq_def)
  apply blast
  by force


lemma Der_ntimes [simp]:
  shows "Der c (A  \<up> (Suc n)) = (Der c A) ;; (A \<up> n)"
proof -    
  have "Der c (A  \<up> (Suc n)) = Der c (A ;; A \<up> n)"
    by(simp)
  also have "... = (Der c A) ;; (A \<up> n) \<union> (if [] \<in> A then Der c (A \<up> n) else {})"
    by simp
  also have "... =  (Der c A) ;; (A \<up> n)"
    using test by force
  finally show "Der c (A  \<up> (Suc n)) = (Der c A) ;; (A \<up> n)" .
qed



lemma Der_UNIV [simp]:
  "Der c (UNIV - A) = UNIV - Der c A"
unfolding Der_def
by (auto)

lemma Der_pow [simp]:
  shows "Der c (A \<up> (Suc n)) = (Der c A) ;; (A \<up> n) \<union> (if [] \<in> A then Der c (A \<up> n) else {})"
unfolding Der_def 
by(auto simp add: Cons_eq_append_conv Seq_def)

lemma concI_if_Nil2: "[] \<in> B \<Longrightarrow> xs \<in> A \<Longrightarrow> xs \<in> A ;; B"
  using Matcher2.Seq_def by auto

lemma Der_pow2:
  shows "Der c (A \<up> n) = (if n = 0 then {} else (Der c A) ;; (A \<up> (n - 1)))"
  apply(induct n arbitrary: A)
  using Der_ntimes by auto


lemma Der_UNION [simp]: 
  shows "Der c (\<Union>x\<in>A. B x) = (\<Union>x\<in>A. Der c (B x))"
  by (auto simp add: Der_def)

lemma if_f:
  shows "f(if B then C else D) = (if B then f(C) else f(D))"
  by simp


lemma der_correctness:
  shows "L (der c r) = Der c (L r)"
proof(induct r)
  case ZERO
  then show ?case by simp
next
  case ONE
  then show ?case by simp
next
  case (CH x)
  then show ?case by simp
next
  case (SEQ r1 r2)
  then show ?case
    by (simp add: nullable_correctness) 
next
  case (ALT r1 r2)
  then show ?case by simp
next
  case (STAR r)
  then show ?case
    by simp 
next
  case (NOT r)
  then show ?case by simp
next
  case (PLUS r)
  then show ?case by simp
next
  case (OPT r)
  then show ?case by simp
next
  case (NTIMES r n)
  then show ?case
    apply(auto simp add: Seq_def)
    using Der_ntimes Matcher2.Seq_def less_iff_Suc_add apply fastforce
    using Der_ntimes Matcher2.Seq_def less_iff_Suc_add by auto
next
  case (BETWEEN r n m)
  then show ?case 
    apply(auto simp add: Seq_def)
    apply (metis (mono_tags, lifting) Der_ntimes Matcher2.Seq_def Suc_pred atLeast0AtMost atMost_iff diff_Suc_Suc
        diff_is_0_eq mem_Collect_eq)
      apply(subst (asm) Der_pow2)
      apply(case_tac xa)
       apply(simp)
      apply(auto simp add: Seq_def)[1]
    apply (metis atMost_iff diff_Suc_1' diff_le_mono)
    apply (metis (mono_tags, lifting) Der_ntimes Matcher2.Seq_def Suc_le_mono Suc_pred atLeastAtMost_iff
        mem_Collect_eq)
    apply(subst (asm) Der_pow2)
      apply(case_tac xa)
       apply(simp)
    apply(auto simp add: Seq_def)[1]
    by force
next
  case (UPTO r x2)
  then show ?case 
    apply(auto simp add: Seq_def)
    apply (metis (mono_tags, lifting) Der_ntimes Matcher2.Seq_def Suc_le_mono Suc_pred atMost_iff
        mem_Collect_eq)
    apply(subst (asm) Der_pow2)
    apply(case_tac xa)
     apply(simp)
    apply(auto simp add: Seq_def)
    by (metis atMost_iff diff_Suc_1' diff_le_mono)
qed

lemma matcher_correctness:
  shows "matcher r s \<longleftrightarrow> s \<in> L r"
by (induct s arbitrary: r)
   (simp_all add: nullable_correctness der_correctness Der_def)

end