Języki obliczalne, częściowo obliczalne i nieobliczalne

W poprzednim wykładzie poznaliśmy definicje języków obliczalnych i częściowo obliczalnych. Jak dotąd, wszystkie przykłady języków, jakie rozważaliśmy były obliczalne. Poznamy teraz przykłady języków, dla których problem przynależności słów do języka nie jest obliczalny, a nawet nie jest częściowo obliczalny.

Poznamy też hierarchię Chomsky'ego, hierarchię klas języków, która podsumowuje większość poznanych przez nas klas języków i formalizmów.

Problem stopu

Mówiliśmy wcześniej o uniwersalnej maszynie Turinga. Sprecyzujmy jej postać. Ustalamy alfabet wejściowy $\Sigma = \{0,1,\$\}$. Uniwersalna maszyna Turinga symuluje działanie danej innej maszyny Turinga na podstawie jej opisu oraz jej wejścia. Zarówno opis symulowanej maszyny, jak i jej wejście maszyna uniwersalna otrzymuje na swoim wejściu w postaci ciągów zer i jedynek. Wymaga to zakodowania opisu symulowanej maszyny Turinga jako (ciągu bitów) słowa nad alfabetem {0,1}. Nie opisujemy tutaj takiego kodowania, tylko zakładamy, że takie kodowanie jest ustalone. (Jest to problem czysto techniczny.) Podobnie, symulowana maszyna może operować na słowach nad innym alfabetem niż {0,1}. Zakładamy że słowa te są, w miarę potrzeby, niejawnie kodowane -- to że znaki dowolnego alfabetu można zakodować jako ciągi bitów odpowiedniej długości jest oczywiste. Uniwersalną maszynę Turinga będziemy oznaczać przez U. Przyjmujemy, że akceptuje ona następujący język:

\begin{displaymath}
L(U) = \{ \mbox{kod }M \$ x : x \in L(M) \}
\end{displaymath}

Wynik działania maszyny uniwersalnej jest dokładnie taki sam, jak wynik działania symulowanej maszyny M dla danego słowa x.

Problem stopu to problem decyzyjny polegający na stwierdzeniu, czy dana maszyna Turinga M zatrzyma się dla danego słowa x. Problem ten możemy zdefiniować w formie języka:

\begin{displaymath}
\textsl{STOP} =
\{ \mbox{kod }M \$ x : M \mbox{ zatrzymuje się dla słowa } x\}
\end{displaymath}


\begin{fact}
Język \textsl{STOP} jest częściowo obliczalny.
\end{fact}

Dowód:

Maszyna Turinga $M_{\textsl{STOP}}$ akceptująca język STOP to prosta przeróbka maszyny uniwersalnej. $M_{\textsl{STOP}}$ działa tak samo jak U, z tą różnicą, że gdy maszyna symulowana odrzuca (a więc zatrzymuje się), to $M_{\textsl{STOP}}$ akceptuje. \qed

Maszyna $M_{\textsl{STOP}}$ nigdy nie odrzuca, natomiast zapętla się gdy symulowana maszyna się zapętla.


\begin{theorem}
Język \textsl{STOP} nie jest obliczalny.
\end{theorem}

Dowód:

Dowód przebiega nie wprost. Załóżmy, że istnieje maszyna Turinga M', która akceptuje język $L(M') = \textsl{STOP}$ i zawsze się zatrzymuje. Niech maszyna M'' będzie wynikiem przeróbki M': M'' dostaje na wejściu kod maszyny M i działa tak jak M' dla słowa $\mbox{kod }M\$\mbox{kod }M$, przy czym jeśli M' odrzuca, to M'' akceptuje, a jeśli M' akceptuje, to M'' zapętla się. Tak więc

\begin{displaymath}
L(M'') =
\{ \mbox{kod } M : M \mbox{ zapętla się dla kodu } M\}
\end{displaymath}

