Języki, automaty i obliczenia/Wykład 13: Złożoność obliczeniowa.: Różnice pomiędzy wersjami

Z Studia Informatyczne
Przejdź do nawigacjiPrzejdź do wyszukiwania
Linia 338: Linia 338:
konstruować liczbę <math>\displaystyle 2n</math>, mając dane <math>\displaystyle n</math>).
konstruować liczbę <math>\displaystyle 2n</math>, mając dane <math>\displaystyle n</math>).


==3. Języki maszyn Turinga i rodzina <math>\displaystyle \mathcal{L}_{0}</math>==


Powstaje naturalne pytanie o związki pomiędzy  klasą
języków rozpoznawanych przez maszyny Turinga a klasami zadanymi
poprzez gramatyki. Odpowiemy na to pytanie w tej części
wykładu.
{{twierdzenie|3.1||
Każdy język akceptowany przez maszynę Turinga jest typu
'''(0)'''.
<center><math>\displaystyle \mathcal{L}(MT)\subset \mathcal{L}_{0}.</math></center>
}}
{{dowod|||
Niech  <math>\displaystyle L  </math>  będzie językiem akceptowanym przez maszynę Turinga  <math>\displaystyle \mathbf{MT}=(\Sigma _{T},S,f,s_{0},S_{F})  </math> , o której założymy, że
<math>\displaystyle f(s_{0},\#)=(s',\#,1)  </math> , jeśli para  <math>\displaystyle (s_{0},\#)  </math>  należy do
dziedziny funkcji przejść  <math>\displaystyle f  </math>  maszyny Turinga. Założenie to nie
ogranicza ogólności rozważań. Wyróżnimy pewien podzbiór  <math>\displaystyle \overline{S}_{F}  </math>  zbioru stanów  <math>\displaystyle S  </math> , którego elementy,
jak wskazuje oznaczenie, skojarzone są ze stanami końcowymi. Do
zbioru  <math>\displaystyle \overline{S}_{F}  </math>  należy każdy stan  <math>\displaystyle \overline{s}\in S
</math> , dla którego istnieje ciąg stanów  <math>\displaystyle s_{1}=\overline{s},...,s_{k}  </math>  dla  <math>\displaystyle k\geqslant 1  </math>  taki, że  <math>\displaystyle (s_{i},\#)\rightarrow (s_{i+1},\#,0)  </math>  dla  <math>\displaystyle k=1,...,k-1  </math>  oraz
<math>\displaystyle (s_{k},\#)\rightarrow (s,\#,1)  </math> , gdzie  <math>\displaystyle s\in S_{F}  </math> .
Zauważmy, iż wraz ze stanem  <math>\displaystyle \overline{s}  </math>  do zbioru  <math>\displaystyle \overline{S}_{F}  </math>  należą wszystkie elementy ciągu  <math>\displaystyle s_{1}=\overline{s},...,s_{k}  </math> .
Określamy teraz gramatykę  <math>\displaystyle G=(V_{N},V_{T},v_{0},P)  </math> . Zbiór
symboli nieterminalnych  <math>\displaystyle V_{N}  </math>  zawiera wyłącznie
następujące symbole:
# dla każdego stanu  <math>\displaystyle s\in S  </math>  i  <math>\displaystyle a\in \Sigma _{T}\setminus \{\#\}  </math>  symbole <math>\displaystyle v_{sa},\: ^{\#}v_{sa},\: v_{sa}^{\#},\: ^{\#}v_{sa}^{\#},  </math>
# dla każdej litery  <math>\displaystyle a\in \Sigma _{T}\setminus \{\#\}  </math>  symbole <math>\displaystyle \, ^{\#}a  </math> i  <math>\displaystyle a^{\#},  </math>
# wszystkie elementy zbioru  <math>\displaystyle \Sigma _{T}\setminus (\Sigma _{I}\cup \{\#\}),  </math>
# symbole  <math>\displaystyle v_{0},\: v_{1}  </math>  nie należące do  <math>\displaystyle \Sigma _{T}.  </math>
Zbiór praw  <math>\displaystyle P  </math>  składa się z praw wymienionych poniżej:
#  <math>\displaystyle v_{0}\rightarrow \, ^{\#}v_{sa}^{\#}  </math> ,  <math>\displaystyle v_{0}\rightarrow v_{1}v_{sa}^{\#}  </math>, jeśli  <math>\displaystyle f(s,a)=(\overline{s},b,1)  </math>  dla pewnego  <math>\displaystyle b\in \Sigma _{T}\setminus \{\#\}  </math> , <math>\displaystyle \overline{s}\in \overline{S}_{F}  </math> ,
#  <math>\displaystyle v_{1}\rightarrow \, ^{\#}a  </math> ,  <math>\displaystyle v_{1}\rightarrow v_{1}a  </math>  dla każdego <math>\displaystyle a\in \Sigma _{T}\setminus \{\#\}  </math> ,
#  <math>\displaystyle v_{s_{1}c}b\rightarrow cv_{sa}  </math>  ,  <math>\displaystyle \, ^{\#}v_{s_{1}c}b\rightarrow \, ^{\#}cv_{sa}  </math> ,  <math>\displaystyle v_{s_{1}c}b^{\#}\rightarrow cv^{\#}_{sa}  </math>  ,  <math>\displaystyle \, ^{\#}v_{s_{1}c}b^{\#}\rightarrow \, ^{\#}cv^{\#}_{sa}  </math>,  jeśli  <math>\displaystyle f(s,a)=(s_{1},b,-1)  </math>  i  <math>\displaystyle c\in \Sigma _{T}\setminus \{\#\}  </math> ,
#  <math>\displaystyle bv_{s_{1}c}\rightarrow v_{sa}c  </math>  ,  <math>\displaystyle \, ^{\#}bv_{s_{1}c}\rightarrow \, ^{\#}v_{sa}c  </math> ,  <math>\displaystyle bv_{s_{1}c}^{\#}\rightarrow v_{sa}c^{\#}  </math>  ,  <math>\displaystyle \, ^{\#}bv_{s_{1}c}^{\#}\rightarrow \, ^{\#}v_{sa}c^{\#}  </math>,  jeśli  <math>\displaystyle f(s,a)=(s_{1},b,1)  </math>  i  <math>\displaystyle c\in \Sigma _{T}\setminus \{\#\}  </math> ,
#  <math>\displaystyle v_{s_{1}b}\rightarrow v_{sa}  </math>  ,  <math>\displaystyle \, ^{\#}v_{s_{1}b}\rightarrow \, ^{\#}v_{sa}  </math> ,  <math>\displaystyle v_{s_{1}b}^{\#}\rightarrow v^{\#}_{sa}  </math>  ,  <math>\displaystyle \, ^{\#}v_{s_{1}b}^{\#}\rightarrow \, ^{\#}v^{\#}_{sa}  </math>, jeśli  <math>\displaystyle f(s,a)=(s_{1},b,0)  </math> ,
#  <math>\displaystyle v_{s_{1}b}^{\#}\rightarrow v^{\#}_{sa}  </math>  ,  <math>\displaystyle \, ^{\#}v_{s_{1}b}^{\#}\rightarrow \, ^{\#}v^{\#}_{sa}  </math> , jeśli istnieją  <math>\displaystyle s_{1}',...,s_{k}'\in S  </math>  dla  <math>\displaystyle k\geqslant 1  </math>,  takie że  <math>\displaystyle f(s,a)=(s_{1}',b,1)  </math> ,  <math>\displaystyle f(s_{i}',\#)=(s_{i+1}',\#,0)  </math>  dla <math>\displaystyle i=1,...,k-1  </math>  oraz  <math>\displaystyle f(s_{k}',\#)=(s_{1},\#,-1)  </math> ,
#  <math>\displaystyle \, ^{\#}v_{s_{1}b}\rightarrow \, ^{\#}v_{sa}  </math>  ,  <math>\displaystyle \, ^{\#}v_{s_{1}b}^{\#}\rightarrow \, ^{\#}v^{\#}_{sa}  </math> , jeśli  istnieją  <math>\displaystyle s_{1}',...,s_{k}'\in S  </math>  dla  <math>\displaystyle k\geqslant 1  </math> takie, że  <math>\displaystyle f(s,a)=(s_{1}',b,-1)  </math> ,  <math>\displaystyle f(s_{i}',\#)=(s_{i+1}',\#,0)  </math>  dla  <math>\displaystyle i=1,...,k-1  </math>  oraz  <math>\displaystyle f(s_{k}',\#)=(s_{1},\#,1)  </math> ,
#  <math>\displaystyle a^{\#}\rightarrow a  </math>  dla wszystkich  <math>\displaystyle a\in \Sigma _{T}\setminus \{\#\}  </math> ,
#  <math>\displaystyle \, ^{\#}v_{sa}\rightarrow a  </math>  ,  <math>\displaystyle \, ^{\#}v_{sa}^{\#}\rightarrow a  </math> , jeśli  <math>\displaystyle f(s_{0},\#)=(s,\#,1)  </math>  (porównaj założenie na początku dowodu),
#  <math>\displaystyle v_{0}\Rightarrow 1  </math>,  jeśli  <math>\displaystyle 1\in L  </math> .
Określona powyżej gramatyka  <math>\displaystyle G  </math>  jest gramatyką typu
'''(0)'''. Rozważmy teraz dowolne słowo  <math>\displaystyle w  </math> , dla którego
istnieje wyprowadzenie w gramatyce  <math>\displaystyle G  </math>  ze stanu
początkowego  <math>\displaystyle v_{0}  </math>  przy użyciu praw 1-7. Słowo  <math>\displaystyle w  </math>  zawiera
dokładnie jeden z następujących symboli  <math>\displaystyle v_{sa},\,
^{\#}v_{sa},v_{sa}^{\#}  </math>  lub  <math>\displaystyle \, ^{\#}v_{sa}^{\#}  </math> . Pierwsza
litera słowa  <math>\displaystyle w  </math>  oznaczona jest markerem  <math>\displaystyle \#  </math>  z lewej
strony, a ostatnia litera słowa  <math>\displaystyle w  </math>  oznaczona jest markerem  <math>\displaystyle \#  </math>  ze strony prawej. Ponadto żadna z liter występujących pomiędzy
pierwszą a ostatnią nie jest oznaczona markerem  <math>\displaystyle \#  </math> . Z każdym
takim słowem kojarzymy konfigurację poprzez zastąpienie symbolu  <math>\displaystyle v_{sa}  </math>  przez  <math>\displaystyle sa  </math>  oraz przez dopisanie symbolu  <math>\displaystyle \#  </math>  po
lewej lub prawej stronie znaczonej przez ten marker litery, zgodnie
z jego występowaniem. Jeśli np.  <math>\displaystyle w=\, ^{\#}v_{sa}^{\#}  </math> , to
skojarzona konfiguracja jest postaci  <math>\displaystyle \#sa\#  </math> . Zauważmy, że
jeśli słowa  <math>\displaystyle u  </math>  i  <math>\displaystyle w  </math>  są w powyższej formie, to fakt, iż  <math>\displaystyle u\mapsto^{*}w  </math> , jest równoważny stwierdzeniu, że z
konfiguracji skojarzonej ze słowem  <math>\displaystyle w  </math>  maszyna Turinga
<math>\displaystyle MT  </math>  może przejść (bezpośrednie następstwo) do
konfiguracji skojarzonej ze słowem  <math>\displaystyle u  </math> . Każdy krok
obliczenia realizowanego przez  <math>\displaystyle MT  </math>  ma swój odpowiednik - krok w
wyprowadzeniu w gramatyce  <math>\displaystyle G  </math> . Z tym, że wobec praw 6 i 7
sekwencja obliczeń
<center><math>\displaystyle vsa\#\rightarrow vbs_{1}'\#\rightarrow ...\rightarrow
vbs_{k}'\#\rightarrow vs_{1}b\#</math></center>
jest traktowana jako jeden krok w
obliczeniu prowadzonym przez maszynę Turinga. Analogicznie
traktujemy sekwencję z markerem  <math>\displaystyle \#  </math>  występującym po lewej
stronie. Ze stanu początkowego  <math>\displaystyle v_{0}  </math>  gramatyki  <math>\displaystyle G  </math>
można wyprowadzić wszystkie słowa  <math>\displaystyle w  </math> , dla których konfiguracja
jest równa  <math>\displaystyle \#vsa\#  </math>,  dla pewnego  <math>\displaystyle v\in (\Sigma _{I}\setminus
\{\#\})^{*}  </math>  oraz maszyna Turinga realizuje obliczenie:
<center><math>\displaystyle sa\#\rightarrow bs_{1}'\#\rightarrow ...\rightarrow
bs_{k}'\#\rightarrow b\#s_{1},\quad s_{1}\in S_{F}.</math></center>
Wynika to z
praw 1 i 2 skonstruowanej gramatyki  <math>\displaystyle G  </math> . Z kolei prawa
typu 9 służą do zastąpienia symboli nieterminalnych typu
<math>\displaystyle \, ^{\#}v_{sa},\, ^{\#}v_{sa}^{\#}  </math>  przez litery terminalne,
a&nbsp;prawa typu 8 eliminują symbole nieterminalne typu  <math>\displaystyle a^{\#}  </math> . A
zatem dla niepustego słowa  <math>\displaystyle w\in (\Sigma _{I}\setminus \{\#\})^{*}
</math> spełniona jest równoważność
<center><math>\displaystyle v_{0}\mapsto_{G}^{*}w\: \Leftrightarrow \: s_{0}\#w\#\rightarrow
_{TM}^{*}\#u\#s_{1}, </math></center>
gdzie  <math>\displaystyle u\in (\Sigma _{I}\setminus
\{\#\})^{*}  </math> oraz  <math>\displaystyle s_{1}\in S_{F}  </math> . Prawo 10. zapewnia, że
powyższa równoważność prawdziwa jest także dla słowa pustego  <math>\displaystyle 1
</math> . A to kończy dowód tego twierdzenia.
}}
Język  <math>\displaystyle L  </math>  nazywamy '''rekurencyjnie przeliczalnym''',
jeśli istnieje efektywny
algorytm wyliczający wyłącznie słowa z  <math>\displaystyle L  </math> . Przez efektywny
algorytm rozumiemy skończony zbiór instrukcji, który w jednoznaczny
sposób opisuje działanie tego algorytmu. Klasę języków rekurencyjnie
przeliczalnych oznaczamy symbolem  <math>\displaystyle \mathcal{RP}  </math> .
Zauważmy, że każda gramatyka  <math>\displaystyle G  </math>  typu '''(0)''' jest
algorytmem wyliczającym wyłącznie słowa z  <math>\displaystyle L=L(G)  </math> . Dla każdej
liczby naturalnej  <math>\displaystyle k  </math>  można bowiem rozważyć skończony zbiór
wyprowadzeń w  <math>\displaystyle G  </math>,  rozpoczynających się od symbolu początkowego
<math>\displaystyle v_{0}  </math>  i o długości równej  <math>\displaystyle k  </math> . Z tego zbioru można z kolei
wybrać wyłącznie te wyprowadzenia, które kończą się słowem
nad alfabetem terminalnym gramatyki  <math>\displaystyle G  </math>  i tylko te
słowa dodawać do listy składającej się na język  <math>\displaystyle L  </math> . Są to, jak
łatwo zauważyć, wszystkie słowa języka  <math>\displaystyle L  </math>  i nic ponadto. A
zatem
{{twierdzenie|3.2||
Każdy język typu '''(0)''' jest językiem rekurencyjnie
przeliczalnym, czyli  <math>\displaystyle \mathcal{L}_{0}\subset \mathcal{RP}  </math> .
}}
Język  <math>\displaystyle L  </math>  nazywamy '''rekurencyjnym''',
jeśli istnieje efektywny algorytm
rozstrzygający dla każdego słowa  <math>\displaystyle w\in A^{*}  </math>  jego
przynależność do języka  <math>\displaystyle L  </math> . Klasę języków
rekurencyjnych oznaczamy symbolem  <math>\displaystyle \mathcal{R}  </math> .
Klasa języków kontekstowych zawiera się istotnie w klasie
języków rekurencyjnych, o czym przekonuje poniższe
twierdzenie.
{{twierdzenie|3.3||
Każdy język kontekstowy jest językiem rekurencyjnym, czyli <math>\displaystyle \mathcal{L}_{1}\subset \mathcal{R}.</math>
}}
{{dowod|||
Niech  <math>\displaystyle L  </math>  będzie dowolnym językiem kontekstowym. Istnieje więc
gramatyka kontekstowa  <math>\displaystyle G=(V_{N},V_{T},v_{0},P)  </math>  taka, że  <math>\displaystyle L=L(G)  </math> . Bezpośrednio z&nbsp;definicji gramatyki
kontekstowej wynika, iż słowo puste  <math>\displaystyle 1\in L  </math>  wtedy i tylko
wtedy, gdy  <math>\displaystyle v_{0}\rightarrow 1\in P  </math> . Załóżmy teraz, że dane
jest słowo  <math>\displaystyle w\in V^{*}_{T}  </math> , o którym mamy zadecydować,  czy
należy do języka  <math>\displaystyle L  </math> . W tym celu rozważmy wszystkie ciągi słów
<center><math>\displaystyle y_{0}=v_{0},\: y_{1},...,y_{n-1},\: y_{n}=w</math></center>
o tej własności, że  <math>\displaystyle y_{i}\in (V_{N}\cup V_{T})^{*}  </math> są parami różne, dla  <math>\displaystyle i=0,...,n
</math> ,  <math>\displaystyle n\geqslant 1  </math>  oraz  <math>\displaystyle \mid y_{i}\mid \leqslant \mid y_{i+1}\mid  </math> .
Ilość takich ciągów jest skończona i słowo  <math>\displaystyle w\in L  </math>  wtedy i
tylko wtedy, gdy wśród powyższych ciągów znajdziemy choć jeden taki,
że tworzy wyprowadzenie w gramatyce  <math>\displaystyle G  </math> . Czyli
<center><math>\displaystyle y_{0}=v_{0}\rightarrow y_{1}\rightarrow ...\rightarrow
y_{n-1}\rightarrow y_{n}=w. </math></center>
Ponieważ ilość ciągów podlegających rozważaniom jest
skończona oraz ponieważ stwierdzenie, czy pomiędzy dowolnymi słowami
zachodzi relacja  <math>\displaystyle \rightarrow  </math> , sprowadza się do przeszukania
skończonego zbioru praw  <math>\displaystyle P  </math> , efektywnie rozstrzygniemy, czy  <math>\displaystyle w
</math>  należy do języka  <math>\displaystyle L  </math>, czy też nie.
}}
Uzyskane dotąd rezultaty możemy podsumować następująco:
<center><math>\displaystyle \mathcal{L}(MT)\subset \mathcal{L}_{0}\subset \mathcal{RP}.</math></center>
W określeniu języka rekurencyjnie przeliczalnego oraz języka
rekurencyjnego wystąpiło pojęcie efektywnego algorytmu,
efektywnej procedury. Pojęcie to, intuicyjnie dość jasne, nie
zostało precyzyjnie określone. Co za tym idzie, dla
matematycznie poprawnych definicji języka rekurencyjnie
przeliczalnego i języka rekurencyjnego należałoby
sformalizować pojęcie algorytmu. W dotychczasowych rozważaniach
intuicja efektywnej procedury była o tyle wystarczająca, że
naszym celem było wskazanie istnienia takiej procedury. W
sytuacji, gdyby naszym celem było wykazanie, że taka procedura nie
istnieje, formalizacja tego pojęcia byłaby wręcz konieczna. We
wszystkich takich przypadkach powszechnie przyjmuje się, że maszyna
Turinga jest właśnie taką formalizacją. Na zdefiniowaną
w poprzednim wykładzie maszynę Turinga można spojrzeć jako na
algorytm, efektywną procedurę dającą odpowiedź pozytywną lub
negatywną w zależności od akceptacji lub nieakceptowania słowa
wejściowego. Proces obliczenia prowadzony przez maszynę Turinga
zgadza się z&nbsp;intuicyjnym rozumieniem algorytmu. O tym, że
każda efektywna procedura jest reprezentowana przez pewną
maszynę Turinga, mówi, powszechnie przyjęta jako prawdziwa, teza
Churcha.
'''Teza Churcha'''
''Każda efektywna''
''procedura (algorytm) da się opisać przez maszynę Turinga. ''
Konsekwencją przyjęcia tezy Churcha jest inkluzja  <math>\displaystyle \mathcal{RP}\subset \mathcal{L}(MT)  </math> . Biorąc pod uwagę udowodnione
powyżej twierdzenia, mamy:
<center><math>\displaystyle \mathcal{L}(MT)\subset \mathcal{L}_{0}\subset \mathcal{RP},</math></center>
co ostatecznie prowadzi do równości  <math>\displaystyle \mathcal{L}_{0}=\mathcal{L}(MT)  </math> .


==4. Rodziny <math>\displaystyle \mathcal{L}_{1}</math> i <math>\displaystyle \mathcal{L}_{0}</math> - zamkniętość na działania==
==4. Rodziny <math>\displaystyle \mathcal{L}_{1}</math> i <math>\displaystyle \mathcal{L}_{0}</math> - zamkniętość na działania==

Wersja z 18:28, 3 wrz 2006

Sformułujemy definicje podstawowych klas złożoności w języku maszyn Turinga oraz metodę ich porównywania. Przeanalizujemy związki między rodziną języków określonych przez maszyny Turinga a rodziną języków typu (0) z hierarchii Chomsky'ego. Podamy dalsze własności języków kontekstowych i typu (0). Wprowadzimy pojęcie języka rekurencyjnie przeliczalnego oraz przedstawimy tezę Churcha. Następnie omówimy teoretyczne podstawy teorii rozstrzygalności oraz przeanalizujemy kilka problemów nierozstrzygalnych w teorii języków.

Klasy złożoności obliczeniowej

Jednym z podstawowych celów wprowadzania maszyn Turinga jest dążenie do formalnej definicji złożoności obliczeniowej. Na podstawie wcześniejszych uwag możemy utożsamiać akceptację słowa przez maszynę Turinga z jej zatrzymaniem się. Intuicyjnie, można takie zachowanie maszyny Turinga utożsamić z wykonaniem programu, który zwraca odpowiedź "Tak" na postawione przez nas pytanie.

Definicja 1.1

Ustalmy funkcje t,s:. Mówimy, że maszyna Turinga 𝒯 (deterministyczna lub niedeterministyczna) akceptuje słowo wΣI* w czasie t(|w|), jeśli istnieje ciąg kt(|w|) konfiguracji d1,d2,,dk takich, że d1=s0w, dk=w1sFw2 dla pewnych w1,w2ΣT*,sFSF oraz didi+1 dla i=1,,k1.

Jeśli istnieje ciąg konfiguracji d1d2dm, gdzie d1=s0w, dm jest konfiguracją akceptującą (tzn. dm=w1sFw2 dla pewnych w1,w2ΣT*,sFSF) oraz dodatkowo |di|s(|w|)+2, to mówimy, że maszyna 𝒯 akceptuje słowo wΣI* w pamięci s(|w|).

Mówimy, że język L jest akceptowany w czasie t(n) (pamięci s(n)), jeśli istnieje maszyna Turinga 𝒯, dla której L(𝒯)=L oraz każde słowo wL jest akceptowane w czasie t(|w|) (pamięci s(|w|) odpowiednio).

Uwaga 1.1

W niektórych podejściach wykorzystuje się, do definicji złożoności pamięciowej, tak zwanych maszyn Turinga off-line. Pomysł polega na tym, aby nie uwzględniać komórek taśmy, z których maszyna czytała informacje, a jedynie te, do których następował zapis. Dzięki temu zabiegowi można w sposób "rozsądny" mówić o akceptacji słowa w pamięci logn itp. W ujęciu prezentowanym w tym wykładzie zajmujemy się akceptacją w pamięci nk, dla k1, zatem nie ma potrzeby dodatkowego definiowania maszyn Turinga off-line.

Definicja 1.2

Oznaczmy przez Dtime(t(n)) oraz Dspace(s(n)) rodzinę języków akceptowanych w czasie t(n) i odpowiednio pamięci s(n) przez deterministyczną maszynę Turinga. Dla maszyn niedeterministycznych wprowadzamy w identyczny sposób klasy Ntime(t(n)) oraz Nspace(s(n)).

Określamy następujące klasy złożoności (klasy języków):

Parser nie mógł rozpoznać (nieznana funkcja „\aligned”): {\displaystyle \displaystyle \aligned \textbd{P} \displaystyle =\bigcup_{k=0}^\infty Dtime(n^k), &\qquad\qquad& \textbd{NP} \displaystyle =\bigcup_{k=0}^\infty Ntime(n^k), \\ \textbd{PSPACE} \displaystyle =\bigcup_{k=0}^\infty Dspace(n^k), && \textbd{NSPACE} \displaystyle =\bigcup_{k=0}^\infty Nspace(n^k). \endaligned}

Wprost z definicji otrzymujemy zależności P NP oraz PSPACE NPSPACE . W dalszej części wykładu udowodnimy kilka mniej oczywistych zależności.

Przykład 1.1

Rozważmy język:

Parser nie mógł rozpoznać (błąd składni): {\displaystyle \displaystyle L=\left\{1^i 2^j 3^k\: k=i\cdot j,\: i,j\geqslant 1\right\}. }

Język L P . Deterministyczna maszyna Turinga MT3 akceptująca taki język może wyglądać następująco (zaczynamy od konfiguracji s0w):

  1. Jeśli symbol pod głowicą, to 1 zamień go na . Inaczej odrzuć.
  2. Przejdź od lewego ogranicznika do prawego, sprawdzając, czy po 1 występuje 1 lub 2, po 2 tylko 2 lub 3, a po 3 kolejny symbol 3 lub ogranicznik. Jeśli ta zależność nie jest spełniona, odrzuć. Gdy osiągniesz ogranicznik wykonaj następny krok.
  3. Gdy przed ogranicznikiem nie znajduje się symbol 3, odrzuć. W przeciwnym razie zamień symbol 3 na , a następnie poruszaj się w lewo, aż dotrzesz do symbolu innego niż 3 i .
  4. Jeśli symbol do którego dotarłeś to 2, zamień go na . Sprawdź symbol po lewej. Jeśli to 2, poruszaj się w prawo aż do ogranicznika. Następnie przejdź do kroku 3.
  5. Jeśli dotarłeś do symbolu 1, poruszaj się w lewo aż do ogranicznika. Zamień symbol 1 przy ograniczniku na , a następnie idź w prawo, zamieniając wszystkie symbole na 2. Gdy dojdziesz do ogranicznika, przejdź do kroku 3.
  6. Jeśli dotarłeś do ogranicznika, oznacza to, że skasowano już wszystkie symbole 1. Przejdź w prawo aż do ogranicznika. Jeśli natrafisz na symbol 3, odrzuć. W przeciwnym przypadku, akceptuj.

Nietrudno zaobserwować, że maszyna MT3 przechodzi przez taśmę w prawo i w lewo tyle razy, ile symboli 3 zawiera taśma oraz wykonuje jeden dodatkowy przebieg na starcie. Zatem słowa z L są akceptowane w czasie ograniczonym wielomianowo.

Przykład 1.2

Rozważmy teraz język

Parser nie mógł rozpoznać (błąd składni): {\displaystyle \displaystyle L=\left\{3^k\: : \: k=i\cdot j } dla pewnych i,j>1}.

Najprostszą metodą uzasadnienia, że L NP jest konstrukcja tak zwanej wyroczni. Polega ona na następującej dwuetapowej procedurze:

  1. Skonstruuj niedeterministyczną maszynę Turinga (wyrocznia) generującą pewne słowo (certyfikat).
  2. Zweryfikuj w sposób deterministyczny spełnienie założeń przez certyfikat.

W naszym przykładzie Etap 1 wygląda następująco:

  1. Użyj dwóch taśm. Na pierwszej z nich znajduje się 3k.
  2. Idź po pierwszej taśmie, wykorzystując niedeterministyczną funkcję przejść. Napotykając 3, możesz wypisać 1 na taśmie drugiej i przejść o jedną komórkę w prawo na taśmie pierwszej lub przejść do następnego kroku. Jeśli dotarłeś do prawego ogranicznika taśmy pierwszej, przejdź do kroku 3.
  3. Powróć do początku pierwszej taśmy. Wykonaj sekwencję jak w kroku 2, z tą różnicą, że teraz na drugiej taśmie wypisuj symbole 2.
  4. Jako ostatnią część tego etapu przekopiuj symbole 3 z pierwszej taśmy na drugą (po symbolach 1 i 2).

W konstrukcji wykorzystaliśmy dwie taśmy, ale oczywiście w nawiązaniu do wcześniejszych uwag, całą konstrukcję można wykonać na jednej taśmie (z odpowiednio rozszerzonym alfabetem i bardziej skomplikowaną funkcją przejść).

Etap 2 polega na weryfikacji, czy na taśmie drugiej znajduje się słowo postaci 1i2j3k, gdzie i,j>1 oraz k=ij. Jeśli tak, to słowo wejściowe 3k pochodziło z języka L i akceptujemy. Można do tego wykorzystać deterministyczną maszynę Turinga, niemal identyczną z opisaną w przykładzie poprzednim.

Jeśli słowo wejściowe pochodzi z języka L, to jedno z obliczeń maszyny niedeterministycznej z Etapu 1. prowadzi do konstrukcji odpowiedniego słowa na drugiej taśmie. Nie wiemy, jaka dokładnie ścieżka obliczeń ma być wykorzystana, ale dla akceptacji języka L nie ma to znaczenia.

Zastanów się, czy da się wykazać, że także L P (Ćwiczenie 1.3, do tego wykładu).

Definicja 1.3

Funkcja s(n) jest konstruowalna pamięciowo, jeśli istnieje maszyna Turinga 𝒯=(ΣT,S,f,s0,SF), dla której d1*d2, gdzie d1=s01n, d2=s11s(n)w dla s1SF, w(ΣT{1})* oraz dodatkowo d2 jest konfiguracją końcową.

Inaczej mówiąc, funkcję s(n) nazywamy konstruowalną pamięciowo, jeśli istnieje maszyna Turinga 𝒯, otrzymując na wejściu słowo w długości |w|=n, zaznacza na taśmie roboczej s(n) klatek i zatrzymuje się (akceptując słowo w).

Przykład 1.3

Funkcja s(n)=2n jest konstruowalna pamięciowo. Maszyna MT4, która konstruuje s(n) działa według schematu:

  1. Przejdź do prawego markera. Jeśli napotkano symbol inny niż 1, to odrzuć.
  2. Idź w lewo aż do pierwszego symbolu 1 lub markera
  3. Jeśli napotkałeś symbol 1, zamień go na i przejdź do prawego markera. Dopisz do słowa symbol (zwiększając tym samym długość słowa na taśmie o 1). Następnie powtórz cykl od 2.
  4. Jeśli napotkałeś marker, idź w prawo, zamieniając wszystkie wystąpienia na 1. Następnie wracaj do lewego markera i zatrzymaj się, akceptując.

Twierdzenie 1.1 liniowa kompresja pamięci

Niech będzie dany język L oraz maszyna Turinga 𝒯 akceptująca L w pamięci s(n). Dla dowolnego ε>0 istnieje maszyna Turinga 𝒯 akceptująca L w pamięci max{n,εs(n)}.

Dowód

(Szkic) Ustalamy liczbę naturalną k, dla której εk2. Maszynę 𝒯 definiujemy następująco:

  1. Przekoduj słowo wejściowe, łącząc po r kolejnych symboli w jeden blok stanowiący nowy symbol na taśmie.
  2. Symuluj maszynę 𝒯 na skompresowanej taśmie. Położenie głowicy wewnątrz bloku zakoduj w stanach maszyny 𝒯.

Zauważmy, że w kroku 1. maszyna 𝒯 wykorzystuje n komórek pamięci do odczytania słowa wejściowego. Kompresja taśmy zapewnia, że podczas symulowania maszyny 𝒯 nie wykorzystamy więcej niż s(n)kεs(n) komórek. Jednocześnie można założyć, że 𝒯 akceptuje słowa wejściowe z języka L o długości mniejszej niż k bez symulowania 𝒯.

Twierdzenie 1.2 Savitch

Dla dowolnej funkcji s(n) konstruowalnej pamięciowo spełniającej warunek s(n)log2n prawdziwa jest inkluzja Nspace(s(n))DSpace(s2(n)).

Dowód

Niech 𝒩𝒯 będzie niedeterministyczną maszyną Turinga akceptującą język L=L(𝒩𝒯) w pamięci s(n). Niech k(n) oznacza liczbę konfiguracji potrzebną do zaakceptowania słowa o długości n. Istnieje liczba c>1, dla której k(n)cs(n), co z kolei oznacza, że każde słowo o długości n jest akceptowane w cs(n) krokach czasowych.

Rozważmy algorytm:

Algorytm


  1  Wejście: słowo w długości |w|=n
  2  oblicz s(n)
  3  for każda konfiguracja akceptująca dA dla której |dA|s(n)
  4    do if Test(s0w, dA, s(n)log2c) then akceptuj

gdzie procedura Test ma następującą postać:

Algorytm Procedure Test(d,d,i)


  1  if i=0 and [ (d=d) or (dd)] then return true
  2    else for każda konfiguracja d dla której |d|s(n)
  3      do if Test(d,d,i1) and Test d,d,i1)
  4        then return true;
  5  return false

Przedstawiony algorytm można zrealizować za pomocą wielotaśmowej maszyny Turinga. Założenie dotyczące konstruowalności pamięciowej jest istotnie wykorzystywane w tej konstrukcji przy implementacji linii 3 algorytmu i linii 2 procedury Test. Musimy zaznaczyć s(n) komórek taśmy, aby móc konstruować konfiguracje o długości ograniczonej przez s(n) i móc następnie wykonywać na nich symulację maszyny 𝒩𝒯.

Zauważmy, że ilość konfiguracji jest ograniczona przez s(n), a głębokość rekursji przez logcs(n). Oznacza to, że jesteśmy w stanie skonstruować maszynę Turinga, która wymaga cs2(n) pamięci, gdzie c jest pewną stałą. Na mocy Twierdzenia 1.1 jesteśmy w stanie określić maszynę 𝒯 działającą w pamięci s2(n).

Wniosek 1.1

PSPACE = NPSPACE

Lemat 1.1

Jeśli g(n)n, to Dtime(g(n))Dspace(g(n)) oraz Ntime(g(n))Nspace(g(n)).

Dowód

Niech będzie dana maszyna deterministyczna 𝒯 akceptująca dany język L w czasie g(n). Do akceptacji słowa w o długości n maszyna wykorzystuje co najwyżej g(n) kroków czasowych, czyli odwiedza co najwyżej g(n)+1 komórek taśmy.

Na podstawie Twierdzenia 1.1 istnieje maszyna Turinga 𝒯 wykorzystująca

max{n,12(g(n)+1)}g(n)

komórek pamięci. Dla niedeterministycznych maszyn Turinga argumentacja jest identyczna.

Wniosek 1.2

P NP PSPACE = NPSPACE
Uwaga 1.2

Nie jest znany przykład wykazujący silną inkluzję P NP ani dowód wykluczający istnienie takiego przykładu. Powszechnie uznawana hipoteza głosi:

P NP.

Rozstrzygnięcie jej prawdziwości lub fałszywości stanowi jeden z najważniejszych, a zarazem najtrudniejszych problemów współczesnej informatyki. Jak widzieliśmy w Przykładzie 1.2, nawet w przypadku konkretnego języka L NP, problem uzasadnienia, że także L P, jest nietrywialny, gdyż wymaga zazwyczaj konstrukcji całkiem nowej maszyny Turinga niż ta do weryfikacji L NP .

Redukcja i problemy zupełne

Definicja 2.1 transformacja wielomianowa

Niech L1,L2 będą dowolnymi językami nad pewnym alfabetem ΣI. Mówimy, że L1 redukuje się do L2 w czasie wielomianowym, co oznaczamy L1L2, gdy istnieje deterministyczna maszyna Turinga 𝒯=(ΣT,S,f,s0,SF) taka, że dla dowolnego wΣI* istnieje wΣI* i stan s1SF o własności

s0w*s1w

oraz

wL1wL2.

Lemat 2.1

Załóżmy, że L1L2. Wtedy zachodzą implikacje:

  1. L2 P      L1 P,
  2. L2 NP      L1 NP,
  3. L2 PSPACE      L1 PSPACE.

Dowód

Dane słowo w transformujemy do w w czasie wielomianowym, co gwarantuje założenie L1L2. Dzięki założeniu L2 P możemy rozstrzygnąć, czy wL2 (tzn. jeśli akceptujemy w, to robimy to w czasie wielomianowym). Tym sposobem (korzystając z definicji transformacji wielomianowej) akceptujemy w w czasie wielomianowym, o ile tylko wL1. Dowód dla pozostałych implikacji jest identyczny.

Definicja 2.2

Niech 𝒞 oznacza pewną klasę języków. Język L nazywamy 𝒞-trudnym, jeśli spełniony jest warunek:

L𝒞LL.

Jeżeli dodatkowo spełniony jest warunek L𝒞, to język L nazywamy 𝒞-zupełnym.

Intuicyjnie, fakt, że język jest 𝒞-zupełny, oznacza, że jest on najbardziej skomplikowany (pod względem obliczeniowym) wśród języków z klasy 𝒞, natomiast język 𝒞-trudny jest bardziej skomplikowany niż każdy z klasy 𝒞, choć sam nie musi do niej należeć.

Uwaga 2.1

Rozważając klasę P , NP i PSPACE, możemy mówić o językach (problemach) P -zupełnych, NP -zupełnych, czy też PSPACE -zupełnych. To samo odnosi się do języków trudnych (tzn. klasa języków P -trudnych, itd.).

Przykład 2.1

Rozważmy języki:

Parser nie mógł rozpoznać (błąd składni): {\displaystyle \displaystyle L_1=\left\{1^i 2^j 3^k\: k=i\cdot j,\: i,j\geqslant 1\right\}\quad,\quad L_2=\left\{1^i 2^j 4^{2k}\: k=i\cdot j,\: i,j\geqslant 1\right\}. }

Języki: L1 oraz L2 wyglądają na bardzo podobne, zatem wydaje się, że L1L2 oraz L2L1. Uzasadnienie tego faktu jest prawie natychmiastowe.

Konstruujemy deterministyczną maszynę Turinga która działa w następujący sposób:

  1. Jeśli słowo wejściowe jest puste, to stop.
  2. Przejdź do prawego ogranicznika. Jeśli przy ograniczniku nie występuje symbol 4, to wykonaj krok 1.
  3. Jeśli w słowie wejściowym występuje symbol 4, to sprawdź, czy słowo przetwarzane jest postaci w4s, gdzie s1 oraz w(ΣI{4})* oraz czy dodatkowo s jest liczbą parzystą. Jeśli nie, to wykonaj krok 1.
  4. Zamień słowo 4s na słowo 3s2s2 i wykonaj krok 1.
  5. Przejdź nad pierwszy symbol po lewym ograniczniku i zatrzymaj się.

W ten sposób zawsze przeprowadzamy konfigurację s0w na konfigurację s1w, przy czym w=1i2j3k tylko, gdy w=1i2j42k. Zatem wL2 wtedy i tylko wtedy, gdy wL1. Wykazaliśmy, że L2L1.

Warunek L1L2 otrzymujemy w sposób identyczny. Trzeba tylko wypisać odpowiednią ilość symboli 4 (a wiemy już, jak konstruować liczbę 2n, mając dane n).


4. Rodziny 1 i 0 - zamkniętość na działania

Dla kompletności tej części wykładu przedstawimy własności zamkniętości rodziny języków kontekstowych 1 i języków typu (0) 0 ze względu na najczęściej używane operacje. W niektórych przypadkach dowody dotyczące obu klas są takie same. W dowodach posłużymy się specjalną postacią gramatyk, a mianowicie taką, w której symbole terminalne występują tylko po prawej stronie. Prawdziwe bowiem jest twierdzenie

Twierdzenie 4.1

Dla każdej gramatyki istnieje równoważna gramatyka tego samego typu taka, że każda produkcja, w której występuje symbol terminalny a , jest postaci va .

Elementarny dowód tej własności pozostawiamy jako zadanie domowe.

Twierdzenie 4.2

Rodziny 0 i 1 są zamknięte ze względu na:

  1. sumę mnogościową,
  2. iloczyn mnogościowy,
  3. katenację,
  4. iterację *,
  5. odbicie zwierciadlane.

Dowód

1. Niech dla i=1,2Gi=(VNi,VT,v0i,Pi) będą gramatykami typu (1) (odpowiednio typu (0) ) takimi, że VN1VN2= . I niech Li=L(Gi) . Określamy gramatykę G typu (1) (typu (0) ) generującą język L1L2 .

Jeśli 1L1L2 , to przyjmujemy:

G=(VN1VN2{v0},VT,v0,P1P2{v0v01,v0v02}).

Zauważmy, że wówczas w żadnej z gramatyk nie ma prawa wymazującego. Jeśli natomiast 1L1L2 , to konstruujemy gramatykę G dla języków L1{1} i L2{1} , jak powyżej, a następnie dodajemy nowy symbol początkowy v0 i prawa v0v0,v01 .

2. Przecięcie udowodnimy tylko dla języków typu (0) . Dowód dla języków kontekstowych został przeprowadzony wcześniej.

Niech dla i=1,2Gi=(VNi,VT,v0i,Pi) będą gramatykami typu (0) takimi, że VN1VN2= . Niech Li=L(Gi) . Określamy gramatykę G typu (0) generującą język L1L2, przyjmując:

G=(VN1VN2VN,VT,v0,P1P2P),

gdzie: VN={va:aVT}{v0,v1,v2} , a do zbioru P należą prawa:
(1) v0v1v01v2v02v1,
(2) v2avav2 dla aVT,
(3) bvavab dla a,bVT,
(4) v1vaaav1 dla aVT,
(5) v1v2v11.
Przy pomocy prawa (1) i wszystkich praw ze zbioru P1P2 można wygenerować zbiór słów:

{v1w1v2w2v1:w1L1,w2L2}.

Z dowolnego słowa należącego do tego zbioru, korzystając z praw (2)-(4), można wyprowadzić słowo w1v1v2v1 wtedy i tylko wtedy, gdy w1=w2 . Korzystając z prawa (5), dostajemy słowo w1 . A więc L(G)=L1L2 .

3. Niech dla i=1,2Gi=(VNi,VT,v0i,Pi) będą tak jak poprzednio gramatykami typu (1) ( (0) ) takimi, że VN1VN2= oraz spełniającymi warunki powyższego twierdzenia. Niech Li=L(Gi) . Określamy gramatykę G odpowiednio typu (1) ( (0) ) generującą język L1L2 .

Jeśli 1L1L2 , to przyjmujemy:

G=(VN1VN2{v0},VT,v0,P1P2{v0v01v02}).

Jeśli 1L1L2 , to oznaczamy L1=L1{1},L2=L2{1} . Wówczas:

Parser nie mógł rozpoznać (nieznana funkcja „\begin{array}”): {\displaystyle \displaystyle L_{1}L_{2}=\left\{ \begin{array} {lll} L_{1}'L_{2}'\cup L_{1}', & gdy & 1\in L_{2},\: 1\notin L_{1},\\ L_{1}'L_{2}'\cup L_{2}', & gdy & 1\in L_{1},\: 1\notin L_{2},\\ L_{1}'L_{2}'\cup L_{1}'\cup L_{2}'\cup \left\{ 1\right\}, & gdy & 1\in L_{1},\: 1\in L_{2}. \end{array} \right. }

Wykorzystując poprzednią konstrukcję i zamkniętość ze względu na sumę w każdym z tych przypadków, otrzymujemy gramatykę generującą katenację języków L1 i L2 .

4. Niech G=(VN,VT,v0,P) będzie gramatyką typu (1) (typu (0) ) taką, że symbole terminalne nie występują po lewej stronie żadnej produkcji z P . Załóżmy też, że 1L=L(G) . Gramatyka

G=(VN{v0,v1},VT,v0,P),

gdzie

Parser nie mógł rozpoznać (nieznana funkcja „\begin{array}”): {\displaystyle \displaystyle \overline{P}=P\cup \begin{array} [t]{l} \left\{ \overline{v}_{0}\rightarrow 1,\: \overline{v}_{0}\rightarrow v_{0},\: \overline{v}_{0}\rightarrow \overline{v}_{1}v_{0}\right\} \cup \\ \left\{ \overline{v}_{1}a\rightarrow \overline{v}_{1}v_{0}a\, :\, a\in V_{T}\right\} \cup \\ \left\{ \overline{v}_{1}a\rightarrow v_{0}a\, :\, a\in V_{T}\right\} \end{array} }

generuje język L* . Jeśli 1L , to usuwamy prawo wymazujące v01 i dla języka L{1} konstruujemy gramatykę G . Z faktu, że (L{1})*=L* , wynika, że również L(G)=L* .

5. Jeśli G=(VN,VT,v0,P) jest gramatyką typu (1) (typu (0) ) taką, że L(G)=L , to gramatyka G=(VN,VT,v0,P) , gdzie P={xy:xyP} generuje język L .

Zauważmy na koniec, że rodzina 0 nie jest zamknięta ze względu na uzupełnienie. Stwierdzenie to wynika z przyjęcia jako obowiązujacej tezy Churcha, która w tym wypadku implikuje równość rodziny języków 0 i rodziny języków rekurencyjnie przeliczalnych oraz z faktu, iż istnieje język rekurencyjnie przeliczalny, którego uzupełnienie nie jest rekurencyjnie przeliczalne. Ten ostatni fakt podajemy bez dowodu. Dodajmy, że własność zamkniętości ze względu na uzupełnienie dla rodziny 1 przez długi czas pozostawała problemem otwartym. Dopiero w roku 1987 udowodniono, iż własność ta jest spełniona dla języków kontekstowych. Podsumowanie własności zamkniętości ze względu na działania dla różnych klas języków hierarchii Chomsky'ego zawarte jest w poniższej tabeli:

          3       2       1       0   
          T       T       T       T   
          T       T       T       T   
          T       T       T       T   
          T       N       T       N   
          T       N       T       T   

Na koniec podamy twierdzenie o wzajemnych relacjach pomiędzy rodzinami języków z hierarchii Chomsky'ego. Dowód tego twierdzenia wynika w części z definicji typów gramatyk wprowadzonych na wykładzie 2, a w części z udowodnionych własności poszczególnych rodzin języków z hierarchii Chomsky'ego (zakładając obowiązywanie tezy Churcha).

Twierdzenie 4.3

Rodziny języków hierarchii Chomsky'ego spełniają następujące relacje:

0/1/2/3.

5. Problemy rozstrzygalne

W poprzednim wykładzie uzasadniliśmy, że dla każdej deterministycznej maszyny Turinga jesteśmy w stanie wskazać taką, która akceptuje dany język i jednocześnie zatrzymuje się tylko na słowach akceptowanych. Wymagało to przejścia przez maszynę niedeterministyczną, a następnie jej symulację na maszynie deterministycznej. Z tego powodu ograniczamy się w dalszej części wykładu tylko do tego typu maszyn Turinga (akceptacja=stop). Jak to uzasadniono wcześniej, przy założeniu tezy Churcha, maszyna Turinga może być rozpatrywana jako matematycznie ścisła definicja algorytmu.

Pojęcie rozstrzygalnego problemu zostało wprowadzone wcześniej, na innym wykładzie, i jest ono znane. Przypomnijmy więc tylko, że rozstrzygalność, czy też nierozstrzygalność, odnosi się do pewnej klasy, którą tworzą określone przypadki ustalonego problemu. Jeśli istnieje algorytm, który rozwiązuje taki problem dla wszystkich przypadków w tej klasy, to mówimy, że problem jest rozstrzygalny (w tej klasie). Zatem taki algorytm jest uniwersalnym sposobem rozwiązywania problemu dla wszystkich danych wejściowych określających poszczególne przypadki w tej klasie. Jak łatwo zauważyć dla ustalenia rozstrzygalności problemu wystarczy się opierać na intuicyjnym pojęciu algorytmu. Są jednak takie problemy, dla których nie istnieje, w rozważanej klasie przypadków, uniwersalny sposób ich rozwiazywania. Takie problemy nazywamy nierozstrzygalnymi w danej klasie. Aby wykazać nierozstrzygalność jakiegoś problemu, nieodzownym jest sformalizowanie pojęcia algorytmu. Standardowo taką formalizacją jest, o czym wspomniano już wcześniej, maszyna Turinga.

Zwróćmy uwagę, że maszyna Turinga akceptuje języki, gdy tymczasem przyzwyczajeni jesteśmy, że algorytmy (programy) rozwiązują pewne, niekiedy bardzo skomplikowane, problemy (określone przy pomocy list, kolejek, grafów itp.). Zwracamy zatem uwagę na fakt, że w przypadku maszyny Turinga musimy wykonać wstępne umowne kodowanie naszego problemu. W tym przypadku rozważany język określa te spośród "sensownych" kodowań, które stanowią rozwiązanie postawionego problemu. Z drugiej strony maszyna, akceptując słowo w1$w2, może informować nas o tym, że wynikiem obliczeń numerycznych na danych zakodowanych w w1 rzeczywiście jest liczba zakodowana w w2 itp.

Dla ilustracji powyższych dywagacji rozważmy problem skończoności w klasie jezyków regularnych. Problem ten jest rozstrzygalny, bo w oparciu o lemat o pompowaniu można skonstruować algorytm, który dla dowolnego języka regularnego rozstrzygnie, czyli odpowie twierdząco lub przecząco na pytanie o jego skończoność. W tym przypadku można np. przyjąć, że jako słowo wejściowe podajemy zakodowany opis gramatyki generującej język.

Nierozstrzygalność algorytmiczna problemu w ustalonej klasie nie oznacza, podkreślmy, niemożliwości rozwiązania konkretnego zadania z tej klasy. Nierostrzygalność oznacza niemożliwość rozwiązania za pomocą tego samego algorytmu, tej samej metody, wszystkich przypadków tego problemu należących do danej klasy.

W zamieszczonej poniżej tabeli przedstawiamy najczęściej rozważane pod kątem rozstrzygalności problemy z dziedziny języków formalnych w ramach hierarchii Chomsky'ego. Litera R oznacza rozstrzygalność problemu, N nierostrzygalność, a znak - pojawiający się przy problemie jednoznaczności oznacza, że problemu tego nie formułuje się dla gramatyk kontekstowych i typu (0):

własność (3) (2) (1) (0)
należenie wL R R R N
inkluzja L1L2 R N N N
równoważność R N N N
pustość L= R R N N
nieskończoność cardL=0 R R N N
jednoznaczność gramatyki R N - -

Najczęściej używaną metodą dowodzenia nierozstrzygalności problemu P jest redukcja tego problemu do innego, powiedzmy P , dla którego nierozstrzygalność została ustalona wcześniej. Redukcja taka prowadzi do sformułowania implikacji:

jeśli P byłby rozstrzygalny, to i P byłby rozstrzygalny.

A ponieważ to ostatnie (następnik implikacji) nie jest prawdą, więc problem P nie jest rozstrzygalny.

Należy w tym miejscu podkreślić fakt, że dowody nierozstrzygalności problemów uniwersalnych (takich jak problem Posta rozważany dalej) wiążą się z konstrukcją odpowiednich maszyn Turinga, kodowaniem problemu, a następnie dowodem uzasadniającym, że problem jest rzeczywiście nierozstrzygalny. Tematyka ta wykracza poza ramy wykładu. Z tego też powodu ograniczymy się tutaj do zaprezentowania jednego ze znanych problemów nierozstrzygalnych bez dowodu nierozstrzygalności.

Najczęściej występującym w literaturze problemem nierozstrzygalnym jest, bez wątpienia, problem Posta przedstawiony poniżej.

 

Problem Posta

Dla dowolnego alfabetu A , o co najmniej dwóch elementach ( A2 ), załóżmy, iż dana jest, tak zwana, lista słów, a dokładniej: par słów Parser nie mógł rozpoznać (błąd składni): {\displaystyle \displaystyle \left( u_{1},w_{1}\right) \: \left( u_{2},w_{2}\right) \: \ldots \left( u_{n},w_{n}\right), } gdzie ui,wiA+ , n . Mówimy, że taka lista ma własność Posta (problem Posta ma rozwiązanie), jeśli istnieje ciąg indeksów i1,,ik{1,...,n} taki, że

ui1uik=wi1wik.

Jest to w ogólnym przypadku problem nierozstrzygalny.

Problem ten można sformułować równoważnie następująco. Niech A będzie alfabetem interpretowanym jako zbiór indeksów, a B dowolnym alfabetem. Niech Parser nie mógł rozpoznać (błąd składni): {\displaystyle \displaystyle h:A^{*}\longrightarrow B^{*},\: g:A^{*}\longrightarrow B^{*} } będą dowolnymi homomorfizmami. Problem Posta, inaczej sformułowany, polega na odpowiedzi na pytanie, czy istnieje słowo xA+ takie, że h(x)=g(x) .

Dwa kolejne przykłady ilustrują technikę redukcji pewnych problemów do problemu Posta. W efekcie uzyskujemy nierozstrzygalność w sposób opisany powyżej.

Twierdzenie 5.1

W klasie gramatyk bezkontekstowych problem niejednoznaczności jest nierozstrzygalny.

Dowód

Udowodnimy, że problem jest nierozstrzygalny dla gramatyk bezkontekstowych generujących języki nad alfabetem dwuelementowym A={a,b} . Oznaczmy B={d,e} i określmy homomorfizm h:B*A* , przyjmując h(d)=ba2 oraz h(e)=ba3 . Niech u będzie ciągiem u1,...,unB+ dowolnie wybranych i ustalonych słów. Dla dowolnej liczby naturalnej i>0 niech i=dei . Określony poniżej język

Parser nie mógł rozpoznać (błąd składni): {\displaystyle \displaystyle L_{u}=\{h(\overline{i_{1}}).....h(\overline{i_{k}})bah(u_{i_{k}}),...,h(u_{i_{1}})\in A^{*}\: :\: k\geqslant 1,\: 1\leqslant i_{j}\leqslant n\}}

jest językiem bezkontekstowym, jako generowany przez gramatykę Gu=(VN,VT,v0,Pu) , dla której

Parser nie mógł rozpoznać (błąd składni): {\displaystyle \displaystyle V_{N}=\{v_{u}\},\: V_{T}=\{a,b\},\: v_{0}=v_{u} } oraz Parser nie mógł rozpoznać (błąd składni): {\displaystyle \displaystyle P_{x}=\{v_{u}\rightarrow h(\overline{i})v_{u}h(u_{i}),\: v_{u}\rightarrow h(\overline{i})bah(u_{i})\} } .

Niech teraz u i w oznaczają ciągi dowolnie wybranych i ustalonych słów u1,...,unB+ i w1,...,wnB+ . Tworzą one listę słów Parser nie mógł rozpoznać (błąd składni): {\displaystyle \displaystyle \left( u_{1},w_{1}\right) \: \left( u_{2},w_{2}\right) \: \ldots \left( u_{n},w_{n}\right), } . Zatem zasadne jest postawienie pytania, czy lista ta ma własność Posta. Niech Gu oraz Gw będą gramatykami bezkontekstowymi określonymi tak jak powyżej. Gramatyka G=({v0,vu,vw},{a,b},v0,P) , gdzie Parser nie mógł rozpoznać (błąd składni): {\displaystyle \displaystyle P=\{v_{0}\rightarrow v_{u},\: v_{0}\rightarrow v_{w}\}\cup P_{u}\cup P_{w} } jest bezkontekstowa. Gramatyka ta jest niejednoznaczna wtedy i tylko wtedy, gdy LuLy . Ten ostatni warunek równoważny jest istnieniu liczb i1,...,ik takich, że ui1.....uik=wi1.....wik, czyli własności Posta listy Parser nie mógł rozpoznać (błąd składni): {\displaystyle \displaystyle \left( u_{1},w_{1}\right) \: \left( u_{2},w_{2}\right) \: \ldots \left( u_{n},w_{n}\right) } .Ostatecznie więc rozstrzygalność problemu niejednoznaczności w klasie gramatyk bezkontekstowych prowadziłaby do rozstrzygalności własności Posta.

Dla drugiego przykładu przyjmijmy jako alfabety Parser nie mógł rozpoznać (błąd składni): {\displaystyle \displaystyle A_{2}=\left\{ a,b\right\} ,\: A_{3}=\left\{ a,b,c\right\} } oraz określmy język

L={v1cv2cv2cv1:v1,v2A2*}.

Ustalmy listę Posta Parser nie mógł rozpoznać (błąd składni): {\displaystyle \displaystyle \left( u_{1},w_{1}\right) \: \left( u_{2},w_{2}\right) \: \ldots \left( u_{n},w_{n}\right) } nad alfabetem A2 , gdzie ui,wiA2+ . Wprowadzamy teraz języki Parser nie mógł rozpoznać (błąd składni): {\displaystyle \displaystyle L_{u},\: L_{w}\: L_{PP} } nad alfabetem A3, przyjmując:

Parser nie mógł rozpoznać (nieznana funkcja „\aligned”): {\displaystyle \displaystyle \aligned L_{u} &= \left\{ ba^{i_{k}}b\ldots ba^{i_{1}}cu_{i_{1}}\ldots u_{i_{k}}\, :\, k\geqslant 1,1\leqslant i_{j}\leqslant n\right\} \\ L_{w} &= \left\{ ba^{i_{k}}b\ldots ba^{i_{1}}cw_{i_{1}}\ldots w_{i_{k}}\, :\, k\geqslant 1,1\leqslant i_{j}\leqslant n\right\} \endaligned}

oraz definiujemy język

LPP=LucLw.

Określone powyżej języki nad alfabetem A3 mają własności konieczne do zastosowania lematu, który przytoczymy bez dowodu.

Lemat 5.1

Języki Parser nie mógł rozpoznać (błąd składni): {\displaystyle \displaystyle L,\: L_{PP},\: A_{3}^{*}\setminus L,\: A_{3}^{*}\setminus L_{PP} } są bezkontekstowe.

Dla języków L i LPP uzasadnienie ich bezkontekstowości jest proste poprzez konstrukcję odpowiednich gramatyk. Aby uzyskać bezkontekstowość ich uzupełnień, należy podzielić rozważane języki na rozłączne podzbiory i konstruować gramatyki bezkontekstowe dla tych wyróżnionych podzbiorów, a w końcu wykorzystać fakt, że suma języków bezkontekstowych jest językiem bezkontekstowym.

Zauważmy teraz, że istnienie rozwiązania problemu Posta nad alfabetem A3 jest równoważne temu, że LPPL .

Jeśli bowiem LPPLbaikbai1cui1uikcwi1wikcai1baikb , gdzie k1,1ijn , to oczywiście ui1uik=wi1wik . Jeśli ciąg i1,,ik jest rozwiązaniem problemu Posta, to (i1,,ik)(i1,,ik) też. Zatem jeśli LPPL , to język LPPL jest nieskończony.

Wobec nierozstrzygalności problemu Posta wnioskujemy, że nierozstrzygalny jest problem pustości i problem nieskończoności przecięcia L1L2 w klasie języków bezkontekstowych.