Złożoność obliczeniowa/Wykład 4: Redukcje i zupełność: Różnice pomiędzy wersjami

Z Studia Informatyczne
Przejdź do nawigacjiPrzejdź do wyszukiwania
Pitab (dyskusja | edycje)
Nie podano opisu zmian
 
m Zastępowanie tekstu – „ </math>” na „</math>”
 
(Nie pokazano 24 wersji utworzonych przez 5 użytkowników)
Linia 1: Linia 1:
==Redukcje i zupełność==
W poprzednim module przedstawione zostały podstawowe klasy złożoności dla
W poprzednim module przedstawione zostały podstawowe klasy złożoności dla
problemów, jak również zależności między nimi. W tym rozdziale poznamy
problemów, jak również zależności między nimi. W tym rozdziale poznamy
Linia 6: Linia 4:
zadanej klasy złożoności - redukcje.
zadanej klasy złożoności - redukcje.


===Redukcje===
==Redukcje==


{{definicja|||
{{definicja|1.1||
Niech <math>\mathcal F</math> będzie pewną rodziną funkcji o sygnaturze
Niech <math>\mathcal F</math> będzie pewną rodziną funkcji o sygnaturze


  <math>\{ 0, 1 \} ^{\star} \rightarrow \{ 0, 1 \} ^{\star}</math>
<center><math>\{ 0, 1 \} ^{\star} \rightarrow \{ 0, 1 \} ^{\star}</math></center>


domkniętą na składanie i zawierającą identyczność. Niech <math>L_1</math> i <math>L_2</math> będą językami nad alfabetem <math>\{ 0, 1 \}</math> (czyli inaczej mówiąc zakodowanymi binarnie problemami decyzyjnymi). Mówimy, że problem <math>L_1</math> jest redukowalny do problemu <math>L_2</math> w sensie rodziny <math>\mathcal F</math> i zapisujemy
domkniętą na składanie i zawierającą identyczność. Niech <math>L_1</math> i <math>L_2</math> będą językami nad alfabetem <math>\{ 0, 1 \}</math> (czyli inaczej mówiąc zakodowanymi binarnie problemami decyzyjnymi). Mówimy, że problem <math>L_1</math> jest redukowalny do problemu <math>L_2</math> w sensie rodziny <math>\mathcal F</math> i zapisujemy


  <math>L_1 \leq_{\mathcal F} L_2</math>
<center><math>L_1 \leq_{\mathcal F} L_2</math>.</center>


wtedy i tylko wtedy, gdy
wtedy i tylko wtedy, gdy


  <math>\exists_{f \in \mathcal F} \forall_{w \in \{ 0, 1 \} ^\star}
<center><math>\exists_{f \in \mathcal F} \forall_{w \in \{ 0, 1 \} ^\star}
w \in L_1 \iff f(w) \in L_2</math>
w \in L_1 \iff f(w) \in L_2</math></center>


}}
}}


Intuicyjnie problem <math>L_1</math> jest w pewnym sensie co najwyżej tak trudny jak problem <math>L_2</math> - jeżeli znamy rozwiązanie problemu <math>L_2</math> oraz odpowiednią funkcję (zwaną redukcją lub transformacją), to znamy również rozwiązanie problemu <math>L_1</math>. Warto zauważyć, że relacja <math>\leq_{\mathcal F}</math> jest preporządkiem, to znaczy jest zwrotna (ze względu na obecność identyczności) i przechodnia (ze względu na domkniętość rodziny <math>\mathcal F</math> na składanie).
Intuicyjnie problem <math>L_1</math> jest w pewnym sensie co najwyżej tak trudny, jak problem <math>L_2</math> - jeżeli znamy rozwiązanie problemu <math>L_2</math> oraz odpowiednią funkcję (zwaną redukcją lub transformacją), to znamy również rozwiązanie problemu <math>L_1</math>. Warto zauważyć, że relacja <math>\leq_{\mathcal F}</math> jest preporządkiem, to znaczy jest zwrotna (ze względu na obecność identyczności) i przechodnia (ze względu na domkniętość rodziny <math>\mathcal F</math> na składanie).


Przedstawmy teraz najczęściej stosowane rodziny redukcji.
Przedstawmy teraz najczęściej stosowane rodziny redukcji.


'''Redukcje wielomianowe'''
===Redukcje wielomianowe===


[[File:ZO-4-1.mp4|250x250px|thumb|right|Przekształcenie grafu dwudzielnego w sieć przepływową.]]
<!-- [[ZO-4-1. Przekształcenie grafu dwudzielnego w sieć przepływową.]] -->
Rodzina redukcji wielomianowych (Karpa) to rodzina funkcji <math>\{ 0, 1 \} ^{\star} \rightarrow \{ 0, 1 \} ^{\star}</math> obliczalnych nadeterministycznej maszynie Turinga w czasie wielomianowym. Redukowalność w sensie rodziny redukcji wielomianowych najczęściej po prostu nazywa się redukowalnością wielomianową.
Rodzina redukcji wielomianowych (Karpa) to rodzina funkcji <math>\{ 0, 1 \} ^{\star} \rightarrow \{ 0, 1 \} ^{\star}</math> obliczalnych nadeterministycznej maszynie Turinga w czasie wielomianowym. Redukowalność w sensie rodziny redukcji wielomianowych najczęściej po prostu nazywa się redukowalnością wielomianową.


