TD N° 1

Transcription

TD N° 1
Licence d'Informatique 2010-11
UL5 — Langages et applications
TD N° 1
0. Langages et alphabets
On dit dans le cours que les langues « naturelles » alphabétiques comme le français
constituent un langage. En fait, plusieurs langages différents (au sens « formel ») peuvent
être considéré. En donner (au moins) trois exemples, en précisant à chaque fois quel est
« l’alphabet ».
1. Expressions régulières (ou rationnelles)
- Décrire les langages suivants (« les mots qui … », donner des exemples de mots du
langage) : (a|b)*(ab)+
(a|b)*(cd) +(a|b)*
a*b(a|b)*
- Donner une expression régulière pour les langages suivants :
-
{a, b, aa, ab, ba, bb}
-
les mots constitués d'un a seul ou d’au moins 2 a suivis d'un b
2. Expressions régulières et automates finis déterministes (AFD)
Quels langages les automates suivants reconnaissent-ils (Σ = {a,b} ou {a,b,c}) ? Donner
une expression régulière équivalente. Construire la table de transition de l’automate.
a)
a
a,b
b
b)
a
a
b
b
c)
a,b
0
c
1
a,b
1
3. Propriétés algébriques des expressions régulières
a. Comparer les langages définis par les expressions régulières (égalité, inclusion…).
-
(a|b)* et a*|b*
-
(a|b)(c|d) et ac|bd
-
(b*a)+ et a+|(a|b)*a. Si égales, donnez une 3° forme.
b. Compléter : E | E = ?
(E|F)* = ?
ε*=?
E*|E = ?
(E*)* = ?
(donner notamment : une expression sans "|")
4. Définitions régulières
Pour écrire des expressions régulières (sur un alphabet de lettres) "en pratique" on utilise
un certain nombre d'abréviations :
[abc] pour a|b|c
[a-z] pour a|b|…|z
[a-zA-Z0-9] pour toutes les lettres et chiffres
x? pour un x optionnel
Il est également commode d'introduire des définitions régulières
d1 = r1
d2 = r2
…
dn = rn
où les di sont des identificateurs et les ri des expressions régulières sur ∑ ∪ {d1,…,di-1}.
NB. Notez bien : ri ne peut pas contenir d’occurrence de dj pour j≥i.
Exemple : nombres = suites de chiffres ne commençant pas par 0, ou bien 0 seul.
chiffre_non_nul = [1-9]
chiffre = chiffre_non_nul | 0
entier = chiffre_non_nul chiffre* | 0
N.B. entier peut ensuite servir dans une autre définition (cf plus loin)
a. Un identificateur est une suite de lettres ou de chiffres commençant par une lettre.
Ecrire une définition régulière.
b. Idem, mais en imposant la première lettre soit une majuscule (variables dans le
langage de programmation Prolog, noms de type en Haskell)
c. Chaines de lettres avec les 5 voyelles dans l'ordre a,e,i,o,u (avec répétitions possibles).
Exemple : un début peut être kdhaghahjeeejemdmiggki…
d. Nombres réels, tels que :
543 67.45 0.5
67.45E3
67.45E+3
67.45E-5
Indication : on pourra définir plusieurs « sous langages » : entiers, partie décimale…
Discutez du format : acceptation du 0 en tête de partie entière, partie entière vide…
2
5. Complémentaire et produit. Ecrire un automate reconnaissant les langages
suivants.
a) Ecrire un automate reconnaissant le langage complémentaire du 2.c.(Indication :
commencez par le complété et appliquez la méthode du cours).
b) L0 = {ε} et L1 = tous les mots non vides. Construire l’automate pour L1
« directement » et à partir de celui de L0.
c) Mots contenant un nombre pair de a et de b. Procédez par produit d’automates
(cf. question 2b). Interprétez l’automate obtenu.
6. Les langages finis sont réguliers
a) Ecrire un automate qui reconnaît le langage (fini) : L0 = {aab,baa,aaa}. Ecrire un AFD
incomplet A en forme d’arbre, puis l’AFD complet correspondant. NB. L’AFD
incomplet arborescent est appelé « écorché » de L0.
b) Quel est le langage engendré quand on rend finaux tous les états de l’automate
(incomplet) précédent ? Comment pourrait-on étiqueter les états de A de manière
« parlante » ?
c) De manière générale, décrire 1 automate (AFD incomplet) qui reconnaît un langage
fini quelconque L.
Indications : En vous inspirant de la question b, définir l’ensemble des états. Définir la
fonction de transition ∂(q,x). Définir l’état initial i et l’ensemble F des états finaux.
NB. C’est une technique de représentation de lexiques (alternative par exemple au
hachage, efficace et particulièrement économique en mémoire) connue comme les
« arbres de lettres » (anglais « tries » : de « tree » et « retrieval »). Très utilisée en
traitement du langage naturel.
d) Application : reconnaissance de mots dans un texte. Il s’agit de savoir si un texte T
(assimilé à un « grand » mot) contient un mot w d’un certain ensemble fini L. Par
exemple : bababaabbabaa contient baa (plusieurs fois) et aab.
- Imaginez un algorithme simple utilisant l’automate complet du a. L’appliquez à
l’exemple donné (bababaabbabaa et langage L0 du a). Variantes : trouver 1 occurrence
ou toutes les occurrences.
- Une autre manière, plus efficace, de procéder est de compléter l’automate incomplet
(l’écorché) « astucieusement » pour faire le même travail. Indication : il faut donc savoir
« que faire » si on rencontre une lettre non prévue.
Remarque : il s’agit donc de reconnaître le langage Σ*L (les mots qui finissent par un mot
de L).
3
Licence d'Informatique 2010-11
UL5 — Langages et Applications
TD N° 1 - CORRECTION
0. Pour le français
- ∑ = tous les caractères, y compris la ponctuation. L1= tous les textes possibles.
- Même alphabet, L2 = toutes les phrases grammaticalement correctes
- ∑ = toutes les lettres + l’apostrophe et le -. L3 = tous les mots du français.
- ∑ = tous les mots + les ponctuations, L4 = Toutes les phrases.
1 – Mots sur {a,b} finissant par une succession de (ab).
- une suite de (cd) prise entre deux mots quelconques sur {a,b}
- Mots contenant au moins 1 b
- Donner une expression régulière pour les langages suivants :
-
{a, b, aa, ab, ba, bb} : (a|b| ε) (a|b)
-
les mots constitués d'un a seul ou d’au moins 2 a suivis d'un b : a|aa+b = a (ε | a+b)
2. a) mots contenant au moins 1 b. a*b(a|b)*
a
b
1
1
2
2
2
2
Init = 1, Fin = {2}
b) nombre pair (éventuellement nul) de b. (a|ba*b)*
a
b
1
1
2
2
2
1
Init = 1, Fin = {1}
c) « tout c est suivi d’un a ou d’un b »
3. a. (a|b)* contient strictement a*|b*
(a|b)(c|d) = ac|ad|bc|bd contient strictement ac|bd
(b*a)+ = a+|(a|b)*a = (a|b)*a = mots finissant par a (contenant au moins 1 a).
b. E | E = E
ε*=ε
E*|E = E*
(E*)* = E*
(E|F)* = (E*|F*)* = (E* F*)*= … beaucoup d’autres formes
4. Définitions régulières
a. lettre = [a-zA-Z] chiffre=[0-9] ident = lettre (lettre|chiffre)*
b. maj = [A-Z]
var = maj (lettre|chiffre)*
c. consonne = [bcdfgh....z]
mot = consonne* (a consonne*)* … (u consonne*)*
d. chiffre_non_nul = [1-9]
4
chiffre = chiffre_non_nul | 0
entier = chiffre_non_nul chiffre* | 0
decimal = .chiffre+
expt = E[+-]?entier
reel = [+-] ? (entier decimal? | decimal) expt?
NB. entier ? decimal? ne peut convenir comme partie centrale, car elle admet le mot
vide.
5. Complémentaire et produit
a) Complémentaire = présence de 2 c consécutif
a,b
c
0
1
a,b
c
P
a,b,c
b) L0
L1 = le complémentaire
a,b
a,b
a,b
Complété
a,b
c) L’automate cherché est le produit de A1, reconnaissant les mots avec un nombre pair
de a, et A2 similaire pour b (cf. question 2b). L’indice de p dans (pi,qj) donne la parité du
nombre de a lus (1-> impair, 2->pair) et de même pour q avec les b.
A1
A2
b
p1
a
b
p2
a
q1
b
a
q2
A1
p1
p2
A2
q1
q2
a
p2
p1
a
q1
q2
b
p1
p2
b
q2
q1
PRODUIT
5
A1xA2
(p1,q1)
(p1,q2)
(p2,q1)
(p2,q2)
a
(p2,q1)
(p2,q2)
(p1,q1)
(p1,q2)
b
(p1,q2)
(p1,q1)
(p2,q2)
(p2,q1)
6. Langages finis
a) L0 = {aab,baa,aaa}.
Automate incomplet :
a
a
aaa
a
a
ε
ε
b
aa
a
b
aab
b
a
ba
baa
a
Automate complet (avec état Puits ou ici « rejet »).
a
a
ε
ε
b
b
a
a
aa
a
b
b
a
aaa
aab
b
ba
a,b
a,b
a,b
Rejet
baa
a
b) Soit K = l'ensemble des préfixes du langage fini L donné. (sur l’exemple :
{ε,a,b,aa,ba,aaa,aab,baa})
L’automate est défini par :
Q = {qw : w dans K} U {qrejet} ;
état initial qε ;
δ(qw , x) = qwx si wx dans K et qrejet sinon
et
F = {qw : w dans L}
δ( qrejet, x) = qrejet
Propriété :
δ(qε , w) = qw si w dans K et indéfini sinon
(ou, sur le complété : δ(qε , w) = qw si w dans K et qrejet sinon.)
6
NB. On peut en faire la preuve par induction sur w (autrement dit : sa longueur)
Cas de base : δ(i, ε) = i = qε
Pas d’induction : w = w’x, et la propriété est vraie pour w’.
-
Si w est dans K, w’ qui est un préfixe est aussi dans K. Par hypothèse
d’induction, δ(qε , w’) = qw’ et δ(qε , w) = δ (δ (qε , w),x) = δ ( qw’ , x)) =
qw’x = qw.
-
Si w n’est pas dans K : soit w’ n’est déjà pas dans K et δ(qε , w’) = qrejet
donc également δ(qε , w) = qrejet ; soit w’ est dans K, δ(qε , w’) = qw’ mais
comme w=w’x n’est pas dans K, et de nouveau δ(qε , w) = qrejet.
Il faut alors montrer que
δ(qε , w) est dans F ssi w est dans L
-
si w est dans L, alors il est dans K, donc δ(qε , w) est défini et vaut qw . Donc qw
dans F par définition de F.
-
si w n’est dans L, alors : soit w est dans K, donc δ(qε ,w) est défini et vaut qw,
non final ; soit w n’est pas dans K et δ(qε ,w) n’est défini. Dans les 2 cas, w est
rejeté par l’automate.
c) L’algorithme « naïf » serait :
-
essayer de reconnaître un des mots clés m à partir de la position courante (avec
l’automate du a)
-
si on arrive dans l’état « rejet », on avance d’un caractère dans la chaîne lue, et on
recommence à partir de l’état initial (qε).
Méthode plus efficace :
On commence par construire l’automate incomplet reconnaissant le langage
(« l’écorché de L »). Puis on complète « astucieusement » les transitions manquantes.
L’idée est d’essayer de repartir dans l’automate « le plus loin possible ».
Une procédure pour faire cela automatiquement est celle de Morris et Pratt. Elle repose
sur la notion de fonction d’échec.
Supposons que les état s et t représentent, dans l’écorché, resp. les préfixes u et v d’un
des mots clés.
F(s) = t si v est le suffixe propre le plus long de u qui est aussi préfixe d’un des motclés. ε sinon (pas de suffixe propre…)
1) Calculer la fonction d’échec pour l’exemple.
2) En déduire la construction de l’automate « optimisé ».
Fonction d’échec :
s:
ε
a
aa
aaa
aab
b
ba
baa
F(s) : ε
ε
a
aa
b
ε
a
aa
On complète alors les transitions manquantes : s –x—>t
si
F(s) –x-->t
7
a
a
a
ε
ε
b
aaa
a
a
aa
a
b
b
b
b
b
b
aab
a
b
a
ba
baa
a
8
a