|
(* Copyright (C) 2008 YesLogic Pty. Ltd |
|
* This file is distributed under the GNU General Public License, version 3.0 |
|
* http://www.gnu.org/licenses/gpl-3.0.html |
|
* |
|
* This module is based on a paper by Valentin Antimirov: |
|
* Partial derivatives of regular expressions and finite automaton constructions |
|
* http://citeseer.ist.psu.edu/43569.html |
|
*) |
|
|
|
Require Import Bool. |
|
Require Import List. |
|
Require Import Le. |
|
Require Import Plus. |
|
|
|
(* symbol alphabet *) |
|
|
|
Variable A : Set. |
|
Variable eq_A_dec : forall (a1 a2:A), {a1=a2}+{a1<>a2}. |
|
|
|
(* regular expressions *) |
|
|
|
Inductive regexp : Set := |
|
| Rzero : regexp |
|
| Runit : regexp |
|
| Rsym : A -> regexp |
|
| Ralt : regexp -> regexp -> regexp |
|
| Rcat : regexp -> regexp -> regexp |
|
| Rstar : regexp -> regexp. |
|
|
|
(* |
|
Notation "a + b" := (Ralt a b) (at level 50, left associativity). |
|
Notation "a * b" := (Rcat a b) (at level 40, left associativity). |
|
*) |
|
|
|
Definition eq_regexp_dec (a b:regexp) : {a=b}+{a<>b}. |
|
decide equality ; apply eq_A_dec. |
|
Defined. |
|
|
|
(* matching semantics *) |
|
|
|
Inductive regexp_match : regexp -> list A -> Prop := |
|
| Match_unit : regexp_match Runit nil |
|
| Match_sym : forall (c:A), |
|
regexp_match (Rsym c) (c::nil) |
|
| Match_alt_l : forall (a b:regexp) (l:list A), |
|
regexp_match a l -> |
|
regexp_match (Ralt a b) l |
|
| Match_alt_r : forall (a b:regexp) (l:list A), |
|
regexp_match b l -> |
|
regexp_match (Ralt a b) l |
|
| Match_cat : forall (a b:regexp) (la lb:list A), |
|
regexp_match a la -> |
|
regexp_match b lb -> |
|
regexp_match (Rcat a b) (la ++ lb) |
|
| Match_star_nil : forall (r:regexp), |
|
regexp_match (Rstar r) nil |
|
| Match_star_cons : forall (r:regexp) (l1 l2:list A), |
|
regexp_match r l1 -> |
|
regexp_match (Rstar r) l2 -> |
|
regexp_match (Rstar r) (l1 ++ l2). |
|
|
|
(* nullable expressions can match the empty string *) |
|
|
|
Fixpoint nullable (r:regexp) : bool := |
|
match r with |
|
| Rzero => false |
|
| Runit => true |
|
| Rsym _ => false |
|
| Ralt a b => orb (nullable a) (nullable b) |
|
| Rcat a b => andb (nullable a) (nullable b) |
|
| Rstar a => true |
|
end. |
|
|
|
Lemma matches_nil_nullable : forall (a:regexp), |
|
regexp_match a nil -> nullable a = true. |
|
Proof. |
|
intros a H. |
|
remember (nil:list A) as l. |
|
induction H ; try discriminate Heql ; simpl ; subst ; trivial. |
|
(* Case: Match_alt_l *) |
|
rewrite IHregexp_match ; auto. |
|
(* Case: Match_alt_r *) |
|
rewrite IHregexp_match ; auto. |
|
case (nullable a) ; auto. |
|
(* Case: Match_cat *) |
|
elim (app_eq_nil la lb Heql) ; intros L1 L2. |
|
rewrite IHregexp_match1 ; auto. |
|
Qed. |
|
|
|
Lemma nullable_matches_nil : forall (a:regexp), |
|
nullable a = true -> regexp_match a nil. |
|
Proof. |
|
intros a H. |
|
induction a. |
|
(* Case: Rzero *) |
|
inversion H. |
|
(* Case: Runit *) |
|
apply Match_unit. |
|
(* Case: Rsym *) |
|
inversion H. |
|
(* Case: Ralt *) |
|
simpl in H. |
|
apply orb_prop in H. |
|
elim H ; intro P. |
|
apply Match_alt_l ; auto. |
|
apply Match_alt_r ; auto. |
|
(* Case: Rcat *) |
|
simpl in H. |
|
apply andb_prop in H. |
|
elim H ; intros P1 P2. |
|
rewrite app_nil_end. |
|
apply Match_cat ; auto. |
|
(* Case: Rstar *) |
|
apply Match_star_nil. |
|
Qed. |
|
|
|
(* Brzozowski derivatives of regular expressions *) |
|
|
|
Definition o (r:regexp) : regexp := |
|
if nullable r then Runit else Rzero. |
|
|
|
Fixpoint derivative (x:A) (r:regexp) {struct r} : regexp := |
|
match r with |
|
| Rzero => Rzero |
|
| Runit => Rzero |
|
| Rsym y => if eq_A_dec x y then Runit else Rzero |
|
| Ralt a b => Ralt (derivative x a) (derivative x b) |
|
| Rcat a b => Ralt (Rcat (derivative x a) b) (Rcat (o a) (derivative x b)) |
|
| Rstar a => Rcat (derivative x a) (Rstar a) |
|
end. |
|
|
|
Fixpoint derivative_word (w:list A) (r:regexp) {struct w} : regexp := |
|
match w with |
|
| nil => r |
|
| x::w' => derivative_word w' (derivative x r) |
|
end. |
|
|
|
Theorem derivative_match : forall (r:regexp) (x:A) (l:list A), |
|
regexp_match r (x::l) -> regexp_match (derivative x r) l. |
|
Proof. |
|
intros r x. |
|
induction r ; intros l H. |
|
(* Case: Rzero *) |
|
inversion H. |
|
(* Case: Runit *) |
|
inversion H. |
|
(* Case: Rsym *) |
|
inversion H ; subst ; simpl. |
|
case (eq_A_dec x x) ; intro P. |
|
apply Match_unit. |
|
elim P ; trivial. |
|
(* Case: Ralt *) |
|
inversion H ; subst ; simpl. |
|
apply Match_alt_l ; auto. |
|
apply Match_alt_r ; auto. |
|
(* Case: Rcat *) |
|
inversion H ; subst ; simpl. |
|
induction la. |
|
(* la = nil *) |
|
simpl in H2 ; subst. |
|
apply Match_alt_r. |
|
unfold o. |
|
rewrite matches_nil_nullable ; auto. |
|
replace l with (nil ++ l) ; auto. |
|
apply Match_cat ; auto. |
|
apply Match_unit. |
|
(* la = cons *) |
|
apply Match_alt_l. |
|
rewrite <- app_comm_cons in H2. |
|
injection H2 ; intros ; subst. |
|
apply Match_cat ; auto. |
|
(* Case: Rstar *) |
|
remember (Rstar r) as rs. |
|
remember (x::l) as xl. |
|
induction H ; try discriminate Heqrs ; inversion Heqrs ; subst. |
|
discriminate Heqxl. |
|
induction l1. |
|
auto. |
|
rewrite <- app_comm_cons in Heqxl. |
|
injection Heqxl ; intros ; subst. |
|
simpl. |
|
apply Match_cat ; auto. |
|
Qed. |
|
|
|
(* FIXME new bit *) |
|
|
|
Theorem derivative_match_cat : forall (a b:regexp) (x:A) (l:list A), |
|
(forall la, regexp_match (derivative x a) la -> regexp_match a (x :: la)) -> |
|
(forall lb, regexp_match (derivative x b) lb -> regexp_match b (x :: lb)) -> |
|
regexp_match (derivative x (Rcat a b)) l -> regexp_match (Rcat a b) (x::l). |
|
Proof. |
|
intros a b x l Ha Hb. |
|
simpl ; unfold o. |
|
assert (P:nullable a = true \/ nullable a = false). |
|
case (nullable a) ; [left ; trivial | right ; trivial]. |
|
elim P ; clear P ; intro P ; rewrite P. |
|
(* nullable a = true *) |
|
inversion 1 ; subst. |
|
inversion H3 ; subst. |
|
rewrite app_comm_cons. |
|
apply Match_cat ; auto. |
|
inversion H3 ; subst. |
|
inversion H2 ; subst. |
|
replace (x :: nil ++ lb) with (nil ++ x :: lb) ; auto. |
|
apply Match_cat. |
|
apply nullable_matches_nil ; assumption. |
|
auto. |
|
inversion 1 ; subst. |
|
inversion H3 ; subst. |
|
rewrite app_comm_cons. |
|
apply Match_cat ; auto. |
|
inversion H3 ; inversion H2. |
|
Qed. |
|
|
|
Theorem derivative_match_star : forall (a:regexp) (x:A) (l:list A), |
|
(forall la, regexp_match (derivative x a) la -> regexp_match a (x :: la)) -> |
|
regexp_match (derivative x (Rstar a)) l -> regexp_match (Rstar a) (x::l). |
|
Proof. |
|
intros a x l Ha. |
|
simpl. |
|
intro H1. |
|
inversion H1 ; subst. |
|
rewrite app_comm_cons. |
|
apply Match_star_cons ; auto. |
|
Qed. |
|
|
|
Theorem derivative_match2 : forall (r:regexp) (x:A) (l:list A), |
|
regexp_match (derivative x r) l -> regexp_match r (x::l). |
|
Proof. |
|
induction r ; simpl ; intros. |
|
inversion H. |
|
inversion H. |
|
destruct (eq_A_dec x a). |
|
subst ; inversion H. |
|
constructor. |
|
inversion H. |
|
inversion H ; subst. |
|
apply Match_alt_l ; auto. |
|
apply Match_alt_r ; auto. |
|
apply derivative_match_cat ; auto. |
|
inversion H ; subst. |
|
apply derivative_match_star ; auto. |
|
Qed. |
|
|
|
Definition matches (r:regexp) (w:list A) : bool := |
|
nullable (derivative_word w r). |
|
|
|
Lemma matches_dec1 : forall w r, |
|
matches r w = true -> regexp_match r w. |
|
Proof. |
|
unfold matches. |
|
induction w ; simpl. |
|
apply nullable_matches_nil. |
|
intros r Hn. |
|
apply derivative_match2. |
|
apply IHw. |
|
assumption. |
|
Qed. |
|
|
|
Lemma matches_dec2 : forall w r, |
|
regexp_match r w -> matches r w = true. |
|
Proof. |
|
unfold matches. |
|
induction w ; simpl. |
|
apply matches_nil_nullable. |
|
intros r Hm. |
|
apply IHw. |
|
apply derivative_match. |
|
assumption. |
|
Qed. |
|
|
|
Lemma matches_dec : forall w r, |
|
{regexp_match r w}+{~regexp_match r w}. |
|
Proof. |
|
intros. |
|
assert (P:{matches r w = true}+{matches r w = false}). |
|
case (matches r w) ; [left | right] ; reflexivity. |
|
destruct P. |
|
left ; apply matches_dec1 ; assumption. |
|
right ; red ; intro H. |
|
generalize (matches_dec2 w r H). |
|
rewrite e. |
|
intro P ; discriminate P. |
|
Qed. |
|
|
|
(* equivalence axioms *) |
|
|
|
Inductive equiv_regexp : regexp -> regexp -> Prop := |
|
| Equiv_refl : forall (a:regexp), equiv_regexp a a |
|
| Equiv_symmetric : forall (a b:regexp), |
|
equiv_regexp a b -> equiv_regexp b a |
|
| Equiv_transitive : forall (a b c:regexp), |
|
equiv_regexp a b -> equiv_regexp b c -> equiv_regexp a c |
|
| Equiv_alt_rec : forall (a b c d:regexp), |
|
equiv_regexp a c -> equiv_regexp b d -> equiv_regexp (Ralt a b) (Ralt c d) |
|
| Equiv_cat_rec : forall (a b c d:regexp), |
|
equiv_regexp a c -> equiv_regexp b d -> equiv_regexp (Rcat a b) (Rcat c d) |
|
| Equiv_star_rec : forall (a b:regexp), |
|
equiv_regexp a b -> equiv_regexp (Rstar a) (Rstar b) |
|
(* Axiom 1: a + (b + c) = (a + b) + c *) |
|
| Equiv_alt_distributes : forall (a b c:regexp), equiv_regexp (Ralt a (Ralt b c)) (Ralt (Ralt a b) c) |
|
(* Axiom 2: a + b = b + a *) |
|
| Equiv_alt_symmetric : forall (a b:regexp), equiv_regexp (Ralt a b) (Ralt b a) |
|
(* Axiom 3: a + a = a *) |
|
| Equiv_alt_same : forall (a:regexp), equiv_regexp a (Ralt a a) |
|
(* Axiom 4: a + 0 = a *) |
|
| Equiv_alt_zero_r : forall (a:regexp), equiv_regexp a (Ralt a Rzero) |
|
(* Axiom 5: (a.b).c = a.(b.c) *) |
|
| Equiv_cat_distributes : forall (a b c:regexp), equiv_regexp (Rcat a (Rcat b c)) (Rcat (Rcat a b) c) |
|
(* Axiom 6: a.1 = 1.a = a *) |
|
| Equiv_cat_unit_l : forall (a:regexp), equiv_regexp a (Rcat Runit a) |
|
| Equiv_cat_unit_r : forall (a:regexp), equiv_regexp a (Rcat a Runit) |
|
(* Axiom 7: a.0 = 0.a = 0 *) |
|
| Equiv_cat_zero_l : forall (a:regexp), equiv_regexp Rzero (Rcat Rzero a) |
|
| Equiv_cat_zero_r : forall (a:regexp), equiv_regexp Rzero (Rcat a Rzero) |
|
(* Axiom 8: a.(b + c) = a.b + a.c *) |
|
| Equiv_cat_distributes_l : forall (a b c:regexp), |
|
equiv_regexp (Rcat a (Ralt b c)) (Ralt (Rcat a b) (Rcat a c)) |
|
(* Axiom 9: (a + b).c = a.c + b.c *) |
|
| Equiv_cat_distributes_r : forall (a b c:regexp), |
|
equiv_regexp (Rcat (Ralt a b) c) (Ralt (Rcat a c) (Rcat b c)) |
|
(* Kleene star axioms *) |
|
| Equiv_star_unit : equiv_regexp Runit (Rstar Runit) |
|
| Equiv_star_alt_unit : forall (a:regexp), equiv_regexp (Rstar a) (Rstar (Ralt Runit a)) |
|
| Equiv_star_cat : forall (a:regexp), equiv_regexp (Rstar a) (Ralt Runit (Rcat a (Rstar a))) |
|
| Equiv_star_nested : forall (a:regexp), equiv_regexp (Rstar a) (Rstar (Rstar a)). |
|
|
|
Ltac subst_regexp b := |
|
match goal with |
|
| [ |- (equiv_regexp ?a ?c) ] => apply (Equiv_transitive a b c) |
|
end. |
|
|
|
Lemma Equiv_alt_zero_l : forall (a:regexp), equiv_regexp a (Ralt Rzero a). |
|
Proof. |
|
intro a. |
|
subst_regexp (Ralt a Rzero). |
|
apply Equiv_alt_zero_r. |
|
apply Equiv_alt_symmetric. |
|
Qed. |
|
|
|
Ltac auto_iff := |
|
match goal with |
|
| [ H:(forall l:list A, regexp_match ?a l <-> regexp_match ?b l) |- (regexp_match ?b ?l) ] => |
|
elim (H l) ; intros M1 M2 ; apply M1 ; clear H M1 M2 ; auto ; auto_iff |
|
| [ H:(forall l:list A, regexp_match ?a l <-> regexp_match ?b l) |- (regexp_match ?a ?l) ] => |
|
elim (H l) ; intros M1 M2 ; apply M2 ; clear H M1 M2 ; auto ; auto_iff |
|
end. |
|
|
|
(* equivalent regular expressions match the same strings *) |
|
|
|
Theorem equiv_matches : forall (a b:regexp), |
|
equiv_regexp a b -> (forall l:list A, regexp_match a l <-> regexp_match b l). |
|
Proof. |
|
intros a b H1. |
|
induction H1 ; intros l ; split ; intro H2. |
|
(* Case: Equiv_refl *) |
|
auto. |
|
auto. |
|
(* Case: Equiv_symmetric *) |
|
auto_iff. |
|
auto_iff. |
|
(* Case: Equiv_transitive *) |
|
auto_iff. |
|
auto_iff. |
|
(* Case: Equiv_alt_rec *) |
|
inversion H2. |
|
apply Match_alt_l ; auto_iff. |
|
apply Match_alt_r ; auto_iff. |
|
inversion H2. |
|
apply Match_alt_l ; auto_iff. |
|
apply Match_alt_r ; auto_iff. |
|
(* Case: Equiv_cat_rec *) |
|
inversion H2 ; apply Match_cat ; auto_iff. |
|
inversion H2 ; apply Match_cat ; auto_iff. |
|
(* Case: Equiv_star_rec *) |
|
remember (Rstar a) as ra. |
|
induction H2 ; try discriminate Heqra. |
|
apply Match_star_nil. |
|
apply Match_star_cons. |
|
inversion Heqra ; subst. |
|
auto_iff. |
|
auto. |
|
(* <- *) |
|
remember (Rstar b) as rb. |
|
induction H2 ; try discriminate Heqrb. |
|
apply Match_star_nil. |
|
apply Match_star_cons. |
|
inversion Heqrb ; subst. |
|
auto_iff. |
|
auto. |
|
(* Case: Equiv_alt_distributes *) |
|
inversion H2. |
|
apply Match_alt_l ; apply Match_alt_l ; auto. |
|
inversion H3. |
|
apply Match_alt_l ; apply Match_alt_r ; auto. |
|
apply Match_alt_r ; auto. |
|
(* <- *) |
|
inversion H2. |
|
inversion H3. |
|
apply Match_alt_l ; auto. |
|
apply Match_alt_r ; apply Match_alt_l ; auto. |
|
apply Match_alt_r ; apply Match_alt_r ; auto. |
|
(* Case: Equiv_alt_symmetric *) |
|
inversion H2. |
|
apply Match_alt_r ; auto. |
|
apply Match_alt_l ; auto. |
|
(* <- *) |
|
inversion H2. |
|
apply Match_alt_r ; auto. |
|
apply Match_alt_l ; auto. |
|
(* Case: Equiv_alt_same *) |
|
apply Match_alt_l ; auto. |
|
(* <- *) |
|
inversion H2 ; auto. |
|
(* Case: Equiv_alt_zero_r *) |
|
apply Match_alt_l ; auto. |
|
(* <- *) |
|
inversion H2 ; auto. |
|
inversion H3. |
|
(* Case: Equiv_cat_distributes *) |
|
inversion H2. |
|
inversion H4. |
|
rewrite <- app_ass. |
|
apply Match_cat. |
|
apply Match_cat ; auto. |
|
auto. |
|
(* <- *) |
|
inversion H2. |
|
inversion H1. |
|
rewrite app_ass. |
|
apply Match_cat ; auto. |
|
apply Match_cat ; auto. |
|
(* Case: Equiv_cat_unit_l *) |
|
replace l with (nil ++ l) ; auto. |
|
apply Match_cat ; auto ; apply Match_unit. |
|
(* <- *) |
|
inversion H2. |
|
inversion H1. |
|
simpl ; auto. |
|
(* Case: Equiv_cat_unit_r *) |
|
rewrite app_nil_end. |
|
apply Match_cat ; auto ; apply Match_unit. |
|
(* <- *) |
|
inversion H2. |
|
inversion H4. |
|
rewrite <- app_nil_end. |
|
auto. |
|
(* Case: Equiv_cat_zero_l *) |
|
inversion H2. |
|
(* <- *) |
|
inversion H2. |
|
inversion H1. |
|
(* Case: Equiv_cat_zero_r *) |
|
inversion H2. |
|
(* <- *) |
|
inversion H2. |
|
inversion H4. |
|
(* Case: Equiv_cat_distributes_l *) |
|
inversion H2. |
|
inversion H4. |
|
apply Match_alt_l ; apply Match_cat ; auto. |
|
apply Match_alt_r ; apply Match_cat ; auto. |
|
(* <- *) |
|
inversion H2. |
|
inversion H3. |
|
apply Match_cat ; auto. |
|
apply Match_alt_l ; auto. |
|
inversion H3. |
|
apply Match_cat ; auto. |
|
apply Match_alt_r ; auto. |
|
(* Case: Equiv_cat_distributes_r *) |
|
inversion H2. |
|
inversion H1. |
|
apply Match_alt_l ; apply Match_cat ; auto. |
|
apply Match_alt_r ; apply Match_cat ; auto. |
|
(* <- *) |
|
inversion H2. |
|
inversion H3. |
|
apply Match_cat ; auto. |
|
apply Match_alt_l ; auto. |
|
inversion H3. |
|
apply Match_cat ; auto. |
|
apply Match_alt_r ; auto. |
|
(* Case: Equiv_star_unit *) |
|
inversion H2. |
|
apply Match_star_nil. |
|
(* <- *) |
|
remember (Rstar Runit) as ru. |
|
induction H2 ; try discriminate Heqru. |
|
apply Match_unit. |
|
inversion Heqru ; subst. |
|
inversion H2_. |
|
simpl ; auto. |
|
(* Case: Equiv_star_alt_unit *) |
|
remember (Rstar a) as ra. |
|
induction H2 ; try discriminate Heqra. |
|
apply Match_star_nil. |
|
apply Match_star_cons. |
|
inversion Heqra ; subst. |
|
apply Match_alt_r ; auto. |
|
auto. |
|
(* <- *) |
|
remember (Rstar (Ralt Runit a)) as ra. |
|
induction H2 ; try discriminate Heqra. |
|
apply Match_star_nil. |
|
inversion Heqra ; subst. |
|
clear IHregexp_match1. |
|
inversion H2_. |
|
inversion H2. |
|
simpl ; auto. |
|
apply Match_star_cons ; auto. |
|
(* Case: Equiv_star_cat *) |
|
inversion H2. |
|
apply Match_alt_l ; apply Match_unit. |
|
apply Match_alt_r ; apply Match_cat ; auto. |
|
(* <- *) |
|
inversion H2. |
|
inversion H3. |
|
apply Match_star_nil. |
|
inversion H3. |
|
apply Match_star_cons ; auto. |
|
(* Case: Equiv_star_nested *) |
|
rewrite app_nil_end. |
|
apply Match_star_cons ; auto || apply Match_star_nil. |
|
(* <- *) |
|
remember (Rstar (Rstar a)) as rra. |
|
induction H2 ; try discriminate Heqrra. |
|
apply Match_star_nil. |
|
inversion Heqrra ; subst. |
|
clear IHregexp_match1. |
|
remember (Rstar a) as ra. |
|
induction H2_ ; try discriminate Heqra. |
|
simpl ; auto. |
|
rewrite app_ass. |
|
apply Match_star_cons ; auto. |
|
Qed. |
|
|
|
Definition setreg := list regexp. |
|
|
|
Fixpoint p (r:regexp) : setreg := |
|
match r with |
|
| Rzero => nil |
|
| Ralt a b => p a ++ p b |
|
| _ => r :: nil |
|
end. |
|
|
|
Fixpoint sigma (l:list regexp) : regexp := |
|
match l with |
|
| nil => Rzero |
|
| r::l' => Ralt r (sigma l') |
|
end. |
|
|
|
Record mono : Set := Mono { mono_letter : A; mono_term : list regexp }. |
|
|
|
Definition lin := list mono. |
|
|
|
Definition lcat0 (b:list regexp) (m:mono) : mono := |
|
match m with |
|
| Mono x p => Mono x (p ++ b) |
|
end. |
|
|
|
Definition lcat (l:lin) (b:regexp) : lin := |
|
match b with |
|
| Rzero => nil |
|
| Runit => l |
|
| _ => map (lcat0 (b::nil)) l |
|
end. |
|
|
|
Fixpoint lf (r:regexp) : lin := |
|
match r with |
|
| Rzero => nil |
|
| Runit => nil |
|
| Rsym x => (Mono x nil) :: nil |
|
| Ralt a b => (lf a) ++ (lf b) |
|
| Rcat a b => (lcat (lf a) b) ++ (if nullable a then lf b else nil) |
|
| Rstar a => lcat (lf a) (Rstar a) |
|
end. |
|
|
|
Definition llcat (l:lin) (b:list regexp) : lin := map (lcat0 b) l. |
|
|
|
Fixpoint llf (l:list regexp) : lin := |
|
match l with |
|
| nil => nil |
|
| a::l' => (llcat (lf a) l') ++ (if nullable a then llf l' else nil) |
|
end. |
|
|
|
Fixpoint fold_cat (l:list regexp) : regexp := |
|
match l with |
|
| nil => Runit |
|
| a::l' => Rcat a (fold_cat l') |
|
end. |
|
|
|
Definition unpack (m:mono) : regexp := |
|
match m with |
|
| Mono x l => Rcat (Rsym x) (fold_cat l) |
|
end. |
|
|
|
Definition sigma_lin (l:lin) : regexp := |
|
sigma (map unpack l). |
|
|
|
Definition choose (x':A) (m:mono) : bool := |
|
match m with |
|
| Mono x p => |
|
if eq_A_dec x' x then true else false |
|
end. |
|
|
|
Definition delta (x:A) (t:regexp) : list regexp := |
|
map fold_cat (map mono_term (filter (choose x) (lf t))). |
|
|
|
Fixpoint condense (l:list (list regexp)) : list regexp := |
|
match l with |
|
| nil => nil |
|
| x::l' => x ++ condense l' |
|
end. |
|
|
|
Definition delta_set (x:A) (r:list regexp) : list regexp := |
|
condense (map (delta x) r). |
|
|
|
Fixpoint delta_word (w:list A) (t:regexp) {struct w} : list regexp := |
|
match w with |
|
| nil => nil |
|
| x::w' => delta_set x (delta_word w' t) |
|
end. |
|
|
|
Fixpoint cat_star_occurs (t:regexp) : nat := |
|
match t with |
|
| Rzero => 0 |
|
| Runit => 0 |
|
| Rsym _ => 0 |
|
| Ralt a b => cat_star_occurs a + cat_star_occurs b |
|
| Rcat a b => cat_star_occurs a + cat_star_occurs b + 1 |
|
| Rstar a => cat_star_occurs a + 1 |
|
end. |
|
|
|
Fixpoint alphabetic_width (t:regexp) : nat := |
|
match t with |
|
| Rzero => 0 |
|
| Runit => 0 |
|
| Rsym _ => 1 |
|
| Ralt a b => alphabetic_width a + alphabetic_width b |
|
| Rcat a b => alphabetic_width a + alphabetic_width b |
|
| Rstar a => alphabetic_width a |
|
end. |
|
|
|
Ltac simplify_regexp_step r := |
|
let simplify_alt_step r := |
|
match r with |
|
| Ralt ?a ?a => a |
|
| Ralt Rzero ?a => a |
|
| Ralt ?a Rzero => a |
|
| Ralt ?a ?b => let a' := simplify_regexp_step a in constr: (Ralt a' b) |
|
| Ralt ?a ?b => let b' := simplify_regexp_step b in constr: (Ralt a b') |
|
end in |
|
let simplify_cat_step r := |
|
match r with |
|
| Rcat Rzero _ => Rzero |
|
| Rcat _ Rzero => Rzero |
|
| Rcat Runit ?a => a |
|
| Rcat ?a Runit => a |
|
| Rcat ?a ?b => let a' := simplify_regexp_step a in constr: (Rcat a' b) |
|
| Rcat ?a ?b => let b' := simplify_regexp_step b in constr: (Rcat a b') |
|
end in |
|
let simplify_star_step r := |
|
match r with |
|
| Rzero => Runit |
|
| Runit => Runit |
|
| Rstar ?a => constr: (Rstar a) |
|
| ?a => let a' := simplify_regexp_step a in constr: (Rstar a') |
|
end in |
|
match r with |
|
| Ralt ?a ?b => simplify_alt_step (Ralt a b) |
|
| Rcat ?a ?b => simplify_cat_step (Rcat a b) |
|
| Rstar ?a => simplify_star_step a |
|
end. |
|
|
|
Ltac show_equiv_done := |
|
match goal with |
|
| [ _:(equiv_regexp ?a ?b) |- (equiv_regexp ?a ?b) ] => auto |
|
| [ |- (equiv_regexp ?a ?a) ] => apply Equiv_refl |
|
| [ |- (equiv_regexp ?a (Ralt ?a ?a)) ] => apply Equiv_alt_same |
|
| [ |- (equiv_regexp (Ralt ?a ?b) (Ralt ?b ?a)) ] => apply Equiv_alt_symmetric |
|
| [ |- (equiv_regexp (Ralt ?a (Ralt ?b ?c)) (Ralt (Ralt ?a ?b) ?c)) ] => apply Equiv_alt_distributes |
|
| [ |- (equiv_regexp ?a (Ralt Rzero ?a)) ] => apply Equiv_alt_zero_l |
|
| [ |- (equiv_regexp ?a (Ralt ?a Rzero)) ] => apply Equiv_alt_zero_r |
|
| [ |- (equiv_regexp (Rcat ?a (Rcat ?b ?c)) (Rcat (Rcat ?a ?b) ?c)) ] => apply Equiv_cat_distributes |
|
| [ |- (equiv_regexp Rzero (Rcat Rzero ?a)) ] => apply Equiv_cat_zero_l |
|
| [ |- (equiv_regexp Rzero (Rcat ?a Rzero)) ] => apply Equiv_cat_zero_r |
|
| [ |- (equiv_regexp ?a (Rcat Runit ?a)) ] => apply Equiv_cat_unit_l |
|
| [ |- (equiv_regexp ?a (Rcat ?a Runit)) ] => apply Equiv_cat_unit_r |
|
| [ |- (equiv_regexp (Rcat ?a (Rcat ?b ?c)) (Rcat (Rcat ?a ?b) ?c)) ] => apply Equiv_cat_distributes |
|
| [ |- (equiv_regexp (Rcat ?a (Ralt ?b ?c)) (Ralt (Rcat ?a ?b) (Rcat ?a ?c))) ] => apply Equiv_cat_distributes_l |
|
| [ |- (equiv_regexp (Rcat (Ralt ?a ?b) ?c) (Ralt (Rcat ?a ?c) (Rcat ?b ?c))) ] => apply Equiv_cat_distributes_r |
|
| [ |- (equiv_regexp (Rstar ?a) (Rstar (Ralt Runit ?a))) ] => apply Equiv_star_alt_unit |
|
end. |
|
|
|
Ltac show_equiv_step := |
|
match goal with |
|
| [ |- (equiv_regexp (Ralt ?a ?b) (Ralt ?c ?d)) ] => apply Equiv_alt_rec |
|
| [ |- (equiv_regexp (Rcat ?a ?b) (Rcat ?c ?d)) ] => apply Equiv_cat_rec |
|
| [ |- (equiv_regexp (Rstar ?a) (Rstar ?b)) ] => apply Equiv_star_rec |
|
| [ |- (equiv_regexp ?a ?b) ] => let b' := simplify_regexp_step b in subst_regexp b' |
|
end. |
|
|
|
Ltac show_equiv := |
|
(show_equiv_done || (apply Equiv_symmetric ; show_equiv_done)) || |
|
(show_equiv_step ; show_equiv) || (apply Equiv_symmetric ; show_equiv_step ; show_equiv). |
|
|
|
Ltac alt_flip r := |
|
match r with |
|
| Ralt ?a ?b => constr: (Ralt b a) |
|
end. |
|
|
|
Ltac alt_distribute_l r := |
|
match r with |
|
| Ralt ?a (Ralt ?b ?c) => constr: (Ralt (Ralt a b) c) |
|
end. |
|
|
|
Ltac alt_distribute_r r := |
|
match r with |
|
| Ralt (Ralt ?a ?b) ?c => constr: (Ralt a (Ralt b c)) |
|
end. |
|
|
|
Ltac cat_distribute_l r := |
|
match r with |
|
| Rcat ?a (Ralt ?b ?c) => constr: (Ralt (Rcat a b) (Rcat a c)) |
|
| Rcat ?a (Rcat ?b ?c) => constr: (Rcat (Rcat a b) c) |
|
end. |
|
|
|
Ltac cat_distribute_r r := |
|
match r with |
|
| Rcat (Ralt ?a ?b) ?c => constr: (Ralt (Rcat a c) (Rcat b c)) |
|
| Rcat (Rcat ?a ?b) ?c => constr: (Rcat a (Rcat b c)) |
|
end. |
|
|
|
Ltac left_branch t r := |
|
match r with |
|
| Ralt ?a ?b => let a' := t a in constr: (Ralt a' b) |
|
| Rcat ?a ?b => let a' := t a in constr: (Rcat a' b) |
|
| Rstar ?a => let a' := t a in constr: (Rstar a') |
|
end. |
|
|
|
Ltac right_branch t := fun r => |
|
match r with |
|
| Ralt ?a ?b => let b' := t b in constr: (Ralt a b') |
|
| Rcat ?a ?b => let b' := t b in constr: (Rcat a b') |
|
end. |
|
|
|
Ltac apply_tac t := |
|
match goal with |
|
| [ |- (equiv_regexp ?a ?b) ] => let b' := t b in subst_regexp b' ; show_equiv || idtac |
|
end. |
|
|
|
Ltac apply_tac_left t := |
|
match goal with |
|
| [ |- (equiv_regexp ?a ?b) ] => |
|
let b' := left_branch t b in subst_regexp b' ; show_equiv || idtac |
|
end. |
|
|
|
Ltac apply_tac_right t := |
|
match goal with |
|
| [ |- (equiv_regexp ?a ?b) ] => |
|
let b' := right_branch t b in subst_regexp b' ; show_equiv || idtac |
|
end. |
|
|
|
Lemma o_alt_equiv : forall (a b:regexp), equiv_regexp (o (Ralt a b)) (Ralt (o a) (o b)). |
|
Proof. |
|
intros a b. |
|
unfold o ; simpl. |
|
case (nullable a) ; case (nullable b) ; simpl ; show_equiv. |
|
Qed. |
|
|
|
Lemma o_cat_equiv : forall (a b:regexp), equiv_regexp (o (Rcat a b)) (Rcat (o a) (o b)). |
|
Proof. |
|
intros a b. |
|
unfold o ; simpl. |
|
case (nullable a) ; case (nullable b) ; simpl ; show_equiv. |
|
Qed. |
|
|
|
Lemma sigma_app_equiv : forall (la lb:list regexp), |
|
equiv_regexp (sigma (la ++ lb)) (Ralt (sigma la) (sigma lb)). |
|
Proof. |
|
intros la lb. |
|
induction la ; simpl. |
|
apply Equiv_alt_zero_l. |
|
apply_tac alt_distribute_r. |
|
Qed. |
|
|
|
Lemma sigma_lin_app_equiv : forall (la lb:lin), |
|
equiv_regexp (sigma_lin (la ++ lb)) (Ralt (sigma_lin la) (sigma_lin lb)). |
|
Proof. |
|
intros la lb. |
|
unfold sigma_lin. |
|
rewrite map_app. |
|
apply sigma_app_equiv. |
|
Qed. |
|
|
|
Lemma setreg_equiv_regexp : forall (a:regexp), |
|
equiv_regexp a (sigma (p a)). |
|
Proof. |
|
induction a ; simpl ; show_equiv || idtac. |
|
subst_regexp (Ralt (sigma (p a1)) (sigma (p a2))). |
|
show_equiv. |
|
apply Equiv_symmetric. |
|
apply sigma_app_equiv. |
|
Qed. |
|
|
|
Lemma fold_cat_equiv : forall (l:list regexp) (a:regexp), |
|
equiv_regexp (fold_cat (l ++ a::nil)) (Rcat (fold_cat l) a). |
|
Proof. |
|
intros l a. |
|
induction l ; simpl. |
|
subst_regexp a ; show_equiv. |
|
apply_tac cat_distribute_r. |
|
Qed. |
|
|
|
Lemma fold_cat_app_equiv : forall (la lb:list regexp), |
|
equiv_regexp (fold_cat (la ++ lb)) (Rcat (fold_cat la) (fold_cat lb)). |
|
Proof. |
|
intros la lb. |
|
induction la ; simpl ; try show_equiv. |
|
apply_tac cat_distribute_r. |
|
Qed. |
|
|
|
Lemma lcat_cases : forall (a:regexp), |
|
a = Rzero \/ a = Runit \/ a <> Rzero /\ a <> Runit. |
|
Proof. |
|
intro a. |
|
case a ; auto ; right ; right ; split ; discriminate. |
|
Qed. |
|
|
|
Lemma map_lcat0 : forall (l:lin) (b:regexp), |
|
b <> Rzero -> b <> Runit -> map (lcat0 (b::nil)) l = lcat l b. |
|
Proof. |
|
intros a b. |
|
induction b ; intros H1 H2 ; auto. |
|
elim H1 ; trivial. |
|
elim H2 ; trivial. |
|
Qed. |
|
|
|
Lemma lcat0_nil : forall (m:mono), |
|
lcat0 nil m = m. |
|
Proof. |
|
intro m. |
|
case m ; intros ml mt. |
|
simpl ; rewrite <- app_nil_end ; auto. |
|
Qed. |
|
|
|
Lemma lcat_nil : forall (b:regexp), |
|
lcat nil b = nil. |
|
Proof. |
|
intro b ; case b ; auto. |
|
Qed. |
|
|
|
Lemma llcat_nil : forall (l:lin), |
|
llcat l nil = l. |
|
Proof. |
|
induction l ; simpl ; auto. |
|
rewrite IHl. |
|
rewrite lcat0_nil ; auto. |
|
Qed. |
|
|
|
Lemma lcat_app : forall (la1 la2:lin) (b:regexp), |
|
lcat (la1 ++ la2) b = lcat la1 b ++ lcat la2 b. |
|
Proof. |
|
intros la1 la2 b. |
|
elim (lcat_cases b). |
|
(* b = Rzero *) |
|
intro P ; subst ; auto. |
|
intros [ P | [ P1 P2 ] ]. |
|
(* b = Runit *) |
|
subst ; auto. |
|
(* b <> Rzero /\ b <> Runit *) |
|
rewrite <- map_lcat0 ; auto. |
|
rewrite map_app. |
|
rewrite map_lcat0 ; auto. |
|
rewrite map_lcat0 ; auto. |
|
Qed. |
|
|
|
Lemma lcat_cons : forall (l:lin) (m:mono) (b:regexp), |
|
lcat (m::l) b = lcat (m::nil) b ++ lcat l b. |
|
Proof. |
|
intros l m b. |
|
elim (lcat_cases b). |
|
(* b = Rzero *) |
|
intro P ; subst ; auto. |
|
intros [ P | [ P1 P2 ] ]. |
|
(* b = Runit *) |
|
subst ; auto. |
|
(* b <> Rzero /\ b <> Runit *) |
|
rewrite <- map_lcat0 ; auto. |
|
rewrite <- map_lcat0 ; auto. |
|
rewrite <- map_lcat0 ; auto. |
|
Qed. |
|
|
|
Lemma llcat_app : forall (la lb:lin) (lc:list regexp), |
|
llcat (la ++ lb) lc = llcat la lc ++ llcat lb lc. |
|
Proof. |
|
intros la lb lc. |
|
induction la ; simpl ; auto. |
|
rewrite IHla ; auto. |
|
Qed. |
|
|
|
Lemma llf_single_equiv_lf : forall (a:regexp), |
|
llf (a::nil) = lf a. |
|
Proof. |
|
intro a ; simpl. |
|
rewrite llcat_nil. |
|
case (nullable a) ; rewrite <- app_nil_end ; auto. |
|
Qed. |
|
|
|
Lemma llcat_single_equiv_lcat : forall (l:lin) (b:regexp), |
|
b <> Rzero -> b <> Runit -> |
|
llcat l (b::nil) = lcat l b. |
|
Proof. |
|
intros l b P1 P2. |
|
unfold llcat. |
|
rewrite map_lcat0 ; auto. |
|
Qed. |
|
|
|
Lemma llf_double_equiv_lf : forall (a b:regexp), |
|
b <> Rzero -> b <> Runit -> |
|
llf (a::b::nil) = lf (Rcat a b). |
|
Proof. |
|
intros a b P1 P2. |
|
simpl. |
|
rewrite llcat_nil. |
|
rewrite llcat_single_equiv_lcat ; auto. |
|
case (nullable b) ; rewrite <- app_nil_end ; auto. |
|
Qed. |
|
|
|
Lemma llcat_equiv_lcat : forall (l:lin) (b:list regexp), |
|
equiv_regexp (sigma_lin (llcat l b)) (sigma_lin (lcat l (fold_cat b))). |
|
Proof. |
|
intros l b. |
|
induction l ; simpl. |
|
(* l = nil *) |
|
rewrite lcat_nil ; show_equiv. |
|
(* l = cons *) |
|
unfold sigma_lin. |
|
simpl. |
|
fold (sigma_lin (llcat l b)). |
|
rewrite lcat_cons. |
|
rewrite map_app. |
|
subst_regexp (Ralt (sigma (map unpack (lcat (a::nil) (fold_cat b)))) |
|
(sigma (map unpack (lcat l (fold_cat b))))). |
|
fold (sigma_lin (lcat l (fold_cat b))). |
|
apply Equiv_alt_rec ; auto. |
|
case a ; intros ml mt. |
|
simpl. |
|
subst_regexp (Rcat (Rsym ml) (Rcat (fold_cat mt) (fold_cat b))). |
|
apply Equiv_cat_rec ; try show_equiv ; apply fold_cat_app_equiv. |
|
elim (lcat_cases (fold_cat b)). |
|
(* fold_cat b = Rzero *) |
|
intro P ; rewrite P ; simpl ; show_equiv. |
|
intros [ P | [ P1 P2 ] ]. |
|
(* fold_cat b = Runit *) |
|
rewrite P ; simpl ; show_equiv. |
|
(* fold_cat b <> Rzero /\ fold_cat b <> Runit *) |
|
rewrite <- map_lcat0 ; auto. |
|
simpl. |
|
subst_regexp (Rcat (Rsym ml) (fold_cat (mt ++ fold_cat b::nil))) ; try show_equiv. |
|
apply Equiv_cat_rec ; try show_equiv. |
|
subst_regexp (Rcat (fold_cat mt) (fold_cat (fold_cat b :: nil))). |
|
simpl ; show_equiv. |
|
apply Equiv_symmetric ; apply fold_cat_app_equiv. |
|
apply Equiv_symmetric ; apply sigma_app_equiv. |
|
Qed. |
|
|
|
Lemma llf_equiv_lf : forall (l:list regexp), |
|
equiv_regexp (sigma_lin (llf l)) (sigma_lin (lf (fold_cat l))). |
|
Proof. |
|
induction l ; simpl ; try show_equiv. |
|
subst_regexp (Ralt (sigma_lin (llcat (lf a) l)) (sigma_lin (if nullable a then llf l else nil))). |
|
apply sigma_lin_app_equiv. |
|
subst_regexp (Ralt (sigma_lin (lcat (lf a) (fold_cat l))) (sigma_lin (if nullable a then lf (fold_cat l) else nil))). |
|
apply Equiv_alt_rec. |
|
apply llcat_equiv_lcat. |
|
case (nullable a) ; auto ; show_equiv. |
|
apply Equiv_symmetric ; apply sigma_lin_app_equiv. |
|
Qed. |
|
|
|
Lemma sigma_lin_lcat : forall (la:lin) (b:regexp), |
|
equiv_regexp (Rcat (sigma_lin la) b) (sigma_lin (lcat la b)). |
|
Proof. |
|
intros la b. |
|
elim (lcat_cases b) ; intro P. |
|
(* b = Rzero *) |
|
subst ; unfold sigma_lin ; simpl ; show_equiv. |
|
elim P ; clear P ; intro P. |
|
(* b = Runit *) |
|
subst ; simpl ; show_equiv. |
|
elim P ; clear P ; intros P1 P2. |
|
(* b <> Rzero /\ b <> Runit *) |
|
rewrite <- map_lcat0 ; auto. |
|
induction la ; unfold sigma_lin ; simpl ; try show_equiv. |
|
fold (sigma_lin la). |
|
fold (sigma_lin (map (lcat0 (b::nil)) la)). |
|
apply Equiv_symmetric. |
|
apply_tac cat_distribute_r. |
|
apply Equiv_alt_rec ; try show_equiv. |
|
case a ; intros ml mt. |
|
unfold lcat0. |
|
unfold unpack. |
|
apply_tac cat_distribute_r. |
|
apply Equiv_cat_rec ; try show_equiv. |
|
apply fold_cat_equiv. |
|
Qed. |
|
|
|
Lemma sigma_cat_equiv : forall (a b:regexp), |
|
(equiv_regexp b (Ralt (o b) (sigma_lin (lf b)))) -> |
|
equiv_regexp (sigma_lin (lf (Rcat a b))) |
|
(Ralt (Rcat (sigma_lin (lf a)) (o b)) (Rcat (Ralt (o a) (sigma_lin (lf a))) (sigma_lin (lf b)))). |
|
Proof. |
|
intros a b H. |
|
simpl. |
|
subst_regexp (Ralt (sigma_lin (lcat (lf a) b)) (sigma_lin (if nullable a then lf b else nil))). |
|
apply sigma_lin_app_equiv. |
|
subst_regexp (Ralt (sigma_lin (lcat (lf a) b)) (Rcat (o a) (sigma_lin (lf b)))). |
|
apply Equiv_alt_rec ; try show_equiv. |
|
unfold o ; case (nullable a) ; unfold sigma_lin ; simpl ; show_equiv. |
|
subst_regexp (Ralt (Rcat (sigma_lin (lf a)) b) (Rcat (o a) (sigma_lin (lf b)))). |
|
apply Equiv_alt_rec ; (apply Equiv_symmetric ; apply sigma_lin_lcat) || apply Equiv_refl. |
|
subst_regexp (Ralt (Rcat (sigma_lin (lf a)) (Ralt (o b) (sigma_lin (lf b)))) (Rcat (o a) (sigma_lin (lf b)))). |
|
show_equiv. |
|
apply_tac_right cat_distribute_r. |
|
apply_tac_right alt_flip. |
|
apply_tac alt_distribute_l. |
|
Qed. |
|
|
|
Lemma sigma_rstar_equiv : forall (r:regexp), |
|
equiv_regexp r (Ralt (o r) (sigma_lin (lf r))) -> |
|
equiv_regexp (Rstar r) (Rstar (sigma_lin (lf r))). |
|
Proof. |
|
intros r H. |
|
subst_regexp (Rstar (Ralt (o r) (sigma_lin (lf r)))) ; try show_equiv. |
|
unfold o ; case (nullable r) ; show_equiv. |
|
Qed. |
|
|
|
Theorem linear_factorization : forall (r:regexp), |
|
equiv_regexp r (Ralt (o r) (sigma_lin (lf r))). |
|
Proof. |
|
induction r ; try (unfold o ; unfold sigma_lin ; simpl ; show_equiv). |
|
(* Case: Ralt *) |
|
simpl. |
|
subst_regexp (Ralt (Ralt (o r1) (o r2)) (Ralt (sigma_lin (lf r1)) (sigma_lin (lf r2)))). |
|
apply_tac alt_distribute_r. |
|
apply_tac_right alt_flip. |
|
apply_tac_right alt_distribute_r. |
|
apply_tac alt_distribute_l. |
|
apply_tac_right alt_flip. |
|
apply Equiv_alt_rec ; apply Equiv_symmetric. |
|
apply o_alt_equiv. |
|
apply sigma_lin_app_equiv. |
|
(* Case: Rcat *) |
|
subst_regexp (Rcat (Ralt (o r1) (sigma_lin (lf r1))) (Ralt (o r2) (sigma_lin (lf r2)))). |
|
show_equiv. |
|
subst_regexp (Ralt (Rcat (o r1) (o r2)) (sigma_lin (lf (Rcat r1 r2)))). |
|
apply Equiv_symmetric. |
|
apply_tac cat_distribute_l. |
|
apply_tac_left cat_distribute_r. |
|
apply_tac alt_distribute_r. |
|
apply Equiv_alt_rec ; try show_equiv. |
|
apply sigma_cat_equiv ; apply IHr2. |
|
apply Equiv_alt_rec ; try show_equiv. |
|
apply Equiv_symmetric ; apply o_cat_equiv. |
|
(* Case: Rstar *) |
|
unfold o ; unfold nullable. |
|
replace (lf (Rstar r)) with (lcat (lf r) (Rstar r)) ; auto. |
|
subst_regexp (Ralt Runit (Rcat (sigma_lin (lf r)) (Rstar r))). |
|
subst_regexp (Ralt Runit (Rcat (sigma_lin (lf r)) (Rstar (sigma_lin (lf r))))). |
|
subst_regexp (Rstar (sigma_lin (lf r))). |
|
apply sigma_rstar_equiv ; apply IHr. |
|
apply Equiv_star_cat. |
|
apply Equiv_alt_rec ; try show_equiv. |
|
apply Equiv_cat_rec ; try show_equiv. |
|
apply Equiv_symmetric. |
|
apply sigma_rstar_equiv ; apply IHr. |
|
apply Equiv_alt_rec ; try show_equiv. |
|
apply sigma_lin_lcat. |
|
Qed. |
|
|
|
Lemma condense_app : forall (la lb:list (list regexp)), |
|
condense (la ++ lb) = condense la ++ condense lb. |
|
Proof. |
|
induction la ; intro lb ; simpl. |
|
trivial. |
|
rewrite IHla. |
|
rewrite app_ass. |
|
trivial. |
|
Qed. |
|
|
|
Lemma choose_app : forall (x:A) (la lb:lin), |
|
filter (choose x) (la ++ lb) = filter (choose x) la ++ filter (choose x) lb. |
|
Proof. |
|
induction la ; simpl. |
|
trivial. |
|
intro lb. |
|
case (choose x a). |
|
rewrite <- app_comm_cons. |
|
rewrite IHla. |
|
trivial. |
|
apply IHla. |
|
Qed. |
|
|
|
Lemma sigma_delta_lcat : forall (a b:regexp) (x:A), |
|
equiv_regexp |
|
(Rcat (sigma (delta x a)) b) |
|
(sigma (map fold_cat (map mono_term (filter (choose x) (lcat (lf a) b))))). |
|
Proof. |
|
intros a b x. |
|
unfold delta. |
|
elim (lcat_cases b) ; intro P. |
|
(* b = Rzero *) |
|
subst ; simpl ; show_equiv. |
|
elim P ; clear P ; intro P. |
|
(* b = Runit *) |
|
subst ; simpl ; show_equiv. |
|
elim P ; clear P ; intros P1 P2. |
|
(* b <> Rzero /\ b <> Runit *) |
|
rewrite <- map_lcat0 ; auto. |
|
induction (lf a) ; simpl ; try show_equiv. |
|
case a0 ; intros ml mt ; simpl. |
|
case (eq_A_dec x ml) ; intro ; simpl. |
|
apply Equiv_symmetric. |
|
apply_tac cat_distribute_r. |
|
apply Equiv_alt_rec ; try show_equiv. |
|
apply fold_cat_equiv. |
|
apply IHl. |
|
Qed. |
|
|
|
Lemma sigma_delta_alt : forall (a b:regexp) (x:A), |
|
equiv_regexp (Ralt (sigma (delta x a)) (sigma (delta x b))) (sigma (delta x (Ralt a b))). |
|
Proof. |
|
intros a b x. |
|
unfold delta at 3 ; simpl. |
|
rewrite choose_app. |
|
rewrite map_app. |
|
rewrite map_app. |
|
fold (delta x a). |
|
fold (delta x b). |
|
subst_regexp (Ralt (sigma (delta x a)) (sigma (delta x b))). |
|
show_equiv. |
|
apply Equiv_symmetric. |
|
apply sigma_app_equiv. |
|
Qed. |
|
|
|
Lemma sigma_delta_cat : forall (a b:regexp) (x:A), |
|
equiv_regexp (Ralt (Rcat (sigma (delta x a)) b) (Rcat (o a) (sigma (delta x b)))) |
|
(sigma (delta x (Rcat a b))). |
|
Proof. |
|
intros a b x. |
|
unfold delta at 3. |
|
simpl ; unfold o. |
|
assert (P:nullable a = true \/ nullable a = false). |
|
case (nullable a) ; auto. |
|
elim P ; clear P ; intro P ; rewrite P. |
|
(* Case: nullable a = true *) |
|
rewrite choose_app. |
|
rewrite map_app. |
|
rewrite map_app. |
|
fold (delta x b). |
|
subst_regexp (Ralt |
|
(sigma (map fold_cat (map mono_term (filter (choose x) (lcat (lf a) b))))) |
|
(sigma (delta x b))). |
|
apply Equiv_alt_rec ; try show_equiv. |
|
apply sigma_delta_lcat. |
|
apply Equiv_symmetric. |
|
apply sigma_app_equiv. |
|
(* Case: nullable a = false *) |
|
rewrite <- app_nil_end. |
|
subst_regexp (Rcat (sigma (delta x a)) b) ; try show_equiv. |
|
apply sigma_delta_lcat. |
|
Qed. |
|
|
|
Lemma sigma_delta_star : forall (a:regexp) (x:A), |
|
equiv_regexp (Rcat (sigma (delta x a)) (Rstar a)) (sigma (delta x (Rstar a))). |
|
Proof. |
|
intros a x. |
|
unfold delta at 2 ; simpl. |
|
fold (lcat (lf a) (Rstar a)). |
|
apply sigma_delta_lcat. |
|
Qed. |
|
|
|
Theorem partial_derivative : forall (t:regexp) (x:A), |
|
equiv_regexp (derivative x t) (sigma (delta x t)). |
|
Proof. |
|
intros t x. |
|
induction t ; simpl ; try show_equiv. |
|
(* Case: Rsym *) |
|
unfold delta ; simpl. |
|
case (eq_A_dec x a) ; intro ; simpl ; show_equiv. |
|
(* Case: Ralt *) |
|
subst_regexp (Ralt (sigma (delta x t1)) (sigma (delta x t2))). |
|
show_equiv. |
|
apply sigma_delta_alt. |
|
(* Case: Rcat *) |
|
subst_regexp (Ralt (Rcat (sigma (delta x t1)) t2) (Rcat (o t1) (sigma (delta x t2)))). |
|
show_equiv. |
|
apply sigma_delta_cat. |
|
(* Case: Rstar *) |
|
subst_regexp (Rcat (sigma (delta x t)) (Rstar t)). |
|
show_equiv. |
|
apply sigma_delta_star. |
|
Qed. |
|
|
|
Inductive subterm : regexp -> regexp -> Prop := |
|
| Subterm_star_refl : forall (a:regexp), subterm (Rstar a) (Rstar a) |
|
| Subterm_trans : forall (a b c:regexp), subterm a b -> subterm b c -> subterm a c |
|
| Subterm_alt_l : forall (a b:regexp), subterm a (Ralt a b) |
|
| Subterm_alt_r : forall (a b:regexp), subterm b (Ralt a b) |
|
| Subterm_cat_l : forall (a b:regexp), subterm a (Rcat a b) |
|
| Subterm_cat_r : forall (a b:regexp), subterm b (Rcat a b) |
|
| Subterm_star : forall (a:regexp), subterm a (Rstar a). |
|
|
|
Definition subterm_list (l:list regexp) (r:regexp) := |
|
forall (s:regexp), In s l -> subterm s r. |
|
|
|
Definition subterm_lin (l:lin) (r:regexp) := |
|
forall (m:mono), In m l -> subterm_list (mono_term m) r. |
|
|
|
Lemma subterm_list_nil : forall (r:regexp), subterm_list nil r. |
|
Proof. |
|
unfold subterm_list. |
|
intros r s H. |
|
elim H. |
|
Qed. |
|
|
|
Lemma subterm_lin_nil : forall (r:regexp), subterm_lin nil r. |
|
Proof. |
|
unfold subterm_lin. |
|
intros r m H. |
|
elim H. |
|
Qed. |
|
|
|
Lemma subterm_list_cons : forall (r s:regexp) (l:list regexp), |
|
subterm s r -> subterm_list l r -> subterm_list (s::l) r. |
|
Proof. |
|
unfold subterm_list. |
|
intros r s l H1 H2 s0 H3. |
|
elim H3 ; clear H3 ; intro H3 ; subst ; auto. |
|
Qed. |
|
|
|
Lemma subterm_lin_cons : forall (r:regexp) (m:mono) (l:lin), |
|
subterm_list (mono_term m) r -> subterm_lin l r -> subterm_lin (m::l) r. |
|
Proof. |
|
unfold subterm_lin. |
|
intros r m l H1 H2 m0 H3. |
|
elim H3 ; clear H3 ; intro H3 ; subst ; auto. |
|
Qed. |
|
|
|
Lemma subterm_list_app : forall (l1 l2:list regexp) (r:regexp), |
|
subterm_list l1 r -> subterm_list l2 r -> subterm_list (l1 ++ l2) r. |
|
Proof. |
|
unfold subterm_list. |
|
intros l1 l2 r H1 H2 s H3. |
|
apply in_app_or in H3. |
|
elim H3 ; auto. |
|
Qed. |
|
|
|
Lemma subterm_lin_app : forall (l1 l2:lin) (r:regexp), |
|
subterm_lin l1 r -> subterm_lin l2 r -> subterm_lin (l1 ++ l2) r. |
|
Proof. |
|
unfold subterm_lin. |
|
intros l1 l2 r H1 H2 m H3. |
|
apply in_app_or in H3. |
|
elim H3 ; auto. |
|
Qed. |
|
|
|
Lemma subterm_list_trans : forall (l:list regexp) (a b:regexp), |
|
subterm_list l a -> subterm a b -> subterm_list l b. |
|
Proof. |
|
unfold subterm_list. |
|
intros l a b H1 H2 s H3. |
|
apply (Subterm_trans s a b) ; auto. |
|
Qed. |
|
|
|
Lemma subterm_lin_trans : forall (l:lin) (a b:regexp), |
|
subterm_lin l a -> subterm a b -> subterm_lin l b. |
|
Proof. |
|
unfold subterm_lin. |
|
intros l a b H1 H2 m H3. |
|
eapply subterm_list_trans ; auto. |
|
Qed. |
|
|
|
Lemma subterm_lin_map : forall (l:lin) (r:regexp) (f:mono -> mono), |
|
(forall m:mono, subterm_list (mono_term m) r -> subterm_list (mono_term (f m)) r) -> |
|
subterm_lin l r -> subterm_lin (map f l) r. |
|
Proof. |
|
unfold subterm_lin. |
|
intros l r f H1 H2 m H3. |
|
elim (in_map_iff f l m). |
|
intros H4 H5 ; clear H5. |
|
elim (H4 H3) ; clear H4. |
|
intros x H4 ; elim H4 ; clear H4. |
|
intros H4 H5. |
|
subst ; auto. |
|
Qed. |
|
|
|
Lemma lcat0_structure : forall (b r:regexp) (m:mono), |
|
subterm b r -> |
|
subterm_list (mono_term m) r -> |
|
subterm_list (mono_term (lcat0 (b::nil) m)) r. |
|
Proof. |
|
intros b r m H1 H2. |
|
replace (mono_term (lcat0 (b::nil) m)) with (mono_term m ++ b::nil). |
|
apply subterm_list_app ; auto. |
|
apply subterm_list_cons ; auto. |
|
apply subterm_list_nil. |
|
case m ; auto. |
|
Qed. |
|
|
|
Theorem lf_structure : forall (a:regexp), |
|
subterm_lin (lf a) a. |
|
Proof. |
|
induction a ; simpl. |
|
(* Case: Rzero *) |
|
apply subterm_lin_nil. |
|
(* Case: Runit *) |
|
apply subterm_lin_nil. |
|
(* Case: Rsym *) |
|
apply subterm_lin_cons. |
|
simpl. |
|
apply subterm_list_nil. |
|
apply subterm_lin_nil. |
|
(* Case: Ralt *) |
|
apply subterm_lin_app. |
|
apply (subterm_lin_trans (lf a1) a1 (Ralt a1 a2)) ; auto. |
|
apply Subterm_alt_l. |
|
apply (subterm_lin_trans (lf a2) a2 (Ralt a1 a2)) ; auto. |
|
apply Subterm_alt_r. |
|
(* Case: Rcat *) |
|
apply subterm_lin_app. |
|
elim (lcat_cases a2) ; intro P. |
|
(* a2 = Rzero *) |
|
subst ; simpl. |
|
apply subterm_lin_nil. |
|
elim P ; clear P ; intro P. |
|
(* a2 = Runit *) |
|
subst ; simpl. |
|
apply (subterm_lin_trans (lf a1) a1 (Rcat a1 Runit)) ; auto. |
|
apply Subterm_cat_l. |
|
elim P ; clear P ; intros P1 P2. |
|
(* a2 <> Rzero /\ a2 <> Runit *) |
|
rewrite <- map_lcat0 ; auto. |
|
apply subterm_lin_map. |
|
intros m H. |
|
apply lcat0_structure ; auto. |
|
apply Subterm_cat_r. |
|
apply (subterm_lin_trans (lf a1) a1 (Rcat a1 a2)) ; auto. |
|
apply Subterm_cat_l. |
|
case (nullable a1). |
|
apply (subterm_lin_trans (lf a2) a2 (Rcat a1 a2)) ; auto. |
|
apply Subterm_cat_r. |
|
apply subterm_lin_nil. |
|
(* Case: Rstar *) |
|
apply subterm_lin_map. |
|
intros m H. |
|
apply lcat0_structure ; auto. |
|
apply Subterm_star_refl. |
|
apply (subterm_lin_trans (lf a) a (Rstar a)) ; auto. |
|
apply Subterm_star. |
|
Qed. |
|
|
|
Theorem lf_size : forall (a:regexp) (m:mono), |
|
In m (lf a) -> length (mono_term m) <= cat_star_occurs a. |
|
Proof. |
|
induction a ; simpl ; intros m H ; try (elim H ; fail). |
|
(* Case: Rsym *) |
|
elim H ; clear H ; intro H. |
|
subst ; simpl ; auto. |
|
elim H. |
|
(* Case: Ralt *) |
|
apply in_app_or in H. |
|
elim H ; clear H ; intro H. |
|
apply le_plus_trans ; auto. |
|
rewrite plus_comm. |
|
apply le_plus_trans ; auto. |
|
(* Case: Rcat *) |
|
apply in_app_or in H. |
|
elim H ; clear H ; intro H. |
|
elim (lcat_cases a2) ; intro P. |
|
(* a2 = Rzero *) |
|
subst ; simpl in H ; elim H. |
|
elim P ; clear P ; intro P. |
|
(* a2 = Runit *) |
|
subst ; simpl in H. |
|
apply le_plus_trans ; apply le_plus_trans ; auto. |
|
elim P ; clear P ; intros P1 P2. |
|
(* a2 <> Rzero /\ a2 <> Runit *) |
|
rewrite <- map_lcat0 in H ; auto. |
|
elim (in_map_iff (lcat0 (a2::nil)) (lf a1) m). |
|
intros H1 H2 ; clear H2. |
|
elim (H1 H) ; clear H1 ; intros x [ H1 H2 ]. |
|
subst. |
|
replace (mono_term (lcat0 (a2::nil) x)) with (mono_term x ++ a2::nil). |
|
rewrite app_length ; simpl. |
|
apply plus_le_compat_r. |
|
apply le_plus_trans ; auto. |
|
case x ; auto. |
|
revert H ; case (nullable a1) ; intro H. |
|
apply le_plus_trans. |
|
rewrite plus_comm. |
|
apply le_plus_trans ; auto. |
|
elim H. |
|
(* Case: Rstar *) |
|
elim (in_map_iff (lcat0 ((Rstar a)::nil)) (lf a) m). |
|
intros H1 H2 ; clear H2. |
|
elim (H1 H) ; clear H1 ; intros x [ H1 H2 ]. |
|
subst. |
|
replace (mono_term (lcat0 ((Rstar a)::nil) x)) with (mono_term x ++ (Rstar a)::nil). |
|
rewrite app_length ; simpl. |
|
apply plus_le_compat_r ; auto. |
|
case x ; auto. |
|
Qed. |
|
|
|
Lemma lf_nonzero_nonunit : forall (a:regexp) (m:mono) (s:regexp), |
|
In m (lf a) -> In s (mono_term m) -> s <> Rzero /\ s <> Runit. |
|
Proof. |
|
induction a ; simpl ; intros m s H1 H2. |
|
(* Case: Rzero *) |
|
elim H1. |
|
(* Case: Runit *) |
|
elim H1. |
|
(* Case: Rsym *) |
|
elim H1 ; clear H1 ; intro H1. |
|
subst ; simpl in H2 ; elim H2. |
|
elim H1. |
|
(* Case: Ralt *) |
|
apply in_app_or in H1. |
|
elim H1 ; clear H1 ; intro H1. |
|
apply (IHa1 m) ; auto. |
|
apply (IHa2 m) ; auto. |
|
(* Case: Rcat *) |
|
apply in_app_or in H1. |
|
elim H1 ; clear H1 ; intro H1. |
|
elim (lcat_cases a2) ; intro P. |
|
(* a2 = Rzero *) |
|
subst ; simpl in H1 ; elim H1. |
|
elim P ; clear P ; intro P. |
|
(* a2 = Runit *) |
|
subst ; simpl in H1. |
|
apply (IHa1 m) ; auto. |
|
elim P ; clear P ; intros P1 P2. |
|
(* a2 <> Rzero /\ a2 <> Runit *) |
|
rewrite <- map_lcat0 in H1 ; auto. |
|
elim (in_map_iff (lcat0 (a2::nil)) (lf a1) m). |
|
intros H3 H4 ; clear H4. |
|
elim (H3 H1) ; clear H3 ; intros x [ H3 H4 ]. |
|
subst. |
|
replace (mono_term (lcat0 (a2::nil) x)) with (mono_term x ++ a2::nil) in H2. |
|
apply in_app_or in H2. |
|
elim H2 ; clear H2 ; intro H2. |
|
apply (IHa1 x) ; auto. |
|
elim H2 ; clear H2 ; intro H2. |
|
subst ; auto. |
|
elim H2. |
|
case x ; auto. |
|
revert H1 ; case (nullable a1) ; simpl ; intro H1. |
|
apply (IHa2 m) ; auto. |
|
elim H1. |
|
(* Case: Rstar *) |
|
elim (in_map_iff (lcat0 ((Rstar a)::nil)) (lf a) m). |
|
intros H3 H4 ; clear H4. |
|
elim (H3 H1) ; clear H3 ; intros x [ H3 H4 ]. |
|
subst. |
|
replace (mono_term (lcat0 ((Rstar a)::nil) x)) with (mono_term x ++ (Rstar a)::nil) in H2. |
|
apply in_app_or in H2. |
|
elim H2 ; clear H2 ; intro H2. |
|
apply (IHa x) ; auto. |
|
elim H2 ; clear H2 ; intro H2. |
|
subst ; split ; discriminate. |
|
elim H2. |
|
case x ; auto. |
|
Qed. |
|
|
|
(* WARNING: very random from here onwards *) |
|
|
|
(* |
|
Lemma plus_trans : forall (a b c:nat), |
|
b = c -> a + b = a + c. |
|
Proof. |
|
intros a b c H. |
|
induction a ; auto. |
|
Qed. |
|
|
|
Lemma fold_cat_alphabetic_width : forall (l:list regexp) (a:regexp), |
|
alphabetic_width (fold_cat (l ++ a::nil)) = alphabetic_width (fold_cat l) + alphabetic_width a. |
|
Proof. |
|
intros l a. |
|
induction l ; simpl. |
|
auto with arith. |
|
rewrite <- plus_assoc. |
|
apply plus_trans ; auto. |
|
Qed. |
|
|
|
Lemma foo : forall (a:regexp) (m:mono), |
|
In m (lf a) -> alphabetic_width (fold_cat (mono_term m)) < alphabetic_width a. |
|
Proof. |
|
induction a ; simpl ; intros m H. |
|
(* Case: Rzero *) |
|
elim H. |
|
(* Case: Runit *) |
|
elim H. |
|
(* Case: Rsym *) |
|
elim H ; clear H ; intro H. |
|
subst ; auto. |
|
elim H. |
|
(* Case: Ralt *) |
|
apply in_app_or in H. |
|
elim H ; clear H ; intro H. |
|
apply lt_plus_trans ; auto. |
|
rewrite plus_comm. |
|
apply lt_plus_trans ; auto. |
|
(* Case: Rcat *) |
|
apply in_app_or in H. |
|
elim H ; clear H ; intro H. |
|
elim (lcat_cases a2) ; intro P. |
|
(* a2 = Rzero *) |
|
subst ; simpl in H ; elim H. |
|
elim P ; clear P ; intro P. |
|
(* a2 = Runit *) |
|
subst ; simpl in H. |
|
apply lt_plus_trans ; auto. |
|
elim P ; clear P ; intros P1 P2. |
|
(* a2 <> Rzero /\ a2 <> Runit *) |
|
rewrite <- map_lcat0 in H ; auto. |
|
elim (in_map_iff (lcat0 a2) (lf a1) m). |
|
intros H1 H2 ; clear H2. |
|
elim (H1 H) ; clear H1. |
|
intros x H1. |
|
elim H1 ; clear H1 ; intros ; subst. |
|
replace (mono_term (lcat0 a2 x)) with (mono_term x ++ a2::nil). |
|
rewrite fold_cat_alphabetic_width. |
|
apply plus_lt_compat_r ; auto. |
|
case x ; auto. |
|
(* ++ *) |
|
revert H ; case (nullable a1) ; intro H. |
|
rewrite plus_comm. |
|
apply lt_plus_trans ; auto. |
|
elim H. |
|
(* Case: Rstar *) |
|
elim (in_map_iff (lcat0 (Rstar a)) (lf a) m). |
|
intros H1 H2 ; clear H2. |
|
elim (H1 H) ; clear H1. |
|
intros x H1. |
|
elim H1 ; clear H1 ; intros ; subst. |
|
replace (mono_term (lcat0 (Rstar a) x)) with (mono_term x ++ (Rstar a)::nil). |
|
rewrite fold_cat_alphabetic_width. |
|
*) |
|
|
|
Inductive last : regexp -> list regexp -> Prop := |
|
| last_single : forall (a:regexp), last a (a::nil) |
|
| last_cons : forall (a b:regexp) (l:list regexp), last a l -> last a (b::l). |
|
|
|
Lemma last_app : forall (a:regexp) (l:list regexp), last a (l ++ a::nil). |
|
Proof. |
|
induction l ; simpl. |
|
apply last_single. |
|
apply last_cons ; auto. |
|
Qed. |
|
|
|
Inductive split_tail : list regexp -> list regexp -> regexp -> Prop := |
|
| Tail_single : forall (a:regexp), split_tail (a::nil) nil a |
|
| Tail_cons : forall (a b:regexp) (l la:list regexp), |
|
split_tail l la a -> split_tail (b::l) (b::la) a. |
|
|
|
Lemma split_tail_app : forall (a:regexp) (l:list regexp), |
|
split_tail (l ++ a::nil) l a. |
|
Proof. |
|
intros a l. |
|
induction l ; simpl. |
|
apply Tail_single. |
|
apply Tail_cons ; auto. |
|
Qed. |
|
|
|
Lemma split_tail_app2 : forall (a b:regexp) (l:list regexp), |
|
split_tail (l ++ a::nil) l b -> a = b. |
|
Proof. |
|
intros a b l. |
|
induction l ; simpl ; intro H ; inversion H ; auto. |
|
Qed. |
|
|
|
(* |
|
Lemma split_tail_app3 : forall (a:regexp) (la l:list regexp), |
|
split_tail (l ++ a::nil) la a -> l = la. |
|
Proof. |
|
induction l ; simpl ; intro H. |
|
(* l = nil *) |
|
inversion H ; subst ; auto. |
|
inversion H4. |
|
(* l = cons *) |
|
inversion H ; subst. |
|
generalize (app_cons_not_nil l nil a) ; unfold not ; intro H3 ; elim H3 ; auto. |
|
|
|
|
|
Lemma split_tail_app3 : forall (a b:regexp) (l la:list regexp), |
|
split_tail (l ++ a::nil) la b -> a = b /\ l = la. |
|
Proof. |
|
intros a b l la. |
|
induction l ; simpl ; intro H. |
|
(* l = nil *) |
|
inversion H ; subst ; auto. |
|
inversion H4. |
|
(* l = cons *) |
|
|
|
*) |
|
|
|
Axiom split_tail_app_hack : forall (a b:regexp) (l la:list regexp), |
|
split_tail (l ++ a::nil) la b -> a = b /\ l = la. |
|
|
|
Inductive PD : list regexp -> regexp -> Prop := |
|
(* | PD_refl : forall (a:regexp), PD (a::nil) a *) |
|
| PD_step : forall (a:regexp) (m:mono), In m (lf a) -> PD (mono_term m) a |
|
| PD_trans : forall (a:regexp) (l:list regexp) (m:mono), |
|
PD l a -> In m (lf (fold_cat l)) -> PD (mono_term m) a. |
|
|
|
Lemma PD_cat_star : forall (a b c:regexp) (l la:list regexp), |
|
PD l (Rcat a (Rstar b)) -> split_tail l la c -> (PD la a \/ PD la b) /\ c = (Rstar b). |
|
Proof. |
|
intros a b c l la H1 H2. |
|
inversion H1 ; subst. |
|
(* PD_step *) |
|
simpl in H. |
|
apply in_app_or in H. |
|
elim H ; clear H ; intro H. |
|
elim (in_map_iff (lcat0 ((Rstar b)::nil)) (lf a) m). |
|
intros H3 H4 ; clear H4. |
|
elim (H3 H) ; clear H3 ; intros x [ H3 _ ]. |
|
subst. |
|
replace (mono_term (lcat0 ((Rstar b)::nil) x)) with (mono_term x ++ (Rstar b)::nil) in *. |
|
generalize (split_tail_app_hack (Rstar b) c (mono_term x) la H2). |
|
intros [ H4 H5 ]. |
|
split ; auto. |
|
subst. |
|
left ; apply PD_step ; auto. |
|
case x ; auto. |
|
revert H ; case (nullable a) ; intro H. |
|
elim (in_map_iff (lcat0 ((Rstar b)::nil)) (lf b) x). |
|
intros H3 H4 ; clear H4. |
|
elim (H3 H) ; clear H3. |
|
intros x H3. |
|
elim H3 ; clear H3 ; intros ; subst. |
|
replace (mono_term (lcat0 (Rstar b) x)) with (mono_term x ++ (Rstar b)::nil) in *. |
|
generalize (split_tail_app_hack (Rstar b) c (mono_term x) la H2). |
|
intro H4 ; elim H4 ; clear H4 ; intros H4 H5. |
|
split ; auto. |
|
subst. |
|
right ; apply PD_step ; auto. |
|
case x ; auto. |
|
elim H. |
|
(* PD_trans *) |
|
|
|
|
|
Inductive LF : list regexp -> regexp -> Prop := |
|
| LF_step : forall (a:regexp) (m:mono), In m (lf a) -> LF (mono_term m) a |
|
| LF_trans : forall (a:regexp) (l:list regexp) (m:mono), |
|
LF l a -> In m (lf (fold_cat l)) -> LF (mono_term m) a. |
|
|
|
Lemma LF_star : forall (a b:regexp) (l la:list regexp), |
|
LF l (Rstar a) -> split_tail l la b -> LF la a /\ b = (Rstar a). |
|
Proof. |
|
intros a b l la H1 H2. |
|
inversion H1 ; subst. |
|
(* Case: LF_step *) |
|
simpl in H. |
|
elim (in_map_iff (lcat0 (Rstar a)) (lf a) m). |
|
intros H3 H4 ; clear H4. |
|
elim (H3 H) ; clear H3. |
|
intros x H3. |
|
elim H3 ; clear H3 ; intros ; subst. |
|
replace (mono_term (lcat0 (Rstar a) x)) with (mono_term x ++ (Rstar a)::nil) in H2. |
|
generalize (split_tail_app_hack (Rstar a) b (mono_term x) la H2). |
|
intro H4 ; elim H4 ; clear H4 ; intros H4 H5. |
|
split ; auto. |
|
subst. |
|
apply LF_step ; auto. |
|
case x ; auto. |
|
(* Case: LF_trans *) |
|
induction l0 ; simpl in H0. |
|
elim H0. |
|
apply in_app_or in H0. |
|
elim H0 ; clear H0 ; intro H0. |
|
apply IHl0. |
|
|
|
|
|
Lemma lf_star : forall (a:regexp) (m:mono), |
|
In m (lf (Rstar a)) -> last (Rstar a) (mono_term m). |
|
Proof. |
|
intros a m. |
|
simpl. |
|
induction (lf a) ; simpl ; intro H. |
|
elim H. |
|
elim H ; clear H ; intro H ; auto. |
|
subst. |
|
case a0 ; intros ml mt. |
|
simpl. |
|
apply last_app. |
|
Qed. |
|
|
|
Definition pd_single (t:regexp) : list regexp := |
|
map fold_cat (map mono_term (lf t)). |
|
|
|
Definition pd_step (l:list regexp) : list regexp := |
|
flat_map pd_single l. |
|
|
|
Fixpoint pd (l:list regexp) : list regexp := |
|
match l with |
|
| nil => nil |
|
| a::al => |
|
match pd_single a with |
|
| nil => a :: pd al |
|
| b::bl => |
|
end |
|
end. |
|
|
|
Inductive pd : regexp -> list regexp -> Prop := |
|
| PD_refl : forall (a:regexp), pd a (a::nil) |
|
| PD_lf : forall (a:regexp) (m:mono), |
|
In m (lf a) -> pd a (mono_term m) |
|
| PD_rec : forall (a:regexp) (d:list regexp) (m:mono), |
|
pd a d -> In m (lf (fold_cat d)) -> pd a (mono_term m). |
|
|
|
|
|
|
|
Record states : Set := States { |
|
states_pd : list regexp; |
|
states_ds : list regexp |
|
}. |
|
|
|
Fixpoint delta_step (s:states) : states := |
|
let pd := states_pd s ++ states_ds s in |
|
let ds := |
|
|
|
|
|
Lemma delta_word_zero : forall (w:list A), |
|
delta_word w Rzero = nil. |
|
Proof. |
|
induction w ; simpl. |
|
trivial. |
|
rewrite IHw. |
|
simpl ; trivial. |
|
Qed. |
|
|
|
Lemma delta_word_unit : forall (w:list A), |
|
delta_word w Runit = nil. |
|
Proof. |
|
induction w ; simpl. |
|
trivial. |
|
rewrite IHw. |
|
simpl ; trivial. |
|
Qed. |
|
|
|
Lemma delta_word_sym : forall (x:A) (w:list A), |
|
delta_word w (Rsym x) = nil. |
|
Proof. |
|
induction w ; simpl. |
|
auto. |
|
rewrite IHw. |
|
simpl ; auto. |
|
Qed. |
|
|
|
Lemma delta_word_alt : forall (w:list A) (a b:regexp), |
|
delta_word w (Ralt a b) = delta_word w a ++ delta_word w b. |
|
Proof. |
|
intros w a b. |
|
induction w ; simpl. |
|
auto. |
|
unfold delta_set. |
|
rewrite <- condense_app. |
|
rewrite <- map_app. |
|
rewrite IHw. |
|
trivial. |
|
Qed. |
|
|
|
Theorem something : forall (t:regexp) (w:list A), |
|
length (delta_word w t) <= alphabetic_width t. |
|
Proof. |
|
induction t ; intro w ; simpl. |
|
(* Case: Rzero *) |
|
rewrite delta_word_zero ; auto. |
|
(* Case: Runit *) |
|
rewrite delta_word_unit ; auto. |
|
(* Case: Rsym *) |
|
rewrite delta_word_sym ; auto. |
|
(* Case: Ralt *) |
|
rewrite delta_word_alt. |
|
rewrite app_length. |
|
apply plus_le_compat ; auto. |
|
(* Case: Rcat *) |
|
induction w ; simpl. |
|
auto with arith. |
|
|
|
|
|
|
|
(* |
|
Open Local Scope char_scope. |
|
|
|
Definition r := Rcat (Rsym "a") (Rstar (Rsym "b")). |
|
|
|
Definition w1 := "a" :: nil. |
|
|
|
Eval compute in simplify (simplify (deltaw w1 r)). |
|
*) |