• Nie Znaleziono Wyników

Materiały do wykładu z Podstaw Teorii Obliczalności dla II. roku Zaocznego Studium Informatyki

N/A
N/A
Protected

Academic year: 2021

Share "Materiały do wykładu z Podstaw Teorii Obliczalności dla II. roku Zaocznego Studium Informatyki"

Copied!
55
0
0

Pełen tekst

(1)

Materiały do wykładu z Podstaw Teorii Obliczalności

dla II. roku Zaocznego Studium Informatyki

Barbara Klunder 11 lutego 2005 roku

W wykładzie tym będziemy zajmować się trzema podstawowymi dziedzi- nami teorii obliczeń: obliczalnością, złożonością i automatami. Są one powią- zane z pytaniem

Jakie są podstawowe możliwości i ograniczenia komputerów?

Pytanie to pojawiło się już w latach 30-tych, gdy logicy matematyczni zaczęli precyzować pojęcie obliczenia.

Teoria obliczalności pyta

Czy każdy problem jest rozstrzygalny przez pewną procedurę obliczeniową?

Jeśli nie, to które problemy są rozstrzygalne przez takie procedury?

Teoria złożoności próbuje odpowiedzieć na pytanie

Co czyni pewne problemy obliczeniowo trudnymi, a inne łatwymi?

Teoria automatów (i gramatyk) definiuje i bada własności dwóch modeli ob- liczeń: automatów i gramatyk.

W wykładzie najpierw zajmiemy się teorią obliczalności; wprowadzimy dwie formalizacje pojęcia obliczenia-algorytmu i wykażemy, że istnieją ważne problemy, które nie są rozstrzygalne w (każdej z tych) formalizacji. Następnie omówimy teoretyczne aspekty teorii złożoności.

W drugiej części wykładu skupimy się na teorii automatów i gramatyk, która ma duże znaczenie przy definiowaniu języków programowania i kon- struowaniu kompilatorów dla nich.

(2)

1 Teza Churcha-Turinga

W wykładze zastanawiać będziemy się nad dwoma kluczowymi pytaniami:

Czym jest efektywna procedura? Hardwarem czy softwarem? Urzą- dzeniem, które realizuje określone obliczenia (pierwsze komputery), czy cią- giem instrukcji (programem) w naszym ulubionym języku programowania?

Czym jest problem rozwiązywalny przez efektywną procedurę? Czy istnieją problemy nierozwiązywalne?

Intuicyjnie czujemy, że będziemy wykonywać obliczenia.

Zasdaniczo prowadzić będziemy obliczenia na (skończonych ciągach liczb) liczbach naturalnych.

Przypuśćmy, że chcemy prowadzić obliczenia na zbiorze wejść i wyjść X różnym od N. Możemy to zrobić przyporządkowując każdemu elementowi z X liczbę naturalną zwaną jej kodem tak, aby różne elementy X miały różne kody.

Mając wejścia z X należy zastąpić je ich kodami i wykonać obliczenia, które zwracają numeryczne wyjście. Jeśli to wyjście jest kodem elementu z X, to ten element traktujemy jako końcowy wynik obliczeń.

Chcemy, by pierwszy i ostatni krok tej procedury był realizowany w sposób algorytmiczny. Wtedy mówimy, że kodowanie jest efektywne.

U nas X będzie: zbiorem wszystkich skończonych ciągów liczb naturalnych lub słów nad ustalonym (skończonym) alfabetem, zbiorem instrukcji lub pro- gramów pewnego języka itp.

Kodowania i numeracje

Przypomnijmy dwie definicje zbioru przeliczalnego.

Definicja 1.1 Kodowaniem zbioru X nazywamy dowolną funkcję rónowar- tościową f : X −→ N .

Zbiór jest przeliczalny, jeśli jest równoliczny z pewnym podzbiorem N.

Definicja 1.2 Numeracją (lub wyliczeniem) zbioru X nazywamy dowolną funkcję g : N −→ X, która jest ”na”.

Zbiór jest przeliczalny, jeśli jego elementy można ustawić w ciąg.

Przykłady

(3)

1. Funkcja π : N × N −→ N określona wzorem π(n.m) = 2n(2m + 1) − 1 jest bijektywnym kodowaniem par liczb naturalnych.

Funkcja odwrotna zadana jest przez funkcje π1, π2 : N −→ N zdefinio- wane następująco:

π1(x) = n wtw, gdy 2 pojawia się w rozkładzie x+1 na czynniki pierw- sze z wykładnikiem n;

π2(x) = 12(2x+1π1(x) − 1)

2. Wtedy funkcja β : N × N × N −→ N, β(n, m, p) = π(π(n, m), p) jest bijektywnym kodowaniem trójek liczb naturalnych. Jak wygląda funkcja odwrotna?

3. Rozważmy funkcję τ :Sk>0Nk−→ N taką, że

τ (a0, a1, . . . , ak−1) = 2a0 + 2a0+a1+1+ . . . + 2a0+a1+...ak−1+k−1− 1.

Jest to bijektywne kodowanie wszystkich skończonych ciągów liczb na- turalnych.

Pokażemy później, że funkcje π i β są (RAM-)obliczalne, a numeracja τ−1 jest efektywna. Będą to kluczowe rezultaty techniczne. Pozwolą one na porównanie omówionych poniżej modeli obliczeń.

1.1 Maszyny z nieograniczoną pamięcią RAM (She- perdson & Sturgis)

Budowa maszyny realizującej programy w języku zbliżonym do popularnych imperatywnych języków programowania, który będziemy rozważać, przypo- mina budowę rzeczywistych komputerów: maszyna składa się z licznika roz- kazów oraz pamięci, która jest nieskończoną tablicą. Komórki pamięci są numerowane kolejnymi liczbami naturalnymi i mogą zawierać, tak jak licz- nik rozkazów, dowolną liczbę naturalną. W czasie obliczeń prawie wszystkie komórki pamięci zawierają liczbę 0.

Oznaczenie z[x] oznacza zawartość komórki o numerze x.

Lista instrukcji RAM

(4)

Kod instrukcji

Kod

adresów Oznaczenie Semantyka Uwagi

0 n Z(n) z[n]:=0 Licznik rozkazów

zwiększ o 1

1 n S(n) z[n]:=z[n]+1 Licznik rozkazów

zwiększ o 1

2 π(m, n) T(m,n) z[n]:=z[m] Licznik rozkazów

zwiększ o 1

3 β(m, n, q) I(m,n,q) if z[m]=z[n]

then goto q

Licznik rozkazów zwiększ o 1, gdy z[m] 6= z[n],

w przeciwnym przypadku umieść w nim q

Instrukcje typu 0, 1, 2 nazywamy arytmetycznymi , a typu 3 warunkowy- mi.

Definicja 1.3 Programem (na RAM) nazywamy dowolny niepusty ciąg RAM-instrukcji.

Semantyka instrukcji typu 3 wymusza numerowanie instrukcji w programie.

Kultura matematyczna wymaga od nas sformalizowania pojęć stanu, instrukcji, semantyki programu itp. Na razie wykorzystamy naszą intuicję.

Przykładowy program

0 I(1,2,5) if z[1]=z[2] then goto 5

1 S(2) z[2]:=z[2]+1

2 S(3) z[3]:=z[2]+1

3 I(1,2,5) if z[1]=z[2] then goto 5 4 I(1,1,1) if z[1]=z[1] then goto 1

5 T(3,0) z[0]:=z[3]

Co liczy ten program?

Oczywiście interesują nas komórki pamięci, które są aktywne w czasie obli- czeń. Program zatrzymuje się, gdy z[1]=z[2]. Jeśli więc na początku z[2]¬z[1], to wykonuje się zwiększanie z[2], aż równość stanie się prawdziwa. Zwiększa się z[3] o ilość dodawań, czyli z[1]-z[2]. Jeśli więc z[i] oznacza początkową zawartość komórki, to po zakończeniu obliczeń w komórce o numerze 0 znaj- duje się liczba z[3]+z[1]-z[2]. Zauważmy, że program nie zatrzyma się, gdy na początku z[2]>z[1]!