Ponieważ M'' nie odrzuca, więc zatrzymuje się dla kodu M, wtw., gdy M nie zatrzymuje się dla własnego kodu. Czy M'' zatrzyma się dla własnego kodu? Jeśli się zatrzymuje i akceptuje, to tym samym powinna się zapętlić. I na odwrót, jeżeli się zapętla, to powinna zaakceptować swój własny kod. Sprzeczność. Tak więc założenie, że język STOP jest obliczalny jest fałszywe. \qed

Własności klasy języków obliczalnych i częściowo obliczalnych

Poznaliśmy przykład języka, który nie jest obliczalny. Dalej poznamy przykład języka, który nie jest nawet częściowo obliczalny. Wcześniej jednak poznajmy trochę własności języków obliczalnych i częściowo obliczalnych.


\begin{fact}
Jeśli $A$\ i $\overline{A}$\ są częściowo obliczalne, to $A$\ jest
obliczalny.
\end{fact}

Dowód:

Powiedzmy, że mamy dwie maszyny Turinga, M1 i M2, akceptujące odpowiednio A i $\overline{A}$. Możemy skonstruować maszynę M (z dwoma ścieżkami i głowicami), która będzie symulować równocześnie działanie M1 i M2. Maszyna ta patrzy, która z maszyn M1 i M2 zaakceptuje słowo i odpowiednio akceptuje lub odrzuca. Ponieważ któraś z maszyn M1, M2 musi zaakceptować, więc M nie zapętla się. \qed


\begin{fact}
Język $\overline{\textsl{STOP}}$\ nie jest częściowo
obliczalny.
\end{fact}

Dowód:

Wiemy, że $\textsl{STOP}$ jest częściowo obliczalny. Gdyby $\overline{\textsl{STOP}}$ był częściowo obliczalny, to $\textsl{STOP}$ byłby obliczalny, a wiemy, że taki nie jest. \qed

Gramatyki ogólne (typu 0)

Jak dotąd, dla każdej poznawanej klasy języków mieliśmy dwa równoważne modele -- jeden nastawiony na opisywanie składni i jeden na modelowanie obliczeń. Czy istnieje formalizm nastawiony na opisywanie składni równoważny maszynom Turinga? Tak. Są to Gramatyki ogólne (tzw. typu 0). Ich definicja jest analogiczna do definicji gramatyk bezkontekstowych, ale po obu stronach produkcji mogą stać słowa.

Definicja

Gramatyka ogólna (typu 0), to dowolna taka czwórka $G=\angles{N, \Sigma, P, S}$, gdzie:
Produkcja $\alpha \to \beta$ pozwala w trakcie wyprowadzenia zamienić dowolne podsłowo $\alpha$ na $\beta$. Definicje wyprowadzenia i języka generowanego są analogiczne do tych dla języków bezkontekstowych. Jednak siła wyrazu gramatyk ogólnych jest dużo większa.


\begin{theorem}
Niech $A \subseteq \Sigma^*$\ będzie językiem.
Następujące dw...
...$A = L(G)$\ dla pewnej gramatyki ogólnej (typu 0).
\end{itemize} \end{theorem}

Szkic dowodu:

Nie będziemy tutaj szczegółowo dowodzić. Dowód przebiega przez pokazanie implikacji w obie strony.

Zauważmy jednak, że język generowany przez gramatykę ogólną może być nierozstrzygalny. Jest tak dlatego, że dla każdego języka częściowo obliczalnego mamy generującą go gramatykę ogólną, ale nie każdy język częściowo obliczalny jest obliczalny.

Gramatyki kontekstowe

Gramatyki kontekstowe to takie gramatyki ogólne, w których prawe strony produkcji nie są krótsze od lewych.

Definicja

Gramatyka kontekstowa, to dowolna taka czwórka $G=\angles{N, \Sigma, P, S}$, gdzie:

Definicja

Powiemy, że język A jest kontekstowy, jeżeli istnieje generująca go gramatyka kontekstowa.
Klasie języków kontekstowych odpowiadają maszyny Turinga ograniczone liniowo i gramatyki kontekstowe. Maszyny Turinga ograniczone liniowo to takie maszyny, których głowica nie wyjedzie dalej niż (o jeden znak za) słowo dane na wejściu. Inaczej mówiąc, są to maszyny, które dysponują pamięcią proporcjonalną do długości słowa danego na wejściu.


