1 (**************************************************************************)
4 (* ||A|| A project by Andrea Asperti *)
6 (* ||I|| Developers: *)
7 (* ||T|| The HELM team. *)
8 (* ||A|| http://helm.cs.unibo.it *)
10 (* \ / This file is distributed under the terms of the *)
11 (* v GNU General Public License Version 2 *)
13 (**************************************************************************)
17 (* The type re of regular expressions over an alphabet $S$ is the smallest
18 collection of objects generated by the following constructors: *)
20 inductive re (S: DeqSet) : Type[0] ≝
24 | c: re S → re S → re S
25 | o: re S → re S → re S
28 interpretation "re epsilon" 'epsilon = (e ?).
29 interpretation "re or" 'plus a b = (o ? a b).
30 interpretation "re cat" 'middot a b = (c ? a b).
31 interpretation "re star" 'star a = (k ? a).
33 notation < "a" non associative with precedence 90 for @{ 'ps $a}.
34 notation > "` term 90 a" non associative with precedence 90 for @{ 'ps $a}.
35 interpretation "atom" 'ps a = (s ? a).
37 notation "`∅" non associative with precedence 90 for @{ 'empty }.
38 interpretation "empty" 'empty = (z ?).
40 (* The language sem{e} associated with the regular expression e is inductively
41 defined by the following function: *)
43 let rec in_l (S : DeqSet) (r : re S) on r : word S → Prop ≝
48 | c r1 r2 ⇒ (in_l ? r1) · (in_l ? r2)
49 | o r1 r2 ⇒ (in_l ? r1) ∪ (in_l ? r2)
50 | k r1 ⇒ (in_l ? r1) ^*].
52 notation "\sem{term 19 E}" non associative with precedence 75 for @{'in_l $E}.
53 interpretation "in_l" 'in_l E = (in_l ? E).
54 interpretation "in_l mem" 'mem w l = (in_l ? l w).
56 lemma rsem_star : ∀S.∀r: re S. \sem{r^*} = \sem{r}^*.
60 Pointed Regular expressions
62 We now introduce pointed regular expressions, that are the main tool we shall
63 use for the construction of the automaton.
64 A pointed regular expression is just a regular expression internally labelled
65 with some additional points. Intuitively, points mark the positions inside the
66 regular expression which have been reached after reading some prefix of
67 the input string, or better the positions where the processing of the remaining
68 string has to be started. Each pointed expression for $e$ represents a state of
69 the {\em deterministic} automaton associated with $e$; since we obviously have
70 only a finite number of possible labellings, the number of states of the automaton
73 Pointed regular expressions provide the tool for an algebraic revisitation of
74 McNaughton and Yamada's algorithm for position automata, making the proof of its
75 correctness, that is far from trivial, particularly clear and simple. In particular,
76 pointed expressions offer an appealing alternative to Brzozowski's derivatives,
77 avoiding their weakest point, namely the fact of being forced to quotient derivatives
78 w.r.t. a suitable notion of equivalence in order to get a finite number of states
79 (that is not essential for recognizing strings, but is crucial for comparing regular
82 Our main data structure is the notion of pointed item, that is meant whose purpose
83 is to encode a set of positions inside a regular expression.
84 The idea of formalizing pointers inside a data type by means of a labelled version
85 of the data type itself is probably one of the first, major lessons learned in the
86 formalization of the metatheory of programming languages. For our purposes, it is
87 enough to mark positions preceding individual characters, so we shall have two kinds
88 of characters •a (pp a) and a (ps a) according to the case a is pointed or not. *)
90 inductive pitem (S: DeqSet) : Type[0] ≝
95 | pc: pitem S → pitem S → pitem S
96 | po: pitem S → pitem S → pitem S
97 | pk: pitem S → pitem S.
99 (* A pointed regular expression (pre) is just a pointed item with an additional
100 boolean, that must be understood as the possibility to have a trailing point at
101 the end of the expression. As we shall see, pointed regular expressions can be
102 understood as states of a DFA, and the boolean indicates if
103 the state is final or not. *)
105 definition pre ≝ λS.pitem S × bool.
107 interpretation "pitem star" 'star a = (pk ? a).
108 interpretation "pitem or" 'plus a b = (po ? a b).
109 interpretation "pitem cat" 'middot a b = (pc ? a b).
110 notation < ".a" non associative with precedence 90 for @{ 'pp $a}.
111 notation > "`. term 90 a" non associative with precedence 90 for @{ 'pp $a}.
112 interpretation "pitem pp" 'pp a = (pp ? a).
113 interpretation "pitem ps" 'ps a = (ps ? a).
114 interpretation "pitem epsilon" 'epsilon = (pe ?).
115 interpretation "pitem empty" 'empty = (pz ?).
117 (* The carrier $|i|$ of an item i is the regular expression obtained from i by
118 removing all the points. Similarly, the carrier of a pointed regular expression
119 is the carrier of its item. *)
121 let rec forget (S: DeqSet) (l : pitem S) on l: re S ≝
127 | pc E1 E2 ⇒ (forget ? E1) · (forget ? E2)
128 | po E1 E2 ⇒ (forget ? E1) + (forget ? E2)
129 | pk E ⇒ (forget ? E)^* ].
131 (* notation < "|term 19 e|" non associative with precedence 70 for @{'forget $e}.*)
132 interpretation "forget" 'norm a = (forget ? a).
134 lemma erase_dot : ∀S.∀e1,e2:pitem S. |e1 · e2| = c ? (|e1|) (|e2|).
137 lemma erase_plus : ∀S.∀i1,i2:pitem S.
138 |i1 + i2| = |i1| + |i2|.
141 lemma erase_star : ∀S.∀i:pitem S.|i^*| = |i|^*.
145 Comparing items and pres
147 Items and pres are very concrete datatypes: they can be effectively compared,
148 and enumerated. In particular, we can define a boolean equality beqitem and a proof
149 beqitem_true that it refects propositional equality, enriching the set (pitem S)
152 let rec beqitem S (i1,i2: pitem S) on i1 ≝
154 [ pz ⇒ match i2 with [ pz ⇒ true | _ ⇒ false]
155 | pe ⇒ match i2 with [ pe ⇒ true | _ ⇒ false]
156 | ps y1 ⇒ match i2 with [ ps y2 ⇒ y1==y2 | _ ⇒ false]
157 | pp y1 ⇒ match i2 with [ pp y2 ⇒ y1==y2 | _ ⇒ false]
158 | po i11 i12 ⇒ match i2 with
159 [ po i21 i22 ⇒ beqitem S i11 i21 ∧ beqitem S i12 i22
161 | pc i11 i12 ⇒ match i2 with
162 [ pc i21 i22 ⇒ beqitem S i11 i21 ∧ beqitem S i12 i22
164 | pk i11 ⇒ match i2 with [ pk i21 ⇒ beqitem S i11 i21 | _ ⇒ false]
167 lemma beqitem_true: ∀S,i1,i2. iff (beqitem S i1 i2 = true) (i1 = i2).
169 [#i2 cases i2 [||#a|#a|#i21 #i22| #i21 #i22|#i3] % // normalize #H destruct
170 |#i2 cases i2 [||#a|#a|#i21 #i22| #i21 #i22|#i3] % // normalize #H destruct
171 |#x #i2 cases i2 [||#a|#a|#i21 #i22| #i21 #i22|#i3] % normalize #H destruct
172 [>(\P H) // | @(\b (refl …))]
173 |#x #i2 cases i2 [||#a|#a|#i21 #i22| #i21 #i22|#i3] % normalize #H destruct
174 [>(\P H) // | @(\b (refl …))]
175 |#i11 #i12 #Hind1 #Hind2 #i2 cases i2 [||#a|#a|#i21 #i22| #i21 #i22|#i3] %
176 normalize #H destruct
177 [cases (true_or_false (beqitem S i11 i21)) #H1
178 [>(proj1 … (Hind1 i21) H1) >(proj1 … (Hind2 i22)) // >H1 in H; #H @H
179 |>H1 in H; normalize #abs @False_ind /2/
181 |>(proj2 … (Hind1 i21) (refl …)) >(proj2 … (Hind2 i22) (refl …)) //
183 |#i11 #i12 #Hind1 #Hind2 #i2 cases i2 [||#a|#a|#i21 #i22| #i21 #i22|#i3] %
184 normalize #H destruct
185 [cases (true_or_false (beqitem S i11 i21)) #H1
186 [>(proj1 … (Hind1 i21) H1) >(proj1 … (Hind2 i22)) // >H1 in H; #H @H
187 |>H1 in H; normalize #abs @False_ind /2/
189 |>(proj2 … (Hind1 i21) (refl …)) >(proj2 … (Hind2 i22) (refl …)) //
191 |#i3 #Hind #i2 cases i2 [||#a|#a|#i21 #i22| #i21 #i22|#i4] %
192 normalize #H destruct
193 [>(proj1 … (Hind i4) H) // |>(proj2 … (Hind i4) (refl …)) //]
197 definition DeqItem ≝ λS.
198 mk_DeqSet (pitem S) (beqitem S) (beqitem_true S).
200 (* We also add a couple of unification hints to allow the type inference system
201 to look at (pitem S) as the carrier of a DeqSet, and at beqitem as if it was the
202 equality function of a DeqSet. *)
204 unification hint 0 ≔ S;
205 X ≟ mk_DeqSet (pitem S) (beqitem S) (beqitem_true S)
206 (* ---------------------------------------- *) ⊢
209 unification hint 0 ≔ S,i1,i2;
210 X ≟ mk_DeqSet (pitem S) (beqitem S) (beqitem_true S)
211 (* ---------------------------------------- *) ⊢
212 beqitem S i1 i2 ≡ eqb X i1 i2.
215 Semantics of pointed regular expressions
217 The intuitive semantic of a point is to mark the position where
218 we should start reading the regular expression. The language associated
219 to a pre is the union of the languages associated with its points. *)
221 let rec in_pl (S : DeqSet) (r : pitem S) on r : word S → Prop ≝
227 | pc r1 r2 ⇒ (in_pl ? r1) · \sem{forget ? r2} ∪ (in_pl ? r2)
228 | po r1 r2 ⇒ (in_pl ? r1) ∪ (in_pl ? r2)
229 | pk r1 ⇒ (in_pl ? r1) · \sem{forget ? r1}^* ].
231 interpretation "in_pl" 'in_l E = (in_pl ? E).
232 interpretation "in_pl mem" 'mem w l = (in_pl ? l w).
234 definition in_prl ≝ λS : DeqSet.λp:pre S.
235 if (\snd p) then \sem{\fst p} ∪ {ϵ} else \sem{\fst p}.
237 interpretation "in_prl mem" 'mem w l = (in_prl ? l w).
238 interpretation "in_prl" 'in_l E = (in_prl ? E).
240 (* The following, trivial lemmas are only meant for rewriting purposes. *)
242 lemma sem_pre_true : ∀S.∀i:pitem S.
243 \sem{〈i,true〉} = \sem{i} ∪ {ϵ}.
246 lemma sem_pre_false : ∀S.∀i:pitem S.
247 \sem{〈i,false〉} = \sem{i}.
250 lemma sem_cat: ∀S.∀i1,i2:pitem S.
251 \sem{i1 · i2} = \sem{i1} · \sem{|i2|} ∪ \sem{i2}.
254 lemma sem_cat_w: ∀S.∀i1,i2:pitem S.∀w.
255 \sem{i1 · i2} w = ((\sem{i1} · \sem{|i2|}) w ∨ \sem{i2} w).
258 lemma sem_plus: ∀S.∀i1,i2:pitem S.
259 \sem{i1 + i2} = \sem{i1} ∪ \sem{i2}.
262 lemma sem_plus_w: ∀S.∀i1,i2:pitem S.∀w.
263 \sem{i1 + i2} w = (\sem{i1} w ∨ \sem{i2} w).
266 lemma sem_star : ∀S.∀i:pitem S.
267 \sem{i^*} = \sem{i} · \sem{|i|}^*.
270 lemma sem_star_w : ∀S.∀i:pitem S.∀w.
271 \sem{i^*} w = (∃w1,w2.w1 @ w2 = w ∧ \sem{i} w1 ∧ \sem{|i|}^* w2).
274 (* Below are a few, simple, semantic properties of items. In particular:
275 - not_epsilon_item : ∀S:DeqSet.∀i:pitem S. ¬ (\sem{i} ϵ).
276 - epsilon_pre : ∀S.∀e:pre S. (\sem{i} ϵ) ↔ (\snd e = true).
277 - minus_eps_item: ∀S.∀i:pitem S. \sem{i} ≐ \sem{i}-{[ ]}.
278 - minus_eps_pre: ∀S.∀e:pre S. \sem{\fst e} ≐ \sem{e}-{[ ]}.
279 The first property is proved by a simple induction on $i$; the other
280 results are easy corollaries. We need an auxiliary lemma first. *)
282 lemma append_eq_nil : ∀S.∀w1,w2:word S. w1 @ w2 = ϵ → w1 = ϵ.
283 #S #w1 #w2 cases w1 // #a #tl normalize #H destruct qed.
285 lemma not_epsilon_lp : ∀S:DeqSet.∀e:pitem S. ¬ (ϵ ∈ e).
286 #S #e elim e normalize /2/
287 [#r1 #r2 * #n1 #n2 % * /2/ * #w1 * #w2 * * #H
288 >(append_eq_nil …H…) /2/
289 |#r1 #r2 #n1 #n2 % * /2/
290 |#r #n % * #w1 * #w2 * * #H >(append_eq_nil …H…) /2/
294 lemma epsilon_to_true : ∀S.∀e:pre S. ϵ ∈ e → \snd e = true.
295 #S * #i #b cases b // normalize #H @False_ind /2/
298 lemma true_to_epsilon : ∀S.∀e:pre S. \snd e = true → ϵ ∈ e.
299 #S * #i #b #btrue normalize in btrue; >btrue %2 //
302 lemma minus_eps_item: ∀S.∀i:pitem S. \sem{i} ≐ \sem{i}-{[ ]}.
304 [#H whd % // normalize @(not_to_not … (not_epsilon_lp …i)) //
309 lemma minus_eps_pre: ∀S.∀e:pre S. \sem{\fst e} ≐ \sem{e}-{[ ]}.
311 [>sem_pre_true normalize in ⊢ (??%?); #w %
312 [/3/ | * * // #H1 #H2 @False_ind @(absurd …H1 H2)]
313 |>sem_pre_false normalize in ⊢ (??%?); #w % [ /3/ | * // ]
320 Intuitively, a regular expression e must be understood as a pointed expression with a single
321 point in front of it. Since however we only allow points before symbols, we must broadcast
322 this initial point inside e traversing all nullable subexpressions, that essentially corresponds
323 to the ϵ-closure operation on automata. We use the notation •(_) to denote such an operation;
324 its definition is the expected one: let us start discussing an example.
327 Let us broadcast a point inside (a + ϵ)(b*a + b)b. We start working in parallel on the
328 first occurrence of a (where the point stops), and on ϵ that gets traversed. We have hence
329 reached the end of a + ϵ and we must pursue broadcasting inside (b*a + b)b. Again, we work in
330 parallel on the two additive subterms b^*a and b; the first point is allowed to both enter the
331 star, and to traverse it, stopping in front of a; the second point just stops in front of b.
332 No point reached that end of b^*a + b hence no further propagation is possible. In conclusion:
333 •((a + ϵ)(b^*a + b)b) = 〈(•a + ϵ)((•b)^*•a + •b)b, false〉
336 (* Broadcasting a point inside an item generates a pre, since the point could possibly reach
337 the end of the expression.
338 Broadcasting inside a i1+i2 amounts to broadcast in parallel inside i1 and i2.
340 〈i1,b1〉 ⊕ 〈i2,b2〉 = 〈i1 + i2, b1 ∨ b2〉
341 then, we just have •(i1+i2) = •(i1)⊕ •(i2).
344 definition lo ≝ λS:DeqSet.λa,b:pre S.〈\fst a + \fst b,\snd a ∨ \snd b〉.
345 notation "a ⊕ b" left associative with precedence 65 for @{'oplus $a $b}.
346 interpretation "oplus" 'oplus a b = (lo ? a b).
348 lemma lo_def: ∀S.∀i1,i2:pitem S.∀b1,b2. 〈i1,b1〉⊕〈i2,b2〉=〈i1+i2,b1∨b2〉.
352 Concatenation is a bit more complex. In order to broadcast a point inside i1 · i2
353 we should start broadcasting it inside i1 and then proceed into i2 if and only if a
354 point reached the end of i1. This suggests to define •(i1 · i2) as •(i1) ▹ i2, where
355 e ▹ i is a general operation of concatenation between a pre and an item, defined by
356 cases on the boolean in e:
358 〈i1,true〉 ▹ i2 = i1 ◃ •(i_2)
359 〈i1,false〉 ▹ i2 = i1 · i2
361 In turn, ◃ says how to concatenate an item with a pre, that is however extremely simple:
363 i1 ◃ 〈i1,b〉 = 〈i_1 · i2, b〉
365 Let us come to the formalized definitions:
368 definition pre_concat_r ≝ λS:DeqSet.λi:pitem S.λe:pre S.
369 match e with [ mk_Prod i1 b ⇒ 〈i · i1, b〉].
371 notation "i ◃ e" left associative with precedence 65 for @{'lhd $i $e}.
372 interpretation "pre_concat_r" 'lhd i e = (pre_concat_r ? i e).
374 (* The behaviour of ◃ is summarized by the following, easy lemma: *)
376 lemma eq_to_ex_eq: ∀S.∀A,B:word S → Prop.
378 #S #A #B #H >H /2/ qed.
380 lemma sem_pre_concat_r : ∀S,i.∀e:pre S.
381 \sem{i ◃ e} ≐ \sem{i} · \sem{|\fst e|} ∪ \sem{e}.
382 #S #i * #i1 #b1 cases b1 [2: @eq_to_ex_eq //]
383 >sem_pre_true >sem_cat >sem_pre_true /2/
386 (* The definition of $•(-)$ (eclose) and ▹ (pre_concat_l) are mutually recursive.
387 In this situation, a viable alternative that is usually simpler to reason about,
388 is to abstract one of the two functions with respect to the other. In particular
389 we abstract pre_concat_l with respect to an input bcast function from items to
392 definition pre_concat_l ≝ λS:DeqSet.λbcast:∀S:DeqSet.pitem S → pre S.λe1:pre S.λi2:pitem S.
394 [ mk_Prod i1 b1 ⇒ match b1 with
395 [ true ⇒ (i1 ◃ (bcast ? i2))
396 | false ⇒ 〈i1 · i2,false〉
400 notation "a ▹ b" left associative with precedence 65 for @{'tril eclose $a $b}.
401 interpretation "item-pre concat" 'tril op a b = (pre_concat_l ? op a b).
403 notation "•" non associative with precedence 65 for @{eclose ?}.
405 (* We are ready to give the formal definition of the broadcasting operation. *)
407 let rec eclose (S: DeqSet) (i: pitem S) on i : pre S ≝
411 | ps x ⇒ 〈 `.x, false〉
412 | pp x ⇒ 〈 `.x, false 〉
413 | po i1 i2 ⇒ •i1 ⊕ •i2
414 | pc i1 i2 ⇒ •i1 ▹ i2
415 | pk i ⇒ 〈(\fst (•i))^*,true〉].
417 notation "• x" non associative with precedence 65 for @{'eclose $x}.
418 interpretation "eclose" 'eclose x = (eclose ? x).
420 (* Here are a few simple properties of ▹ and •(-) *)
422 lemma eclose_plus: ∀S:DeqSet.∀i1,i2:pitem S.
423 •(i1 + i2) = •i1 ⊕ •i2.
426 lemma eclose_dot: ∀S:DeqSet.∀i1,i2:pitem S.
427 •(i1 · i2) = •i1 ▹ i2.
430 lemma eclose_star: ∀S:DeqSet.∀i:pitem S.
431 •i^* = 〈(\fst(•i))^*,true〉.
436 〈i1,true〉 ▹ i2 = i1 ◃ (•i2).
439 lemma odot_true_bis :
441 〈i1,true〉 ▹ i2 = 〈i1 · \fst (•i2), \snd (•i2)〉.
442 #S #i1 #i2 normalize cases (•i2) // qed.
446 〈i1,false〉 ▹ i2 = 〈i1 · i2, false〉.
449 (* The definition of •(-) (eclose) can then be lifted from items to pres
450 in the obvious way. *)
452 definition lift ≝ λS.λf:pitem S →pre S.λe:pre S.
454 [ mk_Prod i b ⇒ 〈\fst (f i), \snd (f i) ∨ b〉].
456 definition preclose ≝ λS. lift S (eclose S).
457 interpretation "preclose" 'eclose x = (preclose ? x).
459 (* Obviously, broadcasting does not change the carrier of the item,
460 as it is easily proved by structural induction. *)
462 lemma erase_bull : ∀S.∀i:pitem S. |\fst (•i)| = |i|.
464 [ #i1 #i2 #IH1 #IH2 >erase_dot <IH1 >eclose_dot
465 cases (•i1) #i11 #b1 cases b1 // <IH2 >odot_true_bis //
466 | #i1 #i2 #IH1 #IH2 >eclose_plus >(erase_plus … i1) <IH1 <IH2
467 cases (•i1) #i11 #b1 cases (•i2) #i21 #b2 //
468 | #i #IH >eclose_star >(erase_star … i) <IH cases (•i) //
472 (* We are now ready to state the main semantic properties of ⊕, ◃ and •(-):
474 sem_oplus: \sem{e1 ⊕ e2} ≐ \sem{e1} ∪ \sem{e2}
475 sem_pcl: \sem{e1 ▹ i2} ≐ \sem{e1} · \sem{|i2|} ∪ \sem{i2}
476 sem_bullet \sem{•i} ≐ \sem{i} ∪ \sem{|i|}
478 The proof of sem_oplus is straightforward. *)
480 lemma sem_oplus: ∀S:DeqSet.∀e1,e2:pre S.
481 \sem{e1 ⊕ e2} ≐ \sem{e1} ∪ \sem{e2}.
482 #S * #i1 #b1 * #i2 #b2 #w %
483 [cases b1 cases b2 normalize /2/ * /3/ * /3/
484 |cases b1 cases b2 normalize /2/ * /3/ * /3/
488 (* For the others, we proceed as follow: we first prove the following
489 auxiliary lemma, that assumes sem_bullet:
492 \sem{•i2} ≐ \sem{i2} ∪ \sem{|i2|} →
493 \sem{e1 ▹ i2} ≐ \sem{e1} · \sem{|i2|} ∪ \sem{i2}.
495 Then, using the previous result, we prove sem_bullet by induction
496 on i. Finally, sem_pcl_aux and sem_bullet give sem_pcl. *)
498 lemma LcatE : ∀S.∀e1,e2:pitem S.
499 \sem{e1 · e2} = \sem{e1} · \sem{|e2|} ∪ \sem{e2}.
502 lemma odot_dot_aux : ∀S.∀e1:pre S.∀i2:pitem S.
503 \sem{•i2} ≐ \sem{i2} ∪ \sem{|i2|} →
504 \sem{e1 ▹ i2} ≐ \sem{e1} · \sem{|i2|} ∪ \sem{i2}.
505 #S * #i1 #b1 #i2 cases b1
506 [2:#th >odot_false >sem_pre_false >sem_pre_false >sem_cat /2/
507 |#H >odot_true >sem_pre_true @(eqP_trans … (sem_pre_concat_r …))
508 >erase_bull @eqP_trans [|@(eqP_union_l … H)]
509 @eqP_trans [|@eqP_union_l[|@union_comm ]]
510 @eqP_trans [|@eqP_sym @union_assoc ] /3/
514 lemma minus_eps_pre_aux: ∀S.∀e:pre S.∀i:pitem S.∀A.
515 \sem{e} ≐ \sem{i} ∪ A → \sem{\fst e} ≐ \sem{i} ∪ (A - {[ ]}).
517 @eqP_trans [|@minus_eps_pre]
518 @eqP_trans [||@eqP_union_r [|@eqP_sym @minus_eps_item]]
519 @eqP_trans [||@distribute_substract]
523 theorem sem_bull: ∀S:DeqSet. ∀i:pitem S. \sem{•i} ≐ \sem{i} ∪ \sem{|i|}.
525 [#w normalize % [/2/ | * //]
527 |#x normalize #w % [ /2/ | * [@False_ind | //]]
528 |#x normalize #w % [ /2/ | * // ]
530 (* lhs = \sem{•(i1 ·i2)} *)
532 (* lhs =\sem{•(i1) ▹ i2)} *)
533 @eqP_trans [|@odot_dot_aux //]
534 (* lhs = \sem{•(i1)·\sem{|i2|}∪\sem{i2} *)
537 [|@eqP_trans [|@(cat_ext_l … IH1)] @distr_cat_r]]
538 (* lhs = \sem{i1}·\sem{|i2|}∪\sem{|i1|}·\sem{|i2|}∪\sem{i2} *)
539 @eqP_trans [|@union_assoc]
540 (* lhs = \sem{i1}·\sem{|i2|}∪(\sem{|i1|}·\sem{|i2|}∪\sem{i2}) *)
541 (* Now we work on the rhs that is
542 rhs = \sem{i1·i2} ∪ \sem{|i1·i2|} *)
544 (* rhs = \sem{i1}·\sem{|i2|} ∪ \sem{i2} ∪ \sem{|i1·i2|} *)
545 @eqP_trans [||@eqP_sym @union_assoc]
546 (* rhs = \sem{i1}·\sem{|i2|}∪ (\sem{i2} ∪ \sem{|i1·i2|}) *)
547 @eqP_union_l @union_comm
548 |#i1 #i2 #IH1 #IH2 >eclose_plus
549 @eqP_trans [|@sem_oplus] >sem_plus >erase_plus
550 @eqP_trans [|@(eqP_union_l … IH2)]
551 @eqP_trans [|@eqP_sym @union_assoc]
552 @eqP_trans [||@union_assoc] @eqP_union_r
553 @eqP_trans [||@eqP_sym @union_assoc]
554 @eqP_trans [||@eqP_union_l [|@union_comm]]
555 @eqP_trans [||@union_assoc] /2/
556 |#i #H >sem_pre_true >sem_star >erase_bull >sem_star
557 @eqP_trans [|@eqP_union_r [|@cat_ext_l [|@minus_eps_pre_aux //]]]
558 @eqP_trans [|@eqP_union_r [|@distr_cat_r]]
559 @eqP_trans [|@union_assoc] @eqP_union_l >erase_star
560 @eqP_sym @star_fix_eps
567 As a corollary of theorem sem_bullet, given a regular expression e, we can easily
568 find an item with the same semantics of $e$: it is enough to get an item (blank e)
569 having e as carrier and no point, and then broadcast a point in it. The semantics of
570 (blank e) is obviously the empty language: from the point of view of the automaton,
571 it corresponds with the pit state. *)
573 let rec blank (S: DeqSet) (i: re S) on i :pitem S ≝
578 | o e1 e2 ⇒ (blank S e1) + (blank S e2)
579 | c e1 e2 ⇒ (blank S e1) · (blank S e2)
580 | k e ⇒ (blank S e)^* ].
582 lemma forget_blank: ∀S.∀e:re S.|blank S e| = e.
583 #S #e elim e normalize //
586 lemma sem_blank: ∀S.∀e:re S.\sem{blank S e} ≐ ∅.
590 |#e1 #e2 #Hind1 #Hind2 >sem_cat
591 @eqP_trans [||@(union_empty_r … ∅)]
592 @eqP_trans [|@eqP_union_l[|@Hind2]] @eqP_union_r
593 @eqP_trans [||@(cat_empty_l … ?)] @cat_ext_l @Hind1
594 |#e1 #e2 #Hind1 #Hind2 >sem_plus
595 @eqP_trans [||@(union_empty_r … ∅)]
596 @eqP_trans [|@eqP_union_l[|@Hind2]] @eqP_union_r @Hind1
598 @eqP_trans [||@(cat_empty_l … ?)] @cat_ext_l @Hind
602 theorem re_embedding: ∀S.∀e:re S.
603 \sem{•(blank S e)} ≐ \sem{e}.
604 #S #e @eqP_trans [|@sem_bull] >forget_blank
605 @eqP_trans [|@eqP_union_r [|@sem_blank]]
606 @eqP_trans [|@union_comm] @union_empty_r.
612 Plus and bullet have been already lifted from items to pres. We can now
613 do a similar job for concatenation ⊙ and Kleene's star ⊛. *)
615 definition lifted_cat ≝ λS:DeqSet.λe:pre S.
616 lift S (pre_concat_l S eclose e).
618 notation "e1 ⊙ e2" left associative with precedence 70 for @{'odot $e1 $e2}.
620 interpretation "lifted cat" 'odot e1 e2 = (lifted_cat ? e1 e2).
622 lemma odot_true_b : ∀S.∀i1,i2:pitem S.∀b.
623 〈i1,true〉 ⊙ 〈i2,b〉 = 〈i1 · (\fst (•i2)),\snd (•i2) ∨ b〉.
624 #S #i1 #i2 #b normalize in ⊢ (??%?); cases (•i2) //
627 lemma odot_false_b : ∀S.∀i1,i2:pitem S.∀b.
628 〈i1,false〉 ⊙ 〈i2,b〉 = 〈i1 · i2 ,b〉.
632 lemma erase_odot:∀S.∀e1,e2:pre S.
633 |\fst (e1 ⊙ e2)| = |\fst e1| · (|\fst e2|).
634 #S * #i1 * * #i2 #b2 // >odot_true_b //
637 (* Let us come to the star operation: *)
639 definition lk ≝ λS:DeqSet.λe:pre S.
643 [true ⇒ 〈(\fst (eclose ? i1))^*, true〉
644 |false ⇒ 〈i1^*,false〉
648 (* notation < "a \sup ⊛" non associative with precedence 90 for @{'lk $a}.*)
649 interpretation "lk" 'lk a = (lk ? a).
650 notation "a^⊛" non associative with precedence 90 for @{'lk $a}.
653 lemma ostar_true: ∀S.∀i:pitem S.
654 〈i,true〉^⊛ = 〈(\fst (•i))^*, true〉.
657 lemma ostar_false: ∀S.∀i:pitem S.
658 〈i,false〉^⊛ = 〈i^*, false〉.
661 lemma erase_ostar: ∀S.∀e:pre S.
662 |\fst (e^⊛)| = |\fst e|^*.
665 lemma sem_odot_true: ∀S:DeqSet.∀e1:pre S.∀i.
666 \sem{e1 ⊙ 〈i,true〉} ≐ \sem{e1 ▹ i} ∪ { [ ] }.
668 cut (e1 ⊙ 〈i,true〉 = 〈\fst (e1 ▹ i), \snd(e1 ▹ i) ∨ true〉) [//]
669 #H >H cases (e1 ▹ i) #i1 #b1 cases b1
670 [>sem_pre_true @eqP_trans [||@eqP_sym @union_assoc]
676 lemma eq_odot_false: ∀S:DeqSet.∀e1:pre S.∀i.
677 e1 ⊙ 〈i,false〉 = e1 ▹ i.
679 cut (e1 ⊙ 〈i,false〉 = 〈\fst (e1 ▹ i), \snd(e1 ▹ i) ∨ false〉) [//]
680 cases (e1 ▹ i) #i1 #b1 cases b1 #H @H
683 (* We conclude this section with the proof of the main semantic properties
687 ∀S.∀e1,e2: pre S. \sem{e1 ⊙ e2} ≐ \sem{e1}· \sem{|\fst e2|} ∪ \sem{e2}.
690 @eqP_trans [|@sem_odot_true]
691 @eqP_trans [||@union_assoc] @eqP_union_r @odot_dot_aux //
692 |>sem_pre_false >eq_odot_false @odot_dot_aux //
696 theorem sem_ostar: ∀S.∀e:pre S.
697 \sem{e^⊛} ≐ \sem{e} · \sem{|\fst e|}^*.
699 [(* lhs = \sem{〈i,true〉^⊛} *)
700 >sem_pre_true (* >sem_pre_true *)
701 (* lhs = \sem{(\fst (•i))^*}∪{ϵ} *)
702 >sem_star >erase_bull
703 (* lhs = \sem{\fst (•i)}·(\sem{|i|)^*∪{ϵ} *)
704 @eqP_trans [|@eqP_union_r[|@cat_ext_l [|@minus_eps_pre_aux //]]]
705 (* lhs = (\sem{i}∪(\sem{|i|}-{ϵ})·(\sem{|i|)^*∪{ϵ} *)
706 @eqP_trans [|@eqP_union_r [|@distr_cat_r]]
707 (* lhs = (\sem{i}·(\sem{|i|)^*∪(\sem{|i|}-{ϵ})·(\sem{|i|)^*∪{ϵ} *)
708 @eqP_trans [|@union_assoc]
709 (* lhs = (\sem{i}·(\sem{|i|)^*∪((\sem{|i|}-{ϵ})·(\sem{|i|)^*∪{ϵ}) *)
710 @eqP_trans [|@eqP_union_l[|@eqP_sym @star_fix_eps]]
711 (* lhs = (\sem{i}·(\sem{|i|)^*∪(\sem{|i|)^* *)
712 (* now we work on the right hand side, that is
713 rhs = \sem{〈i,true〉}·(\sem{|i|}^* *)
714 @eqP_trans [||@eqP_sym @distr_cat_r]
715 (* rhs = (\sem{i}·(\sem{|i|)^*∪{ϵ}·(\sem{|i|)^* *)
716 @eqP_union_l @eqP_sym @epsilon_cat_l
717 |>sem_pre_false >sem_pre_false >sem_star /2/