Klasycznym przykładem redukowalnosci wielomianowej jest redukowalność
Klasycznym przykładem redukowalnosci wielomianowej jest redukowalność
problemu maksymalnego skojarzenia w grafie dwudzielnym do problemu maksymalnego przepływu w grafie skierowanym.
problemu maksymalnego skojarzenia w grafie dwudzielnym do problemu maksymalnego przepływu w grafie skierowanym (animacja [http://osilek.mimuw.edu.pl/images/3/36/ZO-4-1.swf Przekształcenie grafu dwudzielnego w sieć przepływową]).


[[ZO-4-1. Przekształcenie grafu dwudzielnego w sieć przepływową.]]
Redukcje wielomianowe mają ważną własność: jeżeli problem <math>L_1</math> jest redukowalny wielomianowo do problemu <math>L_2</math> oraz <math>L_2</math> należy do klasy <math>P</math>, to <math>L_1</math> również należy do klasy <math>P</math>. Aby uzasadnić własność, wystarczy skonstruować maszynę, która najpierw przekształci instancję problemu <math>L_1</math> do instancji problemu <math>L_2</math> (uczyni to w czasie wielomianowym, bo <math>L_1</math> jest
 
Redukcje wielomianowe mają ważną własność: Jeżeli problem <math>L_1</math> jest redukowalny wielomianowo do problemu <math>L_2</math> oraz <math>L_2</math> należy do klasy <math>P</math>, to <math>L_1</math> również należy do klasy <math>P</math>. Aby uzasadnić własność wystarczy skonstruować maszynę, która najpierw przekształci instancję problemu <math>L_1</math> do instancji problemu <math>L_2</math> (uczyni to w czasie wielomianowym, bo <math>L_1</math> jest
wielomianowo redukowalne do <math>L_2</math>), po czym w czasie wielomianowym da odpowiedź dla instancji problemu <math>L_2</math>.
wielomianowo redukowalne do <math>L_2</math>), po czym w czasie wielomianowym da odpowiedź dla instancji problemu <math>L_2</math>.


{{cwiczenie|1||
{{cwiczenie|1.2||
Załóżmy, że <math>L_1</math> jest wielomianowo redukowalne do <math>L_2</math> oraz <math>L_2</math> należy do klasy <math>NP</math>. Pokaż, że <math>L_1</math> również należy do klasy <math>NP</math>.
Załóżmy, że <math>L_1</math> jest wielomianowo redukowalne do <math>L_2</math> oraz <math>L_2</math> należy do klasy <math>NP</math>. Pokaż, że <math>L_1</math> również należy do klasy <math>NP</math>.
}}
}}


<div class="mw-collapsible mw-made=collapsible mw-collapsed"><span class="mw-collapsible-toogle mw-collapsible-toogle-default style="font-variant:small-caps">Rozwiązanie </span><div class="mw-collapsible-content" style="display:none"> Należy tutaj skorzystać z faktu, że deterministyczna maszyna Turinga jest specjalnym przypadkiem maszyny niedeterministycznej. Wystarczy zatem najpierw uruchomić deterministyczną maszynę implementującą redukcję z <math>L_1</math> do <math>L_2</math>, po czym uruchomić niedeterministyczną maszynę, rozwiązującą problem <math>L_2</math> w czasie wielomianowym. Otrzymamy w tym momencie niedeterministyczną maszynę rozwiązującą problem <math>L_1</math>. Należy jeszcze tylko uzasadnić, czemu łączny czas działania tej maszyny będzie wielomianowo zależny od wielkości wejścia; wiemy jednak, że wyjście redukcji jest co najwyżej wielomianowo zależne
<div class="mw-collapsible mw-made=collapsible mw-collapsed"><span class="mw-collapsible-toogle mw-collapsible-toogle-default style="font-variant:small-caps">Rozwiązanie </span><div class="mw-collapsible-content" style="display:none"> Należy tutaj skorzystać z faktu, że deterministyczna maszyna Turinga jest specjalnym przypadkiem maszyny niedeterministycznej. Wystarczy zatem najpierw uruchomić deterministyczną maszynę implementującą redukcję z <math>L_1</math> do <math>L_2</math>, po czym uruchomić niedeterministyczną maszynę, rozwiązującą problem <math>L_2</math> w czasie wielomianowym. Otrzymamy w tym momencie niedeterministyczną maszynę rozwiązującą problem <math>L_1</math>. Należy jeszcze tylko uzasadnić, dlaczego łączny czas działania tej maszyny będzie wielomianowo zależny od wielkości wejścia; wiemy jednak, że wyjście redukcji jest co najwyżej wielomianowo zależne
od wielkości wejścia (maszyna "nie ma czasu" żeby zapisać więcej komórek),
od wielkości wejścia (maszyna "nie ma czasu" żeby zapisać więcej komórek),
oraz że złożenie dwóch wielomianów daje w efekcie wielomian. Własności te
oraz że złożenie dwóch wielomianów daje w efekcie wielomian. Własności te
Linia 51: Linia 49:
</div></div>
</div></div>


'''Redukcje logarytmiczne'''
===Redukcje logarytmiczne===


Drugą ciekawą rodziną redukcji jest rodzina redukcji logarytmicznych. Aby
Drugą ciekawą rodziną redukcji jest rodzina redukcji logarytmicznych. Aby
zdefiniować tą rodzinę zmodyfikujemy definicję maszyny Turinga - otóż
zdefiniować tą rodzinę zmodyfikujemy definicję maszyny Turinga - otóż
wyznaczamy na niej dwie specjalne taśmy - wejściową (tylko do odczytu,
wyznaczamy na niej dwie specjalne taśmy: wejściową (tylko do odczytu,
tak jak przy maszynie off-line) i wyjściową. Po zapisie na taśmę wyjściową
tak jak przy maszynie off-line) i wyjściową. Po zapisie na taśmę wyjściową
głowica przesuwa się zawsze w tym samym kierunku, co uniemożliwia odczyt
głowica przesuwa się zawsze w tym samym kierunku, co uniemożliwia odczyt
Linia 68: Linia 66:
wejściowych (lub innych obiektów o podobnej wielkości).
wejściowych (lub innych obiektów o podobnej wielkości).


{{cwiczenie|2||
{{cwiczenie|1.3||
Czy problem maksymalnego skojarzenia w grafie dwudzielnym jest redukowalny
Czy problem maksymalnego skojarzenia w grafie dwudzielnym jest redukowalny
do problemu maksymalnego przepływu w sensie rodziny transformacji
do problemu maksymalnego przepływu w sensie rodziny transformacji
Linia 77: Linia 75:
</div></div>
</div></div>


<div class="mw-collapsible mw-made=collapsible mw-collapsed"><span class="mw-collapsible-toogle mw-collapsible-toogle-default style="font-variant:small-caps">Rozwiązanie </span><div class="mw-collapsible-content" style="display:none"> Załóżmy, że graf dwudzielny jest przedstawiony w postaci macierzy sąsiedztwa (niekoniecznie kwadratowej - w końcu wiemy, że graf wejściowy jest dwudzielny), oraz że na wyjście chcemy również wypisać graf w postaci macierzy sąsiedztwa (tym razem już kwadratowej). Problem ten możemy rozwiązać używając następujących danych na taśmie tymczasowej:
<div class="mw-collapsible mw-made=collapsible mw-collapsed"><span class="mw-collapsible-toogle mw-collapsible-toogle-default style="font-variant:small-caps">Rozwiązanie </span><div class="mw-collapsible-content" style="display:none"> Załóżmy, że graf dwudzielny jest przedstawiony w postaci macierzy sąsiedztwa (niekoniecznie kwadratowej - w końcu wiemy, że graf wejściowy jest dwudzielny) oraz że na wyjście chcemy również wypisać graf w postaci macierzy sąsiedztwa (tym razem już kwadratowej). Problem ten możemy rozwiązać, używając następujących danych na taśmie tymczasowej:


*dwie liczby reprezentujące pozycję aktualnie wypisywanego elementu macierzy wyjściowej (każda o rozmiarze logarytmicznie zależnym od wielkości wejścia),
*dwie liczby reprezentujące pozycję aktualnie wypisywanego elementu macierzy wyjściowej (każda o rozmiarze logarytmicznie zależnym od wielkości wejścia),
Linia 83: Linia 81:
*liczbę pamiętającą aktualną pozycję głowicy na taśmie wejściowej (rozmiar j.w.).
*liczbę pamiętającą aktualną pozycję głowicy na taśmie wejściowej (rozmiar j.w.).


Aby wypisać jakiś element macierzy wyjściowej musimy sprawdzić, jakiego typu są
Aby wypisać jakiś element macierzy wyjściowej, musimy sprawdzić, jakiego typu są
odpowiadające mu wierzchołki, czyli czy są one: źródłem, ujściem, elementem
odpowiadające mu wierzchołki, czyli czy są one: źródłem, ujściem, elementem
pierwszego zbioru czy elementem drugiego zbioru. Taka klasyfikacja może
pierwszego zbioru czy elementem drugiego zbioru. Taka klasyfikacja może
Linia 92: Linia 90:
W tym celu będziemy musieli obliczyć numer komórki na taśmie wejściowej,
W tym celu będziemy musieli obliczyć numer komórki na taśmie wejściowej,
która reprezentuje interesującą nas krawędź; możemy to jednak zrobić z użyciem
która reprezentuje interesującą nas krawędź; możemy to jednak zrobić z użyciem
tylko takiej ilości pamięci, która jest potrzebna aby zapisać wynik. Pozostaje
tylko takiej ilości pamięci, która jest potrzebna, aby zapisać wynik. Pozostaje
nam już tylko przesunąć się do odpowiedniej komórki - ta operacja nie wymaga
nam już tylko przesunąć się do odpowiedniej komórki - ta operacja nie wymaga
już jednak żadnej dodatkowej pamięci.
już jednak żadnej dodatkowej pamięci.
Linia 102: Linia 100:
</div></div>
</div></div>


{{cwiczenie|3||
{{cwiczenie|1.4||
Czy istnienie redukcji logarytmicznej z problemu <math>L_1</math> do problemu <math>L_2</math> implikuje istnienie redukcji wielomianowej z <math>L_1</math> do <math>L_2</math>? Odpowiedź uzasadnij.
Czy istnienie redukcji logarytmicznej z problemu <math>L_1</math> do problemu <math>L_2</math> implikuje istnienie redukcji wielomianowej z <math>L_1</math> do <math>L_2</math>? Odpowiedź uzasadnij.
}}
}}
Linia 111: Linia 109:
<div class="mw-collapsible mw-made=collapsible mw-collapsed"><span class="mw-collapsible-toogle mw-collapsible-toogle-default style="font-variant:small-caps">Rozwiązanie </span><div class="mw-collapsible-content" style="display:none"> Można łatwo oszacować liczbę konfiguracji, w których znajduje się maszyna implementująca redukcję logarytmiczną; składa się na nią ilość pozycji, w których może się znajdować głowica taśmy wejściowej (<math>(O(n))</math> - możemy bezpiecznie założyć, że maszyna nie przesuwa się "zbyt daleko poza wejście" na tej taśmie), liczba stanów oraz liczba różnych napisów, które mogą się znaleźć na taśmie roboczej (<math>2^{O(\log n)} = O(n^k)</math>, dla pewnej stałej <math>k</math>). Liczba konfiguracji tej maszyny jest zatem wielomianowo zależna od wielkości wejścia; czas działania maszyny implementującej redukcję (a zatem "niezapętlającej się") musi być więc co najwyżej wielomianowy w stosunku do wielkości wejścia.
<div class="mw-collapsible mw-made=collapsible mw-collapsed"><span class="mw-collapsible-toogle mw-collapsible-toogle-default style="font-variant:small-caps">Rozwiązanie </span><div class="mw-collapsible-content" style="display:none"> Można łatwo oszacować liczbę konfiguracji, w których znajduje się maszyna implementująca redukcję logarytmiczną; składa się na nią ilość pozycji, w których może się znajdować głowica taśmy wejściowej (<math>(O(n))</math> - możemy bezpiecznie założyć, że maszyna nie przesuwa się "zbyt daleko poza wejście" na tej taśmie), liczba stanów oraz liczba różnych napisów, które mogą się znaleźć na taśmie roboczej (<math>2^{O(\log n)} = O(n^k)</math>, dla pewnej stałej <math>k</math>). Liczba konfiguracji tej maszyny jest zatem wielomianowo zależna od wielkości wejścia; czas działania maszyny implementującej redukcję (a zatem "niezapętlającej się") musi być więc co najwyżej wielomianowy w stosunku do wielkości wejścia.


Istnienie redukcji logarytmicznej pociąga zatem za sobą istnienie redukcji
Istnienie redukcji logarytmicznej pociąga zatem za sobą istnienie redukcji wielomianowej.
wielomianowej.
</div></div>
</div></div>


Warto się zastanowić czy prawdziwa jest następująca hipoteza:
Warto się zastanowić, czy prawdziwa jest następująca hipoteza:


{{hipoteza|||
{{hipoteza|1.5||
Niech <math>L_1 \leq_L L_2</math> i <math>L_2 \in L</math>. Wtedy <math>L_1 \in L</math>.  
Niech <math>L_1 \leq_L L_2</math> i <math>L_2 \in L</math>. Wtedy <math>L_1 \in L</math>.  
}}
}}


Ta niewątpliwie cenna (o ile prawdziwa) hipoteza nie jest jednak tak oczywista
Ta niewątpliwie cenna (o ile prawdziwa) hipoteza nie jest jednak tak oczywista,
jak poprzednio pokazywane analogiczne fakty dla transformacji wielomianowej
jak poprzednio pokazywane analogiczne fakty dla transformacji wielomianowej
i klas <math>P</math> oraz <math>NP</math>. Problem przy "składaniu" dwóch maszyn - transformacji oraz maszyny rozwiązującej <math>L_2</math> - tkwi w tym, że być może nie będziemy w stanie zapisac wyjścia transformacji (o potencjalnie wielomianowej wielkości) na taśmie roboczej.
i klas <math>P</math> oraz <math>NP</math>. Problem przy "składaniu" dwóch maszyn - transformacji oraz maszyny rozwiązującej <math>L_2</math> - tkwi w tym, że być może nie będziemy w stanie zapisać wyjścia transformacji (o potencjalnie wielomianowej wielkości) na taśmie roboczej.


Posłużymy się tutaj następującym trikiem: Uruchomimy maszynę rozwiązującą
Posłużymy się tutaj następującym trikiem: uruchomimy maszynę rozwiązującą
problem <math>L_2</math>; za każdym razem, gdy maszyna ta będzie chciała odwołać się do któregoś - dla ustalenia uwagi <math>i</math>-tego - bitu wejścia, na osobnej taśmie uruchomimy maszynę implementującą redukcję z <math>L_1</math> do <math>L_2</math>. Maszyna ta nie będzie jednak wypisywać kolejnych symboli na wyjście, tylko inkrementować specjalnie utworzony licznik operacji wyjścia; w momencie, gdy wykonana zostanie <math>i</math>-ta operacja wyjścia, maszyna powróci do wykonywania programu rozwiązującego problem <math>L_2</math>, wykorzystująć symbol, który miał zostać wypisany na wyjście przez maszynę transformującą. Takie postępowanie wydaje się mało wydajne - tym niemniej na taśmach roboczych nigdy nie znajduje się większa niż logarytmiczna liczba symboli - a zatem otrzymujemy algorytm dla problemu <math>L_1</math>, wykorzystujący logarytmiczną ilośc symboli. Analogiczny argument można zastosować do pokazania, że rodzina transformacji logarytmicznych jest domknięta na składanie.  
problem <math>L_2</math>; za każdym razem, gdy maszyna ta będzie chciała odwołać się do któregoś - dla ustalenia uwagi <math>i</math>-tego - bitu wejścia, na osobnej taśmie uruchomimy maszynę implementującą redukcję z <math>L_1</math> do <math>L_2</math>. Maszyna ta nie będzie jednak wypisywać kolejnych symboli na wyjście, tylko inkrementować specjalnie utworzony licznik operacji wyjścia; w momencie, gdy wykonana zostanie <math>i</math>-ta operacja wyjścia, maszyna powróci do wykonywania programu rozwiązującego problem <math>L_2</math>, wykorzystując  symbol, który miał zostać wypisany na wyjście przez maszynę transformującą. Takie postępowanie wydaje się mało wydajne - tym niemniej na taśmach roboczych nigdy nie znajduje się większa niż logarytmiczna liczba symboli - a zatem otrzymujemy algorytm dla problemu <math>L_1</math>, wykorzystujący logarytmiczną ilośc symboli. Analogiczny argument można zastosować do pokazania, że rodzina transformacji logarytmicznych jest domknięta na składanie.


'''Transformacja wielomianowa w sensie Turinga'''
===Transformacja wielomianowa w sensie Turinga===


Definiowana tutaj transformacja będzie miała trochę inny charakter od dwóch
Definiowana tutaj transformacja będzie miała trochę inny charakter od dwóch
Linia 134: Linia 131:
zdefiniowania będziemy potrzebować pojęcia maszyny z wyrocznią.
zdefiniowania będziemy potrzebować pojęcia maszyny z wyrocznią.


{{definicja|||
{{definicja|1.6||
Maszyna z wyrocznią <math>Q \subseteq \{ 0, 1 \} ^\star</math> jest wielotaśmową
Maszyna z wyrocznią <math>Q \subseteq \{ 0, 1 \} ^\star</math> jest wielotaśmową
maszyną Turinga, z jedną wyróżnioną taśmą i trzema wyróżnionymi stanami <math>\{ q_a, q_b, q_c \}</math>. Zachowanie maszyny różni się od zachowania zwykłej maszyny Turinga w następujący sposób: Przejście maszyny do stanu <math>q_a</math> jest traktowane jako odwołanie do wyroczni <math>Q</math>. Jeżeli słowo aktualnie zapisane na wyróżnionej taśmie należy do języka <math>Q</math>, to maszyna przechodzi do stanu <math>q_b</math>; w przeciwnym razie przechodzi do stanu <math>q_c</math>. Odwołanie do wyroczni wliczane jest do czasu działania maszyny jako jedno przejście.
maszyną Turinga, z jedną wyróżnioną taśmą i trzema wyróżnionymi stanami <math>\{ q_a, q_b, q_c \}</math>. Zachowanie maszyny różni się od zachowania zwykłej maszyny Turinga w następujący sposób: przejście maszyny do stanu <math>q_a</math> jest traktowane jako odwołanie do wyroczni <math>Q</math>. Jeżeli słowo aktualnie zapisane na wyróżnionej taśmie należy do języka <math>Q</math>, to maszyna przechodzi do stanu <math>q_b</math>; w przeciwnym razie przechodzi do stanu <math>q_c</math>. Odwołanie do wyroczni wliczane jest do czasu działania maszyny jako jedno przejście.
}}
}}


Mówiąc nieformalnie maszyna może w trakcie działania wielokrotnie prosić
Mówiąc nieformalnie, maszyna może w trakcie działania wielokrotnie prosić
wyrocznię o rozwiązanie problemu <math>Q</math>.
wyrocznię o rozwiązanie problemu <math>Q</math>.


{{definicja|||
{{definicja|1.7||
Niech <math>L_1</math> i <math>L_2</math> będą językami nad alfabetem <math>\{ 0, 1 \}</math>. Mówimy, że <math>L_1</math> transformuje się do <math>L_2</math> w sensie wielomianowej transformacji Turinga wtedy i tylko wtedy gdy istnieje maszyna Turinga z wyrocznią <math>L_2</math> rozwiązująca <math>L_1</math> w czasie wielomianowym.
Niech <math>L_1</math> i <math>L_2</math> będą językami nad alfabetem <math>\{ 0, 1 \}</math>. Mówimy, że <math>L_1</math> transformuje się do <math>L_2</math> w sensie wielomianowej transformacji Turinga wtedy i tylko wtedy, gdy istnieje maszyna Turinga z wyrocznią <math>L_2</math>, rozwiązująca <math>L_1</math> w czasie wielomianowym.
}}
}}


Transformacja Turinga intuicyjnie odpowiada stosowaniu podprogramów - jeżeli znamy rozwiązanie problemu <math>L_2</math> to stosujemy go jako podprocedurę
Transformacja Turinga intuicyjnie odpowiada stosowaniu podprogramów - jeżeli znamy rozwiązanie problemu <math>L_2</math>, to stosujemy go jako podprocedurę
przy rozwiązywaniu problemu <math>L_1</math>.
przy rozwiązywaniu problemu <math>L_1</math>.


{{cwiczenie|4||
{{cwiczenie|1.8||
Niech <math>L_1</math> i <math>L_2</math> będą językami nad alfabetem <math>\{ 0, 1 \}</math> oraz niech <math>L_1</math> transformuje się do <math>L_2</math> w sensie transformacji wielomianowej Turinga. Które z poniższych zdań jest prawdziwe:
Niech <math>L_1</math> i <math>L_2</math> będą językami nad alfabetem <math>\{ 0, 1 \}</math> oraz niech <math>L_1</math> transformuje się do <math>L_2</math> w sensie transformacji wielomianowej Turinga. Które z poniższych zdań jest prawdziwe:


Linia 158: Linia 155:
}}
}}


<div class="mw-collapsible mw-made=collapsible mw-collapsed"><span class="mw-collapsible-toogle mw-collapsible-toogle-default style="font-variant:small-caps">Rozwiązanie </span><div class="mw-collapsible-content" style="display:none"> Po pierwsze należy zauważyć, że transformacja z problemu <math>L_1</math> do <math>L_2</math> nie mówi nam absolutnie nic o złożoności problemu <math>L_2</math>. Dodatkowo jeśli <math>L_1 \in P</math> to problem ten transformuje się w sensie Turinga do ''każdego'' problemu decyzyjnego (czyli np. do problemu trywialnego, albo problemu podwójnie wykładniczego) - można rozwiązać ten problem w ogóle nie odwołując się do wyroczni.
<div class="mw-collapsible mw-made=collapsible mw-collapsed"><span class="mw-collapsible-toogle mw-collapsible-toogle-default style="font-variant:small-caps">Rozwiązanie </span><div class="mw-collapsible-content" style="display:none"> Po pierwsze należy zauważyć, że transformacja z problemu <math>L_1</math> do <math>L_2</math> nie mówi nam absolutnie nic o złożoności problemu <math>L_2</math>. Dodatkowo, jeśli <math>L_1 \in P</math> to problem ten transformuje się w sensie Turinga do ''każdego'' problemu decyzyjnego (czyli np. do problemu trywialnego albo problemu podwójnie wykładniczego) - można rozwiązać <math>L_1</math> w ogóle nie odwołując się do wyroczni.


Druga implikacja oczywiście zachodzi. Problem <math>L_1</math> można rozwiązać stosując rozwiązanie problemu <math>L_2</math> jako subrutynę. Złożoność czasowa tego rozwiązania będzie określona od góry przez złożenie dwóch wielomianów - co jak wiemy również jest wielomianem.
Druga implikacja oczywiście zachodzi. Problem <math>L_1</math> można rozwiązać, stosując rozwiązanie problemu <math>L_2</math> jako subrutynę. Złożoność czasowa tego rozwiązania będzie określona od góry przez złożenie dwóch wielomianów - co jak wiemy również jest wielomianem.


Niniejsze ćwiczenie ma za zadanie zaprezentowanie pewnego częstego błędu
Niniejsze ćwiczenie ma za zadanie zaprezentowanie pewnego częstego błędu
logicznego; zazwyczaj bowiem jeśli myślimy o subrutynie, to traktujemy ją
logicznego; zazwyczaj bowiem, jeśli myślimy o subrutynie, to traktujemy ją
jako coś prostszego od całego problemu. W tej sytuacji jednak -- gdy mamy wielomianowy
jako coś prostszego od całego problemu. W tej sytuacji jednak -- gdy mamy wielomianowy
(czyli "prosty") algorytm używający pewnej subrutyny -- widzimy, że jedyna
(czyli "prosty") algorytm używający pewnej subrutyny -- widzimy, że jedyna
Linia 174: Linia 171:
symbolem <math>\leq_T</math>.
symbolem <math>\leq_T</math>.


{{cwiczenie|5||
{{cwiczenie|1.9||
Które z poniższych zdań jest prawdziwe:
Które z poniższych zdań jest prawdziwe:


Linia 190: Linia 187:
</div></div>
</div></div>


===Zupełność===
==Zupełność==


Zastosujemy teraz zdefiniowane uprzednio rodziny transformacji do zdefiniowania
Zastosujemy teraz zdefiniowane uprzednio rodziny transformacji do zdefiniowania
Linia 196: Linia 193:
- swoistej arystokracji w ramach danej klasy.
- swoistej arystokracji w ramach danej klasy.


{{definicja|||
{{definicja|2.1||
Niech <math>\mathcal C</math> będzie pewną klasą złożoności, natomiast <math>\sqsubseteq</math> preporządkiem określonym na językach zawartych w <math>\{ 0, 1 \} ^\star</math> (w domyśle jedną ze zdefiniowanych wcześniej rodzin transformacji). Mówimy, że problem decyzyjny <math>L \subseteq \{ 0, 1 \} ^\star</math> jest <math>\mathcal C</math>-zupełny w sensie preporządku <math>\sqsubseteq</math> wtedy i tylko wtedy, gdy:
Niech <math>\mathcal C</math> będzie pewną klasą złożoności, natomiast <math>\sqsubseteq</math> preporządkiem określonym na językach zawartych w <math>\{ 0, 1 \} ^\star</math> (w domyśle jedną ze zdefiniowanych wcześniej rodzin transformacji). Mówimy, że problem decyzyjny <math>L \subseteq \{ 0, 1 \} ^\star</math> jest <math>\mathcal C</math>-zupełny w sensie preporządku <math>\sqsubseteq</math> wtedy i tylko wtedy, gdy:


Linia 206: Linia 203:
Intuicyjnie problem <math>\mathcal C</math>-zupełny jest najtrudniejszym do rozwiązania problemem w klasie złożoności <math>{\mathcal C}</math>. Warto zauważyć, że może istnieć (i zazwyczaj istnieje) więcej niż jeden problem <math>{\mathcal C}</math>-zupełny. Problemy te są równoważne w sensie relacji preporządku <math>\sqsubseteq</math>.
Intuicyjnie problem <math>\mathcal C</math>-zupełny jest najtrudniejszym do rozwiązania problemem w klasie złożoności <math>{\mathcal C}</math>. Warto zauważyć, że może istnieć (i zazwyczaj istnieje) więcej niż jeden problem <math>{\mathcal C}</math>-zupełny. Problemy te są równoważne w sensie relacji preporządku <math>\sqsubseteq</math>.


{{cwiczenie|6||
{{cwiczenie|2.2||
Scharakteryzuj problemy <math>P</math>-zupełne w sensie transformacji wielomianowej.
Scharakteryzuj problemy <math>P</math>-zupełne w sensie transformacji wielomianowej.
}}
}}


<div class="mw-collapsible mw-made=collapsible mw-collapsed"><span class="mw-collapsible-toogle mw-collapsible-toogle-default style="font-variant:small-caps">Rozwiązanie </span><div class="mw-collapsible-content" style="display:none"> Problemami <math>P</math>-zupełnymi są wszystkie problemy reprezentowane przez nietrywialne (to znaczy nie-puste i nie-pełne) języki. Transformacja języka <math>L_1 \in P</math> do nietrywialnego języka <math>L_2 \in P</math> będzie tutaj polegała na rozwiązaniu problemu <math>L_1</math>, a następnie - w zależności czy obliczenie jest akceptujące czy nie - na wypisaniu jednej z dwóch ustalonych wcześniej instancji problemu <math>L_2</math>, z których pierwsza należy a druga nie należy do <math>L_2</math>.
<div class="mw-collapsible mw-made=collapsible mw-collapsed"><span class="mw-collapsible-toogle mw-collapsible-toogle-default style="font-variant:small-caps">Rozwiązanie </span><div class="mw-collapsible-content" style="display:none"> Problemami <math>P</math>-zupełnymi są wszystkie problemy reprezentowane przez nietrywialne języki (język jest nietrywialny, jeśli jest niepusty i różny od zbioru wszystkich słów nad danym alfabetem). Transformacja języka <math>L_1 \in P</math> do nietrywialnego języka <math>L_2 \in P</math> będzie tutaj polegała na rozwiązaniu problemu <math>L_1</math>, a następnie - w zależności od tego, czy obliczenie jest akceptujące, czy nie - na wypisaniu jednej z dwóch ustalonych wcześniej instancji problemu <math>L_2</math>, z których pierwsza należy, a druga nie należy do <math>L_2</math>.


</div></div>
</div></div>
Linia 216: Linia 213:
Jak zauważyliśmy rozpatrywana powyżej klasa jest mało interesująca. Jeszcze
Jak zauważyliśmy rozpatrywana powyżej klasa jest mało interesująca. Jeszcze
mniej interesująca jest oczywiście klasa problemów <math>P</math>-zupełnych w sensie transformacji wielomianowej Turinga. Dla odróżnienia - klasa problemów
mniej interesująca jest oczywiście klasa problemów <math>P</math>-zupełnych w sensie transformacji wielomianowej Turinga. Dla odróżnienia - klasa problemów
<math>P</math>-zupełnych w sensie transformacji logarytmicznej cieszy się niemałym zainteresowanie specjalistów z dziedziny złożoności obliczeniowej; z tego powodu najczęściej określa się ją po prostu jako klasę problemów <math>P</math>-zupełnych.
<math>P</math>-zupełnych w sensie transformacji logarytmicznej cieszy się niemałym zainteresowaniem specjalistów z dziedziny złożoności obliczeniowej; z tego powodu najczęściej określa się ją po prostu jako klasę problemów <math>P</math>-zupełnych.


{{uwaga|||   
{{uwaga|2.3||   
Przykładem problemu <math>P</math>-zupełnego jest problem HORNSAT. Jego opis można znaleźć w ...
Przykłady problemów <math>P</math>-zupełnych można znaleźć w module 11.
}}
}}


===Klasa NP i NP-zupełność===
==Klasa NP i NP-zupełność==


W ramach tego kursu naszym największym zainteresowaniem będzie się cieszyć klasa
W ramach tego kursu naszym wielkim zainteresowaniem będzie się cieszyć klasa
<math>NP</math>, a w szczególności problemy <math>NP</math>-zipełne w sensie trzech poznanych wcześniej rodzin transformacji. Zanim jednak przejdziemy do problemów <math>NP</math>-zupełnych, poznamy pewną alternatywną definicję klasy złożoności <math>NP</math>.
<math>NP</math>, a w szczególności problemy <math>NP</math>-zupełne w sensie trzech poznanych wcześniej rodzin transformacji. Zanim jednak przejdziemy do problemów <math>NP</math>-zupełnych, poznamy pewną alternatywną definicję klasy złożoności <math>NP</math>.


{{twierdzenie|||
{{twierdzenie|3.1|tw 1|
Niech <math>L \subseteq \{ 0, 1 \} ^\star</math>. Wtedy:
Niech <math>L \subseteq \{ 0, 1 \} ^\star</math>. Wtedy:


Linia 234: Linia 231:
\forall_{n \in {\mathbb N}} \forall_{w \in \{ 0, 1 \} ^n}
\forall_{n \in {\mathbb N}} \forall_{w \in \{ 0, 1 \} ^n}
[w \in L \iff</math><math>(\exists_{v \in \{ 0, 1 \}^{p(n)}} \langle w, v \rangle \in L')
[w \in L \iff</math><math>(\exists_{v \in \{ 0, 1 \}^{p(n)}} \langle w, v \rangle \in L')
]</math>
]</math>.
}}
}}


Zanim udowodnimy powyższy fakt, spróbujmy najpierw prześledzić, co się
Zanim udowodnimy powyższy fakt, spróbujmy najpierw prześledzić, co się
właściwie dzieje po prawej stronie równoważności. Słowo <math>v</math> zwykle nazywane jest ''świadkiem'' (ang. ''witness'') słowa <math>w</math>. Żądamy, żeby każde słowo należące do języka <math>L</math> miało świadka o długości wielomianowej, natomiast żadne słowo spoza <math>L</math> takiego świadka nie miało. Co więcej - żądamy, aby sprawdzanie, czy <math>v</math> jest świadkiem słowa <math>w</math> było wykonywane w czasie wielomianowym na maszynie deterministycznej - dlatego klasę <math>NP</math> czasem nazywamy klasą problemów weryfikowalnych w czasie wielomianowym.
właściwie dzieje po prawej stronie równoważności. Słowo <math>v</math> zwykle nazywane jest ''świadkiem'' (ang. ''witness'') słowa <math>w</math>. Żądamy, żeby każde słowo należące do języka <math>L</math> miało świadka o długości wielomianowej, natomiast żadne słowo spoza <math>L</math> takiego świadka nie miało. Co więcej - żądamy, aby sprawdzanie, czy <math>v</math> jest świadkiem słowa <math>w</math> było wykonywane w czasie wielomianowym na maszynie deterministycznej, dlatego klasę <math>NP</math> czasem nazywamy klasą problemów weryfikowalnych w czasie wielomianowym.


{{przyklad|[<math>NONPRIME</math>]||
{{przyklad|3.2 [<math>NONPRIME</math>]||
Rozważmy problem <math>NONPRIME</math>. Niech <math>w \in \{ 0, 1 \} ^\star</math> będzie reprezentacją liczby naturalnej w systemie binarnym.
Rozważmy problem <math>NONPRIME</math>. Niech <math>w \in \{ 0, 1 \} ^\star</math> będzie reprezentacją liczby naturalnej w systemie binarnym.


  <math>w \in NONPRIME \iff</math> liczba reprezentowana przez <math>w</math> nie jest liczbą pierwszą
<math>w \in NONPRIME \iff</math> liczba reprezentowana przez <math>w</math> nie jest liczbą pierwszą.


Aby pokazać, że liczba nie jest pierwsza, wystarczy podać dowolny jej nietrywialny dzielnik (nie dotyczy to oczywiście liczby 1). Właśnie ten dzielnik będzie naszym świadkiem (w specjalnym przypadku liczby 1 uznamy, że jej świadkiem jest 1). Język <math>L'</math> będzie miał wtedy następującą postać:
Aby pokazać, że liczba nie jest pierwsza, wystarczy podać dowolny jej nietrywialny dzielnik (nie dotyczy to oczywiście liczby 1). Właśnie ten dzielnik będzie naszym świadkiem (w specjalnym przypadku liczby 1 uznamy, że jej świadkiem jest 1). Język <math>L'</math> będzie miał wtedy następującą postać:


  <math>L' := \{ \langle w, v \rangle: (num(v) \neq num(w) \wedge num(v) \neq 1 \wedge num(v)</math><math>\mid num(w)) \vee num(w) = num(v) = 1 \}</math>
<center><math>L' := \{ \langle w, v \rangle: (num(v) \neq num(w) \wedge num(v) \neq 1 \wedge num(v)</math><math>\mid num(w)) \vee num(w) = num(v) = 1 \}</math>,</center>


gdzie <math>num(v)</math> oznacza liczbę reprezentowaną przez słowo <math>v</math>. Łatwo zauważyć, że <math>L'</math> jest implementowalna w czasie wielomianowym na deterministycznej maszynie - wystarczy pisemnie podzielić <math>w</math> przez <math>v</math>, sprawdzić, czy zostanie reszta z dzielenia i ewentualnie obsłużyć przypadek brzegowy (liczbę 1). Zatem jak tylko udowodnimy powyższe twierdzenie, będziemy mogli stwierdzić, że <math>NONPRIME \in NP</math>.
gdzie <math>num(v)</math> oznacza liczbę reprezentowaną przez słowo <math>v</math>. Łatwo zauważyć, że <math>L'</math> jest implementowalna w czasie wielomianowym na deterministycznej maszynie - wystarczy pisemnie podzielić <math>w</math> przez <math>v</math>, sprawdzić, czy zostanie reszta z dzielenia i ewentualnie obsłużyć przypadek brzegowy (liczbę 1). Zatem jak tylko udowodnimy powyższe twierdzenie, będziemy mogli stwierdzić, że <math>NONPRIME \in NP</math>.
}}
}}


{{dowod|||
[[File:ZO-4-2.mp4|250x250px|thumb|right|Przekształcanie rozgałęzienia stopnia k w k-1 rozgałęzień stopnia 2.]]<!-- [[ZO-4-2. Przekształcanie rozgałęzienia stopnia k w k-1 rozgałęzień stopnia 2.]] -->
{{dowod|[Twierdzenia 3.1]||
W stronę <math>\Leftarrow</math> dowód jest prosty - skonstruujemy niedeterministyczną maszynę Turinga, rozwiązującą problem <math>L</math>. Maszyna ta najpierw przesunie głowicę za słowo wejściowe, przez następne <math>p(n)</math> kroków będzie wypisywać na taśmę symbole 0 lub 1 (tu jest stosowany niedeterminizm) i przesuwać głowicę w prawo. Od tej pory maszyna będzie działać całkowicie deterministycznie - przesunie się na początek taśmy i zacznie się zachowywać jak deterministyczna maszyna rozwiązująca problem <math>L'</math> w czasie wielomianowym.
W stronę <math>\Leftarrow</math> dowód jest prosty - skonstruujemy niedeterministyczną maszynę Turinga, rozwiązującą problem <math>L</math>. Maszyna ta najpierw przesunie głowicę za słowo wejściowe, przez następne <math>p(n)</math> kroków będzie wypisywać na taśmę symbole 0 lub 1 (tu jest stosowany niedeterminizm) i przesuwać głowicę w prawo. Od tej pory maszyna będzie działać całkowicie deterministycznie - przesunie się na początek taśmy i zacznie się zachowywać jak deterministyczna maszyna rozwiązująca problem <math>L'</math> w czasie wielomianowym.


Jeżeli dla słowa wejściowego <math>w</math> istnieje świadek, to zostanie on wygenerowany przez jedną ze ścieżek postępowania w etapie niedeterministycznym. W przeciwnym przypadku wszyscy "kandydaci na świadków" zostaną odrzuceni (''zdemaskowani'') przez maszynę rozwiązującą <math>L'</math>.
Jeżeli dla słowa wejściowego <math>w</math> istnieje świadek, to zostanie on wygenerowany przez jedną ze ścieżek postępowania w etapie niedeterministycznym. W przeciwnym przypadku wszyscy "kandydaci na świadków" zostaną odrzuceni (''zdemaskowani'') przez maszynę rozwiązującą <math>L'</math>.


Udowodnijmy teraz przejście w drugą stronę (<math>\Rightarrow</math>). Skoro <math>L \in NP</math> to istnieje niedeterministyczna maszyna Turinga - <math>M</math> - rozstrzygająca problem <math>L</math>. Niech <math>k</math> oznacza ''maksymalny stopień rozgałęzienia'' maszyny <math>M</math>, tj.
Udowodnijmy teraz przejście w drugą stronę (<math>\Rightarrow</math>). Skoro <math>L \in NP</math>, to istnieje niedeterministyczna maszyna Turinga <math>M</math> rozstrzygająca problem <math>L</math>. Niech <math>k</math> oznacza ''maksymalny stopień rozgałęzienia'' maszyny <math>M</math>, tj.
 
  <math>k := \max_{(s, q) \in \Sigma \times Q} \# d(s, q)
</math>


czyli mówiąc nieformalnie największą liczbę rozgałęzień, która może się dokonać
<center><math>k := \max_{(s, q) \in \Sigma \times Q} \# d(s, q)</math>,</center>
w jednym kroku. Łatwo zauważyć, że istnieje równoważna maszyna <math>M'</math> co najwyżej <math>k-1</math>-krotnie wolniejsza (a zatem nadal wielomianowa) o maksymalnym stopniu rozgałęzienia równym 2 - uzasadnienie przedstawione jest na
poniższym rysunku.


[[ZO-4-2. Przekształcanie rozgałęzienia stopnia k w k-1 rozgałęzień stopnia 2.]]
czyli mówiąc nieformalnie, największą liczbę rozgałęzień, która może się dokonać
w jednym kroku. Łatwo zauważyć, że istnieje równoważna maszyna <math>M'</math> co najwyżej <math>k-1</math>-krotnie wolniejsza (a zatem nadal wielomianowa) o maksymalnym stopniu rozgałęzienia równym 2 - uzasadnienie przedstawione jest animacji [http://osilek.mimuw.edu.pl/images/6/63/ZO-4-2.swf Przekształcanie rozgałęzienia stopnia k w k-1 rozgałęzień stopnia 2].


Od tej pory będziemy się zajmować maszyną <math>M'</math>. Oznaczmy jej czas działania jako <math>W(n)</math>; w związku z tym maszyna dla słowa wielkości <math>n</math> wykona co najwyżej <math>W(n)</math> rozgałęzień. Każda ścieżka postępowania maszyny <math>M'</math> jest zatem zdefiniowana poprzez ciąg <math>W(n)</math> bitów mówiących, którą spośród co najwyżej dwóch dostępnych ścieżek została wybrana. Jako "kandydatów na świadków" wybierzmy zatem ciągi <math>\{ 0, 1 \} ^{W(n)}</math>, świadkiem natomiast niech będzie ciąg reprezentujący akceptującą ścieżkę postępowania maszyny <math>M'</math> - o ile
Od tej pory będziemy się zajmować maszyną <math>M'</math>. Oznaczmy jej czas działania jako <math>W(n)</math>; w związku z tym maszyna dla słowa wielkości <math>n</math> wykona co najwyżej <math>W(n)</math> rozgałęzień. Każda ścieżka postępowania maszyny <math>M'</math> jest zatem zdefiniowana poprzez ciąg <math>W(n)</math> bitów mówiących, która spośród co najwyżej dwóch dostępnych ścieżek została wybrana. Jako "kandydatów na świadków" wybierzmy zatem ciągi <math>\{ 0, 1 \} ^{W(n)}</math>, świadkiem natomiast niech będzie ciąg reprezentujący akceptującą ścieżkę postępowania maszyny <math>M'</math> - o ile
taka istnieje.
taka istnieje.


Wystarczy w tym momencie wksazać deterministyczna maszynę Turinga <math>N</math>, rozpoznającą język <math>L'</math> - czyli weryfikującą dla pary słów <math>\langle w, v \rangle</math> czy <math>v</math> jest świadkiem dla <math>w</math>. Maszyna taka jest prosta do skonstruowania w następujący sposób:
Wystarczy w tym momencie wksazać deterministyczna maszynę Turinga <math>N</math>, rozpoznającą język <math>L'</math> - czyli weryfikującą dla pary słów <math>\langle w, v \rangle</math>, czy <math>v</math> jest świadkiem dla <math>w</math>. Maszyna taka jest prosta do skonstruowania w następujący sposób:


*<math>N</math> najpierw przepisuje <math>v</math> na tasmę pomocniczą, po czym wraca na głównej taśmie do początku słowa <math>w</math>,
*<math>N</math> najpierw przepisuje <math>v</math> na tasmę pomocniczą, po czym wraca na głównej taśmie do początku słowa <math>w</math>,


*<math>N</math> zachowuje się podobnie jak maszyna <math>M'</math>; w przypadku, gdy maszyna ma do wyboru dwie opcje, <math>N</math> sięga po kolejny dostępny bit taśmy pomocniczej i na jego podstawie wybiera ścieżkę postępowania.
*<math>N</math> zachowuje się podobnie jak maszyna <math>M'</math>; w przypadku, gdy maszyna ma do wyboru dwie opcje, <math>N</math> sięga po kolejny dostępny bit taśmy pomocniczej i na jego podstawie wybiera ścieżkę postępowania.
Łatwo zauważyc, że <math>M'</math> akceptuje słowo <math>w</math> wtedy i tylko wtedy gdy istnieje świadek, który spowoduje że maszyna <math>N</math> dojdzie do stanu akceptującego.
Łatwo zauważyć, że <math>M'</math> akceptuje słowo <math>w</math> wtedy i tylko wtedy, gdy istnieje świadek, który spowoduje, że maszyna <math>N</math> dojdzie do stanu akceptującego.
}}
}}


Poznaliśmy zatem alternatywna definicję klasy <math>NP</math>. Potocznie często mówi się, że maszyna rozwiązująca problem z klasy <math>NP</math> najpierw "zgaduje" świadka, a potem weryfikuje go w deterministyczny sposób w czasie wielomianowym. Należy jednak pamiętać, że maszyna w rzeczywistości nie "zgaduje" - zamiast tego sprawdza ona ''wszystkich'' możliwych świadków.
Poznaliśmy zatem alternatywną definicję klasy <math>NP</math>. Potocznie często mówi się, że maszyna rozwiązująca problem z klasy <math>NP</math> najpierw "zgaduje" świadka, a potem weryfikuje go w deterministyczny sposób w czasie wielomianowym. Należy jednak pamiętać, że maszyna w rzeczywistości nie "zgaduje" - zamiast tego sprawdza ona ''wszystkich'' możliwych świadków.


Powrócmy teraz do redukcji i problemów zupełnych. Oznaczmy jako <math>NPC</math>, <math>NPC_L</math> i <math>NPC_T</math> klasy problemów <math>NP</math>-zupełnych w sensie odpowiednio transformacji wielomianowej Karpa, transformacji logarytmicznej i transformacji wielomianowej Turinga. W tym momencie w żaden sposób nie uzasadniliśmy jeszcze, dlaczego którakolwiek z tych klas miałaby być niepusta. Mimo to już w tym momencie można okreslić pewne relacje zawierania pomiędzy tymi klasami.
Powróćmy teraz do redukcji i problemów zupełnych. Oznaczmy jako <math>NPC</math>, <math>NPC_L</math> i <math>NPC_T</math> klasy problemów <math>NP</math>-zupełnych w sensie odpowiednio transformacji wielomianowej Karpa, transformacji logarytmicznej i transformacji wielomianowej Turinga. W tym momencie w żaden sposób nie uzasadniliśmy jeszcze, dlaczego którakolwiek z tych klas miałaby być niepusta. Mimo to już w tym momencie można określić pewne relacje zawierania pomiędzy tymi klasami.


{{cwiczenie|7||
{{cwiczenie|3.3||
Uszereguj klasy <math>NPC</math>, <math>NPC_L</math> i <math>NPC_T</math> od najwęższej do najszerszej i uzasadnij to uszeregowanie.
Uszereguj klasy <math>NPC</math>, <math>NPC_L</math> i <math>NPC_T</math> od najwęższej do najszerszej i uzasadnij to uszeregowanie.
}}
}}
Linia 289: Linia 283:
<div class="mw-collapsible mw-made=collapsible mw-collapsed"><span class="mw-collapsible-toogle mw-collapsible-toogle-default style="font-variant:small-caps">Rozwiązanie </span><div class="mw-collapsible-content" style="display:none"> Prawdziwe są następujące zawierania:
<div class="mw-collapsible mw-made=collapsible mw-collapsed"><span class="mw-collapsible-toogle mw-collapsible-toogle-default style="font-variant:small-caps">Rozwiązanie </span><div class="mw-collapsible-content" style="display:none"> Prawdziwe są następujące zawierania:


  <math>NPC_L \subseteq NPC \subseteq NPC_T</math>
<center><math>NPC_L \subseteq NPC \subseteq NPC_T</math>.</center>


Weźmy dowolny problem z <math>NPC_L</math>. Wiemy, że można do niego przekształcić każdy problem z <math>NP</math> z użyciem transformacji logarytmicznej. Na podstawie udowodnionych wcześniej faktów wiemy jednak, że redukowalność logarytmiczna implikuje redukowalność wielomianową; rozpatrywany problem należy zatem do klasy <math>NPC</math>. Analogiczne rozumowanie można zastosować do uzasadnienia drugiej inkluzji.
Weźmy dowolny problem z <math>NPC_L</math>. Wiemy, że można do niego przekształcić każdy problem z <math>NP</math> z użyciem transformacji logarytmicznej. Na podstawie udowodnionych wcześniej faktów wiemy jednak, że redukowalność logarytmiczna implikuje redukowalność wielomianową; rozpatrywany problem należy zatem do klasy <math>NPC</math>. Analogiczne rozumowanie można zastosować do uzasadnienia drugiej inkluzji.


Nie wiadomo czy pomiędzy jakąś parą klas zachodzi równość.
Nie wiadomo, czy pomiędzy jakąś parą klas zachodzi równość.
</div></div>
</div></div>


'''Problem SAT'''
===Problem SAT===


Zdefiniowanie problemu <math>SAT</math> wymaga uprzedniego wprowadzenia (względnieprzypomnienia) kilku pojęć z dziedziny logiki:
Zdefiniowanie problemu <math>SAT</math> wymaga uprzedniego wprowadzenia (względnieprzypomnienia) kilku pojęć z dziedziny logiki:


* ''literałem'' nazywamy zmienną lub jej zaprzeczenie,
* ''literałem'' nazywamy zmienną lub jej negację,


* ''klauzulą'' nazywamy alternatywę skończonej liczby literałów,
* ''klauzulą'' nazywamy alternatywę skończonej liczby literałów,


*mówimy, że formuła logiczna jest w ''koniunkcyjnej postaci normalnej'' wtedy i tylko wtedy gdy jest koniunkcją skończonej liczby klauzul. Przykładem formuły w koniunkcyjnej postaci normalnej jest formuła:
*mówimy, że formuła logiczna jest w ''koniunkcyjnej postaci normalnej'' wtedy i tylko wtedy, gdy jest koniunkcją skończonej liczby klauzul. Przykładem formuły w koniunkcyjnej postaci normalnej jest formuła:


  <math>(x_1 \vee x_2 \vee \neg x_3) \wedge (x_2 \vee x_3) \wedge (\neg x_1 \vee \neg x_4)</math>
<center><math>(x_1 \vee x_2 \vee \neg x_3) \wedge (x_2 \vee x_3) \wedge (\neg x_1 \vee \neg x_4)</math>.</center>


Mówimy, że formuła jest spełnialna wtedy i tylko wtedy gdy istnieje wartościowanie zmiennych, dla których ta formuła jest spełniona. Dla powyższej formuły jednym z wartościowań, dla których jest ona spełniona, jest wartościowanie przypisujące zmiennym <math>x_1</math>, <math>x_2</math>, <math>x_3</math>, <math>x_4</math> odpowiednio wartości 0, 1, 1, 0; w związku
Mówimy, że formuła jest spełnialna wtedy i tylko wtedy gdy istnieje wartościowanie zmiennych, dla których ta formuła jest spełniona. Dla powyższej formuły jednym z wartościowań, dla których jest ona spełniona, jest wartościowanie przypisujące zmiennym <math>x_1</math>, <math>x_2</math>, <math>x_3</math>, <math>x_4</math> odpowiednio wartości 0, 1, 1, 0; w związku
Linia 312: Linia 306:


Do dalszych rozważań ustalmy pewne kodowanie formuł logicznych do słów nad
Do dalszych rozważań ustalmy pewne kodowanie formuł logicznych do słów nad
alfabetem <math>\{ 0, 1\}</math> - na przykład ustalmy, że najpierw zapisujemy liczbę klauzul, następnie dla każdej klauzuli liczbę literałów, a następnie dla
alfabetem <math>\{ 0, 1\}</math> - na przykład ustalmy, że najpierw zapisujemy liczbę klauzul, następnie dla każdej klauzuli liczbę literałów, a dalej dla
każdego literału numer zmiennej oraz bit określający czy zmienna jest zaprzeczona.
każdego literału numer zmiennej oraz bit określający czy zmienna jest zanegowana.


{{definicja|||
{{definicja|3.4||
Niech <math>w \in \{ 0, 1 \} ^\star</math>. Wtedy
Niech <math>w \in \{ 0, 1 \} ^\star</math>. Wtedy <math>w \in SAT \iffw</math> reprezentuje poprawnie zakodowaną formułę logiczną w koniunkcyjnej postaci normalnej i formuła ta jest spelnialna.
 
  <math>w \in SAT \iffw</math> reprezentuje poprawnie zakodowaną formułę logiczną w koniunkcyjnej postaci normalnej i formuła ta jest spelnialna.


}}
}}


{{cwiczenie|8||
{{cwiczenie|3.5||
Pokaż, że problem <math>SAT</math> należy do klasy <math>NP</math>.
Pokaż, że problem <math>SAT</math> należy do klasy <math>NP</math>.
}}
}}


<div class="mw-collapsible mw-made=collapsible mw-collapsed"><span class="mw-collapsible-toogle mw-collapsible-toogle-default style="font-variant:small-caps">Wskazówka </span><div class="mw-collapsible-content" style="display:none"> Wykorzystaj definicję klasy <math>NP</math> wykorzystującą świadka.
<div class="mw-collapsible mw-made=collapsible mw-collapsed"><span class="mw-collapsible-toogle mw-collapsible-toogle-default style="font-variant:small-caps">Wskazówka </span><div class="mw-collapsible-content" style="display:none"> Wykorzystaj definicję klasy <math>NP</math> z użyciem świadka.
</div></div>
</div></div>


Linia 332: Linia 324:
</div></div>
</div></div>


{{twierdzenie|['''(Cook'a-Lewina)''']||
{{twierdzenie|3.6 ['''(Cook'a-Lewina)''']||
Problem <math>SAT</math> jest <math>NP</math>-zupełny w sensie redukcji logarytmicznej.
Problem <math>SAT</math> jest <math>NP</math>-zupełny w sensie redukcji logarytmicznej.
}}
}}
Linia 339: Linia 331:
Pierwszą część dowodu już mamy - wiemy, że <math>SAT \in NP</math>. Do pokazania pozostaje zatem fakt, że
Pierwszą część dowodu już mamy - wiemy, że <math>SAT \in NP</math>. Do pokazania pozostaje zatem fakt, że


  <math>\forall_{L \in NP} L \leq_L SAT</math>  
<center><math>\forall_{L \in NP} L \leq_L SAT</math>.</center>


Weźmy zatem dowolny język <math>L \in NP</math>. Korzystając z udowodnionego wcześniej twierdzenia wiemy, że istnieje <math>p(n)</math> - wielomian określający długość świadka - oraz wielomianowy program dla deterministycznej maszyny Turinga, weryfikujący świadka - jego czas działania oznaczmy jako <math>Q(n)</math>. Załóżmy bez straty ogólności, że program ten kontynuuje działanie po dojściu do stanu akceptującego i pozostaje w tym stanie niezależnie od symbolu pod głowicą ("zapętla się" w tym stanie). Jako że wejściem programu weryfikującego jest konkatenacja słowa wejściowego i świadka, górnym ograniczeniem na czas jego działania w zależności od wielkości wejścia jest  
Weźmy zatem dowolny język <math>L \in NP</math>. Korzystając z udowodnionego wcześniej twierdzenia wiemy, że istnieje <math>p(n)</math> - wielomian określający długość świadka - oraz wielomianowy program dla deterministycznej maszyny Turinga, weryfikujący świadka - jego czas działania oznaczmy jako <math>Q(n)</math>. Załóżmy bez straty ogólności, że program ten kontynuuje działanie po dojściu do stanu akceptującego i pozostaje w tym stanie niezależnie od symbolu pod głowicą ("zapętla się" w tym stanie). Jako że wejściem programu weryfikującego jest konkatenacja słowa wejściowego i świadka, górnym ograniczeniem na czas jego działania w zależności od wielkości wejścia jest  


  <math>T(n) := Q(p(n) + n)</math>
<center><math>T(n) := Q(p(n) + n)</math></center>


(oczywiście ograniczenie to nadal jest wielomianowe).
(oczywiście ograniczenie to nadal jest wielomianowe).


Naszym zadaniem teraz będzie takie przekształcenie słowa wejściowego <math>w</math> w formułę logiczną, aby formuła była spełnialna wtedy i tylko wtedy gdy <math>w \in L</math>. Ustalmy zatem, jakich zmiennych będzie używać nasza formuła logiczna i jakie będzeimy tym zmiennym przypisywać znaczenie.
Naszym zadaniem teraz będzie takie przekształcenie słowa wejściowego <math>w</math> w formułę logiczną, aby formuła była spełnialna wtedy i tylko wtedy, gdy <math>w \in L</math>. Ustalmy zatem, jakich zmiennych będzie używać nasza formuła logiczna i jakie będziemy tym zmiennym przypisywać znaczenie.
}}
}}
{| border="1"
{| border="1"
Linia 364: Linia 356:
Najpierw wymusimy, aby w każdej chwili symulowana głowica znajdowała się w dokładnie jednym miejscu. Dla chwili 0 będzie to wyglądało następująco:
Najpierw wymusimy, aby w każdej chwili symulowana głowica znajdowała się w dokładnie jednym miejscu. Dla chwili 0 będzie to wyglądało następująco:


  <math>(H_{0,-T(n)} \vee H_{0,-T(n)+1} \vee \cdots \vee H_{0,0} \vee \cdots \vee H_{0,T(n)}) \wedge</math>
<center><math>(H_{0,-T(n)} \vee H_{0,-T(n)+1} \vee \cdots \vee H_{0,0} \vee \cdots \vee H_{0,T(n)}) \wedge</math>
  <math>(\neg H_{0,-T(n)} \vee \neg H_{0,-T(n)+1}) \wedge (\neg H_{0,-T(n)} \vee \neg H_{0,-T(n)+2}) \wedge \cdots \wedge</math><math>(\neg H_{0,-T(n)} \vee \neg H_{0,T(n)}) \wedge</math>  
<math>(\neg H_{0,-T(n)} \vee \neg H_{0,-T(n)+1}) \wedge (\neg H_{0,-T(n)} \vee \neg H_{0,-T(n)+2}) \wedge \cdots \wedge</math><math>(\neg H_{0,-T(n)} \vee \neg H_{0,T(n)}) \wedge</math>  
  <math>\cdots</math>
<math>\cdots</math>
  <math>(\neg H_{0,0} \vee \neg H_{0,1}) \wedge \cdots \wedge (\neg H_{0,0} \vee \neg H_{0,T(n)}) \wedge</math>  
<math>(\neg H_{0,0} \vee \neg H_{0,1}) \wedge \cdots \wedge (\neg H_{0,0} \vee \neg H_{0,T(n)}) \wedge</math>  
  <math>\cdots</math>
<math>\cdots</math>
  <math>(\neg H_{0,T(n)-1} \vee \neg H_{0,T(n)})</math>  
<math>(\neg H_{0,T(n)-1} \vee \neg H_{0,T(n)})</math>.</center>


Na tym etapie zapisaliśmy już <math>O(T(n)^2)</math> symboli, a zanosi się, że zapiszemy znacznie więcej. W związku z tym na potrzeby tego dowodu umówimy się, że powyższą formułę (i podobne, których będziemy potrzebować w przyszłości) będziemy skrótowo zapisywać w następujący sposób:
Na tym etapie zapisaliśmy już <math>O(T(n)^2)</math> symboli, a zanosi się, że zapiszemy znacznie więcej. W związku z tym na potrzeby tego dowodu umówimy się, że powyższą formułę (i podobne, których będziemy potrzebować w przyszłości) będziemy skrótowo zapisywać w następujący sposób:


  <math>\bigvee_{-T(n) \leq i \leq T(n)} H_{0,i} \wedge \bigwedge_{-T(n) \leq i < j \leq T(n)} (\neg H_{0,i} \vee \neg H_{0,j})</math>
<center><math>\bigvee_{-T(n) \leq i \leq T(n)} H_{0,i} \wedge \bigwedge_{-T(n) \leq i < j \leq T(n)} (\neg H_{0,i} \vee \neg H_{0,j})</math>.</center>


Oczywiście maszyna dokonująca redukcji będzie musiała się bardziej namęczyć i wypisać wszystkie klauzule; pocieszamy się jednak tym, że na pewno jej się to uda zrobić z użyciem logarytmicznej ilości pamięci.
Oczywiście maszyna dokonująca redukcji będzie musiała się bardziej namęczyć i wypisać wszystkie klauzule; pocieszamy się jednak tym, że na pewno uda się jej to zrobić z użyciem logarytmicznej ilości pamięci.


Powyższa formuła gwarantowała, że w chwili 0 głowica będzie w dokładnie jednym
Powyższa formuła gwarantowała, że w chwili 0 głowica będzie w dokładnie jednym
miejscu. Aby zapewnić to dla każdego kroku działania maszyny, zapisujemy formułę:
miejscu. Aby zapewnić to dla każdego kroku działania maszyny, zapisujemy formułę:


  <math>\bigwedge_{0 \leq t \leq T(n)} [ \bigvee_{-T(n) \leq i \leq T(n)} H_{t,i} \wedge \bigwedge_{-T(n) \leq i < j \leq T(n)} (\neg H_{t,i} \vee \neg H_{t,j}) ]</math>
<center><math>\bigwedge_{0 \leq t \leq T(n)} [ \bigvee_{-T(n) \leq i \leq T(n)} H_{t,i} \wedge \bigwedge_{-T(n) \leq i < j \leq T(n)} (\neg H_{t,i} \vee \neg H_{t,j}) ]</math>.</center>


Analogiczne formuły musimy wypisać aby zagwarantować, że:
Analogiczne formuły musimy wypisać, aby zagwarantować, że:


*w każdej chwili maszyna znajduje się w dokładnie jednym stanie,
*w każdej chwili maszyna znajduje się w dokładnie jednym stanie,
Linia 390: Linia 382:
Dla porządku odpowiednie formuły są podane poniżej:
Dla porządku odpowiednie formuły są podane poniżej:


  <math>\bigwedge_{0 \leq t \leq T(n)} [\bigvee_{0 \leq i < |Q|} Q_{t,i} \wedge
<center><math>\bigwedge_{0 \leq t \leq T(n)} [\bigvee_{0 \leq i < |Q|} Q_{t,i} \wedge
\bigwedge_{0 \leq i < j < |Q|} (\neg Q_{t,i} \vee \neg Q_{t,j}) ]</math>
\bigwedge_{0 \leq i < j < |Q|} (\neg Q_{t,i} \vee \neg Q_{t,j}) ]</math>,


  <math>\bigwedge_{0 \leq t \leq T(n)} \bigwedge_{-T(n) \leq p \leq T(n)} [
<math>\bigwedge_{0 \leq t \leq T(n)} \bigwedge_{-T(n) \leq p \leq T(n)} [
\bigvee_{0 \leq i < |\Sigma|} S_{t,p,i} \wedge \bigwedge_{0 \leq i < j < |\Sigma|} (\neg S_{t,p,i} \vee \neg S_{t,p,j}) ]</math>
\bigvee_{0 \leq i < |\Sigma|} S_{t,p,i} \wedge \bigwedge_{0 \leq i < j < |\Sigma|} (\neg S_{t,p,i} \vee \neg S_{t,p,j}) ]</math>.</center>


Następnie musimy zakodować w formule logicznej funkcję przejścia. Załóżmy, że dla pewnego stanu <math>q</math> i symbolu <math>s</math>  
Następnie musimy zakodować w formule logicznej funkcję przejścia. Załóżmy, że dla pewnego stanu <math>q</math> i symbolu <math>s</math>  


  <math>d(q,s) = (q', s', \leftarrow)</math>
<center><math>d(q,s) = (q', s', \leftarrow)</math></center>


Będziemy wtedy musieli zapisać następującą formułę:
Będziemy wtedy musieli zapisać następującą formułę:


  <math>\bigwedge_{0 \leq t < T(n)} \bigwedge_{-T(n) < p \leq T(n)} [(H_{t,p} \wedge Q_{t,q} \wedge S_{t,p,s}) \Rightarrow (H_{t+1,p-1} \wedge Q_{t+1,q'} \wedge S_{t+1,p,s'})]</math>
<center><math>\bigwedge_{0 \leq t < T(n)} \bigwedge_{-T(n) < p \leq T(n)} [(H_{t,p} \wedge Q_{t,q} \wedge S_{t,p,s}) \Rightarrow (H_{t+1,p-1} \wedge Q_{t+1,q'} \wedge S_{t+1,p,s'})]</math>.</center>


Niestety nie możemy wprost używać implikacji, a zatem musimy formułę trochę przekształcić:
Niestety nie możemy wprost używać implikacji, a zatem musimy formułę trochę przekształcić:


  <math>\bigwedge_{0 \leq t < T(n)} \bigwedge_{-T(n) < p \leq T(n)} [
<center><math>\bigwedge_{0 \leq t < T(n)} \bigwedge_{-T(n) < p \leq T(n)} [
(\neg H_{t,p} \vee \neg Q_{t,q} \vee \neg S_{t,p,s}) \vee</math><math>(H_{t+1,p-1} \wedge Q_{t+1,q'} \wedge S_{t+1,p,s'})]</math>
(\neg H_{t,p} \vee \neg Q_{t,q} \vee \neg S_{t,p,s}) \vee</math><math>(H_{t+1,p-1} \wedge Q_{t+1,q'} \wedge S_{t+1,p,s'})]</math></center>


co z kolei możemy przekształcić do postaci ostatecznej:
co z kolei możemy przekształcić do postaci ostatecznej:


  <math>\bigwedge_{0 \leq t < T(n)} \bigwedge_{-T(n) < p \leq T(n)} [
<center><math>\bigwedge_{0 \leq t < T(n)} \bigwedge_{-T(n) < p \leq T(n)} [
(\neg H_{t,p} \vee \neg Q_{t,q} \vee \neg S_{t,p,s} \vee H_{t+1,p-1})
(\neg H_{t,p} \vee \neg Q_{t,q} \vee \neg S_{t,p,s} \vee H_{t+1,p-1})
\wedge (\neg H_{t,p} \vee \neg Q_{t,q} \vee \neg S_{t,p,s} \vee  
\wedge (\neg H_{t,p} \vee \neg Q_{t,q} \vee \neg S_{t,p,s} \vee  
Q_{t+1,q'})\wedge (\neg H_{t,p} \vee \neg Q_{t,q} \vee \neg S_{t,p,s} \vee  
Q_{t+1,q'})\wedge (\neg H_{t,p} \vee \neg Q_{t,q} \vee \neg S_{t,p,s} \vee  
S_{t+1,p,s'})]</math>
S_{t+1,p,s'})]</math>.</center>


Formuły powyższego typu będziemy musieli wypisać dla każdej pary <math>(q,s)</math> - będzie ich zatem <math>|Q|\cdot|\Sigma|</math>; liczba ta oczywiście nie jest zależna od <math>n</math> (choć oczywiście długości formuł zależą kwadratowo od <math>T(n)</math>).
Formuły powyższego typu będziemy musieli wypisać dla każdej pary <math>(q,s)</math> - będzie ich zatem <math>|Q|\cdot|\Sigma|</math>; liczba ta oczywiście nie jest zależna od <math>n</math> (choć oczywiście długości formuł zależą kwadratowo od <math>T(n)</math>).
Linia 422: Linia 414:
bez zmian:
bez zmian:


  <math>\bigwedge_{0 \leq t < T(n)} \bigwedge_{-T(n) \leq p \leq T(n)}
<center><math>\bigwedge_{0 \leq t < T(n)} \bigwedge_{-T(n) \leq p \leq T(n)}
\bigwedge_{0 \leq s < |\Sigma|} [(\neg H_{t,p} \wedge S_{t,p,s}) \Rightarrow S_{t+1,p,s}]</math>
\bigwedge_{0 \leq s < |\Sigma|} [(\neg H_{t,p} \wedge S_{t,p,s}) \Rightarrow S_{t+1,p,s}]</math>,</center>


czyli
czyli


  <math>\bigwedge_{0 \leq t < T(n)} \bigwedge_{-T(n) \leq p \leq T(n)}
<center><math>\bigwedge_{0 \leq t < T(n)} \bigwedge_{-T(n) \leq p \leq T(n)}
\bigwedge_{0 \leq s < |\Sigma|} [H_{t,p} \vee \neg S_{t,p,s} \vee S_{t+1,p,s}]</math>
\bigwedge_{0 \leq s < |\Sigma|} [H_{t,p} \vee \neg S_{t,p,s} \vee S_{t+1,p,s}]</math>.</center>


Musimy zadbać o to, by zmienne reprezentujące słowo wejściowe (czyli symbole taśmy w chwili 0) były takie jak należy:
Musimy zadbać o to, by zmienne reprezentujące słowo wejściowe (czyli symbole taśmy w chwili 0) były takie jak należy:


  <math>\bigwedge_{-T(n) \leq p < 0} S_{0, p, \#} \wedge \bigwedge_{0 \leq p < |w|} S_{0, p, w_p} \wedge S_{0, |w|, \#} \wedge \bigwedge_{|w| + 1 \leq p \leq |w| + p(n)} (S_{0,p,0} \vee S_{0,p,1}) \wedge \bigwedge_{|w| + p(n) < p <= T(n)} S_{0,p,\#}</math>  
<center><math>\bigwedge_{-T(n) \leq p < 0} S_{0, p, \#} \wedge \bigwedge_{0 \leq p < |w|} S_{0, p, w_p} \wedge S_{0, |w|, \#} \wedge \bigwedge_{|w| + 1 \leq p \leq |w| + p(n)} (S_{0,p,0} \vee S_{0,p,1}) \wedge \bigwedge_{|w| + p(n) < p <= T(n)} S_{0,p,\#}</math>.</center>


Żądamy, by w chwili początkowej na taśmie znalazło się słowo wejściowe oraz "kandydat na świadka". Na koniec żądamy, by po <math>T(n)</math> krokach program znajdował się w stanie akceptującym (mógł się w nim znaleźć wcześniej,
Żądamy, by w chwili początkowej na taśmie znalazło się słowo wejściowe oraz "kandydat na świadka". Na koniec żądamy, by po <math>T(n)</math> krokach program znajdował się w stanie akceptującym (mógł się w nim znaleźć wcześniej,
założyliśmy jednak, że maszyna się w tym stanie "zapętli", więc wystarczy jeśli sprawdzimy w chwili <math>T(n)</math>)
założyliśmy jednak, że maszyna w tym stanie się "zapętli", więc wystarczy, jeśli sprawdzimy w chwili <math>T(n)</math>)


  <math>Q_{T(n), q_{acc}}</math>
<center><math>Q_{T(n), q_{acc}}</math></center>


Widzimy, że jesli koniunkcja powyższych formuł jest spełnialna, to istnieje świadek dla słowa <math>w</math> - będzie on określony przez wartościowanie zmiennych reprezentujących taśmę w chwili początkowej. Z drugiej strony widać, że istnienie świadka dla słowa <math>w</math> implikuje wartościowanie zmiennych spełniające koniunkcję powyższych formuł logicznych. Pozostaje więc tylko uzasadnić to, że przekształcenie słowa <math>w</math> w powyższą formułę odbywa się z uzyciem logarytmicznej pamięci. Widać jednak, ze postać każdej z tych częściowych formuł jest z góry określona i maszyna podczas dokonywania redukcji będzie jedynie potrzebowała przechowywać na taśmie okresloną z góry liczbę iteratorów. Pokazaliśmy zatem, że <math>SAT</math> jest problemem <math>NP</math>-zupełnym w sensie wszystkich trzech zdefiniowanych transformacji.
Widzimy, że jeśli koniunkcja powyższych formuł jest spełnialna, to istnieje świadek dla słowa <math>w</math> - będzie on określony przez wartościowanie zmiennych reprezentujących taśmę w chwili początkowej. Z drugiej strony widać, że istnienie świadka dla słowa <math>w</math> implikuje wartościowanie zmiennych spełniające koniunkcję powyższych formuł logicznych. Pozostaje więc tylko uzasadnić to, że przekształcenie słowa <math>w</math> w powyższą formułę odbywa się z użyciem logarytmicznej pamięci. Widać jednak, że postać każdej z tych częściowych formuł jest z góry określona i maszyna podczas dokonywania redukcji będzie jedynie potrzebowała przechowywać na taśmie określoną z góry liczbę iteratorów. Pokazaliśmy zatem, że <math>SAT</math> jest problemem <math>NP</math>-zupełnym w sensie wszystkich trzech zdefiniowanych transformacji.


'''Charakteryzacja klasy NP w języku logiki'''
===Charakteryzacja klasy NP w języku logiki===


W ostatniej części tego modułu zaprezentujemy bardzo ciekawą charakteryzację
W ostatniej części tego modułu zaprezentujemy bardzo ciekawą charakteryzację
Linia 471: Linia 463:
Formułą może być dla przykładu następujące wyrażenie:
Formułą może być dla przykładu następujące wyrażenie:


  <math>(E(x, y) \wedge E(x,z)) \Rightarrow \neg E(y,z)</math>
<center><math>(E(x, y) \wedge E(x,z)) \Rightarrow \neg E(y,z)</math>.</center>


Takiej formule ciężko jednak przypisać jakieś znaczenie dopóki <math>x</math>, <math>y</math> i <math>z</math> są zmiennymi niezwiązanymi i dopóki nie wiemy czym jest <math>E</math>. Umówmy się zatem, że ''zdaniem pierwszego rzędu dla grafów'' jest formuła logiczna, która:
Takiej formule ciężko jednak przypisać jakieś znaczenie, dopóki <math>x</math>, <math>y</math> i <math>z</math> są zmiennymi niezwiązanymi i dopóki nie wiemy, czym jest <math>E</math>. Umówmy się zatem, że ''zdaniem pierwszego rzędu dla grafów'' jest formuła logiczna, która:


*nie posiada zmiennych niezwiązanych,
*nie posiada zmiennych niezwiązanych,
Linia 481: Linia 473:
*jedynym symbolem relacyjnym, którego używa, jest binarna relacja <math>E</math>, reprezentująca relację sąsiedztwa w grafie.
*jedynym symbolem relacyjnym, którego używa, jest binarna relacja <math>E</math>, reprezentująca relację sąsiedztwa w grafie.


Zdaniem pierwszego rzędu dla grafów jest na przykład
Zdaniem pierwszego rzędu dla grafów jest na przykład:


  <math>\forall_x \forall_y \forall_z [(E(x,y) \wedge E(x,z)) \Rightarrow \neg E(y,z)]</math>
<center><math>\forall_x \forall_y \forall_z [(E(x,y) \wedge E(x,z)) \Rightarrow \neg E(y,z)]</math>.</center>


Ustalmy teraz pewien graf o zbiorze wierzchołków <math>V</math> i relacji sąsiedztwa <math>E \subseteq V^2</math>. Zinterpretujmy wyrażenia <math>\forall_x \cdots</math> jako <math>\forall_{x \in V} \cdots</math>. W tym momencie możemy już rozpatrywać prawdziwość powyższego zdania dla poszczególnych grafów: Zdanie to będzie prawdziwe dla grafów nie posiadających trójkątów i fałszywe dla pozostałych grafów. Widzimy zatem, że zdania pierwszego rzędu mogą wyrażać pewne własności grafów - czyli spośród wszystkich grafów wyłaniać pewne ich podzbiory. Okazuje się jednak, że siła ekspresji zdań pierwszego rzędu nie jest zbyt duża - na przykład nie da się skonstruować zdania, odróżniającego grafy spójne od niespójnych. Zdefiniujmy zatem silniejszą klasę zdań.
Ustalmy teraz pewien graf o zbiorze wierzchołków <math>V</math> i relacji sąsiedztwa <math>E \subseteq V^2</math>. Zinterpretujmy wyrażenia <math>\forall_x \cdots</math> jako <math>\forall_{x \in V} \cdots</math>. W tym momencie możemy już rozpatrywać prawdziwość powyższego zdania dla poszczególnych grafów: zdanie to będzie prawdziwe dla grafów nie posiadających trójkątów i fałszywe dla pozostałych grafów. Widzimy zatem, że zdania pierwszego rzędu mogą wyrażać pewne własności grafów - czyli spośród wszystkich grafów wyłaniać pewne ich podzbiory. Okazuje się jednak, że siła ekspresji zdań pierwszego rzędu nie jest zbyt duża - na przykład nie da się skonstruować zdania, odróżniającego grafy spójne od niespójnych. Zdefiniujmy zatem silniejszą klasę zdań.


''Zdaniem egzystencjalnym drugiego rzędu dla grafów'' jest zdanie
''Zdaniem egzystencjalnym drugiego rzędu dla grafów'' jest zdanie
następującej postaci:
następującej postaci:


  <math>\exists_{R_1}\exists_{R_2}\cdots\exists_{R_k} \phi</math>
<center><math>\exists_{R_1}\exists_{R_2}\cdots\exists_{R_k} \phi</math>,</center>


gdzie <math>R_1, \cdots, R_k</math> to symbole relacyjne o ustalonej arności, natomiast <math>\phi</math> to formuła zdaniowa pierwszego rzędu bez zmiennych niezwiązanych, symboli funkcyjnych i używająca tylko symboli relacyjnych <math>R_1, \cdots, R_k</math> i <math>E</math>. Klasę egzystencjalnych zdań drugiego rzędu będziemy oznaczać jako <math>ESO</math>. Przykładem takiego zdania jest:
gdzie <math>R_1, \cdots, R_k</math> to symbole relacyjne o ustalonej arności, natomiast <math>\phi</math> to formuła zdaniowa pierwszego rzędu bez zmiennych niezwiązanych, symboli funkcyjnych i używająca tylko symboli relacyjnych <math>R_1, \cdots, R_k</math> i <math>E</math>. Klasę egzystencjalnych zdań drugiego rzędu będziemy oznaczać jako <math>ESO</math>. Przykładem takiego zdania jest:


  <math>\exists_{U - unarna} [\forall_x \forall_y (E(x,y) \wedge U(x)) \Rightarrow U(y)] \wedge [\exists_x \exists_y (U(x) \wedge \neg U(y))]</math>
<center><math>\exists_{U - unarna} [\forall_x \forall_y (E(x,y) \wedge U(x)) \Rightarrow U(y)] \wedge [\exists_x \exists_y (U(x) \wedge \neg U(y))]</math></center>
   
   
Powyższa formuła jest spełniona wtedy i tylko wtedy, gdy rozpatrywany graf jest niespójny; relację unarną można rozumieć jako wybór pewnych wierzchołków, przy czym pierwsza część formuły zapewnia, że jeżeli zostanie wybrany jakiś wierzchołek, to zostanie również wybrana cała jego spójna składowa. Druga część formuły żąda istnienia dwóch wierzchołków, z których jeden jest wybrany a drugi nie - a co za tym idzie leżących w różnych spójnych składowych.
Powyższa formuła jest spełniona wtedy i tylko wtedy, gdy rozpatrywany graf jest niespójny; relację unarną można rozumieć jako wybór pewnych wierzchołków, przy czym pierwsza część formuły zapewnia, że jeżeli zostanie wybrany jakiś wierzchołek, to zostanie również wybrana cała jego spójna składowa. Druga część formuły żąda istnienia dwóch wierzchołków, z których jeden jest wybrany a drugi nie - a co za tym idzie, leżących w różnych spójnych składowych.


Zastanówmy się teraz, czy jesteśmy w stanie napisać egzystencjalne zdanie drugiego rzędu, które jest prawdziwe wtedy i tylko wtedy gdy rozpatrywany graf jest spójny. Widać, że problem polega na tym, że nie wolno nam zapisać wyrażenia
Zastanówmy się teraz, czy jesteśmy w stanie napisać egzystencjalne zdanie drugiego rzędu, które jest prawdziwe wtedy i tylko wtedy, gdy rozpatrywany graf jest spójny. Widać, że problem polega na tym, nie wolno nam zapisać wyrażenia
<math>\forall_U \cdots</math>. W ogólności nie wiadomo, czy dopełnienie klasy grafów charakteryzowanej przez jakieś zdanie z <math>ESO</math> jest charakteryzowalne przez zdanie z <math>ESO</math>. W tym przypadku jednak mamy szczęście - poniższe zdanie charakteryzuje grafy spójne:
<math>\forall_U \cdots</math>. W ogólności nie wiadomo, czy dopełnienie klasy grafów charakteryzowanej przez jakieś zdanie z <math>ESO</math> jest charakteryzowalne przez zdanie z <math>ESO</math>. W tym przypadku jednak mamy szczęście - poniższe zdanie charakteryzuje grafy spójne:


  <math>\exists_{P - binarna} [\forall_x P(x,x)] \wedge [\forall_x \forall_y
<center><math>\exists_{P - binarna} [\forall_x P(x,x)] \wedge [\forall_x \forall_y
P(x,y) \vee P(y,x)] \wedge [\forall_x \forall_y \forall_z (P(x,y)\wedge P(y,z)) \Rightarrow P(x, z)] \wedge \exists_m[\forall_n(P(n,m) \Rightarrow (n = m)) \wedge \forall_n(\neg P(n, m) \Rightarrow \exists_k (P(k, n) \wedge E(k, n)))]</math>
P(x,y) \vee P(y,x)] \wedge [\forall_x \forall_y \forall_z (P(x,y)\wedge P(y,z)) \Rightarrow P(x, z)] \wedge \exists_m[\forall_n(P(n,m) \Rightarrow (n = m)) \wedge \forall_n(\neg P(n, m) \Rightarrow \exists_k (P(k, n) \wedge E(k, n)))]</math>.</center>


Nie podamy tutaj szczegółowego wyjaśnienia powyższego zdania; warto jednak wspomnieć, że od <math>P</math> oczekujemy, by była to relacja liniowego porządku na wierzchołkach, z elementem najmniejszym <math>m</math>.
Nie podamy tutaj szczegółowego wyjaśnienia powyższego zdania; warto jednak wspomnieć, że od <math>P</math> oczekujemy, by była to relacja liniowego porządku na wierzchołkach, z elementem najmniejszym <math>m</math>.


'''Egzystencjalne zdania drugiego rzędu a złożoność'''
===Egzystencjalne zdania drugiego rzędu a złożoność===


Wybierzmy jakieś zdanie z <math>ESO</math>. Będziemy chcieli skonstruować
Wybierzmy jakieś zdanie z <math>ESO</math>. Będziemy chcieli skonstruować
niedeterministyczną maszynę Turinga, która będzie oczekiwała na wejściu opisów grafów i będzie akceptowała te grafy, dla których wybrana formuła jest spełniona. Okazuje się, że nasza (niedeterministyczna) maszyna może to zrobić w czasie wielomianowym. Niech <math>s_1, s_2, \cdots, s_k</math> będą arnościami kolejnych relacji w zdaniu. Aby zdefiniować te relacje potrzeba odpowiednio <math>n^{s_1}, n^{s_2}, \cdots, n^{s_k}</math> bitów. Maszyna zatem najpierw wygeneruje "kandydatów na świadków" o długości <math>n^{s_1} + n^{s_2} + \cdots + n^{s_k}</math> bitów (definiując tym samym wszystkie relacje), po czym zweryfikuje prawdziwość formuły pierwszego rzędu. W formule pierwszego rzędu kwantyfikatory odpowiadają pętlom od 1 do <math>n</math> - zatem czas weryfikacji całej formuły wynosi <math>O(n^d)</math>, gdzie <math>d</math> to maksymalne "zagłębienie kwantyfikatorów" w tej formule. Jest zatem jasne, że dla każdej formuły z <math>ESO</math> rozpoznawanie spełniających ją grafów jest zadaniem z klasy <math>NP</math>.
niedeterministyczną maszynę Turinga, która będzie oczekiwała na wejściu opisów grafów i będzie akceptowała te grafy, dla których wybrana formuła jest spełniona. Okazuje się, że nasza (niedeterministyczna) maszyna może to zrobić w czasie wielomianowym. Niech <math>s_1, s_2, \cdots, s_k</math> będą arnościami kolejnych relacji w zdaniu. Aby zdefiniować te relacje, potrzeba odpowiednio <math>n^{s_1}, n^{s_2}, \cdots, n^{s_k}</math> bitów. Maszyna zatem najpierw wygeneruje "kandydatów na świadków" o długości <math>n^{s_1} + n^{s_2} + \cdots + n^{s_k}</math> bitów (definiując tym samym wszystkie relacje), po czym zweryfikuje prawdziwość formuły pierwszego rzędu. W formule pierwszego rzędu kwantyfikatory odpowiadają pętlom od 1 do <math>n</math> - zatem czas weryfikacji całej formuły wynosi <math>O(n^d)</math>, gdzie <math>d</math> to maksymalne "zagłębienie kwantyfikatorów" w tej formule. Jest zatem jasne, że dla każdej formuły z <math>ESO</math> rozpoznawanie spełniających ją grafów jest zadaniem z klasy <math>NP</math>.


'''Twierdzenie Fagina'''
===Twierdzenie Fagina===


Przejdźmy teraz do dużo ciekawszego spostrzeżenia. Stwierdzimy bowiem, że
Przejdźmy teraz do dużo ciekawszego spostrzeżenia. Stwierdzimy bowiem, że
Linia 525: Linia 517:
*grafy przypisane dwóm różnym słowom nie są izomorficzne.
*grafy przypisane dwóm różnym słowom nie są izomorficzne.


Ostatnie założenie wynika z prostej obserwacji: Zdanie z <math>ESO</math> nie jest w stanie rozróżnić grafów, które są izomorficzne. Skonstruowanie powyższej konwersji pozostawione jest Czytelnikowi.
Ostatnie założenie wynika z prostej obserwacji: zdanie z <math>ESO</math> nie jest w stanie rozróżnić grafów, które są izomorficzne. Skonstruowanie powyższej konwersji pozostawione jest Czytelnikowi.


Wybierzmy teraz dowolny problem decyzyjny <math>L</math> z klasy <math>NP</math>. Jest jasne, że odpowiadający mu problem <math>L'</math>, oczekujący wejścia w postaci grafów, również należy do <math>NP</math> - można go rozwiązać poprzez zdekodowanie grafu do słowa binarnego i uruchomienie maszyny dla oryginalnego problemu. Weźmy zatem maszynę zachowującą się w ten sposób i oznaczmy ją jako <math>M</math>. Załóżmy bez straty ogólności, że maszyna ta jest jednostronnie ograniczona oraz że jej maksymalny stopień rozgałęzienia wynosi 2. Będziemy teraz - podobnie jak wcześniej przy twierdzeniu Cook'a-Lewina - starali się skonstruować formułę logiczną symulującą działanie <math>M</math>. W tym przypadku jednak formuła nie może być generowana na bieżąco po wczytaniu wejścia; tutaj skonstruujemy jedną formułę, która będzie działać dla każdego wejścia.
Wybierzmy teraz dowolny problem decyzyjny <math>L</math> z klasy <math>NP</math>. Jest jasne, że odpowiadający mu problem <math>L'</math>, oczekujący wejścia w postaci grafów, również należy do <math>NP</math> - można go rozwiązać poprzez zdekodowanie grafu do słowa binarnego i uruchomienie maszyny dla oryginalnego problemu. Weźmy zatem maszynę zachowującą się w ten sposób i oznaczmy ją jako <math>M</math>. Załóżmy bez straty ogólności, że maszyna ta jest jednostronnie ograniczona oraz że jej maksymalny stopień rozgałęzienia wynosi 2. Będziemy teraz - podobnie jak wcześniej przy twierdzeniu Cook'a-Lewina - starali się skonstruować formułę logiczną symulującą działanie <math>M</math>. W tym przypadku jednak formuła nie może być generowana na bieżąco po wczytaniu wejścia; tutaj skonstruujemy jedną formułę, która będzie działać dla każdego wejścia.
Linia 531: Linia 523:
Przejdźmy zatem do konstrukcji. Załóżmy, że maszyna <math>M</math> działa pesymistycznie w czasie <math>n^k</math>, gdzie <math>n</math> to liczba wierzchołków w grafie wejściowym. W naszej formule będziemy używać liniowego porządku, podobnego do zdefiniowanego w formule charakteryzującej spójność. Użyjemy go jednak głównie po to, by zdefiniować liniowy porządek leksykograficzny na <math>k</math>-elementowych ciągach wierzchołków. Załóżmy zatem, że mamy porządek:
Przejdźmy zatem do konstrukcji. Załóżmy, że maszyna <math>M</math> działa pesymistycznie w czasie <math>n^k</math>, gdzie <math>n</math> to liczba wierzchołków w grafie wejściowym. W naszej formule będziemy używać liniowego porządku, podobnego do zdefiniowanego w formule charakteryzującej spójność. Użyjemy go jednak głównie po to, by zdefiniować liniowy porządek leksykograficzny na <math>k</math>-elementowych ciągach wierzchołków. Załóżmy zatem, że mamy porządek:


  <math>v_1, v_2, \cdots, v_n</math>
<center><math>v_1, v_2, \cdots, v_n</math>.</center>


Chcemy na jego podstawie stworzyć porządek leksykograficzny dla <math>k</math>-elementowych ciągów:
Chcemy na jego podstawie stworzyć porządek leksykograficzny dla <math>k</math>-elementowych ciągów:


  <math>(v_1,v_1,\cdots,v_1),(v_1,v_1,\cdots,v_1,v_2),\cdots,(v_n,v_n,\cdots,v_n)</math>
<center><math>(v_1,v_1,\cdots,v_1),(v_1,v_1,\cdots,v_1,v_2),\cdots,(v_n,v_n,\cdots,v_n)</math>.</center>
   
   
Tworzenie takiego porządku jest mało ciekawe - dlatego założymy po prostu, że
Tworzenie takiego porządku jest mało ciekawe - dlatego założymy po prostu, że
mamy <math>2k</math>-arną relację <math>\bar P(\bar x, \bar y)</math>, wyznaczającą powyższy porządek. Z tej relacji również łatwo możemy wywieść relację następnika; <math>\bar x</math> będzie w relacji z <math>\bar y</math> wtedy i tylko wtedy gdy <math>\bar y</math> będzie najmniejszym leksykograficznie ciągiem większym od <math>\bar x</math>. Relację następnika oznaczamy jako <math>Succ</math>.
mamy <math>2k</math>-arną relację <math>\bar P(\bar x, \bar y)</math>, wyznaczającą powyższy porządek. Z tej relacji również łatwo możemy wywieść relację następnika; <math>\bar x</math> będzie w relacji z <math>\bar y</math> wtedy i tylko wtedy, gdy <math>\bar y</math> będzie najmniejszym leksykograficznie ciągiem większym od <math>\bar x</math>. Relację następnika oznaczamy jako <math>Succ</math>.


Możemy zatem patrzeć na <math>k</math>-elementowe ciągi wierzchołków jako na
Możemy zatem patrzeć na <math>k</math>-elementowe ciągi wierzchołków jako na
Linia 544: Linia 536:
możemy potrzebować czasu i klatek pamięci podczas działania maszyny <math>M</math>. Od tej pory ciągi <math>k</math> wierzchołków będziemy traktować po prostu jako liczniki wskazujące na pewien krok postępowania maszyny lub na pewną komórkę taśmy; zapomnimy przy tym zupełnie o pierwotnym znaczeniu tych obiektów.
możemy potrzebować czasu i klatek pamięci podczas działania maszyny <math>M</math>. Od tej pory ciągi <math>k</math> wierzchołków będziemy traktować po prostu jako liczniki wskazujące na pewien krok postępowania maszyny lub na pewną komórkę taśmy; zapomnimy przy tym zupełnie o pierwotnym znaczeniu tych obiektów.
   
   
W tym momencie jesteśmy gotowi do zdefiniowania relacji, oraz znaczenia, które im będziemy przypisywali. Będą one beardzo podobne do zmiennych, używanych w dowodzie twierdzenia Cook'a-Lewina.
W tym momencie jesteśmy gotowi do zdefiniowania relacji oraz znaczenia, które im będziemy przypisywali. Będą one beardzo podobne do zmiennych, używanych w dowodzie twierdzenia Cook'a-Lewina.


*<math>H(\bar x, \bar y)</math> -- <math>\bar x</math> jest w relacji z <math>\bar y</math> wtw. gdy w chwili <math>\bar y</math> głowica jest w miejscu <math>\bar x</math>,
*<math>H(\bar x, \bar y)</math> -- <math>\bar x</math> jest w relacji z <math>\bar y</math> wtedy i tylko wtedy, gdy w chwili <math>\bar y</math> głowica jest w miejscu <math>\bar x</math>,


*<math>S_\sigma(\bar x, \bar y)</math> -- <math>\bar x</math> jest w relacji z <math>\bar y</math> wtw. gdy w chwili <math>\bar y</math> na taśmie w miejscu <math>\bar x</math> jest symbol <math>\sigma</math> (relacji tego typu jest tyle, ile symboli taśmowych),
*<math>S_\sigma(\bar x, \bar y)</math> -- <math>\bar x</math> jest w relacji z <math>\bar y</math> wtedy i tylko wtedy, gdy w chwili <math>\bar y</math> na taśmie w miejscu <math>\bar x</math> jest symbol <math>\sigma</math> (relacji tego typu jest tyle, ile symboli taśmowych),


*<math>Q_q(\bar y)</math> - <math>\bar y</math> należy do relacji wtw. gdy w chwili <math>\bar y</math> maszyna jest w stanie <math>q</math> (relacji tego typu jest tyle, ile stanów).
*<math>Q_q(\bar y)</math> - <math>\bar y</math> należy do relacji wtedy i tylko wtedy, gdy w chwili <math>\bar y</math> maszyna jest w stanie <math>q</math> (relacji tego typu jest tyle, ile stanów).


Musimy teraz wymusić odpowiednią postać tych relacji - taką, aby reprezentowały
Musimy teraz wymusić odpowiednią postać tych relacji - taką, aby reprezentowały
Linia 556: Linia 548:
znajdowała się w dokładnie jednym miejscu:
znajdowała się w dokładnie jednym miejscu:


  <math>\forall_{\bar x}\forall_{{\bar x}'}\forall_{\bar y}[\bar x = {\bar x}' \vee \neg H(\bar x, \bar y) \vee \neg H({\bar x}', {\bar y})]</math>
<center><math>\forall_{\bar x}\forall_{{\bar x}'}\forall_{\bar y}[\bar x = {\bar x}' \vee \neg H(\bar x, \bar y) \vee \neg H({\bar x}', {\bar y})]</math>.</center>


Stosujemy tutaj pewne skróty myślowe (w końcu <math>\bar x</math>, <math>{\bar x}'</math> i <math>{\bar y}</math> reprezentują <math>k</math>-elementowe ciągi). <math>\forall_{\bar x}</math> jest zatem tak naprawdę sekwencją <math>k</math> kwantyfikatorów: <math>\forall_{x_0}\forall_{x_1}\cdots\forall_{x_{k-1}}</math>. Natomiast wyrażenie <math>\bar x = {\bar x}'</math> jest koniunkcją <math>k</math> równości. Podobne formuły należy wypisać aby zagwarantować obecność dokładnie jednego symbolu w klatce i to, że w każdym kroku maszyna jest w dokładnie jednym stanie:
Stosujemy tutaj pewne skróty myślowe (w końcu <math>\bar x</math>, <math>{\bar x}'</math> i <math>{\bar y}</math> reprezentują <math>k</math>-elementowe ciągi). <math>\forall_{\bar x}</math> jest zatem tak naprawdę sekwencją <math>k</math> kwantyfikatorów: <math>\forall_{x_0}\forall_{x_1}\cdots\forall_{x_{k-1}}</math>. Natomiast wyrażenie <math>\bar x = {\bar x}'</math> jest koniunkcją <math>k</math> równości. Podobne formuły należy wypisać, aby zagwarantować obecność dokładnie jednego symbolu w klatce i to, że w każdym kroku maszyna jest w dokładnie jednym stanie:


  <math>\forall_{\bar x}\forall_{\bar y}(\neg S_{\sigma_0} \vee \neg S_{\sigma_1}) \wedge (\neg S_{\sigma_0} \vee \neg S_{\sigma_2}) \wedge \cdots </math>
<center><math>\forall_{\bar x}\forall_{\bar y}(\neg S_{\sigma_0} \vee \neg S_{\sigma_1}) \wedge (\neg S_{\sigma_0} \vee \neg S_{\sigma_2}) \wedge \cdots</math>


  <math>\forall_{\bar y}(\neg Q_{q_0} \vee \neg Q_{q_1}) \wedge (\neg Q_{q_0}\vee \neg Q_{q_2}) \wedge \cdots </math>
<math>\forall_{\bar y}(\neg Q_{q_0} \vee \neg Q_{q_1}) \wedge (\neg Q_{q_0}\vee \neg Q_{q_2}) \wedge \cdots</math></center>


Musimy określić początkową zawartość taśmy:
Musimy określić początkową zawartość taśmy:


  <math>\forall_{x_{k-2}}\forall_{x_{k-1}} S_1((0, \cdots, 0, x_{k-2}, x_{k-1}),  
<center><math>\forall_{x_{k-2}}\forall_{x_{k-1}} S_1((0, \cdots, 0, x_{k-2}, x_{k-1}),  
(0, \cdots, 0)) \iff E(x_{k-2}, x_{k-1})</math>
(0, \cdots, 0)) \iff E(x_{k-2}, x_{k-1})</math>,


  <math>\forall_{x_{k-2}}\forall_{x_{k-1}} S_0((0, \cdots, 0, x_{k-2}, x_{k-1}),  
<math>\forall_{x_{k-2}}\forall_{x_{k-1}} S_0((0, \cdots, 0, x_{k-2}, x_{k-1}),  
(0, \cdots, 0)) \iff \neg E(x_{k-2}, x_{k-1})</math>
(0, \cdots, 0)) \iff \neg E(x_{k-2}, x_{k-1})</math>,


  <math>\forall_{\bar x} (x_0 \neq 0 \vee x_1 \neq 0 \vee \cdots \vee x_{k-3} \neq 0)\Rightarrow T_\# (\bar x, (0, \cdots, 0))</math>
<math>\forall_{\bar x} (x_0 \neq 0 \vee x_1 \neq 0 \vee \cdots \vee x_{k-3} \neq 0)\Rightarrow T_\# (\bar x, (0, \cdots, 0))</math>.</center>


Skorzystaliśmy tutaj z symbolu <math>0</math>; reprezentuje on najmniejszy wierzchołek w sensie porządku <math>P</math> i jest zdefiniowany następująco:
Skorzystaliśmy tutaj z symbolu <math>0</math>; reprezentuje on najmniejszy wierzchołek w sensie porządku <math>P</math> i jest zdefiniowany następująco:


  <math>\exists_0 \forall_x P(0, x)</math>
<center><math>\exists_0 \forall_x P(0, x)</math>.</center>


Stan początkowy i początkowe położenie głowicy definiowane są następującą formułą:
Stan początkowy i początkowe położenie głowicy definiowane są następującą formułą:


  <math>H((0, \cdots, 0), (0, \cdots, 0)) \wedge Q_{q_0} ((0, \cdots, 0))</math>
<center><math>H((0, \cdots, 0), (0, \cdots, 0)) \wedge Q_{q_0} ((0, \cdots, 0))</math>,</center>


natomiast oczekiwany stan końcowy to:
natomiast oczekiwany stan końcowy to:


  <math>Q_{q_{acc}} ((\tau, \cdots, \tau))</math>
<center><math>Q_{q_{acc}} ((\tau, \cdots, \tau))</math>,</center>


gdzie <math>\tau</math> to wierzchołek maksymalny w sensie porządku <math>P</math>, zdefiniowany analogicznie jak <math>0</math>. Do zdefiniowania pozostało nam jeszcze tylko dynamiczne zachowanie maszyny. Zdefiniujmy zatem funkcję przejścia; niech dla przykładu  
gdzie <math>\tau</math> to wierzchołek maksymalny w sensie porządku <math>P</math>, zdefiniowany analogicznie jak <math>0</math>. Do zdefiniowania pozostało nam jeszcze tylko dynamiczne zachowanie maszyny. Zdefiniujmy zatem funkcję przejścia; niech dla przykładu:


  <math>d((q, \sigma)) = \{(q', \sigma', \leftarrow), (q'', \sigma'', \rightarrow)\}</math>
<center><math>d((q, \sigma)) = \{(q', \sigma', \leftarrow), (q'', \sigma'', \rightarrow)\}</math>.</center>


Zapisujemy wtedy formułę:
Zapisujemy wtedy formułę:


  <math>\forall_{\bar x} \forall_{\bar x'} \forall_{\bar x''} \forall_{\bar y}
<center><math>\forall_{\bar x} \forall_{\bar x'} \forall_{\bar x''} \forall_{\bar y}
\forall_{\bar y'} [Succ(\bar x', \bar x) \wedge Succ(\bar x, \bar x'') \wedge Succ(\bar y', \bar y) \wedge Q_q(\bar y) \wedge S_\sigma(\bar x, \bar y) \wedge H(\bar x, \bar y) \Rightarrow (Q_{q'}(\bar y') \wedge S_{\sigma'}(\bar x, \bar y') \wedge H(\bar x'', \bar y')) \vee (Q_{q''}(\bar y') \wedge S_{\sigma''}(\bar x, \bar y') \wedge H(\bar x', \bar y'))]</math>
\forall_{\bar y'} [Succ(\bar x', \bar x) \wedge Succ(\bar x, \bar x'') \wedge Succ(\bar y', \bar y) \wedge Q_q(\bar y) \wedge S_\sigma(\bar x, \bar y) \wedge H(\bar x, \bar y) \Rightarrow (Q_{q'}(\bar y') \wedge S_{\sigma'}(\bar x, \bar y') \wedge H(\bar x'', \bar y')) \vee (Q_{q''}(\bar y') \wedge S_{\sigma''}(\bar x, \bar y') \wedge H(\bar x', \bar y'))]</math>.</center>


Ostatnia formuła gwarantuje zachowanie tego samego symbolu na taśmie, gdy w danej komórce nie ma głowicy:
Ostatnia formuła gwarantuje zachowanie tego samego symbolu na taśmie, gdy w danej komórce nie ma głowicy:


  <math>\forall_{\bar x}\forall_{\bar y}\forall_{\bar y'}[Succ(\bar y', \bar y) \wedge S_\sigma(\bar x, \bar y) \wedge \neg H(\bar x, \bar y)\Rightarrow S_\sigma(\bar x, \bar y')]</math>
<center><math>\forall_{\bar x}\forall_{\bar y}\forall_{\bar y'}[Succ(\bar y', \bar y) \wedge S_\sigma(\bar x, \bar y) \wedge \neg H(\bar x, \bar y)\Rightarrow S_\sigma(\bar x, \bar y')]</math>.</center>


{{uwaga|||   
{{uwaga|3.7||   
Powyższe formuły bardzo przypominają te, które zostały zdefiniowane przy twierdzeniu Cook'a-Lewina. Jedyna znacząca różnica jest w funkcji przejścia:
Powyższe formuły bardzo przypominają te, które zostały zdefiniowane przy twierdzeniu Cook'a-Lewina. Jedyna znacząca różnica jest w funkcji przejścia:
W tym dowodzie symulujemy maszynę niedeterministyczną, podczas gdy w poprzednim generowaliśmy świadka i postępowaliśmy deterministycznie. Do tej różnicy nie należy jednak przywiązywać wagi - moglibyśmy również tutaj stosować definicję ze świadkiem. Nie czynimy tego tylko dlatego, że utrudniłoby nam to wypisanie formuły definiującej początkowy stan taśmy.   
tym dowodzie symulujemy maszynę niedeterministyczną, podczas gdy w poprzednim generowaliśmy świadka i postępowaliśmy deterministycznie. Do tej różnicy nie należy jednak przywiązywać wagi - moglibyśmy również tutaj stosować definicję ze świadkiem. Nie czynimy tego tylko dlatego, że utrudniłoby nam to wypisanie formuły definiującej początkowy stan taśmy.   
}}
}}


Jeżeli teraz poskładamy powyższe formuły w jedną całość i dopiszemy kwantyfikatory  
Jeżeli teraz poskładamy powyższe formuły w jedną całość i dopiszemy kwantyfikatory:


  <math>\exists_P \exists_{\bar P} \exists_{Succ} \exists_{S_{\sigma_0}} \cdots \exists_{S_{\sigma_{|\Sigma|-1}}} \exists_{Q_{q_0}} \cdots \exists_{Q_{q_{|Q|-1}}} \exists_H \cdots </math>
<center><math>\exists_P \exists_{\bar P} \exists_{Succ} \exists_{S_{\sigma_0}} \cdots \exists_{S_{\sigma_{|\Sigma|-1}}} \exists_{Q_{q_0}} \cdots \exists_{Q_{q_{|Q|-1}}} \exists_H \cdots</math></center>


to otrzymamy formułę z rodziny <math>ESO</math>, charakteryzującą grafy z <math>L'</math>.
to otrzymamy formułę z rodziny <math>ESO</math>, charakteryzującą grafy z <math>L'</math>.
Linia 612: Linia 604:
Udowodniliśmy zatem fakt znany jako twierdzenie Fagina.
Udowodniliśmy zatem fakt znany jako twierdzenie Fagina.


{{twierdzenie|[Fagina]||
{{twierdzenie|3.8 [Fagina]|tw 3|
Klasę <math>NP</math> stanowią dokładnie te problemy, które sa charakteryzowalne przez egzystencjalne zdania drugiego rzędu.
Klasę <math>NP</math> stanowią dokładnie te problemy, które sa charakteryzowalne przez egzystencjalne zdania drugiego rzędu.
}}
}}
==Testy końcowe==

Aktualna wersja na dzień 11:02, 5 wrz 2023

W poprzednim module przedstawione zostały podstawowe klasy złożoności dla problemów, jak również zależności między nimi. W tym rozdziale poznamy narzędzie bardzo pomocne przy określaniu przynależności problemów do zadanej klasy złożoności - redukcje.

Redukcje

Definicja 1.1

Niech będzie pewną rodziną funkcji o sygnaturze

{0,1}{0,1}

domkniętą na składanie i zawierającą identyczność. Niech L1 i L2 będą językami nad alfabetem {0,1} (czyli inaczej mówiąc zakodowanymi binarnie problemami decyzyjnymi). Mówimy, że problem L1 jest redukowalny do problemu L2 w sensie rodziny i zapisujemy

L1L2.

wtedy i tylko wtedy, gdy

fw{0,1}wL1f(w)L2

Intuicyjnie problem L1 jest w pewnym sensie co najwyżej tak trudny, jak problem L2 - jeżeli znamy rozwiązanie problemu L2 oraz odpowiednią funkcję (zwaną redukcją lub transformacją), to znamy również rozwiązanie problemu L1. Warto zauważyć, że relacja jest preporządkiem, to znaczy jest zwrotna (ze względu na obecność identyczności) i przechodnia (ze względu na domkniętość rodziny na składanie).

Przedstawmy teraz najczęściej stosowane rodziny redukcji.

Redukcje wielomianowe

Przekształcenie grafu dwudzielnego w sieć przepływową.

Rodzina redukcji wielomianowych (Karpa) to rodzina funkcji {0,1}{0,1} obliczalnych nadeterministycznej maszynie Turinga w czasie wielomianowym. Redukowalność w sensie rodziny redukcji wielomianowych najczęściej po prostu nazywa się redukowalnością wielomianową.

Klasycznym przykładem redukowalnosci wielomianowej jest redukowalność problemu maksymalnego skojarzenia w grafie dwudzielnym do problemu maksymalnego przepływu w grafie skierowanym (animacja Przekształcenie grafu dwudzielnego w sieć przepływową).

Redukcje wielomianowe mają ważną własność: jeżeli problem L1 jest redukowalny wielomianowo do problemu L2 oraz L2 należy do klasy P, to L1 również należy do klasy P. Aby uzasadnić tę własność, wystarczy skonstruować maszynę, która najpierw przekształci instancję problemu L1 do instancji problemu L2 (uczyni to w czasie wielomianowym, bo L1 jest wielomianowo redukowalne do L2), po czym w czasie wielomianowym da odpowiedź dla instancji problemu L2.

Ćwiczenie 1.2

Załóżmy, że L1 jest wielomianowo redukowalne do L2 oraz L2 należy do klasy NP. Pokaż, że L1 również należy do klasy NP.

Rozwiązanie

Redukcje logarytmiczne

Drugą ciekawą rodziną redukcji jest rodzina redukcji logarytmicznych. Aby zdefiniować tą rodzinę zmodyfikujemy definicję maszyny Turinga - otóż wyznaczamy na niej dwie specjalne taśmy: wejściową (tylko do odczytu, tak jak przy maszynie off-line) i wyjściową. Po zapisie na taśmę wyjściową głowica przesuwa się zawsze w tym samym kierunku, co uniemożliwia odczyt poprzednio zapisanych symboli.

Powróćmy teraz do redukcji. Redukcja logarytmiczna jest funkcją obliczalną na deterministycznej maszynie Turinga z użyciem logarytmicznej ilości pamięci na taśmie roboczej. Zauważmy, że nie nakładamy żadnych ograniczeń na wielkość słowa wyjściowego - najczęśniej jego wielkość będzie wielomianowo zależna od wielkości słowa wejściowego. Intuicyjnie transformacja logarytmiczna pozwala przechowywać na taśmie roboczej stałą liczbę wskaźników do komórek wejściowych (lub innych obiektów o podobnej wielkości).

Ćwiczenie 1.3

Czy problem maksymalnego skojarzenia w grafie dwudzielnym jest redukowalny do problemu maksymalnego przepływu w sensie rodziny transformacji logarytmicznych?

Wskazówka
Rozwiązanie

Ćwiczenie 1.4

Czy istnienie redukcji logarytmicznej z problemu L1 do problemu L2 implikuje istnienie redukcji wielomianowej z L1 do L2? Odpowiedź uzasadnij.

Wskazówka
Rozwiązanie

Warto się zastanowić, czy prawdziwa jest następująca hipoteza:

Szablon:Hipoteza

Ta niewątpliwie cenna (o ile prawdziwa) hipoteza nie jest jednak tak oczywista, jak poprzednio pokazywane analogiczne fakty dla transformacji wielomianowej i klas P oraz NP. Problem przy "składaniu" dwóch maszyn - transformacji oraz maszyny rozwiązującej L2 - tkwi w tym, że być może nie będziemy w stanie zapisać wyjścia transformacji (o potencjalnie wielomianowej wielkości) na taśmie roboczej.

Posłużymy się tutaj następującym trikiem: uruchomimy maszynę rozwiązującą problem L2; za każdym razem, gdy maszyna ta będzie chciała odwołać się do któregoś - dla ustalenia uwagi i-tego - bitu wejścia, na osobnej taśmie uruchomimy maszynę implementującą redukcję z L1 do L2. Maszyna ta nie będzie jednak wypisywać kolejnych symboli na wyjście, tylko inkrementować specjalnie utworzony licznik operacji wyjścia; w momencie, gdy wykonana zostanie i-ta operacja wyjścia, maszyna powróci do wykonywania programu rozwiązującego problem L2, wykorzystując symbol, który miał zostać wypisany na wyjście przez maszynę transformującą. Takie postępowanie wydaje się mało wydajne - tym niemniej na taśmach roboczych nigdy nie znajduje się większa niż logarytmiczna liczba symboli - a zatem otrzymujemy algorytm dla problemu L1, wykorzystujący logarytmiczną ilośc symboli. Analogiczny argument można zastosować do pokazania, że rodzina transformacji logarytmicznych jest domknięta na składanie.

Transformacja wielomianowa w sensie Turinga

Definiowana tutaj transformacja będzie miała trochę inny charakter od dwóch poprzednich - w szczególności formalnie nie będzie ona redukcją. Do jej zdefiniowania będziemy potrzebować pojęcia maszyny z wyrocznią.

Definicja 1.6

Maszyna z wyrocznią Q{0,1} jest wielotaśmową maszyną Turinga, z jedną wyróżnioną taśmą i trzema wyróżnionymi stanami {qa,qb,qc}. Zachowanie maszyny różni się od zachowania zwykłej maszyny Turinga w następujący sposób: przejście maszyny do stanu qa jest traktowane jako odwołanie do wyroczni Q. Jeżeli słowo aktualnie zapisane na wyróżnionej taśmie należy do języka Q, to maszyna przechodzi do stanu qb; w przeciwnym razie przechodzi do stanu qc. Odwołanie do wyroczni wliczane jest do czasu działania maszyny jako jedno przejście.

Mówiąc nieformalnie, maszyna może w trakcie działania wielokrotnie prosić wyrocznię o rozwiązanie problemu Q.

Definicja 1.7

Niech L1 i L2 będą językami nad alfabetem {0,1}. Mówimy, że L1 transformuje się do L2 w sensie wielomianowej transformacji Turinga wtedy i tylko wtedy, gdy istnieje maszyna Turinga z wyrocznią L2, rozwiązująca L1 w czasie wielomianowym.

Transformacja Turinga intuicyjnie odpowiada stosowaniu podprogramów - jeżeli znamy rozwiązanie problemu L2, to stosujemy go jako podprocedurę przy rozwiązywaniu problemu L1.

Ćwiczenie 1.8

Niech L1 i L2 będą językami nad alfabetem {0,1} oraz niech L1 transformuje się do L2 w sensie transformacji wielomianowej Turinga. Które z poniższych zdań jest prawdziwe:

  • L1PL2P,
  • L2PL1P?
Rozwiązanie

Łatwo zauważyć, że transformacja wielomianowa w sensie Turinga wyznacza preporządek na językach zawartych w {0,1}. Oznaczamy ją symbolem T.

Ćwiczenie 1.9

Które z poniższych zdań jest prawdziwe:

  • L1TL2L1PL2,
  • L1PL2L1TL2?
Rozwiązanie

Zupełność

Zastosujemy teraz zdefiniowane uprzednio rodziny transformacji do zdefiniowania dla wybranych klas złożoności ich najbardziej reprezentatywnych przedstawicieli - swoistej arystokracji w ramach danej klasy.

Definicja 2.1

Niech 𝒞 będzie pewną klasą złożoności, natomiast preporządkiem określonym na językach zawartych w {0,1} (w domyśle jedną ze zdefiniowanych wcześniej rodzin transformacji). Mówimy, że problem decyzyjny L{0,1} jest 𝒞-zupełny w sensie preporządku wtedy i tylko wtedy, gdy:

  • L𝒞,
  • L𝒞LL.

Intuicyjnie problem 𝒞-zupełny jest najtrudniejszym do rozwiązania problemem w klasie złożoności 𝒞. Warto zauważyć, że może istnieć (i zazwyczaj istnieje) więcej niż jeden problem 𝒞-zupełny. Problemy te są równoważne w sensie relacji preporządku .

Ćwiczenie 2.2

Scharakteryzuj problemy P-zupełne w sensie transformacji wielomianowej.

Rozwiązanie

Jak zauważyliśmy rozpatrywana powyżej klasa jest mało interesująca. Jeszcze mniej interesująca jest oczywiście klasa problemów P-zupełnych w sensie transformacji wielomianowej Turinga. Dla odróżnienia - klasa problemów P-zupełnych w sensie transformacji logarytmicznej cieszy się niemałym zainteresowaniem specjalistów z dziedziny złożoności obliczeniowej; z tego powodu najczęściej określa się ją po prostu jako klasę problemów P-zupełnych.

Uwaga 2.3

Przykłady problemów P-zupełnych można znaleźć w module 11.

Klasa NP i NP-zupełność

W ramach tego kursu naszym wielkim zainteresowaniem będzie się cieszyć klasa NP, a w szczególności problemy NP-zupełne w sensie trzech poznanych wcześniej rodzin transformacji. Zanim jednak przejdziemy do problemów NP-zupełnych, poznamy pewną alternatywną definicję klasy złożoności NP.

Twierdzenie 3.1

Niech L{0,1}. Wtedy:

LNPp(x)wielomianLPnw{0,1}n[wL(v{0,1}p(n)w,vL)].

Zanim udowodnimy powyższy fakt, spróbujmy najpierw prześledzić, co się właściwie dzieje po prawej stronie równoważności. Słowo v zwykle nazywane jest świadkiem (ang. witness) słowa w. Żądamy, żeby każde słowo należące do języka L miało świadka o długości wielomianowej, natomiast żadne słowo spoza L takiego świadka nie miało. Co więcej - żądamy, aby sprawdzanie, czy v jest świadkiem słowa w było wykonywane w czasie wielomianowym na maszynie deterministycznej, dlatego klasę NP czasem nazywamy klasą problemów weryfikowalnych w czasie wielomianowym.

Przykład 3.2 [NONPRIME]

Rozważmy problem NONPRIME. Niech w{0,1} będzie reprezentacją liczby naturalnej w systemie binarnym.

wNONPRIME liczba reprezentowana przez w nie jest liczbą pierwszą.

Aby pokazać, że liczba nie jest pierwsza, wystarczy podać dowolny jej nietrywialny dzielnik (nie dotyczy to oczywiście liczby 1). Właśnie ten dzielnik będzie naszym świadkiem (w specjalnym przypadku liczby 1 uznamy, że jej świadkiem jest 1). Język L będzie miał wtedy następującą postać:

L:={w,v:(num(v)num(w)num(v)1num(v)num(w))num(w)=num(v)=1},

gdzie num(v) oznacza liczbę reprezentowaną przez słowo v. Łatwo zauważyć, że L jest implementowalna w czasie wielomianowym na deterministycznej maszynie - wystarczy pisemnie podzielić w przez v, sprawdzić, czy zostanie reszta z dzielenia i ewentualnie obsłużyć przypadek brzegowy (liczbę 1). Zatem jak tylko udowodnimy powyższe twierdzenie, będziemy mogli stwierdzić, że NONPRIMENP.

Przekształcanie rozgałęzienia stopnia k w k-1 rozgałęzień stopnia 2.

Dowód [Twierdzenia 3.1]

W stronę dowód jest prosty - skonstruujemy niedeterministyczną maszynę Turinga, rozwiązującą problem L. Maszyna ta najpierw przesunie głowicę za słowo wejściowe, przez następne p(n) kroków będzie wypisywać na taśmę symbole 0 lub 1 (tu jest stosowany niedeterminizm) i przesuwać głowicę w prawo. Od tej pory maszyna będzie działać całkowicie deterministycznie - przesunie się na początek taśmy i zacznie się zachowywać jak deterministyczna maszyna rozwiązująca problem L w czasie wielomianowym.

Jeżeli dla słowa wejściowego w istnieje świadek, to zostanie on wygenerowany przez jedną ze ścieżek postępowania w etapie niedeterministycznym. W przeciwnym przypadku wszyscy "kandydaci na świadków" zostaną odrzuceni (zdemaskowani) przez maszynę rozwiązującą L.

Udowodnijmy teraz przejście w drugą stronę (). Skoro LNP, to istnieje niedeterministyczna maszyna Turinga M rozstrzygająca problem L. Niech k oznacza maksymalny stopień rozgałęzienia maszyny M, tj.

k:=max(s,q)Σ×Q#d(s,q),

czyli mówiąc nieformalnie, największą liczbę rozgałęzień, która może się dokonać w jednym kroku. Łatwo zauważyć, że istnieje równoważna maszyna M co najwyżej k1-krotnie wolniejsza (a zatem nadal wielomianowa) o maksymalnym stopniu rozgałęzienia równym 2 - uzasadnienie przedstawione jest animacji Przekształcanie rozgałęzienia stopnia k w k-1 rozgałęzień stopnia 2.

Od tej pory będziemy się zajmować maszyną M. Oznaczmy jej czas działania jako W(n); w związku z tym maszyna dla słowa wielkości n wykona co najwyżej W(n) rozgałęzień. Każda ścieżka postępowania maszyny M jest zatem zdefiniowana poprzez ciąg W(n) bitów mówiących, która spośród co najwyżej dwóch dostępnych ścieżek została wybrana. Jako "kandydatów na świadków" wybierzmy zatem ciągi {0,1}W(n), świadkiem natomiast niech będzie ciąg reprezentujący akceptującą ścieżkę postępowania maszyny M - o ile taka istnieje.

Wystarczy w tym momencie wksazać deterministyczna maszynę Turinga N, rozpoznającą język L - czyli weryfikującą dla pary słów w,v, czy v jest świadkiem dla w. Maszyna taka jest prosta do skonstruowania w następujący sposób:

  • N najpierw przepisuje v na tasmę pomocniczą, po czym wraca na głównej taśmie do początku słowa w,
  • N zachowuje się podobnie jak maszyna M; w przypadku, gdy maszyna ma do wyboru dwie opcje, N sięga po kolejny dostępny bit taśmy pomocniczej i na jego podstawie wybiera ścieżkę postępowania.

Łatwo zauważyć, że M akceptuje słowo w wtedy i tylko wtedy, gdy istnieje świadek, który spowoduje, że maszyna N dojdzie do stanu akceptującego.

Poznaliśmy zatem alternatywną definicję klasy NP. Potocznie często mówi się, że maszyna rozwiązująca problem z klasy NP najpierw "zgaduje" świadka, a potem weryfikuje go w deterministyczny sposób w czasie wielomianowym. Należy jednak pamiętać, że maszyna w rzeczywistości nie "zgaduje" - zamiast tego sprawdza ona wszystkich możliwych świadków.

Powróćmy teraz do redukcji i problemów zupełnych. Oznaczmy jako NPC, NPCL i NPCT klasy problemów NP-zupełnych w sensie odpowiednio transformacji wielomianowej Karpa, transformacji logarytmicznej i transformacji wielomianowej Turinga. W tym momencie w żaden sposób nie uzasadniliśmy jeszcze, dlaczego którakolwiek z tych klas miałaby być niepusta. Mimo to już w tym momencie można określić pewne relacje zawierania pomiędzy tymi klasami.

Ćwiczenie 3.3

Uszereguj klasy NPC, NPCL i NPCT od najwęższej do najszerszej i uzasadnij to uszeregowanie.

Rozwiązanie

Problem SAT

Zdefiniowanie problemu SAT wymaga uprzedniego wprowadzenia (względnieprzypomnienia) kilku pojęć z dziedziny logiki:

  • literałem nazywamy zmienną lub jej negację,
  • klauzulą nazywamy alternatywę skończonej liczby literałów,
  • mówimy, że formuła logiczna jest w koniunkcyjnej postaci normalnej wtedy i tylko wtedy, gdy jest koniunkcją skończonej liczby klauzul. Przykładem formuły w koniunkcyjnej postaci normalnej jest formuła:
(x1x2¬x3)(x2x3)(¬x1¬x4).

Mówimy, że formuła jest spełnialna wtedy i tylko wtedy gdy istnieje wartościowanie zmiennych, dla których ta formuła jest spełniona. Dla powyższej formuły jednym z wartościowań, dla których jest ona spełniona, jest wartościowanie przypisujące zmiennym x1, x2, x3, x4 odpowiednio wartości 0, 1, 1, 0; w związku z tym powyższa formuła jest spełnialna.

Do dalszych rozważań ustalmy pewne kodowanie formuł logicznych do słów nad alfabetem {0,1} - na przykład ustalmy, że najpierw zapisujemy liczbę klauzul, następnie dla każdej klauzuli liczbę literałów, a dalej dla każdego literału numer zmiennej oraz bit określający czy zmienna jest zanegowana.

Definicja 3.4

Niech w{0,1}. Wtedy Parser nie mógł rozpoznać (nieznana funkcja „\iffw”): {\displaystyle w \in SAT \iffw} reprezentuje poprawnie zakodowaną formułę logiczną w koniunkcyjnej postaci normalnej i formuła ta jest spelnialna.

Ćwiczenie 3.5

Pokaż, że problem SAT należy do klasy NP.

Wskazówka
Rozwiązanie

Twierdzenie 3.6 [(Cook'a-Lewina)]

Problem SAT jest NP-zupełny w sensie redukcji logarytmicznej.

Dowód

Pierwszą część dowodu już mamy - wiemy, że SATNP. Do pokazania pozostaje zatem fakt, że

LNPLLSAT.

Weźmy zatem dowolny język LNP. Korzystając z udowodnionego wcześniej twierdzenia wiemy, że istnieje p(n) - wielomian określający długość świadka - oraz wielomianowy program dla deterministycznej maszyny Turinga, weryfikujący świadka - jego czas działania oznaczmy jako Q(n). Załóżmy bez straty ogólności, że program ten kontynuuje działanie po dojściu do stanu akceptującego i pozostaje w tym stanie niezależnie od symbolu pod głowicą ("zapętla się" w tym stanie). Jako że wejściem programu weryfikującego jest konkatenacja słowa wejściowego i świadka, górnym ograniczeniem na czas jego działania w zależności od wielkości wejścia jest

T(n):=Q(p(n)+n)

(oczywiście ograniczenie to nadal jest wielomianowe).

Naszym zadaniem teraz będzie takie przekształcenie słowa wejściowego w w formułę logiczną, aby formuła była spełnialna wtedy i tylko wtedy, gdy wL. Ustalmy zatem, jakich zmiennych będzie używać nasza formuła logiczna i jakie będziemy tym zmiennym przypisywać znaczenie.

Zmienna Zakres parametrów Znaczenie
Ht,p 0tT(n), T(n)pT(n) Głowica w chwili t znajduje się w miejscu p.
Qt,q 0tT(n), 0q<|Q| Maszyna w chwili t znajduje się w stanie q.
St,p,s 0tT(n), T(n)pT(n), 0s<|Σ| Na taśmie w chwili t w miejscu p znajduje się symbol s.

Oczywiście maszyna rozwiązująca problem SAT nie ma pojęcia o znaczeniu, jakie przypisujemy zmiennym; musimy to znaczenie wymusić podczas konstrukcji formuły logicznej.

Najpierw wymusimy, aby w każdej chwili symulowana głowica znajdowała się w dokładnie jednym miejscu. Dla chwili 0 będzie to wyglądało następująco:

(H0,T(n)H0,T(n)+1H0,0H0,T(n))

(¬H0,T(n)¬H0,T(n)+1)(¬H0,T(n)¬H0,T(n)+2)(¬H0,T(n)¬H0,T(n)) (¬H0,0¬H0,1)(¬H0,0¬H0,T(n))

(¬H0,T(n)1¬H0,T(n)).

Na tym etapie zapisaliśmy już O(T(n)2) symboli, a zanosi się, że zapiszemy znacznie więcej. W związku z tym na potrzeby tego dowodu umówimy się, że powyższą formułę (i podobne, których będziemy potrzebować w przyszłości) będziemy skrótowo zapisywać w następujący sposób:

T(n)iT(n)H0,iT(n)i<jT(n)(¬H0,i¬H0,j).

Oczywiście maszyna dokonująca redukcji będzie musiała się bardziej namęczyć i wypisać wszystkie klauzule; pocieszamy się jednak tym, że na pewno uda się jej to zrobić z użyciem logarytmicznej ilości pamięci.

Powyższa formuła gwarantowała, że w chwili 0 głowica będzie w dokładnie jednym miejscu. Aby zapewnić to dla każdego kroku działania maszyny, zapisujemy formułę:

0tT(n)[T(n)iT(n)Ht,iT(n)i<jT(n)(¬Ht,i¬Ht,j)].

Analogiczne formuły musimy wypisać, aby zagwarantować, że:

  • w każdej chwili maszyna znajduje się w dokładnie jednym stanie,
  • w każdej chwili w każdej klatce taśmy znajduje się dokładnie jeden symbol.

Dla porządku odpowiednie formuły są podane poniżej:

0tT(n)[0i<|Q|Qt,i0i<j<|Q|(¬Qt,i¬Qt,j)], 0tT(n)T(n)pT(n)[0i<|Σ|St,p,i0i<j<|Σ|(¬St,p,i¬St,p,j)].

Następnie musimy zakodować w formule logicznej funkcję przejścia. Załóżmy, że dla pewnego stanu q i symbolu s

d(q,s)=(q,s,)

Będziemy wtedy musieli zapisać następującą formułę:

0t<T(n)T(n)<pT(n)[(Ht,pQt,qSt,p,s)(Ht+1,p1Qt+1,qSt+1,p,s)].

Niestety nie możemy wprost używać implikacji, a zatem musimy tę formułę trochę przekształcić:

0t<T(n)T(n)<pT(n)[(¬Ht,p¬Qt,q¬St,p,s)(Ht+1,p1Qt+1,qSt+1,p,s)]

co z kolei możemy przekształcić do postaci ostatecznej:

0t<T(n)T(n)<pT(n)[(¬Ht,p¬Qt,q¬St,p,sHt+1,p1)(¬Ht,p¬Qt,q¬St,p,sQt+1,q)(¬Ht,p¬Qt,q¬St,p,sSt+1,p,s)].

Formuły powyższego typu będziemy musieli wypisać dla każdej pary (q,s) - będzie ich zatem |Q||Σ|; liczba ta oczywiście nie jest zależna od n (choć oczywiście długości formuł zależą kwadratowo od T(n)).

Musimy jeszcze zadbać o to, by komórki, w których nie ma głowicy, pozostawały bez zmian:

0t<T(n)T(n)pT(n)0s<|Σ|[(¬Ht,pSt,p,s)St+1,p,s],

czyli

0t<T(n)T(n)pT(n)0s<|Σ|[Ht,p¬St,p,sSt+1,p,s].

Musimy zadbać o to, by zmienne reprezentujące słowo wejściowe (czyli symbole taśmy w chwili 0) były takie jak należy:

T(n)p<0S0,p,#0p<|w|S0,p,wpS0,|w|,#|w|+1p|w|+p(n)(S0,p,0S0,p,1)|w|+p(n)<p<=T(n)S0,p,#.

Żądamy, by w chwili początkowej na taśmie znalazło się słowo wejściowe oraz "kandydat na świadka". Na koniec żądamy, by po T(n) krokach program znajdował się w stanie akceptującym (mógł się w nim znaleźć wcześniej, założyliśmy jednak, że maszyna w tym stanie się "zapętli", więc wystarczy, jeśli sprawdzimy w chwili T(n))

QT(n),qacc

Widzimy, że jeśli koniunkcja powyższych formuł jest spełnialna, to istnieje świadek dla słowa w - będzie on określony przez wartościowanie zmiennych reprezentujących taśmę w chwili początkowej. Z drugiej strony widać, że istnienie świadka dla słowa w implikuje wartościowanie zmiennych spełniające koniunkcję powyższych formuł logicznych. Pozostaje więc tylko uzasadnić to, że przekształcenie słowa w w powyższą formułę odbywa się z użyciem logarytmicznej pamięci. Widać jednak, że postać każdej z tych częściowych formuł jest z góry określona i maszyna podczas dokonywania redukcji będzie jedynie potrzebowała przechowywać na taśmie określoną z góry liczbę iteratorów. Pokazaliśmy zatem, że SAT jest problemem NP-zupełnym w sensie wszystkich trzech zdefiniowanych transformacji.

Charakteryzacja klasy NP w języku logiki

W ostatniej części tego modułu zaprezentujemy bardzo ciekawą charakteryzację klasy NP; jest ona zaskakująca choćby z tego powodu, że nie jest w niej w ogóle użyte pojęcie modelu obliczeń.

W następnych paragrafach będziemy stale korzystać z grafów. Umówmy się zatem, że od tej pory za reprezentację grafu o n wierzchołkach uznajemy n2 bitów, będących macierzą sąsiedztwa tego grafu, wypisaną wierszami.

Zdefiniujemy teraz kilka przydatnych pojęć z dziadziny logiki.

Termem nazywamy:

  • zmienną,
  • wyrażenie f(t1,t2,,tk), gdzie f to k-argumentowy symbol funkcyjny, a t1,t2,,tk to termy.

Formułą pierwszego rzędunazywamy:

  • wyrażenie t1=t2, gdzie t1 i t2 są termami,
  • wyrażenie R(t1,t2,,tk), gdzie R to k-arny symbol relacyjny,
  • wyrażenia (¬ϕ), (ϕψ), (ϕψ), (ϕψ), gdzie ϕ i ψ to formuły,
  • wyrażenia x(ϕ) i x(ϕ), gdzie x jest zmienną a ϕ jest formułą.

(oczywiście możemy pomijać nawiasy, jeśli nie są one konieczne).

Formułą może być dla przykładu następujące wyrażenie:

(E(x,y)E(x,z))¬E(y,z).

Takiej formule ciężko jednak przypisać jakieś znaczenie, dopóki x, y i z są zmiennymi niezwiązanymi i dopóki nie wiemy, czym jest E. Umówmy się zatem, że zdaniem pierwszego rzędu dla grafów jest formuła logiczna, która:

  • nie posiada zmiennych niezwiązanych,
  • nie używa symboli funkcyjnych,
  • jedynym symbolem relacyjnym, którego używa, jest binarna relacja E, reprezentująca relację sąsiedztwa w grafie.

Zdaniem pierwszego rzędu dla grafów jest na przykład:

xyz[(E(x,y)E(x,z))¬E(y,z)].

Ustalmy teraz pewien graf o zbiorze wierzchołków V i relacji sąsiedztwa EV2. Zinterpretujmy wyrażenia x jako xV. W tym momencie możemy już rozpatrywać prawdziwość powyższego zdania dla poszczególnych grafów: zdanie to będzie prawdziwe dla grafów nie posiadających trójkątów i fałszywe dla pozostałych grafów. Widzimy zatem, że zdania pierwszego rzędu mogą wyrażać pewne własności grafów - czyli spośród wszystkich grafów wyłaniać pewne ich podzbiory. Okazuje się jednak, że siła ekspresji zdań pierwszego rzędu nie jest zbyt duża - na przykład nie da się skonstruować zdania, odróżniającego grafy spójne od niespójnych. Zdefiniujmy zatem silniejszą klasę zdań.

Zdaniem egzystencjalnym drugiego rzędu dla grafów jest zdanie następującej postaci:

R1R2Rkϕ,

gdzie R1,,Rk to symbole relacyjne o ustalonej arności, natomiast ϕ to formuła zdaniowa pierwszego rzędu bez zmiennych niezwiązanych, symboli funkcyjnych i używająca tylko symboli relacyjnych R1,,Rk i E. Klasę egzystencjalnych zdań drugiego rzędu będziemy oznaczać jako ESO. Przykładem takiego zdania jest:

Uunarna[xy(E(x,y)U(x))U(y)][xy(U(x)¬U(y))]

Powyższa formuła jest spełniona wtedy i tylko wtedy, gdy rozpatrywany graf jest niespójny; relację unarną można rozumieć jako wybór pewnych wierzchołków, przy czym pierwsza część formuły zapewnia, że jeżeli zostanie wybrany jakiś wierzchołek, to zostanie również wybrana cała jego spójna składowa. Druga część formuły żąda istnienia dwóch wierzchołków, z których jeden jest wybrany a drugi nie - a co za tym idzie, leżących w różnych spójnych składowych.

Zastanówmy się teraz, czy jesteśmy w stanie napisać egzystencjalne zdanie drugiego rzędu, które jest prawdziwe wtedy i tylko wtedy, gdy rozpatrywany graf jest spójny. Widać, że problem polega na tym, iż nie wolno nam zapisać wyrażenia U. W ogólności nie wiadomo, czy dopełnienie klasy grafów charakteryzowanej przez jakieś zdanie z ESO jest charakteryzowalne przez zdanie z ESO. W tym przypadku jednak mamy szczęście - poniższe zdanie charakteryzuje grafy spójne:

Pbinarna[xP(x,x)][xyP(x,y)P(y,x)][xyz(P(x,y)P(y,z))P(x,z)]m[n(P(n,m)(n=m))n(¬P(n,m)k(P(k,n)E(k,n)))].

Nie podamy tutaj szczegółowego wyjaśnienia powyższego zdania; warto jednak wspomnieć, że od P oczekujemy, by była to relacja liniowego porządku na wierzchołkach, z elementem najmniejszym m.

Egzystencjalne zdania drugiego rzędu a złożoność

Wybierzmy jakieś zdanie z ESO. Będziemy chcieli skonstruować niedeterministyczną maszynę Turinga, która będzie oczekiwała na wejściu opisów grafów i będzie akceptowała te grafy, dla których wybrana formuła jest spełniona. Okazuje się, że nasza (niedeterministyczna) maszyna może to zrobić w czasie wielomianowym. Niech s1,s2,,sk będą arnościami kolejnych relacji w zdaniu. Aby zdefiniować te relacje, potrzeba odpowiednio ns1,ns2,,nsk bitów. Maszyna zatem najpierw wygeneruje "kandydatów na świadków" o długości ns1+ns2++nsk bitów (definiując tym samym wszystkie relacje), po czym zweryfikuje prawdziwość formuły pierwszego rzędu. W formule pierwszego rzędu kwantyfikatory odpowiadają pętlom od 1 do n - zatem czas weryfikacji całej formuły wynosi O(nd), gdzie d to maksymalne "zagłębienie kwantyfikatorów" w tej formule. Jest zatem jasne, że dla każdej formuły z ESO rozpoznawanie spełniających ją grafów jest zadaniem z klasy NP.

Twierdzenie Fagina

Przejdźmy teraz do dużo ciekawszego spostrzeżenia. Stwierdzimy bowiem, że każdemu problemowi z klasy NP możemy przypisać charakteryzującą go formułę typu ESO.

Najpierw jednak trzeba się zastanowić, w jaki sposób powiązać ze sobą języki oraz zbiory grafów. Chcielibyśmy zdefiniować konwersję n-bitowego słowa w graf taką, że:

  • wynikowy graf ma O(n) wierzchołków,
  • konwersja w obie strony wykonywana jest na deterministycznej maszynie Turinga w czasie wielomianowym,
  • grafy przypisane dwóm różnym słowom nie są izomorficzne.

Ostatnie założenie wynika z prostej obserwacji: zdanie z ESO nie jest w stanie rozróżnić grafów, które są izomorficzne. Skonstruowanie powyższej konwersji pozostawione jest Czytelnikowi.

Wybierzmy teraz dowolny problem decyzyjny L z klasy NP. Jest jasne, że odpowiadający mu problem L, oczekujący wejścia w postaci grafów, również należy do NP - można go rozwiązać poprzez zdekodowanie grafu do słowa binarnego i uruchomienie maszyny dla oryginalnego problemu. Weźmy zatem maszynę zachowującą się w ten sposób i oznaczmy ją jako M. Załóżmy bez straty ogólności, że maszyna ta jest jednostronnie ograniczona oraz że jej maksymalny stopień rozgałęzienia wynosi 2. Będziemy teraz - podobnie jak wcześniej przy twierdzeniu Cook'a-Lewina - starali się skonstruować formułę logiczną symulującą działanie M. W tym przypadku jednak formuła nie może być generowana na bieżąco po wczytaniu wejścia; tutaj skonstruujemy jedną formułę, która będzie działać dla każdego wejścia.

Przejdźmy zatem do konstrukcji. Załóżmy, że maszyna M działa pesymistycznie w czasie nk, gdzie n to liczba wierzchołków w grafie wejściowym. W naszej formule będziemy używać liniowego porządku, podobnego do zdefiniowanego w formule charakteryzującej spójność. Użyjemy go jednak głównie po to, by zdefiniować liniowy porządek leksykograficzny na k-elementowych ciągach wierzchołków. Załóżmy zatem, że mamy porządek:

v1,v2,,vn.

Chcemy na jego podstawie stworzyć porządek leksykograficzny dla k-elementowych ciągów:

(v1,v1,,v1),(v1,v1,,v1,v2),,(vn,vn,,vn).

Tworzenie takiego porządku jest mało ciekawe - dlatego założymy po prostu, że mamy 2k-arną relację P¯(x¯,y¯), wyznaczającą powyższy porządek. Z tej relacji również łatwo możemy wywieść relację następnika; x¯ będzie w relacji z y¯ wtedy i tylko wtedy, gdy y¯ będzie najmniejszym leksykograficznie ciągiem większym od x¯. Relację następnika oznaczamy jako Succ.

Możemy zatem patrzeć na k-elementowe ciągi wierzchołków jako na sekwencję obiektów. Jest ich nk - a zatem tyle, ile maksymalnie możemy potrzebować czasu i klatek pamięci podczas działania maszyny M. Od tej pory ciągi k wierzchołków będziemy traktować po prostu jako liczniki wskazujące na pewien krok postępowania maszyny lub na pewną komórkę taśmy; zapomnimy przy tym zupełnie o pierwotnym znaczeniu tych obiektów.

W tym momencie jesteśmy gotowi do zdefiniowania relacji oraz znaczenia, które im będziemy przypisywali. Będą one beardzo podobne do zmiennych, używanych w dowodzie twierdzenia Cook'a-Lewina.

  • H(x¯,y¯) -- x¯ jest w relacji z y¯ wtedy i tylko wtedy, gdy w chwili y¯ głowica jest w miejscu x¯,
  • Sσ(x¯,y¯) -- x¯ jest w relacji z y¯ wtedy i tylko wtedy, gdy w chwili y¯ na taśmie w miejscu x¯ jest symbol σ (relacji tego typu jest tyle, ile symboli taśmowych),
  • Qq(y¯) - y¯ należy do relacji wtedy i tylko wtedy, gdy w chwili y¯ maszyna jest w stanie q (relacji tego typu jest tyle, ile stanów).

Musimy teraz wymusić odpowiednią postać tych relacji - taką, aby reprezentowały one obliczenia maszyny Turinga. A zatem - żądamy, by głowica w każdej chwili znajdowała się w dokładnie jednym miejscu:

x¯x¯y¯[x¯=x¯¬H(x¯,y¯)¬H(x¯,y¯)].

Stosujemy tutaj pewne skróty myślowe (w końcu x¯, x¯' i y¯ reprezentują k-elementowe ciągi). x¯ jest zatem tak naprawdę sekwencją k kwantyfikatorów: x0x1xk1. Natomiast wyrażenie x¯=x¯ jest koniunkcją k równości. Podobne formuły należy wypisać, aby zagwarantować obecność dokładnie jednego symbolu w klatce i to, że w każdym kroku maszyna jest w dokładnie jednym stanie:

x¯y¯(¬Sσ0¬Sσ1)(¬Sσ0¬Sσ2) y¯(¬Qq0¬Qq1)(¬Qq0¬Qq2)

Musimy określić początkową zawartość taśmy:

xk2xk1S1((0,,0,xk2,xk1),(0,,0))E(xk2,xk1),

xk2xk1S0((0,,0,xk2,xk1),(0,,0))¬E(xk2,xk1),

x¯(x00x10xk30)T#(x¯,(0,,0)).

Skorzystaliśmy tutaj z symbolu 0; reprezentuje on najmniejszy wierzchołek w sensie porządku P i jest zdefiniowany następująco:

0xP(0,x).

Stan początkowy i początkowe położenie głowicy definiowane są następującą formułą:

H((0,,0),(0,,0))Qq0((0,,0)),

natomiast oczekiwany stan końcowy to:

Qqacc((τ,,τ)),

gdzie τ to wierzchołek maksymalny w sensie porządku P, zdefiniowany analogicznie jak 0. Do zdefiniowania pozostało nam jeszcze tylko dynamiczne zachowanie maszyny. Zdefiniujmy zatem funkcję przejścia; niech dla przykładu:

d((q,σ))={(q,σ,),(q,σ,)}.

Zapisujemy wtedy formułę:

x¯x¯x¯y¯y¯[Succ(x¯,x¯)Succ(x¯,x¯)Succ(y¯,y¯)Qq(y¯)Sσ(x¯,y¯)H(x¯,y¯)(Qq(y¯)Sσ(x¯,y¯)H(x¯,y¯))(Qq(y¯)Sσ(x¯,y¯)H(x¯,y¯))].

Ostatnia formuła gwarantuje zachowanie tego samego symbolu na taśmie, gdy w danej komórce nie ma głowicy:

x¯y¯y¯[Succ(y¯,y¯)Sσ(x¯,y¯)¬H(x¯,y¯)Sσ(x¯,y¯)].
Uwaga 3.7

Powyższe formuły bardzo przypominają te, które zostały zdefiniowane przy twierdzeniu Cook'a-Lewina. Jedyna znacząca różnica jest w funkcji przejścia:

tym dowodzie symulujemy maszynę niedeterministyczną, podczas gdy w poprzednim generowaliśmy świadka i postępowaliśmy deterministycznie. Do tej różnicy nie należy jednak przywiązywać wagi - moglibyśmy również tutaj stosować definicję ze świadkiem. Nie czynimy tego tylko dlatego, że utrudniłoby nam to wypisanie formuły definiującej początkowy stan taśmy.  

Jeżeli teraz poskładamy powyższe formuły w jedną całość i dopiszemy kwantyfikatory:

PP¯SuccSσ0Sσ|Σ|1Qq0Qq|Q|1H

to otrzymamy formułę z rodziny ESO, charakteryzującą grafy z L.

Udowodniliśmy zatem fakt znany jako twierdzenie Fagina.

Twierdzenie 3.8 [Fagina]

Klasę NP stanowią dokładnie te problemy, które sa charakteryzowalne przez egzystencjalne zdania drugiego rzędu.

Testy końcowe