\begin{fact}
Dla każdego języka bezkontekstowego istnieje generująca go
(z dok...
...yków kontekstowych zawiera w sobie
klasę języków bezkontekstowych.
\end{fact}

Dowód:

Zauważmy, że gramatyki bezkontekstowe w postaci normalnej Chomsky'ego są równocześnie gramatykami kontekstowymi. \qed

Przykład

Język $\{a^nb^nc^n : n \ge 1\}$ jest nie tylko obliczalny, ale i kontekstowy. Oto generująca go gramatyka:

\begin{eqnarray*}
S &\to& abc \;\vert\;XaAbBC\\
Xa &\to& aX \\ \
Xb &\to& bX...
...\
cY &\to& Yc\\
BY &\to& YB\\
bY &\to& Yb\\
AY &\to& XA
\end{eqnarray*}


Oto przykładowe wyprowadzenie słowa aaabbbccc:

\begin{displaymath}
\begin{array}{llllllll}
S &\to& XaAbBC &\to& aXAbBC &\to& ...
... &\to& aaabbbXcC &\to& aaabbbcXC &\to& aaabbbccc
\end{array} \end{displaymath}


\begin{fact}
Języki generowane przez gramatyki kontekstowe są obliczalne.
\end{fact}

Dowód:

Dla gramatyki liniowej długość słowa w wyprowadzeniu nie może maleć. Można więc prześledzić wszystkie możliwe do wyprowadzenia słowa o długości nie przekraczającej długości danego na wejściu słowa. \qed

Hierarchia Chomsky'ego

Hierarchia Chomsky'ego to hierarchia czterech poznanych przez nas klas języków. Została ona stworzona przez Noama Chomsky'ego w ramach jego badań lingwistycznych. Są to języki: regularne, bezkontekstowe, kontekstowe i częściowo obliczalne. Każdej z tych klas odpowiada jeden rodzaj gramatyk. Odpowiadają im gramatyki: liniowe, bezkontekstowe kontekstowe i ogólne. Równocześnie tym samym klasom odpowiadają cztery różne modele obliczeniowe: automaty skończone, automaty stosowe oraz maszyny Turinga (ograniczone liniowo i dowolne). To, że niezależnie stworzone modele do opisu języków odpowiadają tym samym klasom wskazuje na ich głębsze znaczenie.

Zwyczajowo klasy języków tworzące hierarchię Chomsky'ego są oznaczane liczbami od 0 do 3. Następująca tabelka podsumowuje hierarchię Chomsky'ego oraz pozostałe klasy języków, które poznaliśmy w trakcie tego kursu. Są one podane w kolejności od klasy najszerszej do najwęższej.

Nr Gramatyki Maszyny Języki
0 ogólne maszyny Turinga częściowo obliczalne
-- -- maszyny Turinga
z własnością stopu
obliczalne
1 kontekstowe maszyny Turinga
ograniczone liniowo
kontekstowe
2 bezkontekstowe automaty stosowe bezkontekstowe
3 liniowe oraz
wzorce
automaty skończone regularne

Podsumowanie

W tym wykładzie poznaliśmy przykłady języków, które nie są, odpowiednio, obliczalne i częściowo obliczalne. Jest to problem stopu i jego dopełnienie. Poznaliśmy też gramatyki ogólne i kontekstowe. Gramatyki ogólne są równoważne maszynom Turinga i opisują dokładnie klasę języków częściowo obliczalnych. Poznane przez nas w trakcie tego kursu gramatyki i klasy języków (liniowe/regularne, bezkontekstowe, kontekstowe i częściowo obliczalne/ogólne) tworzą hierarchię Chomsky'ego. Hierarchia ta podsumowuje większość poznanych przez nas klas języków, z wyjątkiem klasy języków obliczalnych.

Skorowidz

Praca domowa

Napisz program, który wypisuje swój własny kod źródłowy. Uwaga: