Język regularny: Różnice pomiędzy wersjami
[wersja przejrzana] | [wersja przejrzana] |
Usunięta treść Dodana treść
Dodanie domknięcia Kleene'ego do podrozdziału "Operacje na językach regularnych" |
|||
Linia 7:
Regułami gramatyki regularnej są więc na przykład:
: <math>A \
: <math>A \
: <math>A \
: <math>A \
: <math>A \
: <math>A \
Nie są zaś nimi na przykład:
: <math>A \
: <math>AB \
Zależności między językami regularnymi a gramatykami regularnymi są następujące:
* Każdy język regularny '''można''' zapisać za pomocą gramatyki regularnej.
* Każda gramatyka regularna '''generuje''' pewien język regularny.
* Język, który '''nie jest''' regularny '''nie posiada''' gramatyki regularnej.
* Gramatyka, która nie jest regularna '''może''' generować język regularny, acz nie musi. Jeśli takowy generuje, ma on też inną gramatykę, która jest regularna.
Linia 34:
* zbiór wszystkich słów alfabetu <math>\{0,1,2\}</math> w których na przemian występują zera, jedynki i dwójki
Zbiór wszystkich języków regularnych oznacza się przez
== Operacje na językach regularnych ==
Linia 48:
* konkatenacji
** język słów które można podzielić tak, że początkowa część słowa składa się z naprzemiennie ustawionych zer i jedynek, a końcowa z naprzemiennie ustawionych zer, jedynek i dwójek, jest regularny
* [[Domknięcie Kleene’ego|domknięcia
** np. język składający się tylko z 0 i 1 po zastosowaniu domknięcia
== [[Deterministyczny automat skończony|Deterministyczne automaty skończone]] (DFA) ==
Do testowania, czy dane słowo należy do danego języka regularnego można zawsze zbudować '''deterministyczny automat skończony''' – maszynę która ma skończoną liczbę stanów, oraz funkcję przejścia, zmieniającą jej stan po przeczytaniu każdego kolejnego znaku w zależności od przeczytanego znaku oraz stanu aktualnego. Niektóre z tych stanów oznaczone są jako [[stan akceptujący|akceptujące]] – tzn. że przeczytany dotychczas fragment jest poprawnym słowem języka, dla którego zbudowano automat.
Rodzinę języków rozpoznawalnych przez automaty skończone oznacza się przez
=== Przykład automatu deterministycznego ===
Automat służący do sprawdzania czy dane słowo binarne zaczyna się od jedynki mógłby wyglądać tak:
* Stany automatu to Start, ZaczynaSięOdJedynki i ZaczynaSięOdZera.
* Automat zaczyna w stanie Start.
* Jeśli automat jest w stanie Start, to po przeczytaniu 0 przechodzi w stan ZaczynaSięOdZera.
* Jeśli automat jest w stanie Start, to po przeczytaniu 1 przechodzi w stan ZaczynaSięOdJedynki.
* Jeśli automat jest w dowolnym innym stanie, po przeczytaniu jakiegokolwiek znaku nie zmienia stanu.
* Automat akceptuje słowo, jeśli po przeczytaniu całego znajduje się w stanie ZaczynaSięOdJedynki.
=== Przykład automatu deterministycznego (2) ===
Automat służący do sprawdzania czy dane słowo binarne kończy się jedynką mógłby wyglądać tak:
* Stany automatu to Start, OstatniZnakToJedynka i OstatniZnakToZero.
* Automat zaczyna w stanie Start.
* Po przeczytaniu 0, niezależnie od poprzedniego stanu, automat przechodzi w stan OstatniZnakToZero.
* Po przeczytaniu 1, niezależnie od poprzedniego stanu, automat przechodzi w stan OstatniZnakToJedynka.
* Automat akceptuje słowo, jeśli po przeczytaniu całego znajduje się w stanie OstatniZnakToJedynka.
=== Przykład automatu deterministycznego (3) ===
Automat służący do sprawdzania czy dane słowo binarne ma <math>n</math> lub <math>m</math>
* Stany to <math>S_0,</math>
* Stan początkowy to <math>S_0.</math>
* Jeśli automat jest w stanie <math>S_k</math>
* Jeśli automat jest w stanie <math>S_n,</math>
* Jeśli automat jest w stanie ZaDługie, po przeczytaniu dowolnego znaku pozostaje w stanie ZaDługie.
* Akceptujące są stany <math>S_n</math> i <math>S_m.</math>
=== Twierdzenie Kleene’ego ===
Twierdzenie Kleene’ego dokładnie określa relacje pomiędzy rodzinami języków
Główną konsekwencją tego dowodu jest, wspomniana już wcześniej, bezpośrednia zależność języków regularnych i automatów skończonych. Zatem dla każdego języka regularnego można stworzyć automat skończony i, analogicznie, każdy automat skończony rozpoznaje język regularny.
Linia 97 ⟶ 96:
=== Przykład ===
Weźmy NFA rozpoznające język słów nad alfabetem binarnym, których czwartym od końca znakiem jest 1:
* <math>S \
* <math>S \
* <math>S \
* <math>X_1 \
* <math>X_1 \
* <math>X_2 \
* <math>X_2 \
* <math>X_3 \
* <math>X_3 \
* <math>X_4 \
* <math>X_4 \
* Stan startowy to <math>S,</math>
Możemy uruchomić ten automat na słowie <math>0101000{:}</math>
: <math>S \
Choć możemy też uruchomić go tak, żeby nie zaakceptował słowa:
: <math>S \
: <math>S \
=== Konwersja NFA do DFA ===
Linia 122 ⟶ 121:
Nie musimy jednak pamiętać wszystkich ścieżek. Nieważne, co znajdowało się na początku ścieżki – nam wystarcza wiedza, '''jakie stany''' występują na dowolnej ze ścieżek po <math>k</math> krokach.
Na początku bierzemy więc zbiór złożony jedynie ze stanu startowego emulowanego NFA, po każdym kroku zaś zbiór takich stanów <math>X,</math>
Słowo jest akceptowane jeśli wśród zbioru stanów po przeczytaniu całego znajduje się choć jeden stan akceptujący.
Przyjmując zbiory stanów NFA za stany DFA, każde NFA możemy emulować w pełni deterministycznie na DFA. Być może jednak liczba stanów będzie musiała wzrosnąć wykładniczo.
=== Przykład konwersji ===
Weźmy podany wyżej automat rozpoznający słowa, których czwartym od końca znakiem jest jedynka. Następuje wykładnicza eksplozja liczby stanów:
: <math>\{S\} \
: <math>\{S,X_1\} \
: <math>\{S,X_1\} \
: <math>\{S,
: <math>\{S,X_2\} \
: <math>\{S,X_1,X_2\} \
: <math>\{S,X_1,X_2\} \
: <math>\{S,
: <math>\{S,X_3\} \
: <math>\{S,X_1,X_3\} \
: <math>\{S,X_1,X_3\} \
: <math>\{S,
: <math>\{S,X_2,X_3\} \
: <math>\{S,X_1,X_2,X_3\} \
: <math>\{S,X_1,X_2,X_3\} \
: <math>\{S,
: <math>\{S,X_4\} \
: <math>\{S,X_1,X_4\} \
: <math>\{S,X_1,X_4\} \
: <math>\{S,
: <math>\{S,X_2,X_4\} \
: <math>\{S,X_1,X_2,X_4\} \
: <math>\{S,X_1,X_2,X_4\} \
: <math>\{S,
: <math>\{S,X_3,X_4\} \
: <math>\{S,X_1,X_3,X_4\} \
: <math>\{S,X_1,X_3,X_4\} \
: <math>\{S,
: <math>\{S,X_2,X_3,X_4\} \
: <math>\{S,X_1,X_2,X_3,X_4\} \
: <math>\{S,X_1,X_2,X_3,X_4\} \
▲: <math>\{S,X_1,X_2,X_3,X_4\} \rightarrow^1 \{S,X_1,X_2,X_3,X_4\}</math>
Przy czym akceptujące są stany zawierające <math>X_4,</math>
Sprawdźmy tym automatem słowo <math>0101000{:}</math>
: <math>\{S\} \
== Wyrażenia regularne ==
Jeszcze jedną metodą wyrażania języków regularnych są [[Wyrażenie regularne|wyrażenia regularne]]. Wyrażenie takie <math>X</math> tworzy się używając:
* <math>\epsilon</math> – oznaczającego język złożony ze słowa pustego,
* symboli nieterminali <math>
*
*
*
Każde wyrażenie regularne generuje język regularny i każdy język regularny można zapisać za pomocą wyrażenia regularnego.
Wiele innych wygodnych symboli można łatwo zdefiniować używając powyższych:
* plus (jedno lub więcej wystąpień) – <math>X^+ = X X^*,</math>
* znak zapytania (wystąpienie opcjonalne) – <math>X? = X | \epsilon,</math>
* n-krotne wystąpienie – <math>X^
* od n do m wystąpień – <math>X^{n, m} = X^n X^{0, m-n} = X^n X? X^{0, m-n-1} = \cdots</math>
Linia 193 ⟶ 187:
'''''Uwaga''': używane w praktyce tzw. [[Wyrażenie regularne|wyrażenia regularne]] w rzeczywistości posiadają zwykle dodatkowe możliwości, i generują więcej języków niż tylko języki regularne.''
== [[Twierdzenie Myhilla-
[[Twierdzenie Myhilla-
=== Przykład ===
Weźmy język słów o parzystej ilości jedynek i nieparzystej ilości zer. Język ten jest regularny, i prefiksy można pogrupować w 4 klasy:
* prefiksy o parzystej ilości jedynek i zer – prawidłowe sufiksy mają parzyście wiele jedynek i nieparzyście wiele zer,
* prefiksy o parzystej ilości jedynek i nieparzystej zer – prawidłowe sufiksy mają parzyście wiele jedynek i zer,
* prefiksy o nieparzystej ilości jedynek i parzystej zer – prawidłowe sufiksy mają nieparzyście wiele jedynek i zer,
* prefiksy o nieparzystej ilości jedynek i zer – prawidłowe sufiksy mają parzyście wiele zer i nieparzyście wiele jedynek.
=== Przykład (2) ===
Weźmy język <math>\{a^nb^n : n\in N\},</math>
Weźmy ciąg <math>p_k</math> prefiksów postaci <math>a^k,</math>
== [[Lemat o pompowaniu dla języków regularnych|Lemat o pompowaniu]] ==
Załóżmy, że dany język jest regularny. Wtedy istnieje taka stała <math>n,</math>
=== Przykład ===
Weźmy język <math>L=\{a^mb^m : m\in N\},</math>
Weźmy słowo <math>a^mb^m\in L,</math>
Ponieważ <math>L</math> nie spełnia lematu o pompowaniu, to nie jest regularny.
|