Z charakteru RAM wynika, że będziemy zajmować się programami, które na wejściu biorą ciągi (ustalonej długości) liczb naturalnych i zwracają jedną

(5)

liczbę naturalną.

Umowa : Program zwraca zawartość komórki o numerze 0.

Oczywiście nie zawsze program musi się zatrzymać na każdych danych.

Naturalne jest więc pytanie jakie funkcje są obliczane przez RAM-programy.

Będzie to pierwszy problem, którym się zajmiemy. Okaże się, że funkcje aryt- metyczne są RAM-obliczalne.

Definicja 1.4 Niech k > 0. Program P oblicza funkcję częściową f : Nk −→

N , jeśli po umieszczeniu ciągu danych x w komórkach z[1], ... , z[k], wyze- rowaniu pozostałych i uruchomieniu P, P zatrzyma się zwracając wartość f na danych x, dokadnie gdy x ∈ Dom f .

Każdy program P oblicza pewną funkcję k-argumentową, dla k > 0, którą oznaczymy symbolem φ(k)P .

Symbolem Ck oznaczymy zbiór wszystkich funkcji RAM-obliczalnych i k- argumentowych, a C =Sk>0Ck zbiór wszystkich funkcji RAM-obliczalnych.

Przyklad 1 Na gruncie aksjomatyki Peano liczb naturalnych dodawanie definiuje się rekurencyjnie:

x+0=x x+(y+1)=(x+y)+1

Nieformalnie: należy do x dodać 1 y-razy. Oto program RAM obliczający z[1]+z[2], przy założeniu, że z[3]=0.

0 I(2,3,5) if z[2]=z[3] then goto 5

1 S(1) z[1]:=z[1]+1

2 S(3) z[3]:=z[3]+1

3 I(1,1,0) if z[1]=z[1] then goto 0

4 T(1,0) z[0]:=z[1]

Zauważmy, że podany program (bez ostatniej instrukcji!) jest zwykłą pę- tlą for. Nie jest to przypadek.

Przykład 2 Niech x ÷ 1 =

