Reuniunea limbajelor regulate
Fie două limbaje regulate L1, L2. Vom demonstra că reuniunea lor L = L1 ∪ L2 este, de asemenea, un limbaj regulat.
Construcția cu automat determinist
Ideea construcției
Avem două limbaje regulate L1 și L2 și vrem să demonstrăm că reuniunea lor L1 ∪ L2 este tot un limbaj regulat. Deoarece L1 și L2 sunt limbaje regulate, există automate finite A1 și A2 care acceptă limbajele L1 și L2, adică L(A1) = L1 și L(A2) = L2. Vom construi un automat finit A care acceptă limbajul L1 ∪ L2, demonstrând astfel că limbajul L1 ∪ L2 este regulat.
Cum procedăm? Avem automatele finite A1 și A2, care acceptă limbajele inițiale. Putem spune că un cuvânt w aparține limbajului L1 ∪ L2 dacă și numai dacă este acceptat de cel puțin unul dintre automatele A1 sau A2.
Automatul A ar putea funcționa astfel: pentru intrarea w va simula calculul automatului A1 pe intrarea w. Dacă A1 acceptă cuvântul w, atunci și A acceptă cuvântul w. Dacă A1 respinge cuvântul w, A încearcă să simuleze și calculul lui A2 pe intrarea w. Dacă A2 acceptă cuvântul w, atunci și A acceptă cuvântul w. În caz contrar, îl respinge.
Ne rămâne să formalizăm ce înseamnă că automatul A „simulează” calculul altui automat.
Formalizare
Avem două limbaje regulate L1 și L2, acceptate de automatele finite
Construim un automat finit A = ⟨Q, Σ, δ, q, F⟩ care va accepta limbajul L = L1 ∪ L2. Ne folosim de ideea simulării simultane a două automate A1, A2. Să ne închipuim că avem la intrare cuvântul w = w1w2… wn și că simulăm în paralel funcționarea automatelor A1 și A2 pe cuvântul w. Configurația inițială a automatului A1 este ⟨q1, w1w2… wn⟩, iar cea a automatului A2 este ⟨q2, w1w2… wn⟩. Efectuăm acum în fiecare automat câte un pas de calcul și ajungem în configurațiile ⟨δ1(q1, w1), w2… wn⟩ și ⟨δ2(q2, w1), w2… wn⟩.
Vedem că aceste configurații diferă doar prin prima componentă; a doua – partea necitită a cuvântului – este mereu aceeași. În timpul simulării nu trebuie deci să ținem două configurații ale celor două automate, ci ne ajunge una singură, de forma ⟨⟨qi, qj⟩, wl… wn⟩, unde qi ∈ Q1 și qj ∈ Q2. Cu alte cuvinte, automatul A pe care îl construim va avea configurația inițială ⟨⟨q1, q2⟩, w⟩. Prima componentă a perechii ⟨q1, q2⟩ reprezintă starea în care se află în acel moment automatul A1, iar a doua componentă este starea curentă a automatului A2.
Putem scrie așadar că automatul A va avea mulțimea stărilor Q = Q1 × Q2. Este produsul cartezian al stărilor celor două automate de mai sus. Ideea următoare este că automatul A va avea starea inițială ⟨q1, q2⟩ și, dacă automatul A1 trece pentru simbolul w1 în starea qi, iar automatul A2 trece pentru simbolul w1 în starea qj, atunci automatul A trece pentru simbolul w1 în starea ⟨qi, qj⟩.
Funcția de tranziție δ o scriem astfel (presupunem deja că ne aflăm în stările qi și qj):
Rămân doar mici detalii. Pentru alfabet avem Σ= Σ1 ∪ Σ2. Starea inițială este q = ⟨q1, q2⟩. Iar stările finale sunt toate perechile ⟨qi, qj⟩ pentru care qi ∈ F1 sau qj ∈ F2.
Ilustrarea construcției
Fie două automate. Primul este automatul A1, care acceptă toate cuvintele (inclusiv cuvântul vid) în care alternează zerourile și unitățile, adică cuvintele de forma 01, 0101, 010101, …
Al doilea automat, A2, acceptă cuvintele care conțin cel puțin un zero:
Reuniunea acestor limbaje este formată din cuvintele care fie conțin un zero, fie sunt de forma 01, 0101, … Construim acum automatul finit A = ⟨Q, Σ, δ, q, F⟩ care va accepta exact acest limbaj reunit. Mai întâi vedem cum vor arăta stările noului automat A. Ele formează produsul cartezian al stărilor primului și celui de-al doilea automat:
Acestea sunt cele șase stări ale automatului A, care acceptă limbajul reunit L(A1) ∪ L(A2). În diagramă ar arăta astfel:
Nu te speria că stările sunt formate din perechi de stări – așa ne orientăm mai ușor în ceea ce se petrece de fapt în automat. Stările s-ar putea numi foarte bine, ca de obicei, q0, …, q5. Stările finale sunt cele care conțin starea q0 sau p1, adică stările finale ale automatelor inițiale. Starea inițială este ⟨q0, p0⟩.
Acum trebuie să aflăm toate tranzițiile. Scriem un tabel:
Și îl completăm pas cu pas. Mai întâi aflăm unde duce tranziția din starea ⟨q0, p0⟩ pentru intrarea 0. Vedem unde duce tranziția din starea q0 pentru intrarea 0 în automatul A1: duce în starea q1. În automatul A2, tranziția din p0 pentru zero duce în starea p1. În tabel scriem deci ⟨q1, p1⟩:
Pentru intrarea 1 obținem: în automatul A1 avem δ1(q0, 1) = q2, iar în automatul A2 avem δ2(p0, 1) = p0. Obținem astfel starea ⟨q2, p0⟩.
Completăm restul tabelului:
Iar după acest tabel desenăm restul diagramei.
Putem verifica dacă automatul funcționează cum trebuie. Încercăm să acceptăm cuvântul 0100. Automatul trece pe rând prin stările
Deoarece starea ⟨q2, p1⟩ este finală, automatul A acceptă cuvântul 0100. Cum ar fi decurs lucrurile dacă am fi încercat să acceptăm cuvântul 0100 cu automatele A1 și A2? Automatul A1 ar fi trecut pe rând prin stările:
Automatul s-a oprit în starea q2, care nu este finală, deci automatul A1 nu ar accepta acest cuvânt. Dar automatul A2?
Starea p1 este finală, deci automatul A2 ar accepta cuvântul 0100. Observă că automatele A1 și A2 s-au oprit în stările q2 și p1, ceea ce corespunde faptului că automatul A s-a oprit în starea ⟨q2, p1⟩.
Construcția cu automat nedeterminist
Exemplu
Faptul că mulțimea limbajelor regulate este închisă la reuniune îl putem demonstra și construind un automat nedeterminist, mult mai simplu.
Avem deci două limbaje regulate L1, L2 și vrem să demonstrăm că reuniunea lor L = L1 ∪ L2 este tot un limbaj regulat. Deoarece L1, L2 sunt limbaje regulate, trebuie să existe automate A1, A2 care acceptă aceste limbaje. Adică L(A1) = L1 și L(A2) = L2. Cu ajutorul acestor automate construim automatul A, care va accepta limbajul L, adică L(A) = L.
Presupunem că automatele finite A1 și A2 arată astfel:
și
Automatul care ar accepta reuniunea celor două limbaje l-am construi creând o nouă stare inițială, din care ducem două ε-tranziții în stările inițiale originale. Asta e tot. Automatul ar arăta astfel:
Formalizare
Avem două automate A1 = ⟨Q1, Σ, δ1, q1, F1⟩ și A2 = ⟨Q2, Σ, δ2, q2, F2⟩. Construim automatul A = ⟨Q, Σ, δ, q0, F⟩, care va accepta reuniunea limbajelor acceptate de automatele de mai sus, adică L(A) = L(A1) ∪ L(A2). Aici avem:
- Q = Q1 ∪ Q2 ∪ {q0}
- F = F1 ∪ F2
Iar funcția de tranziție δ o definim astfel:
Surse
Capitole: Închiderea la operații, Reuniunea, Intersecția, Diferența, Complementul, Concatenarea, Închiderea Kleene