( x − 1 gdy x ­ 1

0 gdy x = 0 . Funkcja ta jest obli- czana przez następujący program.

(6)

0 I(1,4,9) if z[1]=z[4] then goto 9

1 S(3) z[3]:=z[3]+1

2 I(1,3,6) if z[1]=z[3] then goto 6

3 S(2) z[2]:=z[2]+1

4 S(3) z[3]:=z[3]+1

5 I(1,1,2) if z[1]=z[1] then goto 2

6 T(2,0) z[0]:=z[2]

Uzasadnienie: W czasie obliczeń (od instrukcji 2) różnica z[3]-z[2] stale równa jest 1, a obliczenia zatrzymują się, gdy z[3] osiągnie początkową wartość z[1].

Pytanie: Zgodnie z definicją, możemy zastanawiać się, jaką dwuargumentową funkcję liczy ten program?

Odpowiedź: f (x, y) = y + (x ÷ 1).

Zadanie 0 Jaką funkcję trójargumentową oblicza powyższy program?

Zadanie 1 Pokazać, że następujące funkcje są RAM-obliczalne. Symbol ∞ oznaczać będzie, że wartość funkcji pozostaje nieokreślona.

1. f (x) =

( x

2 gdy x jest parzysta

∞ gdy x jest nieparzysta

2. f (x) =

( 1 gdy x > 0 0 gdy x = 0 3. f (x) = 5

4. f (x, y) =

( 1 gdy x 6= y 0 gdy x = y 5. f (x, y) =

( 1 gdy x ¬ y 0 gdy x > y 6. f (x) =

( x

3 gdy x dzieli się przez 3

∞ w przeciwnym przypadku Umowa: GOTO(n)=I(x,x,n)

Rozwiązania wybranych zadań

Program obliczający funkcję z zadania pierwszego:

(7)

0 I(1,2,5) if z[1]=z[2] then goto 5

1 S(0) z[0]:=z[0]+1

2 S(2) z[2]:=z[2]+1

3 S(2) z[2]:=z[2]+1

4 GOTO(0)

Pomysł jest łatwy do uchwycenia: w jednym cyklu pętli oblicza się kolejną wielokrotność 2 w rejestrze z[2], a w z[0] zapisane jest którą krotność obli- czono. Oczywiście program pętli się dla liczb nieparzystych. Zmodyfikuj go tak, aby dla każdej liczby naturalnej x obliczał część całkowitą z dzielenia x przez 2.

W zadaniu piątym należy napisać program, który wyznaczy mniejszą z liczb x, y i ustali, czy jest to x, czy y.

0 I(3, 1, 4) 1 I(3, 2, 5) 2 S(3) 3 goto 0 4 S(0)

Omówione przykłady pozwalają poczynić pewne obserwacje:

1. Jeśli zmodyfikujemy pierwszy program poprzedając go testowaniem, czy z[1] > z[2] (ostatni przykład), to otrzymamy program P obliczający funkcję x ÷ y =

( x − y gdy x ­ y 0 gdy x < y .

2. Wtedy do obliczania funkcji x ÷ 1 można wykorzystać program P uru- chamiając go na parze danych (x, 1) czyli podstawiając z[2] := 1.

3. Z drugiej strony wiedząc, że funkcja x ÷ 1 jest RAM-obliczalna (przy- kład 2.) możemy tak jak w przykładzie 1. posłużyć się matematyczną rekurencyjną definicją:

x ÷ 0 = x

x ÷ (y + 1) = (x ÷ y) ÷ 1

którą łatwo wykorzystamy do napisania innego programu obliczającego tę funkcję.

Obserwacje te zbierzemy w następnych twierdzeniach.

(8)

Twierdzenie 1.5 (O podstawianiu) Niech f ∈ Cka g1, . . . , gk∈ Cn. Wte- dy funkcja h(x) ' f (g1(x), ..., gk(x)) ∈ Cn.

Idea dowodu Niech g1, . . . , gkbędą obliczane przez programy P1, . . . , Pk odpowiednio. Rozważmy program F obliczający f . Możemy wyznaczyć licz- bę ρ(F ) będącą numerem takiej komórki pamięci, że F nie używa jej ani komórek o numerach wyższych. Wtedy programy Pi możemy wykorzystać do stworzenia procedur wywoływanych ”na boku” (działających w obszarze komórek o numerach większych równych od max{ρ(F ), k + 1} i zwracających wynik do komórek z[i], i = 1 . . . k. Następnie wystarczy uruchomić F na tych danych.

Podstawianie pozwala wprowadzać nieistotne argumenty i je utożsamiać:

jeśli f ∈ C2, to g(x) = f (x, x), h(x, y, z) = f (x, z) są obliczalne.

Rekursja to sposób zadania kolejnej wartości funkcji poprzez wartości wcześniej obliczone.

Twierdzenie 1.6 (O operatorze rekursji) Niech f (x) ∈ Cn i g(x, y, z) ∈ Cn+2. Wtedy funkcja h(x, y) : Nn+1 −→ N określona układem

(Rek) h(x, 0) ' f (x)

h(x, y + 1) ' g(x, y, h(x, y)) jest obliczalna (h ∈ Cn+1).

Przykład

1. W definicji dodawania użyto operatora rekursji do funkcji: f (x) = 0, g(x, y, z) = z + 1. Wykorzystując procedury obliczające funkcje f, g łatwo napisać program obliczający h, będzie to prosta pętla.

2. W definicji odejmowania użyto operatora rekursji do funkcji: f (x) = x, g(x, y, z) = z ÷ 1.

3. Jaką funkcję definiuje operator rekursji zastosowany do funkcji f (x) = 1, g(x, y, z) = z ∗ (y + 1)? Oczywiście h(x, y) = y!. Ponieważ x jest tu zmienną nieistotną taką definicję przez rekursję będziemy zapisywać

h(0) ' 1

h(y + 1) ' g(y, h(y))

(9)

i traktować h jak funkcję jednoargumentową.

Ważne przykłady funkcji RAM-obliczalnych 1. Dodawanie x + y;

2. Mnożenie x · y można zdefiniować przez rekursję wykorzystując doda- wanie: x · 0 = 0; x · (y + 1) = x · y + x. Uwaga: do schematu rekursji dobieramy za f funkcję stałą zero, za g(x, y, z) = z + x.

3. Potęgowanie podobnie definiuje się przez rekursję wykorzystujac mno- żenie: x0 = 1; xy+1 = xy · x.

4. Odejmowanie x ÷ y

Pozostałe przykłady są zebrane w poniższej tabeli.

Funkcja Schemat

sg(x) =

n 0 gdy x = 0

1 gdy x > 0

sg(0) = 0 sg(x + 1) = 1 sg(x) =

n 1 gdy x = 0

0 gdy x > 0 sg(x) = 1 ÷ sg(x)

|x − y| |x − y| = (x ÷ y) + (y ÷ x)

x! ćwiczenie

min(x, y) min(x, y) = x ÷ (x ÷ y)

max(x, y) max(x, y) = x + (y ÷ x)

rm(x, 0) = 0 rm(x, y + 1) =

n 0 rm(x, y) + 1 = x rm(x, y) + 1 rm(x, y) + 1 6= x

rm(x, 0) = 0 rm(x, y + 1) =

(rm(x, y) + 1)sg(|x − (rm(x, y) + 1)|) g(x, y, z) = (z + 1)sg(|x − z + 1)|) qt(x, 0) = 0

qt(x, y + 1) =

n qt(x, y) + 1 rm(x, y) + 1 = x qt(x, y) rm(x, y) + 1 6= x

g(x, y, z) = z + sg(|x − rm(x, y) + 1)|)

div(x, y) =

n 1 x|y

0 x 6 |y div(x, y) = sg(rm(x, y))

Dla f (x, y) : Nn+1 −→ N połóżmy: g(x) ' µ y (f (x, y) = 0) ' najmniejsze y takie, że f (x, z) jest określona dla wszystkich z ¬ y i f (x, y) = 0; gdy takie y nie istnieje wartość funkcji pozostaje nieokreślona. Operator µ nazywamy operatorem minimalizacji; zwany jest też operatorem wyszukiwania.

Twierdzenie 1.7 (O operatorze minimalizacji) Jeśli f ∈ Cn+1, to g ∈ Cn.

(10)

Dowód Załóżmy, że f jest obliczana przez program F. Wtedy podany pro- gram G oblicza funkcję g, o ile procedura F [. . .] pobiera dane ze wskazanych komórek i używa tylko komórek o numerach większych od n + 2.

p F[1, ..., n, n + 1 → 0]

I(0, n + 2, q) S(n + 1) I(1, 1, p) q T(n + 1, 0)

1.2 Maszyny Turinga

Wprowadziliśmy jedną formalizację pojęcia algorytmu: algorytm to program na maszynę RAM. W podsumowaniu zanotujmy, że ostatnie twierdzenia mó- wią, że zbiór funkcji RAM-obliczalnych ma matematyczną strukturę: zawiera proste funkcje arytmetyczne i jest domknięty na postawianie rekursję i mini- malizację. Moglibyśmy je wykorzystać do wykazania, że C jest najmniejszym zbiorem funkcji o tych własnościach. Taką definicję funkcji obliczalnych za- proponował Kleene i nazwał te funkcje częściowo rekurencyjnymi. Było to w latach 50-tych. Inną formalizację (rachunek lambda) zaproponował Church.

Mniej więcej w tym samym czasie (praca Churcha ukazała się w 1936. roku a Turinga w 1937.) Alan Turing wprowadził pojęcie maszyny i funcji obli- czanej przez tę maszynę. Wobec pracy Churcha stanął on przed problemem równoważności tych pojęć. Udowodnił on ich równoważność konstruując ma- szynę uniwersalną. Maszynami/programami uniwersalnymi zajmiemy się w rozdziale następnym. Mając pewną wiedze techniczną na temat budowy kom- putera trudno przyjąć model rozważany wcześniej. Należy też uświadomoć sobie, że prosty pomysł łatwiej zrealizować technicznie. Tę zaletę ma definicja Turinga. Po pierwsze, w tamtych czasach znane były urządzenia mechanicz- nie realizujące żmudne algorytmy takie jak maszyny szyfrujące czy różnicowe.

Po drugie, były one (w najlepszym wypadku) urządzeniami elektrycznymi a nie elektronicznymi. Model Turinga (jedna maszyna) rozwiązuje jeden pro- blem wykonując bardzo proste operacje. Maszyna ta ma nieskończoną taśmę (pamięci) podzieloną na komórki, w których może znajdować się co najwyżej jeden symbol ze skończonego zbioru. Ma też głowicę, która obserwuje do- kładnie jedną komórkę i skończony zbiór stanów. Na postawie tych dwóch informacji (stan, litera) podejmuje decyzję jaką literę umieścić w komórce, jaki ruch wykonać i w jaki stan wejść.

(11)

Definicja 1.8 Jednotaśmową maszyną Turinga nazywamy trójkę < S, Q, P >, gdzie Q jest skończonym alfabetem symboli taśmowych, S skończonym zbio- rem stanów rozłącznym z Q, a P skończonym zbiorem instrukcji postaci:

stan1 litera 1 → litera2 ruch stan2. Matematycznie

P ⊆ S × (Q ∪ {B}) × (Q ∪ {B}) × {L, R, } × S

gdzie B jest nowym symbolem zwanym blank oznaczającym, że komórka jest pusta, a litery L, R, odpowiadają ruchom w lewo, w prawo i w miejscu.

Wejściem dla maszyny będzie dowolne słowo nad alfabetem Q, analizowane od pierwszej litery i początkowego stanu q0. Kolejny etap tej analizy nazywać będziemy konfiguracją.

Definicja 1.9 Niech M =< S, Q, P > będzie ustaloną maszyną Turinga.

1. Konfiguracją M nazywamy każde słowo postaci uqw, gdzie u, w są sło- wami nad alfabetem Q∪{B}, a q jest stanem: u, w ∈ (Q∪{B})?, q ∈ S.

Uwaga Będziemy ignorować symbole puste na początku u i końcu w.

2. Dla instrukcji qa → bRq0 i konfiguracji vqaw wykonanie jej zapisujemy vqaw `M vbq0w.

Uwaga Dokończ definicję: dla instrukcji qa → bLq0 i konfiguracji vqaw...

3. Powyższe wzory definiują relację jednokrokowej zmiany konfiguracji.

Matematycznie zbiór K konfiguracji M równy jest (Q ∪ {B})? × S × (Q ∪ {B})? i `M⊆ K × K. Wtedy relację `?M⊆ K × K będącą zwrotnio- przechodnim domknięciem `M nazywamy relacją zmiany konfiguracji maszyny M .

4. Niech KF będzie zbiorem konfiguracji końcowych t.j. takich w których M nie może wykonać żadnej instrukcji:

KF = {z ∈ K ; ¬∃w∈Kz `M w}

a q0 ∈ S wyróżnionym stanem. Język LqM0 słów akceptowanych przez M przy stanie początkowym q0 definiujemy jako zbiór tych słów s, które

(12)

po umieszczeniu na taśmie słowa, ustawieniu głowicy przy przy jego pierwszej literze w stanie q0, powodują zatrzymanie maszyny:

LqM0 = {s ∈ Q? ; ∃w∈KF q0s `?M w}

Jednotaśmowa maszyna Turinga dla palindromów

Niech X = {a1, . . . , an} będzie dowolnym skończonym i niepustym alfa- betem. Rozważmy MT o instrukcjach

q0ai −→ aiRq0 szukaj prawego końca słowa q0B −→ BLq1 znalazłeś, to czego szukałeś q1ai −→ BLsi zapamiętaj, co było na końcu (ai) sia −→ aLsi a ∈ X wróć na początek (lewy koniec słowa) siB −→ BRti znalazłeś, to czego szukałeś

tiai −→ BRq0 usuń pierwszą literę, jeśli równa jest ai

Maszyna ta zawsze się zatrzyma! W stanie q1 lub ti, gdy słowo na wejściu jest palindromem; W stanie ti, gdy tak nie jest. W pierwszym przypadku na taśmie pozostaną same symbole puste B. Przyjmując powyższą definicję języka akceptowanego przez M należy dopisać instrukcje prowadzące do za- pętlenia w konfiguracjach tiaj dla i 6= j : tiaj → ti aj Po co to robić? Chyba lepiej rozpoznawać, który z tych przypadków zachodzi i móc rozstrzygać, czy słowo na wejściu jest palindromem czy nie. Wprowadźmy więc nowy stan f i instrukcje q1B −→ BLf, tiB −→ BLf .

Definicja 1.10 Niech M =< Q, S, P > będzie maszyną Turinga o wyróż- nionych: stanie początkowym q0 i zbiorze stanów końcowych F ⊆ S. Wtedy zbiór konfiguracji akceptujących KA i język akceptowany przez M przy zbio- rze stanów końcowych F definiujemy:

KA = {zqw ∈ K ; q ∈ F } LqM,F0 = {s ∈ Q? ; ∃w∈KA q0s `?M w}

Przykład sugeruje, że te dwie definicje są równoważne:

Twierdzenie 1.11 Dla dowolnej maszyny Turinga M i wyróżnionego stanu q0 istneje maszyna M0 o wyróżnionym stanie q0 i zbiorze stanów końcowych F taka, że LqM0 = LqM00,F. Dla dowolnej maszyny Turinga M0 o wyróżnionym stanie q0 i zbiorze stanów końcowych F istnieje maszyna M o wyróżnionym stanie q0 taka, że LqM0 = LqM00,F.

(13)

Maszyna Turinga obliczająca następnik słowa w porządku lek- sykograficznym

Załóżmy, że alfabet X = {a1, . . . , an} jest zbiorem uporządkowanym li- niowo: ai < ai+1.

Słowo s poprzedza t w porządku leksykograficznym, jeśli jest krótsze albo s i t są tej samej długości i s poprzedza t w porządku alfabetycznym.

Porządek leksykograficzny jest liniowy i poprawnie określone jest pojęcie następnika słowa:nast(saiakn) = sai+1ak1 nast(akn) = ak+11 .

Rozważmy MT o instrukcjach

q0ai −→ aiRq0 szukaj prawego końca słowa q0B −→ BLq1 znalazłeś, to czego szukałeś

q1an−→ a1Lq1 zastąp ostatnią na końcu pierwszą

q1ai −→ ai+1Lq2 i < n, teraz wystarczy wrócić na początek (lewy) q2ai −→ aiLq2

q2B −→ BRq to koniec

q1B −→ a1Lq2 wszystkie litery były równe an

Maszyna zawsze zatrzymuje się w stanie q, a na taśmie na prawo od gło- wicy znajduje się słowo będące następnikiem wejścia. Maszyna ta ma bardzo ważną cechę, mianowicie jest deterministyczna: do dowolnej konfiguracji może zastosować co najwyżej jedną instrukcję. Tylko takie maszyny możemy traktować jako urządzenia obliczające funkcje. Aby porównać model RAM z maszynami Turinga musimy zdecydować się na jakąś reprezentację liczb naturalnych:

Definicja 1.12 1. Niech n ∈ N będzie dowolną liczbą naturalą. Symbolem b(n) oznaczymy zapis n w systemie binarnym bez zbędnych zer.

2. Niech f : Nn 7→ N będzie dowolną funkcją częściową. Mówimy, że de- terministyczna maszyna Turinga M =< Q, S, P, F, q0 > oblicza funkcję f , jeśli:

x1,...,xn∈Ny∈N f (x1, . . . , xn) = y ⇐⇒ ∃q∈F q0b(x1)B . . . Bb(xn) `?M qb(y).

Niech Tn oznacza zbiór wszystkich n-argumentowych funkcji o tej wła- sności.

3. Niech T =Sn∈NTn oznacza zbiór wszystkich funkcji obliczanych przez maszyny Turinga.

(14)

Maszyna Turinga obliczająca resztę z dzielenia przez 3 liczby naturalnej n, operując zapisami liczb w systemie dwójkowym bez zbędnych zer

q00 −→ BRq0 wczytana liczba daje resztę 0 q01 −→ BRq1 wczytana liczba daje resztę 1 q10 −→ BRq2 mnóż przez 2 liczbę dającą resztę 1

q11 −→ BRq0 mnóż przez 2 i dodaj 1 do liczby dającej resztę 1 q20 −→ BRq1 mnóż przez 2 liczbę dającą resztę 2

q21 −→ BRq2 mnóż przez 2 i dodaj 1 do liczby dającej resztę 2 Zadanie Zdefiniuj pozostałe instrukcje MT tak, aby w konfiguracji qiB wypisywała kod liczby i.

1.3 Teza Churcha-Turinga i argumenty na jej rzecz

Przypomnijmy, że symbolem C oznaczyliśmy zbiór wszystkich funkcji RAM- obliczalnych.

Twierdzenie 1.13 C = T .

Dowód tego twierdzenia prowadzi się zwykle pokazując, że każdy z tych zbiorów równy jest zbiorowi wszystkich funkcji cześciowo rekurencyjnych, czyli (przypomnijmy) najmniejszemu zbiorowi funkcji zawierających funkcje f (x) = 0, s(x) = x + 1, prin(x1, . . . , xn) = xi gdzie n ­ 1, 1 ¬ i ¬ n, i domkniętemu na podstawianie, rekursję i minimalizację. Powrócimy do tego zagadnienia omawiając funkcje uniwersalne.

TEZA CHURCHA-TURINGA Intuicyjnie i nieformalnie określona klasa funkcji obliczalnych pokrywa się z klasą funkcji (RAM) obliczalnych

(C) T .

Oczywiście teza ta nie jest matematycznym twierdzeniem, są jednak ważkie argumenty na jej rzecz:

1. Różne formalizacje prowadzą do tej samej klasy funkcji.

2. Szeroka klasa funkcji zawiera się w C.

3. Realizacja programu P , maszyny Turinga M jest oczywistym przykła- dem algorytmu.

(15)

Przyjmując te argumenty często nie prowadzi się dowodów zbyt formalnie.

Zadanie Niech f, g, c ∈ C1 będą obliczalne. Rozważmy funkcję h(x) =

( f (x) c(x) = 1 g(x) c(x) 6= 1

Zastanówmy się czy jest ona obliczalna? W języku programowania wysokiego poziomu definicja ta odpowiada instrukcji if c(x)=1 then f(x) else g(x). Ale, czy zgodnie z tezą Churcha-Turinga możemy uznać, że h jest obliczalna?

Jeśli funkcja c jest totalna oczywiście tak, ale gdy program obliczający c na danej x nie zatrzymuje się? Tym zagdanieniem zajmiemy się w dalszej części wykładu.

1.4 Efektywne numeracje programów

W rozdziale tym zgłębimy oczywistą obserwację, że RAM-programów jest przeliczalnie wiele. Istnieją więc numeracje zbioru Π wszystkich RAM-programów.

Definicja 1.14 Niech β : N −→ Π będzie dowolną numeracją zbioru RAM- programów (czyli funkcją ”na”). Mówimy, że β jest efektywna, jeśli istnieją obliczalne funkcje d : N −→ N, kod, A : N2 −→ N takie, że dla wszelkich x ∈ N i β(x) =< i0, . . . , in> mamy:

d(x) = n;

0¬r¬nir =< kod(x, r), A(x, r) > .

F-cja d określa długość (ilość instrukcji) programu β(x), natomiast kod, A określają kody kolejnych instrukcji oraz adresy komórek, którymi one mani- pulują.

Przypomnienie: Każda instrukcja wykonywana przez maszynę RAM jest jednoznacznie określona przez swój rodzaj opisany jedną z liczb {0, 1, 2, 3}

i liczbę kodującą adresy komórek lub zawartość licznika rozkazów, którymi manipuluje. Matematycznie możemy przyjąć, że zbiór I = {0, 1, 2, 3} × N ⊂ N × N jest zbiorem wszystkich instrukcji.

Niech x ∈ N , x = 4a + k i a będzie częścią całkowitą a k resztą z dzielenia x przez cztery. Odnotujmy oczywisty lemat.

(16)

Lemat 1.15 Funkcja α : N −→ I taka, że α(x) =< k, a > jest bijektywną numeracją zbioru instrukcji.

Posłużymy się nią przy zdefiniowaniu efektywnej numeracji programów.

Rozważmy funkcję τ :Sk>0Nk −→ N taką, że

τ (a0, a1, . . . , ak−1) = 2a0+ 2a0+a1+1+ . . . + 2a0+a1+...+ak−1+k−1− 1 Jest to bijektywne kodowanie wszystkich skończonych ciągów liczb natu- ralnych. Omówimy dokładniej numerację odwrotną τ−1 , gdyż chcemy udo- wodnić lemat.

Lemat 1.16 Funkcja µ : N 7→ Π

µ(x) =< α(a0), . . . , α(an) >, gdzie τ (a0, . . . , an) = x jest efektywną numeracją programów.

Oczywiście funkcja τ−1 powiązana jest z przedstawianiem liczb natural- nych w systemie dwójkowym.

Każda liczba naturalna większa od zera jest sumą rosnących potęg dwójki, czyli dla x ∈ N :

x + 1 = 2b0 + 2b1 + . . . 2bm gdzie bi < bi+1

Wtedy wzory a0 = b0 i ai+1= bi+1− bi− 1 dla i < m opisują ciąg, którego kodem (poprzez τ ) jest liczba x.

Wyznaczanie przedstawienia x opisują podane funkcje (prymitywnie re- kurencyjne).

1. l(x) = µ(y < x)(x < 2y+1) 2. Pomocniczy ciąg

c(0, x) = qt(2, x) c(n + 1, x) = qt(2, c(n, x)) 3. Wtedy

b(0, x) = rm(2, x) b(n + 1, x) = rm(2, c(n, x))

(17)

Zauważmy, że jest to klasyczny algorytm wyznaczania zapisu liczby natural- nej x w systemie binarnym opierający się na spostrzeżeniu, iż cyfra ”jedno- ści” jest resztą z dzielenia przez 2 (b(0, x)), a następną cyfrę (od prawej!) wyznacza się podobnie biorąc zamiast x część całkowitą z tego dzielenia.

Teraz można odszukać cyfry 1 w powyższym przedstawieniu.

l1(x) = Σy¬l(x+1)sg(b(y, x + 1)) b1(0, x) = µ y ¬ l(x + 1)(b(y, x + 1) = 1)

b1(i + 1, x) = µ y ¬ l(x + 1)(b(y, x + 1) = 1 ∧ b1(i, x) < y) a1(0, x) = b1(0, x)

a1(i + 1, x) = b1(i + 1, x) − b1(i, x) − 1 x =

l1(x)

X

i=0

2a1(i,x)− 1

Dowód lematu 1.16 Wystarczy zauważyć, że d(x) = l1(x) kod(x, r) = rm(4, a1(r, x))

A(x, r) = qt(4, a1(r, x)) są poszukiwanymi funkcjami.

Przykład Wyznacz program o numerze 1253.

Ponieważ 1253 + 1 = 1254 = 210+ 27+ 26+ 25+ 22+ 2 program o numerze 1253 składa się z sześciu instrukcji o kolejnych numerach: 1, 0, 2, 0, 0, 2. Po- nieważ liczbie 0 odpowiada instrukcja Z(0), 1 odpowiada instrukcja S(0), a 2 instrukcja T (0, 0) podany program oblicza funkcję f (x) = 0.

Od tej pory używać będziemy tej numeracji i oznaczenia µ(e) = Pe, czyli Pe jest programem, który w tej numeracji otrzymał numer e. Wtedy φ(n)e jest n-argumentową funkcją obliczaną przez ten program.

Nasuwa się wiele pytań: Czy każdy program ma dokładnie jeden numer?

A funkcja obliczalna? Czy dla danej funkcji obliczalnej f istnieje procedura rozsztrzygająca, które liczby naturalne są jej numerami? itp.

Omówimy dwa twierdzenia: o parametryzacji i funkcji uniwersalnej, które dadzą matematyczne narzędzia do odpowiedzi na te pytania. Należy zazna- czyć, że każda formalizacja pojęcia algorytmu powinna mieć te własności (efektywna numeracja algorytmów-programów, tw. o parametryzacji i funk- cji uniwersalnej).

(18)

1.5 Twierdzenie o parametryzacji i funkcji uniwersal- nej

Twierdzenie o parametryzacji pozwoli m.in. odpowiedzieć na pytanie: czy dla danej funkcji f ∈ C2o numerze e można efektywnie wyznaczyć dla dowolnego parametru a ∈ N numer funkcji f (a, )?

Twierdzenie to jest nieco ogólniejsze.

Twierdzenie 1.17 (O parametryzacji, s-m-n ) Dla dowolnych liczb na- turalnych n, m ­ 1 istnieje totalna i obliczalna funkcja smn : N1+m −→ N taka, że

e∈Na∈Nm φ(m+n)e (a, ) ' φ(n)sm n(e,a)( )

Dowód, szkic Dla prostoty założymy, że n = m = 1 i będziemy swo- bodnie używać tych oznaczeń.

Niech e, a ∈ N . Przez Πe,a oznaczymy program powstały z Pe poprzez mo- dyfikacje:

1. na początku umieszczamy ciąg instrukcji T(1,2), Z(1), S(1), . . . , S(1);

przy czym instrukcja S(1) występuje a-razy;

2. potem następuje tekst programu Pe ze zmodyfikowanymi instrukcjami warunkowymi.

Z konstrukcji wynika, że

φ(2)e (a, y) ' φ(1)Πe,a(y)

Pozostaje zauważyć, że µ(m) = Πe,a ⇐⇒ s11(e, a) = m.

Zadanie Sformalizuj powyższy dowód.

Wróćmy do początkowych rozważań.

Wniosek 1.18 Niech n, m ­ 1 i ψ ∈ Cn+mbędzie dowolną funkcją obliczalną n + m-argumentową. Wtedy istnieje totalna funkcja obliczalna f ∈ Cm taka, że

a∈Nm ψ(a, ) ' φ(n)f (a)( )

Dowód Niech e będzie jakimkolwiek numerem ψ. Za f wystarczy wziąć smn(e, ).

Niech n > 0 będzie ustaloną liczbą naturalną.

(19)

Definicja 1.19 Funkcją uniwersalną dla n-argumentowych funkcji RAM- obliczalnych nazywamy funkcję Ψ(n)U : Nn+1 −→ N taką, że:

e∈Nx∈NnΨ(n)U (e, x) ' φ(n)e (x)

Twierdzenie 1.20 (O funkcjach uniwersalnych) Każda funkcja uniwer- salna jest częściowo-rekurencyjna, a więc i RAM-obliczalna.

Definicja 1.21 Każdy program obliczający funkcję uniwersalną nazywamy programem uniwersalnym.

Zanim przystąpimy do omówienia programu uniwersalnego przypomnij- my, że każdy program P na maszynę RAM manipuluje tylko ustaloną skoń- czoną liczbą komórek i numery tych komórek są znane maszynie przy urucha- mianiu programu. Oznacza to, że dowolna konfiguracja z RAM matematycz- nie patrząc jest funkcją z : N ∪ {L} 7→ N , która każdemu numerowi komórki pamięci i licznikowi rozkazów L przyporządkowuje jej/jego zawartość i która dla prawie wszystkich argumentów przyjmuje wartość zero; tak więc wzór

cod(z) = 2z[L]3z[0]5z[1]. . .

jest poprawny (prawie wszystkie czynniki są równe 1) i koduje w sposób różnowartościowy dowolą konfigurację RAM.

Zarys Programu uniwersalnego Dla danej liczby e istnieje procedura wyznaczania kolejnych instrukcji programu Pe. Program uniwersalny dla nu- meru e, ciągu danych x długości n i kroku obliczeń k pamięta liczbę σn(e, x, k) będącą kodem konfiguracji uzyskanej w k-tym kroku obliczeń programu Pe na danych x, potrafi wyznaczyć zawartość licznika rozkazów m, odszukać instrukcję o numerze m w Pe i ją wykonać, jeśli to możliwe, czyli m jest niewiększe od mumeru l(e) ostatniej instrukcji Pe. Jeśli m ­ l(e) + 1 oblicze- nia się kończą. Oczywiście σn(e, x, 0) jest kodem konfiguracji początkowej, w której ciąg x jest umieszczony w komórkach z[1], . . . , z[n] a licznik rozkazów ustawiony jest na 0.

1.6 Rozstrzygalność i częściowa rozstrzygalność

W rozdziale tym wykorzystamy twierdzenia o parametryzacji i funkcji uni- wersalnej do pokazania ograniczeń teorii, którą zbudowaliśmy. Wykażemy, że wiele problemów jest nierozstrzygalnych.

(20)

Definicja 1.22 Dany jest dowolny zbiór A ⊆ Nn ciągów ustalonej długości n ∈ N .

1. Problem x ∈ A nazywamy rozstrzygalnym, jeśli funkcja charakterystycz- na zbioru A

cA(x) =

( 1 x ∈ A 0 x 6∈ A jest RAM-obliczalna.

2. Problem x ∈ A nazywamy częściowo rozstrzygalnym, jeśli częściowa funkcja charakterystyczna zbioru A

ccA(x) =

( 1 x ∈ A

∞ x 6∈ A jest RAM-obliczalna.

Program obliczający cA nazywamy procedurą rozstrzygającą dla x ∈ A, natomiast obliczający ccA sprawdzającą dla x ∈ A. Będziemy też mówili, że problemy innej natury np. φx = 0 są (nie)rozstrzygalne, gdy funkcja charak- terystyczna odpowiadającego im zbioru jest (nie)obliczalna; w przykładzie jest to zbiór numerów tych programów, które obliczają funkcję tożsamościo- wo równą zero.

Najpierw zauważmy, że istnieją funkcje np. jednoargumentowe, które nie są RAM obliczalne. Jest dosyć oczywiste, gdyż programów jest przeliczalnie wiele, a takich funkcji jest dużo więcej. Ciekawszym jest to, że ważne funkcje mające elegancką definicję matematyczną nie są obliczalne.

1.7 Metoda Cantora

Wprowadźmy oznaczenia :

1. φ(n)e oznacza funkcję n-argumentową obliczaną przez program o nume- rze e;

2. Wenoznacza dziedzinę tej funkcji, czyli zbiór wszystkich ciągów danych, na których ten program się zatrzymuje;

3. Een oznacza zbiór wartości tej funkcji;

(21)

Gdy górny indeks równy jest 1 będziemy go pomijać. Rozważmy funkcję:

f (x) =

( φx(x) + 1 x ∈ Wx

0 x 6∈ Wx

Przypuśćmy, że jest ona obliczana przez program o numerze e ∈ N : f = φe. Wtedy

φe(e) = f (e) =

( φe(e) + 1 e ∈ We

0 e 6∈ We

Ponieważ drugi przypadek nie zachodzi (f jest totalna) otrzymujemy, że φe(e) = φe(e) + 1, co oznacza, że f nie jest obliczana przez ten program.

Wobec dowolności e otrzymujemy, że f nie jest obliczalna.

Powyższa matoda została wprowadzona przez Cantora przy dowodzeniu, że zbiór wszystkich podzbiorów N nie jest przeliczalny. Podobnie udowodni- my następne twierdzenie.

Twierdzenie 1.23 Problem ”φx jest totalna” jest nierozstrzygalny.

Dowód( Nie wprost) Przypuśćmy, że funkcja

c(x) =

( 1 φx totalna

0 φx nie jest totalna jest obliczalna. Wtedy obliczalna jest funkcja

t(x, y) =

( ΨU(x, y) c(x) = 1

0 c(x) = 0

Z określenia każda funkcja totalna f ∈ C1 jest postaci t(e, ) dla pewnego e. Rozważmy fukcję g(x) = t(x, x) + 1, która oczywiście jest totalna i obli- czalna. Przypuśćmy, że g(x) = t(i, x); wtedy g(i) = t(i, i) ( z definicji t) i g(i) = t(i, i) + 1 (z definicji g), co daje sprzeczność.

Można udowodnić, że każdy problem rozstrzygalny A jest częściowo roz- strzygalny np. prowadząc do zapętlenia procedurę rozstrzygającą dla A, gdy ta zwróci 0. Nie jest odwrotnie! Rozważmy zbiór/problem

K = {x ∈ N ; x ∈ Wx},

(22)

który jest częściowo rozstrzygalny, gdyż wystarczy zmodyfikować program uniwersalny dla funkcji 1-argumentowych na danych (x, x) tak, aby zwra- cał po zatrzymaniu wartość jeden. Jest to jeden z ważniejszych problemów nierozstrzygalnych.

Twierdzenie 1.24 Problem x ∈ K jest nierozstrzygalny.

Dowód(nie wprost) Przypuśćmy, że funkcja cK jest obliczalna. Rozważmy funkcję

g(x) =

( 0 cK(x) = 0

∞ cK(x) = 1

Z tezy Churcha-Turinga jest ona obliczalna. Niech m ∈ N będzie numerem pewnego programu obliczającego g, wtedy

m ∈ Wm ⇐⇒ m ∈ Domg ⇐⇒ m 6∈ Wm

co daje sprzeczność. Jako wniosek otrzymujemy

Twierdzenie 1.25 Problem stopu y ∈ Wx jest nierozstrzygalny.

Dowód Gdyby funkcja charakterystyczna zbioru A = {(x, y) ∈ N2 ; y ∈ Wx} była obliczalna, to wobec równości cK(x) = cA(x, x), problem x ∈ K byłby rozsrzygalny, co nie jest prawdą.

Podsumujmy dotychczasowe rezultaty. Niestety nie istnieje procedura roz- strzygająca dla dowolnego programu P , czy zatrzyma się on na wszystkich danych. Procedurę taką można by wykorzystać np. na etapie kompilacji i w ten sposób uwolnić się od programów pętlących się. Pokażemy też, że różne wersje problemu poprawności są nierozstrzygalne.

Uwaga Nie oznacza to, że dla konkretnego programu nie możemy ustalić, czy on jest poprawny i ma własność stopu; często nie jest to zbyt trudne zadanie.

Twierdzenie 1.26 Problem φx = 0 jest nierozstrzygalny.

Nieformalnie: nie istnieje procedura rozstrzygająca dla dowolnej liczby x ∈ N czy program Px oplicza fukcję tożsamościowo równą zero.

Dowód Rozważmy funkcję:

f (x, y) =

( 0 cK(x) = 1

∞ cK(x) = 0 =

( 0 x ∈ Wx

∞ x 6∈ Wx

(23)

Jest ona obliczalna, gdyż f (x, y) = 0 ∗ ΨU(x, x). Zastosujmy do niej wniosek 1.18. Niech g(x) będzie totalna, obliczalna i taka, że

x∈Ny∈Nf (x, y) = φg(x)(y).

Wobec definicji f otrzymujemy ∀x∈Nx ∈ Wx ⇐⇒ φg(x) = 0. Gdyby więc funkcja charakterystyczna zbioru A = {x ∈ N ; φx = 0} była obliczalna, to wobec równości cK(x) = cA(g(x)) otrzymalibyśmy, że problem x ∈ K jest rozstrzygalny, co daje sprzeczność z poprzednim twierdzeniem.

Zadanie Wykaż, że dla dowolnej funkcji h ∈ C1 problem φx = h jest nierozstrzygalny.

W dowodzie ostatniego twierdzenia sprowadziliśmy problem x ∈ K do problemu x ∈ A.

Definicja 1.27 Niech A, B ⊆ N . Mówimy, że B jest sprowadzalny do A, jeśli istnieje totalna i obliczalna fukcja g(x) taka, że

x∈Nx ∈ B ⇐⇒ g(x) ∈ A.

Wykorzystaliśmy też ważną własność problemów (częściowo) rozstrzygal- nych.

Lemat 1.28 Jeśli problem x ∈ A jest (częściowo) rozstrzygalny, a zbiór B jest sprowadzalny do A, to problem x ∈ B jest (częściowo) rostrzygalny.

Dowód Z definicji funkcji g sprowadzającej B do A mamy równość cB(x) = cA(g(x)) (ccB(x) = ccA(g(x)). Z obliczalności g i cA(ccA) wynika obliczalność cB (ccB).

Jeśli chcemy wykorzystać powyższy lemat do udowodnienia, że problem x ∈ A jest nierozstrzygalny wystarczy sprowadzić do niego pewien problem x ∈ B o którym już wykazaliśmy, że nie jest rozstrzygalny. Postąpimy tak w ostatnim przykładzie.

Przykład Dla ustalonej liczby naturalnej e ∈ N problemy;

• wejścia: e ∈ Wx;

• wyjścia: e ∈ Ex;

(24)

są nierozstrzygalne, gdyż sprowadzimy problem x ∈ Wx do każdego z tych problemów. W tym celu rozważmy funkcję:

f (x, y) =

( y x ∈ Wx

∞ x 6∈ Wx

Funkcja ta jest obliczalna i stosuje się do niej twierdzenie o parametryzacji;

niech k ∈ C1 będzie totalna i taka, że

x,y f (x, y) = φk(x)(y) czyli

x x ∈ Wx ⇔ Wk(x) = Ek(x)= N co pociąga

x x ∈ Wx ⇔ e ∈ Wk(x) ⇔ e ∈ Ek(x)

Otrzymaliśmy, że problem x ∈ Wx jest sprowadzalny zarówno do problemu wejścia jak i problemu wyjścia.

2 Teoria złożoności obliczeniowej

W rozdziale tym zajmiemy się elementami teorii złożoności obliczeniowej.

Istnieją różne miary złożoności algorytmu. Najważniejsze to czas i pamięć.

Złożoność czasową mierzy się ilością kroków obliczeń. W przypadku modeli maszynowych (RAM czy Turinga) jest to związane z wywoływaniem instruk- cji. Złożoność pamięciową mierzy się ilością komórek pamięci wykorzystywa- nych w czasie obliczenia. Wtedy możemy przyjąć, że interesują nas tylko dodatkowe koszty nie związane z umieszczeniem danych i wyników w pa- mięci. Główne rozważnia dotyczyć będą czasu. W rozdziale tym rozważać będziemy tylko maszyny Turinga. Wybór modelu jest uzasadniony:

1. tradycją;

2. konstrukcją rzeczywistych komputerów: są one raczej maszynami Tu- ringa a nie RAM;

3. istotą problemu: można wykazać, że model RAM z ustalonym skoń- czonym rozmiarem pamięci jest wystarczający w teoretycznych rozwa- żaniach;

(25)

Zacznijmy od przykładu. Rozważmy język A = {0k1k; k ­ 0}. Jak dużo po- trzebuje czasu MT, aby rozstrzygnąć, czy w ∈ A? Trzeba rozważyć konkretną maszynę M1;

M1 na łańcuchu wejściowym w:

1. sprawdza, czy w słowie w pojawia się 0 na prawo od 1; jeśli tak jest odrzuca to słowo;

2. W przeciwnym przypadku powtarza następujące czynności;

3. poszukuje od lewej do prawej pary 0 i 1 usuwając je;

4. jeśli zostały 0 po usunięciu wszystkich 1 lub 1 po usunięciu wszystkich 0, to odrzuca słowo, w przeciwnym przypadku je akceptuje.

Będziemy wyznaczać czas działania algorytmu jako funkcję rozmiaru wejścia.

W przypadku MT jest to długość słowa. Wtedy będziemy liczyć przypadek najgorszy, czyli wymagający najwięcej obliczeń.

Definicja 2.1 Niech M będzie deterministyczną MT zatrzymującą się na wszystkich wejściach. Czasem działania lub złożonością czasową M jest funkcja f : N 7→ N , gdzie f (n) jest maksymalną ilością kroków obliczeń M wykonywanych przez nią na każdym wejściu długości n. Mówimy też, że M działa w czasie f (n).

Widać, że raczej będziemu badać asymptotyczne zachowanie maszyn Turin- ga.

2.1 Notacja O

Definicja 2.2 Niech f, g : N 7→ R+ Mówimy, że f jest rzęd O(g(n)) (zapis f (n) = O(g(n)) jeśli istnieją liczby c ∈ R+, n0 ∈ N takie, że dla każdego n ­ n0 mamy: f (n) ¬ cg(n). Mówi się też, że g(n) jest asymptotycznym ograniczeniem górnym f (n).

Jasne jest, że f (n) = O(5f (n)) więc w notacji tej pomija się współczynniki.

Zadanie Niech f (n) = 5n3+ 2n2+ 22n + 4. Wykaż, że f (n) = O(n3).

Wiemy z analizy, że

limn2n2+ 22n + 4

n3 = 0

(26)

co pociąga, że n3 ­ 2n2 + 22n + 4 dla n ­ n0 (wyznacz takie n0). Wtedy 5n3+ 2n2+ 22n + 4 ¬ 6n3 dla n ­ n0.

Uwaga W tej notacji rozważając logarytmy o podstawie wiekszej od jeden podstawa jest nieważna, gdyż logan = loglogbn

ba.

Teraz oszacujmy czasową złożoność obliczeniową podanej na wstępie ma- szyny M1: dla danego na wejściu słowa długości n realizacja 1-go etapu wy- maga 2n instrukcji (czytanie od lewej do prawej i powrót na początek słowa);

2-go i 3-go polega na dwukrotnym czytaniu (2n) powtarzanym n2 razy co daje O(n2) kroków; na koniec 4-ty zrealizuje się w O(n) krokach: w sumie O(n2).

Rozważać też będziemy niedeterministyczne MT.

Definicja 2.3 Niech M będzie MT zatrzymującą się na wszystkich wej- ściach. Czasem działania lub złożonością czasową M jest funkcja f : N 7→

N , gdzie f (n) jest maksymalną ilością kroków obliczeń M wykonywanych przez nią na każdym wejściu długości n w czasie każdego przebiegu obliczeń.

Mówimy też, że M działa w czasie f (n).

Funkcja f (n) zapewnia, że każde obliczenia M na dowolnym wejściu długości n zakończą się w tym czasie.

Definicja 2.4 Niech t : N 7→ N będzie totalna. Funkcja ta definiuje dwie klasy czasowej złożoności obliczeniowej:

T IM E(t(n)) tych języków L, które są rozstrzygane prez determistyczną ma- szynę Turinga o czasowej złożoności O(t(n))

N T IM E(t(n)) tych języków L, które są rozstrzygane prez maszynę Turinga o czasowej złożoności O(t(n))

Niech

P = [

k∈N

T IM E(nk) i N P = [

k∈N

N T IM E(nk).

Bezpośrednio z definicji mamy Twierdzenie 2.5 P ⊆ N P

Stąd naturalnym jest pytanie, czy P= NP. Jemu poświęcimy ten rozdział.

Często mówi się, że problem z klasy P jest szybko rozwiązalny, a z klasy

(27)

NP szybko weryfikowalny. Jest to związane z charakterem najważniejszych problemów z NP, jak i z równoważną definicją. Problem P=NP jest jednym z siedmiu wielkich problemów milenijnych. Problemy te zostały sformułowane w czasie sesji Clay Mathematical Institute w College de France w Paryżu w maju 2000 r przez znanych uczonych J.Tate i M.Atyiaha. Za rozwiązanie każdego z tych problemów jest wyznaczona nagroda w wysokości 1 milio- na dolarów. Choć dominuje przeświadczenie, że nie jest prawdą, iż P=NP (prównaj Hopcroft, Ullman str. 419-423) nie brak też prób udowodnienia tej równości. Standardowo poszukuje się algorytmów deterministycznych o wielomianowej złożoności czasowej dla problemów NP-zupełnych.

Mam nadzieję, że nagroda miliona dolarów jest wystarczającą zachę- tą, choć i względy praktyczne są równie ważne, gdyż lista problemów NP- zupełnych jest bardzo długa i zawiera mnóstwo praktycznych (dla informaty- ków) problemów. Wystarczy tu wspomnieć o problemie całkowitoliczbowego programowania liniowego czy problemie komiwojażera.

Skupimy się na wyjaśnieniu użytych wyżej pojęć i omówieniu wagi tego problemu. Najpierw ważne twierdzenie.

Twierdzenie 2.6 Dla niedeterministycznej maszyny Turinga M o czasowej złożoności obliczeniowej f (n) takiej, że n ¬ f (n) dla wszystkich n ∈ N , istnieje deterministyczna maszyna Turinga M1 rozpoznająca ten sam język, której czasowa złożoność obliczeniowa jest rzędu O(cf (n)), dla pewnej liczby c > 1.

Idea konstrukcji maszyny M1. Dla ustalenia uwagi załóżmy, że M w każ- dej konfiguracji może wykonać co najwyżej dwie instrukcje. Ponieważ jest nie- deterministyczna w pewnej konfiguracji ma faktycznie wybór pomiędzy dwie- ma instrukcjami. Dokonajmy ponumerowania liczbami 0 lub 1 tych instrukcji dla takich konfiguracji. Każdy ciąg obliczeń M na wejściu długości n można wtedy opisać ciągiem zer i jedynek długości co najwyżej f (n), odpowiada- jącym wyborowi kolejnej instrukcji. Ciągów takich jest 2f (n)+1− 1. Maszynę deterministyczną M1 konstruuje się tak, aby dla wejścia długości n wyzna- czała takie ciągi w pewnym porządku (np. leksykograficznym), a następnie realizowała obliczenia M opisane przez wygenerowany ciąg. Każde z O(2f (n)) obliczeń wymaga co najwyżej f (n) kroków, a f (n)(2f (n)+1− 1) = O(4f (n))./

Można wykazać, że konstruowana w dowodzie deterministyczna MT ma dodatkową własność: jest lewostronnie ograniczona, co oznacza, że można

(28)

użyć dodatkowego znaku  początku słowa będącego na taśmie; w sytuacji, gdy głowica obserwuje ten znak niemożliwy jest ruch w lewo.

2.2 Sprowadzalność problemu ścieżki Hamiltona do pro- blemu spełnialności

Dla digrafu G=(V,E) o n wierzchołkach ponumerowanych kolejnymi liczbami naturalnymi ze zbioru {1, . . . , n} zdefiniujemy wyrażenie logiczne (funkcję zdaniową) fG o n2 zmiennych xij, którym nadamy wartość logiczną 1 wtw, gdy j-ty wierzchołek występuje na i-tej pozycji ścieżki Hamiltona.

Wtedy dla każdego digrafu G, G ma ścieżkę Hamiltona wtw, gdy wyra- żenie fG jest spełnialne.

fG jest koniunkcją wyrażeń logicznych stwierdzających:

1. Każdy wierzchołek j musi się pojawić na ścieżce: (x1j∨ x2j∨ . . . ∨ xnj), ale co najwyżej raz: (¬xkj ∨ ¬xij) dla wszystkich k 6= i;

2. Jakiś wierzchołek musi być na i-tej pozycji: (xi1∨ xi2∨ . . . xin), ale nie dwa: (¬xik∨ ¬xij) dla wszystkich k 6= j;

3. Kolejne wierzchołki muszą być połączone krawędzią: dla każdej pary (j, i) 6∈ E oraz k ∈ {1, . . . , n − 1} : (¬xkj∨ ¬xk+1i) ;

Procedura sprowadzania musi spełniać dodatkowe w-ki. Najogólniej, proces sprowadzania nie może być trudniejszy niż sam problem.

Zauważmy, że procedura sprowadzania problemu ścieżki Hamiltona do problemu spełnialności wymaga oprócz pamięci dla wejścia i wyjścia tylko przechowywania i, j. W tym sensie pamięciowa złożoność algorytmu zależy logarytmicznie od rozmiaru wejścia. Zakładać będziemy, że języki są reku- rencyjne; w związku z tym maszyny Turinga będą zawsze się zatrzymywać i do odróżnienia słów akceptowanych od odrzucanych wykorzystamy stany MT.

2.3 Redukcje

Niech L,L’ będą językami nad ustalonym alfabetem X.

(29)

Definicja 2.7 Redukcją lub sprowadzeniem języka L do L’ nazywamy funkcję R : X? −→ X?, która jest obliczalna przez deterministyczną MT w pamięci logarytmicznej i sprowadzającą L do L’:

x∈X? x ∈ L ↔ R(x) ∈ L0 Niech C będzie klasą złożoności.

Definicja 2.8 Język L ∈ C jest zupełny dla C, jeśli dla każdego L0 ∈ C istnieje redukcja L’ do L.

Twierdzenie 2.9 Niech M będzie maszyną Turinga, która jest determini- styczna i operuje pamięcią O(log n). Wtedy M ma wielomianową czasową złożoność obliczeniową.

Twierdzenie 2.10 ( COOK (1971)) Język SAT wyrażeń logicznych, któ- re są spełnialne jest zupełny w klasie NP.

Ćwiczenie Wykaż, że SAT ∈ NP.

Dowód polega na zbudowaniu w pamięci logarytmicznej dla dowolnej MT M, operującej wejściowym alfabetem X , o wielomianowej czasowej złożonoci obliczeniowej, oraz dowolnego słowa x ∈ X? wyrażenia logicznego R(x), które jest spełnialne wtw, gdy x jest akceptowane prze M.

Definicja 2.11 Wyrażenie logiczne jest w postaci normalnej koniunk- cyjnej PNK, jeżli jest koniunkcją alternatyw zmiennych lub ich zaprzeczeń.

Symbolem PNK oznaczymy zbiór wszystkich takich wyrażeń, SAT-PNK oznacza zbiór wszystkich wyrażeń w PNK, które są spełnialne.

Twierdzenie 2.12 Język SAT-PNK jest NP-zupełny.

Na zakończenie przedstawimy trzy NP-zupełne problemy grafowe.

W tym celu rozważymy język SAT-3PNK spełnialnych wyrażeń w PNK, w której każda alternatywa ma co najwyżej trzy elementy.

Zadanie Rozważmy wyrażenie logiczne f (x) = x1∨ x2∨ . . . ∨ xm, gdzie m > 3 oraz g(x, y) = (x1∨ x2∨ y1) ∧ (¬y1∨ x3∨ y2) ∧ . . . ∧ (¬ym−3∨ xm−1 xm). Wykaż, że wartościowania zmiennych x, dla których f staje się zdaniem prawdziwym, są w odpowiedniości z wartościowaniami zmiennych x, y, dla których g staje się zdaniem prawdziwym.

Twierdzenie 2.13 Język SAT-3PNK jest NP-zupełny.

Cytaty

Powiązane dokumenty

%d kod ASCII znaku, liczba całkowita char * %s łańcuch znaków, napis. char * %s łańcuch

złożone - kilka instrukcji zawartych pomiędzy nawiasami klamrowymi Typy instrukcji

jeśli wyrażenie jest prawdziwe, to wykonywana jest instrukcja1, zaś instrukcja2 nie jest wykonywana gdy wyrażenie jest fałszywe,. to wykonywana jest instrukcja2, zaś instrukcja1

prawdziwe - gdy jego wartość jest różna od zera fałszywe - gdy jego wartość. jest

Informatyka (EDS1B1007), studia stacjonarne I stopnia dr inż..

Mówimy, że zmienna ptr jest typu: wskaźnik do zmiennej typu int Do przechowywania adresu zmiennej typu double trzeba. zadeklarować zmienną typu: wskaźnik do zmiennej

Mówimy, że zmienna ptr jest typu: wskaźnik do zmiennej typu int Do przechowywania adresu zmiennej typu double trzeba. zadeklarować zmienną typu: wskaźnik do zmiennej

&#34;a+&#34; - uaktualnienie (zapis i odczyt) - dopisywanie danych na końcu istniejącego pliku, jeśli pliku nie ma to zostanie utworzony, odczyt może dotyczyć całego pliku,