Złożoność obliczeniowa/Wykład 11: Obliczenia równoległe: Różnice pomiędzy wersjami

Z Studia Informatyczne
Przejdź do nawigacjiPrzejdź do wyszukiwania
Matiunreal (dyskusja | edycje)
m Zastępowanie tekstu – „,...,” na „,\ldots,”
 
(Nie pokazano 25 wersji utworzonych przez 4 użytkowników)
Linia 9: Linia 9:
==Modele obliczeń równoległych==
==Modele obliczeń równoległych==


Najważniejsze modele obliczeń równoległych, to:
Najważniejsze modele obliczeń równoległych to:
* PRAM -- równoległa maszyna RAM
* PRAM -- równoległa maszyna RAM
* sieci procesorów o ustalonej topologii połączeń -- krata, hiperkostka i wiele innych
* sieci procesorów o ustalonej topologii połączeń: krata, hiperkostka i wiele innych,
* układy logiczne
* układy logiczne.


Podstawowym modelem do opisu algorytmów równoległych jest maszyna
Podstawowym modelem do opisu algorytmów równoległych jest maszyna
PRAM, posłużymy się nią przedstawiając równoległe rozwiązania
PRAM, posłużymy się nią, przedstawiając równoległe rozwiązania
przykładowych problemów. Technologicznie PRAM nie jest realizowalna,
przykładowych problemów. Technologicznie PRAM nie jest realizowalna,
ale abstrahuje od uwarunkowań konstrukcyjnych i pozwala wypowiadać
ale abstrahuje od uwarunkowań konstrukcyjnych i pozwala wypowiadać
Linia 27: Linia 27:
Natomiast układy logiczne stanowią dobrze zbadany model, pozwalający
Natomiast układy logiczne stanowią dobrze zbadany model, pozwalający
analizować problemy również pod kątem rozwiązań równoległych, i
analizować problemy również pod kątem rozwiązań równoległych, i
dlatego poświęcimy mu sporo miejsca. Tym bardzie, że na ogół klasy
dlatego poświęcimy mu sporo miejsca. Tym bardziej, że na ogół klasy
złożoności równoległej definuje się dla tego modelu.
złożoności równoległej definuje się dla tego modelu.


Linia 35: Linia 35:
czytelnikowi z kursu ''Zaawansowane algorytmy i struktury
czytelnikowi z kursu ''Zaawansowane algorytmy i struktury
danych''. W maszynie PRAM (ang. ''Parallel Random Access Machine''
danych''. W maszynie PRAM (ang. ''Parallel Random Access Machine''
mamy
mamy:
* nieograniczoną liczbę procesorów, każdy ma swój numer i swoje własne rejestry
* nieograniczoną liczbę procesorów; każdy ma swój numer i swoje własne rejestry,
* nieograniczoną wspólną pamięć, jak w maszynie RAM
* nieograniczoną wspólną pamięć, jak w maszynie RAM,
* mechanizm (''szynę'') umożliwiający komunikację każdego procesora z pamięcią w tym samym czasie (o konfliktach dostępu poniżej)
* mechanizm (''szynę'') umożliwiający komunikację każdego procesora z pamięcią w tym samym czasie (o konfliktach dostępu poniżej).


Najczęściej dla modelu PRAM (ale i również modelu sieci procesorów o ustalonej topologii) zakłada się, że procesory wykonują ''synchronicznie ten sam program'', operując być może na różnych danych w tej samej pamięci, ale w każdym momencie wykonując taki sam rozkaz. Odstępstwo może być tylko jedno: procesor może w danym cyklu rozkazowym nie wykonywać żadnej czynności, czyli wyłączać się na skutek spełnienia określonych warunków.
Najczęściej dla modelu PRAM (ale i również modelu sieci procesorów o ustalonej topologii) zakłada się, że procesory wykonują ''synchronicznie ten sam program'', operując być może na różnych danych w tej samej pamięci, ale w każdym momencie wykonując taki sam rozkaz. Odstępstwo może być tylko jedno: procesor może w danym cyklu rozkazowym nie wykonywać żadnej czynności, czyli wyłączać się na skutek spełnienia określonych warunków.


Opuszczając techniczne problemy przydziału procesorów do poszczególnych operacji, zapiszmy przykładowy prosty algorytm równoległy: mnożenie macierzy. Stosujemy język "work/time", w
Opuszczając techniczne problemy przydziału procesorów do poszczególnych operacji, zapiszmy przykładowy prosty algorytm równoległy: mnożenie macierzy. Stosujemy język "work/time", w
którym opisuje się pracę wykonywaną przez program w kolejnych jednostkach czasu, bez podawania dokładnie które procesory wykonuja daną czynność. Słowo kluczowe '''in-par-do''' jest skrótem od ''in parallel do''.
którym opisuje się pracę wykonywaną przez program w kolejnych jednostkach czasu, bez podawania dokładnie które procesory wykonują daną czynność. Słowo kluczowe '''in-par-do''' jest skrótem od ''in parallel do''.


{{algorytm|[Równoległe mnożenie macierzy]||
{{algorytm|[Równoległe mnożenie macierzy]||
  '''Wejście:''' Macierze <math>\displaystyle A, B</math> rozmiaru <math>\displaystyle n \times n, n=2^p</math>.
  '''Wejście:''' Macierze <math>A, B</math> rozmiaru <math>n \times n, n=2^p</math>.
  '''Wyjście:''' Iloczyn <math>\displaystyle C=AB</math>.
  '''Wyjście:''' Iloczyn <math>C=AB</math>.
  '''begin'''
  '''begin'''
  1.  '''for '''<tt>1 <<nowiki>=</nowiki> i,j,k <<nowiki>=</nowiki> n </tt> '''in-par-do'''
  1.  '''for '''<tt>1 <<nowiki>=</nowiki> i,j,k <<nowiki>=</nowiki> n </tt> '''in-par-do'''
  2.    <tt>D[i,j,k]:<nowiki>=</nowiki>A[i,k]*B[k,j]</tt>
  2.    <tt>D[i,j,k]:<nowiki>=</nowiki>A[i,k]*B[k,j]</tt>
  3.  '''for '''<tt>q<nowiki>=</nowiki>1,2,...,p </tt>'''do'''
  3.  '''for '''<tt>q<nowiki>=</nowiki>1,2,\ldots,p </tt>'''do'''
  4.    '''for '''<tt>1<<nowiki>=</nowiki>i,j<<nowiki>=</nowiki>n, 1<<nowiki>=</nowiki>k<<nowiki>=</nowiki>n/(2**q) </tt>'''in-par-do'''
  4.    '''for '''<tt>1<<nowiki>=</nowiki>i,j<<nowiki>=</nowiki>n, 1<<nowiki>=</nowiki>k<<nowiki>=</nowiki>n/(2**q) </tt>'''in-par-do'''
  5.      <tt>D[i,j,k]:<nowiki>=</nowiki>D[i,j,2k-1]+D[i,j,2k]</tt>
  5.      <tt>D[i,j,k]:<nowiki>=</nowiki>D[i,j,2k-1]+D[i,j,2k]</tt>
Linia 57: Linia 57:
  7.    {<tt>C[i,j]:<nowiki>=</nowiki>D[i,j]</tt>
  7.    {<tt>C[i,j]:<nowiki>=</nowiki>D[i,j]</tt>
  '''end'''
  '''end'''
}}


Algorytm działa na <math>\displaystyle n^3</math> procesorach, w czasie równoległym <math>\displaystyle O(\log
 
Algorytm działa na <math>n^3</math> procesorach, w czasie równoległym <math>O(\log
n)</math>. Praca jaką wykonuje jest następująca:
n)</math>. Praca jaką wykonuje jest następująca:


Krok 2: <math>\displaystyle n^3</math>
Krok 2: <math>n^3</math>.


Krok 5: <math>\displaystyle n^3/2 + n^3/4 + \ldots n^3/n = O(n^3)</math>.
Krok 5: <math>n^3/2 + n^3/4 + \ldots n^3/n = O(n^3)</math>.


Krok 7: <math>\displaystyle n^2</math>.
Krok 7: <math>n^2</math>.


W sumie <math>\displaystyle O(n^3)</math>. Jest to zatem algorytm optymalny pod względem
W sumie <math>O(n^3)</math>. Jest to zatem algorytm optymalny pod względem
pracy. Można go w łatwy sposób przekształcić tak, aby zachowana była
pracy. Można go w łatwy sposób przekształcić, tak aby zachowana była
praca oraz czas, natomiast liczba procesorów była optymalna i
praca oraz czas, natomiast liczba procesorów była optymalna i
wynosiła <math>\displaystyle O(n^3/\log n)</math>.
wynosiła <math>O(n^3/\log n)</math>.


Załóżmy teraz, że na wejściu jest kwadratowa macierz logiczna,
Załóżmy teraz, że na wejściu jest kwadratowa macierz logiczna,
<math>\displaystyle A[i,j]=1</math> oznacza, że w grafie istnieje krawędź z <math>\displaystyle i</math> do <math>\displaystyle j</math>.
<math>A[i,j]=1</math> oznacza, że w grafie istnieje krawędź z <math>i</math> do <math>j</math>.
Interesuje nas rozwiązanie problemu REACHABILITY.
Interesuje nas rozwiązanie problemu REACHABILITY.
 
}}
{{cwiczenie|2.1||
{{cwiczenie|2.1||
Naszkicuj algorytm równoległy znajdowania przechodniego domknięcia
Naszkicuj algorytm równoległy znajdowania przechodniego domknięcia
grafu. Pożądany czas równoległy i praca to odpowiednio <math>\displaystyle O(\log^2n)</math>
grafu. Pożądany czas równoległy i praca to odpowiednio <math>O(\log^2n)</math>
oraz <math>\displaystyle O(n^3\log n)</math>.
oraz <math>O(n^3\log n)</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">   
<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">   
Zastosuj algorytm mnożenia macierzy.
Zastosuj algorytm mnożenia macierzy.
Linia 88: Linia 88:
<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">   
<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">   
W algorytmie mnożenia macierzy załóż, że na wejściu jest macierz
W algorytmie mnożenia macierzy załóż, że na wejściu jest macierz
logiczna <math>\displaystyle A</math>, oraz zamień dodawanie na alternatywę, a mnożenie na
logiczna <math>A</math> oraz zamień dodawanie na alternatywę, a mnożenie na
koniunkcję. Obliczanie przechodniego domknięcia sprowadza się do
koniunkcję. Obliczanie przechodniego domknięcia sprowadza się do
obliczenia <math>\displaystyle A^n</math>. Następnie zastosuj znany Ci na pewno algorytm
obliczenia <math>A^n</math>. Następnie zastosuj znany Ci na pewno algorytm
potęgowania, obliczający <math>\displaystyle x^k</math> za pomocą <math>\displaystyle O(\log k)</math> mnożeń.
potęgowania obliczający <math>x^k</math> za pomocą <math>O(\log k)</math> mnożeń.
</div></div>
</div></div>
}}


===Obwody logiczne===
===Obwody logiczne===


Owody logiczne poznaliśmy już w module 2. Przekonaliśmy się, że
Obwody logiczne poznaliśmy już w module 2. Przekonaliśmy się, że
stanowią uniwersalny model obliczeń: mogą symulować maszyne Turinga.
stanowią uniwersalny model obliczeń: mogą symulować maszynę Turinga.
Ta własność, a jeszcze bardziej jej dowód, przyda nam się podczas
Ta własność, a jeszcze bardziej jej dowód, przyda nam się podczas
omawiania klas złożoności dla obliczeń równoległych.
omawiania klas złożoności dla obliczeń równoległych.
Linia 122: Linia 121:


{{cwiczenie|2.2||
{{cwiczenie|2.2||
Napisz algorytm, który dla zadanego grafu <math>\displaystyle G=(V,E)</math> skierowanego
Napisz algorytm, który dla zadanego grafu <math>G=(V,E)</math> skierowanego
acyklicznego wylicza długość <math>\displaystyle d</math> najdłuższej ścieżki w tym grafie
acyklicznego wylicza długość <math>d</math> najdłuższej ścieżki w tym grafie
oraz dzieli zbiór wierzchołków <math>\displaystyle V</math> na <math>\displaystyle d+1</math> podzbiorów
oraz dzieli zbiór wierzchołków <math>V</math> na <math>d+1</math> podzbiorów
<math>\displaystyle V_0,\ldots,V_d</math> takich, że dla każdego <math>\displaystyle i</math>, <math>\displaystyle V_i</math> jest zbiorem
<math>V_0,\ldots,V_d</math> takich, że dla każdego <math>i</math>, <math>V_i</math> jest zbiorem
niezależnym, oraz dla każdej krawędzi <math>\displaystyle (u,v)</math> w <math>\displaystyle G</math>, jeśli <math>\displaystyle u\in
niezależnym oraz dla każdej krawędzi <math>(u,v)</math> w <math>G</math>, jeśli <math>u\in
V_i, v\in V_j</math>, to <math>\displaystyle i<j</math>.
V_i, v\in V_j</math>, to <math>i<j</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">   
<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">   
Posortuj topologicznie graf <math>\displaystyle G</math>.
Posortuj topologicznie graf <math>G</math>.
</div></div>
</div></div>


Linia 138: Linia 137:
# Obwód logiczny ma ściśle określoną liczbę bramek, a więc rozpoznaje instancje ściśle określonego rozmiaru. Dla innego rozmiaru danych obwód może mieć zupełnie inną "logikę budowy".
# Obwód logiczny ma ściśle określoną liczbę bramek, a więc rozpoznaje instancje ściśle określonego rozmiaru. Dla innego rozmiaru danych obwód może mieć zupełnie inną "logikę budowy".


Aby upodobnić pod tym względem obwody logiczne do innych modeli, nakładamy dodatkowo wymaganie, aby struktura obwodu dla coraz większych rozmiarów danych była obliczalna.
Aby upodobnić pod tym względem obwody logiczne do innych modeli, nakładamy dodatkowo wymaganie, by struktura obwodu dla coraz większych rozmiarów danych była obliczalna.
}}
 


{{definicja|2.3||
{{definicja|2.3||
Rodzina <math>\displaystyle (W_1,W_2,\ldots)</math> obwodów logicznych jest ''jednostajna'', jeśli istnieje maszyna Turinga <math>\displaystyle M</math> o złożoności
Rodzina <math>(W_1,W_2,\ldots)</math> obwodów logicznych jest ''jednostajna'', jeśli istnieje maszyna Turinga <math>M</math> o złożoności
pamięciowej <math>\displaystyle O(\log n)</math>, która dla danych wejściowych postaci <math>\displaystyle 1^n</math>
pamięciowej <math>O(\log n)</math>, która dla danych wejściowych postaci <math>1^n</math>
generuje <math>\displaystyle W_n</math>.
generuje <math>W_n</math>.
}}
}}


Linia 151: Linia 150:
rozwiązać problem nierozstrzygalny! Na przykład, nierozstrzygalny
rozwiązać problem nierozstrzygalny! Na przykład, nierozstrzygalny
jest język unarny (czyli o słowach nad alfabetem jednoelementowym)
jest język unarny (czyli o słowach nad alfabetem jednoelementowym)
<math>\displaystyle L=\{1^{<M,w>} : </math> M akceptuje w <math>\displaystyle  \}</math> (<math>\displaystyle <M,w></math> oznacza kod
<math>L=\{1^{<M,w>} : </math> M akceptuje w <math>\}</math> (<math><M,w></math> oznacza kod
binarny maszyny M i słowa wejściowego w). Układy dla poszczególnych
binarny maszyny M i słowa wejściowego w). Układy dla poszczególnych
<math>\displaystyle n</math> są zbudowane w ten sposób, że jeśli <math>\displaystyle 1^n \in L</math>, to układ
<math>n</math> są zbudowane w ten sposób, że jeśli <math>1^n \in L</math>, to układ
oblicza koniunkcję wszystkich wejść, więc akceptuje tylko gdy są to
oblicza koniunkcję wszystkich wejść, więc akceptuje tylko wtedy, gdy są to
same jedynki, a dla <math>\displaystyle 1^n \notin L</math> ma dodatkową bramkę wyjściową
same jedynki, a dla <math>1^n \notin L</math> ma dodatkową bramkę wyjściową
generującą zero i żadnych innych połączeń (ignoruje wejście). Nie
generującą zero i żadnych innych połączeń (ignoruje wejście). Nie
potrafimy obliczać takich układów dla wszystkich <math>\displaystyle n</math>, ale wiemy że
potrafimy obliczać takich układów dla wszystkich <math>n</math>, ale wiemy, że
one istnieją!
one istnieją!
}}
}}
Linia 164: Linia 163:
Skonstruuj obwód logiczny, możliwie o najmniejszej głębokości,
Skonstruuj obwód logiczny, możliwie o najmniejszej głębokości,
rozwiązujący problem REACHABILITY.
rozwiązujący problem REACHABILITY.
 
}}
<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">   
<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">   
Najprościej jest wykorzystać algorytm równoległy obliczania
Najprościej jest wykorzystać algorytm równoległy obliczania
Linia 173: Linia 172:
<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">   
<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">   
Algorytm ma tę własność, że niezależnie od wyników obliczeń
Algorytm ma tę własność, że niezależnie od wyników obliczeń
dotychczasowych obliczenia następne wykonywane są zawsze dla takich
dotychczasowych, obliczenia następne wykonywane są zawsze dla takich
samych danych (własność niewrażliwości na dane, ang. ''oblivious''. Ponieważ jedyne operacje na danych to alternatywa i
samych danych (własność niewrażliwości na dane, ang. ''oblivious''. Ponieważ jedyne operacje na danych to alternatywa i
koniunkcja, więc algorytm, będący kolejnymi wywołaniami procedury
koniunkcja, więc algorytm, będący kolejnymi wywołaniami procedury
mnożenia macierzy, można zapisać jako wielopiętrowy układ logiczny,
mnożenia macierzy, można zapisać jako wielopiętrowy układ logiczny,
o głębokości równej złożoności algorytmu, czyli <math>\displaystyle O(\log^2n)</math>.
o głębokości równej złożoności algorytmu, czyli <math>O(\log^2n)</math>.
</div></div>
</div></div>
}}


==Klasy złożoności==
==Klasy złożoności==
Linia 189: Linia 187:
procesorów. O problemie mówimy, że można go ''efektywnie
procesorów. O problemie mówimy, że można go ''efektywnie
zrównoleglić'', jeśli ten problem posiada efektywny algorytm
zrównoleglić'', jeśli ten problem posiada efektywny algorytm
równoległy. Formalnie definiujemy takie algorytmy wprowadzając klasę
równoległy. Formalnie definiujemy takie algorytmy, wprowadzając klasę
NC.
NC.


{{definicja|3.1||
{{definicja|3.1||
Dla <math>\displaystyle n\geq 1</math> klasa <math>\displaystyle N^i</math> to zbiór języków <math>\displaystyle L</math> takich, że <math>\displaystyle L</math> jest
Dla <math>n\geq 1</math> klasa <math>N^i</math> to zbiór języków <math>L</math> takich, że <math>L</math> jest
akceptowany przez jednostajną rodzinę układów logicznych rozmiaru
akceptowany przez jednostajną rodzinę układów logicznych rozmiaru
wielomianowego i głębokości <math>\displaystyle O(\log^in)</math>. Przyjmujemy oznaczenie
wielomianowego i głębokości <math>O(\log^in)</math>. Przyjmujemy oznaczenie
<math>\displaystyle NC=\bigcup_{j>0}NC^i</math>.
<math>NC=\bigcup_{j>0}NC^i</math>.
}}
}}


Linia 205: Linia 203:


{{twierdzenie|3.2||
{{twierdzenie|3.2||
<math>\displaystyle NC^1\subseteq L</math>.
<math>NC^1\subseteq L</math>.
}}
}}


Linia 211: Linia 209:


{{twierdzenie|3.3||
{{twierdzenie|3.3||
<math>\displaystyle NL\subseteq NC^2</math>.
<math>NL\subseteq NC^2</math>.
}}
}}


{{dowod|||
{{dowod|||
Niech <math>\displaystyle L</math> bedzie językiem nad alfabetem 0,1 akceptowanym przez
Niech <math>L</math> będzie językiem nad alfabetem 0,1 akceptowanym przez
niedeterministyczna maszynę <math>\displaystyle M</math> o złożoności pamięciowej <math>\displaystyle \log n</math>.
niedeterministyczna maszynę <math>M</math> o złożoności pamięciowej <math>\log n</math>.
Aby wykazać, że istnieje jednostajna rodzina obwodów logicznych
Aby wykazać, że istnieje jednostajna rodzina obwodów logicznych
<math>\displaystyle (W_1,W_2,\dots)</math> akceptujących <math>\displaystyle L</math>, o głębokości <math>\displaystyle O(\log^2n)</math>,
<math>(W_1,W_2,\dots)</math> akceptujących <math>L</math>, o głębokości <math>O(\log^2n)</math>,
należy skonstruować maszynę Turinga <math>\displaystyle M</math>, działająca w pamięci
należy skonstruować maszynę Turinga <math>M</math>, działająca w pamięci
logarytmicznej, która dla słowa wejściowego <math>\displaystyle 1^n</math> generuje obwód
logarytmicznej, która dla słowa wejściowego <math>1^n</math> generuje obwód
<math>\displaystyle W_n</math> akceptujący zbiór <math>\displaystyle L\cap\{0,1\}^n</math>. Najpierw opisujemy
<math>W_n</math> akceptujący zbiór <math>L\cap\{0,1\}^n</math>. Najpierw opisujemy
procedury składowe:
procedury składowe:
# Generowanie grafu konfiguracji <math>\displaystyle G</math>. Konfiguracja składa się ze stanu, zawartości taśmy roboczej i położenia głowic na obu taśmach. Nie zawiera ona zawartości taśmy wejściowej, zatem wierzchołki tego grafu zależą, przy ustalonej <math>\displaystyle M</math>, tylko od <math>\displaystyle n</math>.<br> Niech <math>\displaystyle u,v</math> będą różnymi konfiguracjami, przy czym <math>\displaystyle u</math> zawiera pozycję <math>\displaystyle j</math> na taśmie wejściowej. Definiujemy krawędź <math>\displaystyle (u,v) </math> w <math>\displaystyle G</math>, jeśli <math>\displaystyle v</math> może być osiągnięta z <math>\displaystyle u</math> w 1 ruchu <math>\displaystyle M</math>. Jeśli przejście z <math>\displaystyle u</math> do <math>\displaystyle v</math> ma miejsce tylko gdy <math>\displaystyle i</math>-ty bit wejściowego słowa jest równy 1, to etykietujemy tę krawędź jedynką, jeśli tylko dla 0, to zerem, a jeśli niezależnie od tego bitu, to etykieta jest pusta. Wynikiem jest lista wierzchołków i lista krawędzi, z etykietami.<br> Ponieważ liczba możliwych konfiguracji maszyny <math>\displaystyle M</math> wynosi <math>\displaystyle O(n)</math>, więc skonstruowanie takiego grafu jest wykonalne w pamięci logarytmicznej.
# Generowanie grafu konfiguracji <math>G</math>. Konfiguracja składa się ze stanu, zawartości taśmy roboczej i położenia głowic na obu taśmach. Nie zawiera ona zawartości taśmy wejściowej, zatem wierzchołki tego grafu zależą, przy ustalonej <math>M</math>, tylko od <math>n</math>.<br> Niech <math>u,v</math> będą różnymi konfiguracjami, przy czym <math>u</math> zawiera pozycję <math>j</math> na taśmie wejściowej. Definiujemy krawędź <math>(u,v)</math> w <math>G</math>, jeśli <math>v</math> może być osiągnięta z <math>u</math> w 1 ruchu <math>M</math>. Jeśli przejście z <math>u</math> do <math>v</math> ma miejsce tylko gdy <math>i</math>-ty bit wejściowego słowa jest równy 1, to etykietujemy tę krawędź jedynką, jeśli tylko dla 0, to zerem, a jeśli niezależnie od tego bitu, to etykieta jest pusta. Wynikiem jest lista wierzchołków i lista krawędzi, z etykietami.<br> Ponieważ liczba możliwych konfiguracji maszyny <math>M</math> wynosi <math>O(n)</math>, więc skonstruowanie takiego grafu jest wykonalne w pamięci logarytmicznej.
# Konstrukcja obwodu logicznego obliczającego przechodnie domknięcie grafu <math>\displaystyle H</math> o <math>\displaystyle p</math> wierzchołkach. Bramek wejściowych jest <math>\displaystyle p^2</math> i każda informuje o istnieniu lub nie jednej krawędzi. Problem przechodniego domknięcia należy do <math>\displaystyle NC^2</math>, o czym przekonaliśmy się analizując algorytm równoległy w modelu PRAM dla tego problemu. Zatem procedura 2 działa w pamięci logarytmicznej od rozmiaru grafu.
# Konstrukcja obwodu logicznego obliczającego przechodnie domknięcie grafu <math>H</math> o <math>p</math> wierzchołkach. Bramek wejściowych jest <math>p^2</math> i każda informuje o istnieniu - lub nie - jednej krawędzi. Problem przechodniego domknięcia należy do <math>NC^2</math>, o czym przekonaliśmy się, analizując algorytm równoległy w modelu PRAM dla tego problemu. Zatem procedura 2 działa w pamięci logarytmicznej od rozmiaru grafu.


  Maszyna Turinga <math>\displaystyle M</math> generująca obwód <math>\displaystyle W</math> o <math>\displaystyle n</math> wejściach, działa następująco:
  Maszyna Turinga <math>M</math> generująca obwód <math>W</math> o <math>n</math> wejściach, działa następująco:
  # wywołaj procedurę 1 aby obliczyć rozmiar grafu <math>\displaystyle G</math>
  # wywołaj procedurę 1 aby obliczyć rozmiar grafu <math>G</math>.
  # wypisz nowe bramki wejściowe <math>\displaystyle b_1,\ldots,b_n</math>
  # wypisz nowe bramki wejściowe <math>b_1,\ldots,b_n</math>.
  # wywołaj procedurę 2 zmodyfikowaną następująco:
  # wywołaj procedurę 2 zmodyfikowaną następująco:
  -- za każdym razem gdy wypisujesz na wyjście bramkę wejściową
  - za każdym razem, gdy wypisujesz na wyjście bramkę wejściową
  (odpowiadającą za jakąś krawędź grafu) wywołuj od początku procedurę
  (odpowiadającą za jakąś krawędź grafu) wywołuj od początku procedurę
  1 aby otrzymać etykietę tej krawędzi i jakich konfiguracji dotyczy,
  1, aby otrzymać etykietę tej krawędzi i jakich konfiguracji dotyczy,
  i w zależności czy etykieta jest równa 0, 1 czy pusta, dodaj
  i w zależności czy etykieta jest równa 0, 1 czy pusta, dodaj
  odpowiedni układ pobierający jedną z nowych bramek wejściowych <math>\displaystyle b_i</math>
  odpowiedni układ pobierający jedną z nowych bramek wejściowych <math>b_i</math>,
  -- dodaj układ sprawdzający na końcu czy istniej ścieżka od
  - dodaj układ sprawdzający na końcu czy istniej ścieżka od
  konfiguracji początkowej do akceptującej, jego wynik to
  konfiguracji początkowej do akceptującej; jego wynik to
  wartość wyliczana przez obwód
  wartość wyliczana przez obwód


Zauważmy jeszcze, że w punkcie 3 maszyna <math>\displaystyle M</math> wielokrotnie wywołuje
Zauważmy jeszcze, że w punkcie 3 maszyna <math>M</math> wielokrotnie wywołuje
procedurę 2, gdyż ze względu na ograniczenie pamięciowe nie może
procedurę 2, gdyż ze względu na ograniczenie pamięciowe nie może
sobie pozwolić na zapisanie <math>\displaystyle G</math> na taśmie roboczej. Jest to ten sam
sobie pozwolić na zapisanie <math>G</math> na taśmie roboczej. Jest to ten sam
chwyt, co zastosowany w dowodzie przechodniości redukcji
chwyt, co zastosowany w dowodzie przechodniości redukcji
logarytmicznej, w module 2.
logarytmicznej, w module 2.
Linia 250: Linia 248:


{{twierdzenie|3.4||
{{twierdzenie|3.4||
<math>\displaystyle NC\subseteq P</math>.
<math>NC\subseteq P</math>.
}}
}}


{{cwiczenie|3.5||
{{cwiczenie|3.5||
Udowodnij powyższe twierdzenie.
Udowodnij powyższe twierdzenie.
 
}}
<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">   
<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">   
Dla zadanego języka <math>\displaystyle L\in NC^i</math> należy najpierw wygenerować obwód
Dla zadanego języka <math>L\in NC^i</math> należy najpierw wygenerować obwód
<math>\displaystyle W_i</math>, co mozna zrobić w pamięci logarytmicznej, a więc w czasie
<math>W_i</math>, co można zrobić w pamięci logarytmicznej, a więc w czasie
wielomianowym. Następnie wykonuje się najzwyklejszą symulację
wielomianowym. Następnie wykonuje się najzwyklejszą symulację
obwodu, rozpatrując jego bramki w porządku topologicznym. Bramek
obwodu, rozpatrując jego bramki w porządku topologicznym. Bramek
Linia 264: Linia 262:
znaczenie?
znaczenie?
</div></div>
</div></div>
}}


===Klasy w modelu PRAM===
===Klasy w modelu PRAM===


Ważny aspekt dotyczący modelu PRAM, o którym do tej pory nic nie
Ważny aspekt dotyczący modelu PRAM, o którym do tej pory nic nie
mówilismy, to kwestia konfliktów podczas dostępu do pamięci. Czy
mówiliśmy, to kwestia konfliktów podczas dostępu do pamięci. Czy
dana komórkę w tym samym czasie może czytać lub zapisywać więcej niż
dana komórkę w tym samym czasie może czytać lub zapisywać więcej niż
jeden procesor? Przy równoczesnym zapisie należy jeszcze określić
jeden procesor? Przy równoczesnym zapisie należy jeszcze określić
jego semantykę. Wyróżniamy następujące (pod)modele, w kolejności od
jego semantykę. Wyróżniamy następujące (pod)modele, w kolejności od
najsłabszych:
najsłabszych:
* EREW (''exclusive read/write''): algorytmy, w których równoczesny dostęp do tej samej komórki pamięci w ogóle nie występuje
* EREW (''exclusive read/write''): algorytmy, w których równoczesny dostęp do tej samej komórki pamięci w ogóle nie występuje,
* CREW (''concurrent read, exclusive write''): dopuszczalny jest równoczesny odczyt z tej samej komórki
* CREW (''concurrent read, exclusive write''): dopuszczalny jest równoczesny odczyt z tej samej komórki,
* CRCW: dopuszczalny równoczesny odczyt oraz równoczesny zapis. Z synchroniczności modelu PRAM wynika, że nie jest możliwe, aby jeden procesor czytał a drugi zapisywał w tym samym czasie do tej samej komórki.
* CRCW: dopuszczalny równoczesny odczyt oraz równoczesny zapis. Z synchroniczności modelu PRAM wynika, że nie jest możliwe, aby jeden procesor czytał, a drugi zapisywał w tym samym czasie do tej samej komórki.
   
   
W modelu CRCW wyróżnia się kilka dalszych (pod)modeli, ze względu na
W modelu CRCW wyróżnia się kilka dalszych (pod)modeli, ze względu na
Linia 284: Linia 281:
procesorów (zarazem więc pracę), ale działające w tym samym czasie.
procesorów (zarazem więc pracę), ale działające w tym samym czasie.


Przyjmijmy oznaczenie następujące: <math>\displaystyle \cc{EREW}^k</math> to zbiór języków
Przyjmijmy oznaczenie następujące: <math>\mathrm{EREW}^k</math> to zbiór języków
akceptowanych przez maszynę EREW o wielomianowej liczbie procesorów
akceptowanych przez maszynę EREW o wielomianowej liczbie procesorów
i złożoności czasowej <math>\displaystyle O(\log^kn)</math>. Analogiczne oznaczenia
i złożoności czasowej <math>O(\log^kn)</math>. Analogiczne oznaczenia
wprowadzamy dla modeli CREW i CRCW.
wprowadzamy dla modeli CREW i CRCW.


Linia 292: Linia 289:
wariant jednostajnych obwodów logicznych, w którym pomijamy
wariant jednostajnych obwodów logicznych, w którym pomijamy
ograniczenie na stopień wejściowy bramki. Na przykład, alternatywa
ograniczenie na stopień wejściowy bramki. Na przykład, alternatywa
<math>\displaystyle k</math> bitów może być obliczana obwodem o głębokości 1. <math>\displaystyle AC^j</math> z
<math>k</math> bitów może być obliczana obwodem o głębokości 1. <math>AC^j</math> z
definicji to klasa języków akceptowanych przez takie obwody, o
definicji to klasa języków akceptowanych przez takie obwody, o
głębokości <math>\displaystyle O(log^jn)</math>.
głębokości <math>O(log^jn)</math>.


Znając techniki konstrukcji maszyn PRAM nietrudno dowieść, że
Znając techniki konstrukcji maszyn PRAM, nietrudno dowieść, że
<math>\displaystyle NC^j\subseteq \cc{EREW}^j</math>. Jeszcze łatwiej pokazać, że
<math>NC^j\subseteq \mathrm{EREW}^j</math>. Jeszcze łatwiej pokazać, że
<math>\displaystyle AC^j\subseteq NC^{j+1}, j=0,1,\ldots</math>. Znacznie bardziej złożony
<math>AC^j\subseteq NC^{j+1}, j=0,1,\ldots</math>. Znacznie bardziej złożony
jest dowód trzeciej własności: <math>\displaystyle \cc{CRCW}(log^jn)=AC^j</math>.
jest dowód trzeciej własności: <math>\mathrm{CRCW}(log^jn)=AC^j</math>.


Z powyższych trzech inkluzji otrzymujemy hierarchię klas złożoności
Z powyższych trzech inkluzji otrzymujemy hierarchię klas złożoności
równoległej. Dla <math>\displaystyle j=1,2,\ldots</math>:
równoległej. Dla <math>j=1,2,\ldots</math>:


<center><math>\displaystyle \cc{NC}^j \subseteq \cc{EREW}^j \subseteq \cc{CREW}^j \subseteq \cc{CRCW}^j \subseteq \cc{AC}^j
<center><math>\mathrm{NC}^j \subseteq \mathrm{EREW}^j \subseteq \mathrm{CREW}^j \subseteq \mathrm{CRCW}^j \subseteq \mathrm{AC}^j
\subseteq \cc{NC}^{j+1}.</math></center>
\subseteq \mathrm{NC}^{j+1}</math></center>


==P-zupełność==
==P-zupełność==
Linia 312: Linia 309:
fundamentalną rolę w analizie złożoności problemu pod kątem
fundamentalną rolę w analizie złożoności problemu pod kątem
istnienia rowiązań wielomianowych. Okazuje się, że P-zupełność, poza
istnienia rowiązań wielomianowych. Okazuje się, że P-zupełność, poza
tym że jest to narzędzie badań teoretycznych nad klasami złożoności,
tym, że jest to narzędzie badań teoretycznych nad klasami złożoności,
dostarcza analogicznych narzędzi do badania, czy dany problem jest
dostarcza analogicznych narzędzi do badania, czy dany problem jest
łatwy do zrównoleglenia. To co wiadomo w praktyce, to:
łatwy do zrównoleglenia. To co wiadomo w praktyce, to:
* nie znaleziono jak dotąd żadnego języka wspólnego dla klasy NC oraz P-zupełnych
* nie znaleziono jak dotąd żadnego języka wspólnego dla klasy NC oraz P-zupełnych,
* uzasadniona jest hipoteza, że <math>\displaystyle NC\not\subseteq P</math>.
* uzasadniona jest hipoteza, że <math>NC\not\subseteq P</math>.


W tej sytuacji problemy P-zupełne uważa się za trudne do
W tej sytuacji problemy P-zupełne uważa się za trudne do
Linia 322: Linia 319:


Przypomnijmy definicję problemu P-zupełnego. Formalnie, pojęcie to
Przypomnijmy definicję problemu P-zupełnego. Formalnie, pojęcie to
definiuje się dla języków -- są one odpowiednikami problemów
definiuje się dla języków - są one odpowiednikami problemów
decyzyjnych, powstałymi przez ustalone kodowanie instancji w słowa.
decyzyjnych, powstałymi przez ustalone kodowanie instancji w słowa.


{{definicja|4.1||
{{definicja|4.1||
Język <math>\displaystyle L\subseteq \{0,1\}^*</math> jest P-zupełny, jeśli <math>\displaystyle L\in P</math> oraz dla
Język <math>L\subseteq \{0,1\}^*</math> jest P-zupełny, jeśli <math>L\in P</math> oraz dla
każdego języka <math>\displaystyle L'\in P</math>, istnieje redukcja logarytmiczna <math>\displaystyle L'\leq_L
każdego języka <math>L'\in P</math> istnieje redukcja logarytmiczna <math>L'\leq_L
L</math>.
L</math>.
}}
}}
Linia 339: Linia 336:


{{twierdzenie|4.2||
{{twierdzenie|4.2||
Jeśli <math>\displaystyle Q_1\leq_L Q_2</math> oraz <math>\displaystyle Q_2\in NC^j, j\geq 2</math>, to <math>\displaystyle Q_1\in NC^j</math>.
Jeśli <math>Q_1\leq_L Q_2</math> oraz <math>Q_2\in NC^j, j\geq 2</math>, to <math>Q_1\in NC^j</math>.
}}
}}


{{cwiczenie|4.3||
{{cwiczenie|4.3||
Udowodnij powyższe twierdzenie.
Udowodnij powyższe twierdzenie.
 
}}
<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">   
<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">   
Zauważ, że złożenie dwóch algorytmów klasy <math>\displaystyle NC^j</math> jest algorytmem
Zauważ, że złożenie dwóch algorytmów klasy <math>NC^j</math> jest algorytmem
klasy <math>\displaystyle NC^j</math>. Wystarczy teraz skorzystać z faktu, że <math>\displaystyle NL\subseteq
klasy <math>NC^j</math>. Wystarczy teraz skorzystać z faktu, że <math>NL\subseteq
NC^2</math>.
NC^2</math>.
</div></div>
</div></div>
}}
 


Metodologia dowodzenia zupełności w klasie P jest taka sama jak w
Metodologia dowodzenia zupełności w klasie P jest taka sama jak w
Linia 359: Linia 356:
problemu CIRCUIT VALUE lub którąś z jego modyfikacji.
problemu CIRCUIT VALUE lub którąś z jego modyfikacji.


Przypomnijmy, że aby dowieść, że dany problem <math>\displaystyle \Pi</math> jest P-zupełny,
Przypomnijmy, że aby dowieść, że dany problem <math>\Pi</math> jest P-zupełny,
wystarcza:
wystarcza:
* wykazać, że <math>\displaystyle \Pi\in P</math>
* wykazać, że <math>\Pi\in P</math>,
* wybrać P-zupełny problem <math>\displaystyle Q</math> i zredukować go logarytmicznie do <math>\displaystyle \Pi</math>.
* wybrać P-zupełny problem <math>Q</math> i zredukować go logarytmicznie do <math>\Pi</math>.


Rolę pierwszego problemu zupełnego w P gra na ogół problem wartościowania obwodu logicznego.
Rolę pierwszego problemu zupełnego w P gra na ogół problem wartościowania obwodu logicznego.
Linia 376: Linia 373:


{{dowod|||
{{dowod|||
Dany jest język <math>\displaystyle L\in P</math> i deterministyczna maszyna Turinga <math>\displaystyle M</math>
Dany jest język <math>L\in P</math> i deterministyczna maszyna Turinga <math>M</math>
rozpoznająca <math>\displaystyle L</math> w czasie wielomianowym. Należy skonstruować maszynę
rozpoznająca <math>L</math> w czasie wielomianowym. Należy skonstruować maszynę
Turinga <math>\displaystyle M'</math>, która dla zadanego słowa <math>\displaystyle w\in\{0,1\}^*</math> wygeneruje
Turinga <math>M'</math>, która dla zadanego słowa <math>w\in\{0,1\}^*</math> wygeneruje
obwód <math>\displaystyle C(w)</math> z ustalonymi wartościami bramek wejściowych taki, że
obwód <math>C(w)</math> z ustalonymi wartościami bramek wejściowych taki, że
<math>\displaystyle M</math> akceptuje <math>\displaystyle w</math> wtedy i tylko wtedy gdy <math>\displaystyle C(w)=1</math>.
<math>M</math> akceptuje <math>w</math> wtedy i tylko wtedy, gdy <math>C(w)=1</math>.


Przypomnijmy sobie redukcję maszyny Turinga do obwodu logicznego,
Przypomnijmy sobie redukcję maszyny Turinga do obwodu logicznego,
skonstruowaną w module 2. Redukcja ta miała na celu wykazanie, że
skonstruowaną w module 2. Redukcja ta miała na celu wykazanie, że
maszyna Turinga działająca w czasie <math>\displaystyle T(n)</math> może być symulowana przez
maszyna Turinga działająca w czasie <math>T(n)</math> może być symulowana przez
obwód logiczny o <math>\displaystyle O(T^2(n))</math> bramkach.
obwód logiczny o <math>O(T^2(n))</math> bramkach.


Korzystamy z tej samej redukcji, co zapewnia nam warunek "wtedy i
Korzystamy z tej samej redukcji, co zapewnia nam warunek "wtedy i
tylko wtedy". Uzupełnienia wymaga algorytmiczna strona redukcji.
tylko wtedy". Uzupełnienia wymaga algorytmiczna strona redukcji.
Należy wykazać, że obwód symulujący maszynę może byc skonstruowany
Należy wykazać, że obwód symulujący maszynę może być skonstruowany
przez algorytm o logarytmicznej złożoności pamięciowej.
przez algorytm o logarytmicznej złożoności pamięciowej.


Łatwo jednak zauważyć, że to prawda. Dla ustalonej <math>\displaystyle M</math> podukłady
Łatwo jednak zauważyć, że to prawda. Dla ustalonej <math>M</math> podukłady
stosowane w redukcji są tej samej ustalonej postaci. Algorytm
stosowane w redukcji są tej samej ustalonej postaci. Algorytm
redukcji musi je wyprodukować w odpowiedniej ilości, i łączyć w
redukcji musi je wyprodukować w odpowiedniej ilości i łączyć w
sieć. Ale do tego wystarcza zliczanie -- operacje na indeksach.
sieć. Ale do tego wystarcza zliczanie -- operacje na indeksach.


Linia 405: Linia 402:
nie udało się efektywnie zrównoleglić. Znajduje to odzwierciedlenie
nie udało się efektywnie zrównoleglić. Znajduje to odzwierciedlenie
w jego P-zupełności. Dowodzimy tej własności dla pewnej szczególnej
w jego P-zupełności. Dowodzimy tej własności dla pewnej szczególnej
wersji problemu, mianowicie pytania czy maksymalny przepływ w sieci
wersji problemu, mianowicie pytania, czy maksymalny przepływ w sieci
z całkowitymi przepustowościami jest nieparzysty.
z całkowitymi przepustowościami jest nieparzysty.


Przyjmijmy oznaczenie: sieć przedstawiamy jako piątkę
Przyjmijmy oznaczenie: sieć przedstawiamy jako piątkę
<math>\displaystyle N=(V,E,s,t,c)</math>, gdzie <math>\displaystyle V</math> i <math>\displaystyle E</math> to zbiór wierzchołków i krawędzi,
<math>N=(V,E,s,t,c)</math>, gdzie <math>V</math> i <math>E</math> to zbiór wierzchołków i krawędzi,
<math>\displaystyle s</math> i <math>\displaystyle t</math> to źródło i spływ, <math>\displaystyle c</math> to funkcja przepustowości krawędzi.
<math>s</math> i <math>t</math> to źródło i spływ, <math>c</math> to funkcja przepustowości krawędzi.


{{problem|[PARITY MAX FLOW]||
{{problem|[PARITY MAX FLOW]||
''Wejście: ''Sieć <math>\displaystyle N=(V,E,s,t,c)</math><br>
''Wejście: ''Sieć <math>N=(V,E,s,t,c)</math>.<br>
''Wyjście: ''TAK, jeśli maksymalny przepływ jest liczbą nieparzystą, NIE w przeciwnym przypadku.<br>
''Wyjście: ''TAK, jeśli maksymalny przepływ jest liczbą nieparzystą, NIE w przeciwnym przypadku.<br>
}}
}}
Linia 421: Linia 418:
}}
}}


<div class="thumb tright"><div style="width:250px;">
[[File:ZO-11-1.svg|250x250px|thumb|right|Rysunek 11.1.]]
<flash>file=ZO-11-1.swf|width=250|height=250</flash>
[[File:ZO-11-2.svg|250x250px|thumb|right|Rysunek 11.2.]]
<div.thumbcaption>Rysunek 11.1.</div></div></div>
[[File:ZO-11-3.svg|250x250px|thumb|right|Rysunek 11.3.]]
<div class="thumb tright"><div style="width:250px;">
[[File:ZO-11-4.svg|250x250px|thumb|right|Rysunek 11.4.]]
<flash>file=ZO-11-2.swf|width=250|height=250</flash>
<div.thumbcaption>Rysunek 11.2.</div></div></div>
{{dowod|||
{{dowod|||
Do redukcji wybierzmy problem MONOTONE CIRCUIT VALUE. Obwody
Do redukcji wybierzmy problem MONOTONE CIRCUIT VALUE. Obwody
Linia 432: Linia 427:
oczywiście zawężenie problemu CIRCUIT VALUE, dalej jednak P-zupełne
oczywiście zawężenie problemu CIRCUIT VALUE, dalej jednak P-zupełne
(dowód stanowi ćwiczenie). Na wejściu mamy obwód logiczny w postaci
(dowód stanowi ćwiczenie). Na wejściu mamy obwód logiczny w postaci
grafu skierowanego <math>\displaystyle G=(V,E), |V|=n</math>. Przyjmijmy kilka założeń o tym
grafu skierowanego <math>G=(V,E), |V|=n</math>. Przyjmijmy kilka założeń o tym
grafie.
grafie.


Założenie 1: bramka wyjściowa w <math>\displaystyle G</math> jest typu OR. Jeśli tak
Założenie 1: bramka wyjściowa w <math>G</math> jest typu OR. Jeśli tak
nie jest (czyli jest AND), to można ją dać na wejście do nowej
nie jest (czyli jest AND), to można ją dać na wejście do nowej
wyjściowej bramki OR, której drugim wejściem jest nowa bramka
wyjściowej bramki OR, której drugim wejściem jest nowa bramka
Linia 441: Linia 436:


Założenie 2: każda bramka ma stopień wyjściowy co najwyżej 2. Jeśli
Założenie 2: każda bramka ma stopień wyjściowy co najwyżej 2. Jeśli
tak nie jest, to najpierw przekształcamy obwód, tak jak pokazano na [[rysunku 11.1]]
tak nie jest, to najpierw przekształcamy obwód, tak jak pokazano na [http://osilek.mimuw.edu.pl/images/8/8c/ZO-11-1.swf Rysunku 11.1].
'''CZY TO TEN RYSUNEK??'''.


Założenie 3: Bramki ponumerowane są w odwrotnym porządku
Założenie 3: Bramki ponumerowane są w odwrotnym porządku
topologicznym -- bramka wyjściowa ma numer 0, poprzedniki każdej
topologicznym -- bramka wyjściowa ma numer 0, poprzedniki każdej
bramki mają numery od niej większe. Bramki utożsamiamy z ich
bramki mają numery od niej większe. Bramki utożsamiamy z ich
numerami. Zobacz kolejny [[rysunek 11.2]] '''CZY TO TEN RYSUNEK??'''.
numerami. Zobacz kolejny [http://osilek.mimuw.edu.pl/images/5/50/ZO-11-2.swf Rysunek 11.2].


Graf <math>\displaystyle G</math> przekształcamy w sieć <math>\displaystyle N=(V', E', s, t, c)</math> następująco:
Graf <math>G</math> przekształcamy w sieć <math>N=(V', E', s, t, c)</math> następująco:
* do zbioru wierzchołków dodajemy zródło <math>\displaystyle s</math> i spływ <math>\displaystyle t</math>
* do zbioru wierzchołków dodajemy zródło <math>s</math> i spływ <math>t</math>,
* ze źródła prowadzimy krawędź do każdego wierzchołka wejściowego <math>\displaystyle u</math> o wartości 1 i ustalamy jej przepustowość na <math>\displaystyle d2^u</math>, gdzie <math>\displaystyle d</math> jest stopniem wychodzącym z <math>\displaystyle u</math>
* ze źródła prowadzimy krawędź do każdego wierzchołka wejściowego <math>u</math> o wartości 1 i ustalamy jej przepustowość na <math>d2^u</math>, gdzie <math>d</math> jest stopniem wychodzącym z <math>u</math>,
* każdej krawędzi <math>\displaystyle (u,v)</math> grafu <math>\displaystyle G</math> dajemy przepustowość <math>\displaystyle 2^u</math>
* każdej krawędzi <math>(u,v)</math> grafu <math>G</math> dajemy przepustowość <math>2^u</math>,
* dodajemy krawędź <math>\displaystyle (0,t)</math> z przepustowością 1
* dodajemy krawędź <math>(0,t)</math> z przepustowością 1,
* dla każdego wierzchołka <math>\displaystyle u</math> typu OR dodajemy krawędź <math>\displaystyle (u,s)</math> z przepustowością <math>\displaystyle S(u)</math>, gdzie <math>\displaystyle S(u)</math> to suma pojemności wchodzących minus suma pojemności wychodzących
* dla każdego wierzchołka <math>u</math> typu OR dodajemy krawędź <math>(u,s)</math> z przepustowością <math>S(u)</math>, gdzie <math>S(u)</math> to suma pojemności wchodzących minus suma pojemności wychodzących,
* dla każdego wierzchołka <math>\displaystyle u</math> typu AND dodajemy krawędź <math>\displaystyle (u,t)</math> z przepustowością <math>\displaystyle S(u)</math>, gdzie <math>\displaystyle S(u)</math> to suma pojemności wchodzących minus suma pojemności wychodzących
* dla każdego wierzchołka <math>u</math> typu AND dodajemy krawędź <math>(u,t)</math> z przepustowością <math>S(u)</math>, gdzie <math>S(u)</math> to suma pojemności wchodzących minus suma pojemności wychodzących.


[[Rysunek 11.3]]
Zobacz kolejny [http://osilek.mimuw.edu.pl/images/7/7b/ZO-11-3.swf Rysunek 11.3].


Zauważmy, że rozpatrując tylko krawędzie grafu <math>\displaystyle G</math>, dla każdej
Jeśli rozpatrujemy tylko krawędzie grafu <math>G</math>, to dla każdej
bramki typu AND lub OR przepustowość wchodzącą jest co najmniej dwa
bramki typu AND lub OR otrzymujemy przepustowość wchodzącą co najmniej dwa
razy większa niż wychodzącą -- bo o przepustowości krawędzi decyduje
razy większą niż wychodzącą - bo o przepustowości krawędzi decyduje
numer jej początku, który jest większy niż numer końca. Zatem
numer jej początku, który jest większy niż numer końca. Zatem
krawędzie prowadzące do <math>\displaystyle s</math> i <math>\displaystyle t</math> mają niezerowe przepustowości.
krawędzie prowadzące do <math>s</math> i <math>t</math> mają niezerowe przepustowości.


Przepływ <math>\displaystyle F</math> nazywamy standardowym, jeśli przez każdą bramkę, która
Przepływ <math>F</math> nazywamy standardowym, jeśli przez każdą bramkę, która
ma wartość 1, ten przepływ jest maksymalny (równy sumie
ma wartość 1, ten przepływ jest maksymalny (równy sumie
przepustowości wychodzących) oraz przez każdą bramkę o wartości 0
przepustowości wychodzących) oraz przez każdą bramkę o wartości 0
Linia 473: Linia 467:
wszystkie krawędzie wychodzące ze źródła, co powoduje, że bramki
wszystkie krawędzie wychodzące ze źródła, co powoduje, że bramki
wejściowe z wartością 1 mają pełny przepływ, a bramki wejściowe z
wejściowe z wartością 1 mają pełny przepływ, a bramki wejściowe z
wartościa 0 mają przepływ zerowy. Indukcyjnie, jeśli bramka <math>\displaystyle v</math> jest
wartością 0 mają przepływ zerowy. Indukcyjnie, jeśli bramka <math>v</math> jest
typu OR i ma wartość 1, to co najmniej jeden poprzednik ma wartość 1
typu OR i ma wartość 1, to co najmniej jeden poprzednik ma wartość 1
i przysyła przepływ wystarczający do nasycenia ewentualnych dwóch
i przysyła przepływ wystarczający do nasycenia ewentualnych dwóch
odpływów z bramki <math>\displaystyle v</math>, ewentualny nadmiar odpłynie do <math>\displaystyle s</math>. Jeśli
odpływów z bramki <math>v</math>, ewentualny nadmiar odpłynie do <math>s</math>. Jeśli
bramka OR ma wartość 0, to oba poprzedniki mają wartość 0, i z
bramka OR ma wartość 0, to oba poprzedniki mają wartość 0, i z
założenia indukcyjnego nic nie przysyłają. Podobne rozumowanie
założenia indukcyjnego nic nie przysyłają. Podobne rozumowanie
działa dla bramek typu AND.
działa dla bramek typu AND.
Zobacz kolejny [http://osilek.mimuw.edu.pl/images/8/87/ZO-11-4.swf Rysunek 11.4].


Po drugie, przepływ standardowy jest maksymalny. To łatwo pokazać na
Po drugie, przepływ standardowy jest maksymalny. To łatwo pokazać na
Linia 488: Linia 484:
Na koniec zauważmy, że przepływ standardowy ma wartość nieparzystą
Na koniec zauważmy, że przepływ standardowy ma wartość nieparzystą
wtedy i tylko wtedy, gdy wykorzystuje krawędź z bramki wyjściowej do
wtedy i tylko wtedy, gdy wykorzystuje krawędź z bramki wyjściowej do
spływu, a to ma miejsce jedynie gdy obwód na wyjściu ma wartość 1.
spływu, a to ma miejsce jedynie, gdy obwód na wyjściu ma wartość 1.
}}
}}


Linia 495: Linia 491:
Załóżmy, że bardzo zależy nam, aby dany problem rozwiązać w sposób równoległy, z zachowaniem możliwie najlepszych parametrów złożonościowych. Ustaliwszy jego P-zupełność, zamiast pogodzić się z nieistnieniem (najprawdopodobniej) algorytmu klasy NC, możemy próbować osłabić nie złożoność, a dokładność rozwiązania. Jednak tym razem nie chodzi o podejście aproksymacyjne (jak w przypadku problemów NP-trudnych), a o wykorzystanie randomizacji.
Załóżmy, że bardzo zależy nam, aby dany problem rozwiązać w sposób równoległy, z zachowaniem możliwie najlepszych parametrów złożonościowych. Ustaliwszy jego P-zupełność, zamiast pogodzić się z nieistnieniem (najprawdopodobniej) algorytmu klasy NC, możemy próbować osłabić nie złożoność, a dokładność rozwiązania. Jednak tym razem nie chodzi o podejście aproksymacyjne (jak w przypadku problemów NP-trudnych), a o wykorzystanie randomizacji.


W przypadku obwodów logicznych polega ona na dołożeniu do obwodu <math>\displaystyle W_n</math> o <math>\displaystyle n</math> wejściach kolejnych <math>\displaystyle m(n)</math> bramek wejściowych, które zawierają bity losowe. Zakładamy przy tym, że <math>\displaystyle m(n)</math> jest wielomianem. Taki obwód nazywamy ''randomizowanym''
W przypadku obwodów logicznych polega ona na dołożeniu do obwodu <math>W_n</math> o <math>n</math> wejściach kolejnych <math>m(n)</math> bramek wejściowych, które zawierają bity losowe. Zakładamy przy tym, że <math>m(n)</math> jest wielomianem. Taki obwód nazywamy ''randomizowanym''.


{{definicja|5.1||
{{definicja|5.1||
Klasą <math>\displaystyle \cc{RNC}^j</math>  nazywamy zbiór języków <math>\displaystyle L</math> takich, że <math>\displaystyle L</math> posiada jednostajną rodzinę <math>\displaystyle W_1,W_2,\ldots</math> obwodów logicznych randomizowanych o wysokości <math>\displaystyle O(\log^j(n))</math> i wielomianowej liczbie bramek taką, że dla dowolnego <math>\displaystyle x\in\{0,1\}^n</math>, prawdopodobieństwo, że obwód akceptuje <math>\displaystyle x</math> jest
Klasą <math>\mathrm{RNC}^j</math>  nazywamy zbiór języków <math>L</math> takich, że <math>L</math> posiada jednostajną rodzinę <math>W_1,W_2,\ldots</math> obwodów logicznych randomizowanych o wysokości <math>O(\log^j(n))</math> i wielomianowej liczbie bramek taką, że dla dowolnego <math>x\in\{0,1\}^n</math> prawdopodobieństwo, że obwód akceptuje <math>x</math> jest:
* większe lub równe <math>\displaystyle 1/2</math> jeśli <math>\displaystyle x\in L</math>,
* większe lub równe <math>1/2</math>, jeśli <math>x\in L</math>,
* mniejsze niż <math>\displaystyle 1/2</math>, jeśli <math>\displaystyle x\notin L</math>.
* mniejsze niż <math>1/2</math>, jeśli <math>x\notin L</math>.
}}
}}


Linia 506: Linia 502:


Powyżej wykazaliśmy, że problem maksymalnego przepływu jest P-zupełny, co w praktyce oznacza, że nie jesteśmy w stanie skonstruować algorytmu NC. Blisko związany z maksymalnym przepływem
Powyżej wykazaliśmy, że problem maksymalnego przepływu jest P-zupełny, co w praktyce oznacza, że nie jesteśmy w stanie skonstruować algorytmu NC. Blisko związany z maksymalnym przepływem
jest problem skojarzenia w grafach. W szczególności, problem znajdowania maksymalnego skojarzenia w grafach dwudzielnych redukuje sie do problemu maksymalnego przepływu, na czym zresztą bazuje algorytm Hopcrofta-Karpa dla skojarzeń, który poznaliśmy na kursie ''Zaawansowane algorytmy i struktury danych''.
jest problem skojarzenia w grafach. W szczególności, problem znajdowania maksymalnego skojarzenia w grafach dwudzielnych redukuje się do problemu maksymalnego przepływu, na czym zresztą bazuje algorytm Hopcrofta - Karpa dla skojarzeń, który poznaliśmy na kursie ''Zaawansowane algorytmy i struktury danych''.


Zatem wydaje się, że problem znajdowania maksymalnego skojarzenia jest nieco łatwiejszy niż znajdowanie maksymalnego przepływu. Do tej pory jednak nie znaleziono dla niego ani algorytmu o parametrach klasy {NC}, ani dowodu P-zupełności.
Zatem wydaje się, że problem znajdowania maksymalnego skojarzenia jest nieco łatwiejszy niż znajdowanie maksymalnego przepływu. Do tej pory jednak nie znaleziono dla niego ani algorytmu o parametrach klasy {NC}, ani dowodu P-zupełności.


Okazuje się jednak, że randomizacja może w tym przypadku pomóc. Naszkicujmy ideę (bardzo skomplikowanego) algorytmu RMATCH, znajdującego skojarzenie o maksymalnej liczności w dowolnym grafie.
Okazuje się jednak, że randomizacja może w tym przypadku pomóc. Naszkicujmy ideę (bardzo skomplikowanego) algorytmu RMATCH znajdującego skojarzenie o maksymalnej liczności w dowolnym grafie.


Załóżmy, że na wejściu mamy graf <math>\displaystyle G=(V,E)</math>, o <math>\displaystyle n</math> wierzchołkach i <math>\displaystyle m</math> krawędziach. Tworzymy symboliczną macierz incydencji dla <math>\displaystyle G</math> (macierz Tutte'go), kładąc:
Załóżmy, że na wejściu mamy graf <math>G=(V,E)</math>, o <math>n</math> wierzchołkach i <math>m</math> krawędziach. Tworzymy symboliczną macierz incydencji dla <math>G</math> (macierz Tutte'go), kładąc:
* jeśli <math>\displaystyle (i,j)</math> jest krawędzią (dowolnie ustalamy porządek wierzchołków na krawędzi), to <math>\displaystyle T(i,j)=x_{ij}, T(j,i)=-x_{ij}</math>
* jeśli <math>(i,j)</math> jest krawędzią (dowolnie ustalamy porządek wierzchołków na krawędzi), to <math>T(i,j)=x_{ij}, T(j,i)=-x_{ij}</math>,
* w przeciwnym przypadku <math>\displaystyle T(i,j)=T(j,i)=0</math>
* w przeciwnym przypadku <math>T(i,j)=T(j,i)=0</math>.
   
   
Na przykład, dla grafu <math>\displaystyle G=(V,E)</math>, gdzie <math>\displaystyle V=\{1,2,3,4\}</math>,
Na przykład, dla grafu <math>G=(V,E)</math>, gdzie <math>V=\{1,2,3,4\}</math>,
<math>\displaystyle E=\{(1,2),(2,3),(2,4),(1,3)\}</math>, macierz Tutte'go ma postać:
<math>E=\{(1,2),(2,3),(2,4),(1,3)\}</math>, macierz Tutte'go ma postać:


<center><math>\displaystyle \left[
<center><math>\left[
   \begin{array} {rrrr}
   \begin{array} {rrrr}
     0      & x_{12}  & x{_13}  & 0 \\
     0      & x_{12}  & x{_13}  & 0 \\
Linia 527: Linia 523:
   \end{array}  
   \end{array}  
   \right]
   \right]
</math></center>
</math>.</center>


Wyznacznik tej macierzy to wielomian wielu zmiennych stopnia <math>\displaystyle n</math>.
Wyznacznik tej macierzy to wielomian wielu zmiennych stopnia <math>n</math>.


{{twierdzenie|5.2 [Tutte]||
{{twierdzenie|5.2 [Tutte]||


Graf <math>\displaystyle G</math> ma skojarzenie doskonałe wtedy i tylko wtedy gdy
Graf <math>G</math> ma skojarzenie doskonałe wtedy i tylko wtedy, gdy
<math>\displaystyle det(T)\neq 0</math>.
<math>det(T)\neq 0</math>.
}}
}}


Pierwszą składową algorytmu RMATCH jest procedura randomizacyjna, która sprawdza, czy <math>\displaystyle det(T)</math> nie jest identycznościowo równe 0. Wykorzystuje ona z kolei szybką metodę randomizacyjną obliczania wyznacznika liczbowego. Złożoność tego fragmentu (w modelu PRAM) opisuje poniższy lemat:
Pierwszą składową algorytmu RMATCH jest procedura randomizacyjna, która sprawdza, czy <math>det(T)</math> nie jest identycznościowo równe 0. Wykorzystuje ona z kolei szybką metodę randomizacyjną obliczania wyznacznika liczbowego. Złożoność tego fragmentu (w modelu PRAM) opisuje poniższy lemat:


{{lemat|5.3||
{{lemat|5.3||
Na pytanie, czy zadany graf <math>\displaystyle G</math> posiada doskonałe skojarzenie, można
Na pytanie, czy zadany graf <math>G</math> posiada doskonałe skojarzenie, można
odpowiedzieć za pomocą równoległego algorytmu randomizacyjnego, działającego w czasie <math>\displaystyle O(\log^2n)</math> i wykonującego pracę <math>\displaystyle O(n^{3.5})</math>.
odpowiedzieć za pomocą równoległego algorytmu randomizacyjnego działającego w czasie <math>O(\log^2n)</math> i wykonującego pracę <math>O(n^{3.5})</math>.
}}
}}


Bardzo ciekawy jest również następny krok, polegający na obliczeniu samego skojarzenia. Podstawowa trudność polega na tym, że graf może mieć wiele skojarzeń doskonałych, i wtedy trudno jest "ukierunkowac" obliczenie, aby znajdowało jeden z nich (sytuację taka można uznać za wersję problemu łamania symetrii w algorytmach równoległych).
Bardzo ciekawy jest również następny krok polegający na obliczeniu samego skojarzenia. Podstawowa trudność polega na tym, że graf może mieć wiele skojarzeń doskonałych i wtedy trudno jest "ukierunkować" obliczenie, aby znajdowało jeden z nich (sytuację taka można uznać za wersję problemu łamania symetrii w algorytmach równoległych).


Sposób polega na przypisaniu losowych wag krawędziom, co zapewni z dużym prawdopodobieństwem istnienie unikalnego minimalnego pod wzgledem wagi skojarzenia doskonałego. Następnie ponownie korzysta się z macierzy Tutte'go, zastępując w niej symbole zmiennych wylosowanymi wagami. Badając podwyznaczniki tej macierzy ustala się, która krawędź należy do skojarzenia doskonałego.
Sposób polega na przypisaniu losowych wag krawędziom, co zapewni z dużym prawdopodobieństwem istnienie unikalnego, minimalnego pod względem wagi, skojarzenia doskonałego. Następnie ponownie korzysta się z macierzy Tutte,go, zastępując w niej symbole zmiennych wylosowanymi wagami. Badając podwyznaczniki tej macierzy ustala się, która krawędź należy do skojarzenia doskonałego.


Ten fragment obliczeń można wykonać w takim samym czasie i podobnej pracy jak poprzedni. Otrzymujemy:
Ten fragment obliczeń można wykonać algorytmem działającym w takim samym czasie i wykonującym podobną pracę jak poprzedni. Otrzymujemy:


{{lemat|5.4||
{{lemat|5.4||
Dla zadanego grafu <math>\displaystyle G</math> można znaleźć skojarzenie doskonałe, o ile
Dla zadanego grafu <math>G</math> można znaleźć skojarzenie doskonałe, o ile
takie istnieje, równoległym algorytmem randomizacyjnym, działającym w czasie <math>\displaystyle O(\log^2n)</math> i wykonującym pracę <math>\displaystyle O(mn^{3.5})</math>.
takie istnieje, równoległym algorytmem randomizacyjnym działającym w czasie <math>O(\log^2n)</math> i wykonującym pracę <math>O(mn^{3.5})</math>.
}}
}}


Linia 559: Linia 555:
{{cwiczenie|5.5||
{{cwiczenie|5.5||
Wykaż, że problem znajdowania maksymalnego skojarzenia redukuje się (w sensie redukcji Turinga) do problemu znajdowania maksymalnego skojarzenia doskonałego.
Wykaż, że problem znajdowania maksymalnego skojarzenia redukuje się (w sensie redukcji Turinga) do problemu znajdowania maksymalnego skojarzenia doskonałego.
}}
<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">   
<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">   
Wystarcza dodawać w odpowiedni sposób nowe wierzchołki i sprawdzać, czy powstały graf ma skojarzenie doskonałe.
Wystarczy dodawać w odpowiedni sposób nowe wierzchołki i sprawdzać, czy powstały graf ma skojarzenie doskonałe.
</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">   
<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 maksymalne skojarzenie w <math>\displaystyle G</math> ma liczność <math>\displaystyle s</math>. Czyli, po znalezieniu maksymalnego skojarzenia, <math>\displaystyle p=n-2s</math> wierzchołków pozostaje nieskojarzonych. Jeślibyśmy utworzyli nowy graf <math>\displaystyle G'</math> dodając do <math>\displaystyle G\displaystyle k</math> nowych wierzchołków, wraz z krawędziami łączącymi je ze wszystkimi "starymi" wierzchołkami, to teraz w <math>\displaystyle G'</math> istnieje skojarzenie doskonałe. Co więcej, każde skojarzenie doskonałe w <math>\displaystyle G'</math> zawiera maksymalne skojarzenie w <math>\displaystyle G</math> -- bo między nowymi wierzchołkami nie ma krawędzi.
Załóżmy, że maksymalne skojarzenie w <math>G</math> ma liczność <math>s</math>. Czyli, po znalezieniu maksymalnego skojarzenia, <math>p=n-2s</math> wierzchołków pozostaje nieskojarzonych. Jeślibyśmy utworzyli nowy graf <math>G'</math>, dodając do <math>Gk</math> nowych wierzchołków, wraz z krawędziami łączącymi je ze wszystkimi "starymi" wierzchołkami, to teraz w <math>G'</math> istnieje skojarzenie doskonałe. Co więcej, każde skojarzenie doskonałe w <math>G'</math> zawiera maksymalne skojarzenie w <math>G</math> -- bo między nowymi wierzchołkami nie ma krawędzi.


Redukcja zatem polega na przeglądaniu wartości <math>\displaystyle p, 1\leq p\leq n-2</math>,
Redukcja zatem polega na przeglądaniu wartości <math>p, 1\leq p\leq n-2</math>,
takich że <math>\displaystyle n+p</math> jest parzyste, i sprawdzaniu czy otrzymany po dodaniu <math>\displaystyle p</math> nowych wierzchołków (w sposób opisany powyżej) graf ma skojarzenie doskonałe. Po znalezieniu najmniejszego takiego <math>\displaystyle p</math> skojarzenie dla <math>\displaystyle G</math> już łatwo wyliczyć. Oczywiście, wyszukiwanie <math>\displaystyle p</math> o żądanej własności odbywa się metodą połówkową.
takich że <math>n+p</math> jest parzyste, i sprawdzaniu, czy otrzymany po dodaniu <math>p</math> nowych wierzchołków (w sposób opisany powyżej) graf ma skojarzenie doskonałe. Po znalezieniu najmniejszego takiego <math>p</math> skojarzenie dla <math>G</math> już łatwo wyliczyć. Oczywiście, wyszukiwanie <math>p</math> o żądanej własności odbywa się metodą połówkową.
</div></div>
</div></div>
}}
 


{{twierdzenie|5.6||
{{twierdzenie|5.6||
Maksymalne pod względem liczności skojarzenie w dowolnym grafie można znaleźć równoległym algorytmem randomizacyjnym o złożoności czasowej <math>\displaystyle O(\log^3n)</math> i wykonywanej pracy <math>\displaystyle O(mn^3.5)</math>. A zatem, problem ten należy do klasy RNC.
Maksymalne pod względem liczności skojarzenie w dowolnym grafie można znaleźć równoległym algorytmem randomizacyjnym o złożoności czasowej <math>O(\log^3n)</math> i wykonywanej pracy <math>O(mn^3.5)</math>. A zatem, problem ten należy do klasy RNC.
}}
}}


Linia 579: Linia 575:


{{cwiczenie|6.1||
{{cwiczenie|6.1||
Udowodnij, że <math>\displaystyle NC^1\subseteq L</math>.
Udowodnij, że <math>NC^1\subseteq L</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">   
<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">   
Trzeba w pamięci logarytmicznej dokonać wartościowania obwodu logicznego o głębokości <math>\displaystyle \log n</math>. Algorytm DFS wydaje się być przydatnym, ale są pewne trudności z pamięcią na stos.
Trzeba w pamięci logarytmicznej dokonać wartościowania obwodu logicznego o głębokości <math>\log n</math>. Algorytm DFS wydaje się być przydatny, ale są pewne trudności z pamięcią na stos.
</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">Wskazówka </span><div class="mw-collapsible-content" style="display:none">   
<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">   
Jeśli obwód nie jest drzewem (stopień wyjściowy bramek większy niż 1), to na stosie trzeba pamiętać numery wierzchołków i pamięć wzrasta do <math>\displaystyle \log^2n</math>. Przekształć graf obwodu w drzewo, i umiejętnie składaj procedury. Przypomnij sobie, jak się składa redukcje logarytmiczne.
Jeśli obwód nie jest drzewem (stopień wyjściowy bramek większy niż 1), to na stosie trzeba pamiętać numery wierzchołków i pamięć wzrasta do <math>\log^2n</math>. Przekształć graf obwodu w drzewo i umiejętnie składaj procedury. Przypomnij sobie, jak się składa redukcje logarytmiczne.
</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">   
<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">   
Naszym celem jest skonstruowanie maszyny Turinga z logarytmiczną pamięcią, akceptującą zadany język <math>\displaystyle L\in NC^1</math>. Na wejściu zatem jest słowo o długości n. Składowe maszyny <math>\displaystyle M</math> są następujące:<br>
Naszym celem jest skonstruowanie maszyny Turinga z logarytmiczną pamięcią akceptującą zadany język <math>L\in NC^1</math>. Na wejściu zatem jest słowo o długości n. Składowe maszyny <math>M</math> są następujące:<br>
<div class="thumb tright"><div style="width:250px;">
[[File:ZO-11-5.mp4|250x250px|thumb|right|Rysunek 11.5.]]
<flashwrap>file=ZO-11-5.swf|size=small</flashwrap>
<div.thumbcaption>Rysunek 11.3.</div></div></div>


1. Procedura wypisująca obwód logiczny z danej rodziny uniwersalnej. W opisie obwodu, dla każdej bramki podaje listę (co najwyżej dwuelementową) jej poprzedników.<br>
1. Procedura wypisująca obwód logiczny z danej rodziny uniwersalnej. W opisie obwodu, dla każdej bramki podaje listę (co najwyżej dwuelementową) jej poprzedników.<br>


2. Procedura przekształcająca obwód w drzewo. W tym celu rozpatruje wszystkie możliwe ścieżki od bramki wyjściowej obwodu do bramek wejściowych i powiela odpowiednią liczbę razy każdą bramkę, której stopień wyjściowy jest większy niż 1. Powstaje nowy obwód: drzewo, w którym nazwy wierzchołków są liczbami binarnymi, skonstruowanymi jak na [[rysunku 11.3]] '''CZY TO TEN RYSUNEK??''' .<br>
2. Procedura przekształcająca obwód w drzewo. W tym celu rozpatruje wszystkie możliwe ścieżki od bramki wyjściowej obwodu do bramek wejściowych i powiela odpowiednią liczbę razy każdą bramkę, której stopień wyjściowy jest większy niż 1. Powstaje nowy obwód: drzewo, w którym nazwy wierzchołków są liczbami binarnymi, skonstruowanymi jak na [http://osilek.mimuw.edu.pl/images/1/16/ZO-11-5.swf Rysunku 11.5].<br>


3. Procedura obliczająca wartość obwodu w postaci drzewa. Aby obliczyć wartość danej bramki, załóżmy, że jest to AND, najpierw rekurencyjnie oblicza się wartość lewego poprzednika, i jeśli jest on równy 1, to rekurencyjnie oblicza się prawego następnika (o lewym można już zapomnieć). Powrót z rekurencji odbywa się przez obcięcie ostatniego bitu adresu bramki.
3. Procedura obliczająca wartość obwodu w postaci drzewa. Aby obliczyć wartość danej bramki, załóżmy, że jest to AND, najpierw rekurencyjnie oblicza się wartość lewego poprzednika i jeśli jest on równy 1, to rekurencyjnie oblicza się prawego następnika (o lewym można już zapomnieć). Powrót z rekurencji odbywa się przez obcięcie ostatniego bitu adresu bramki.


Dzieki adresacji węzłów drzewa rekurencję można zrealizować pamiętając jedynie nazwę aktualnego wierzchołka -- adres poprzednika przy powrocie z wywołania rekurencyjnego wyznaczamy przez obcięcie ostatniego bitu w adresie aktualnego węzła. Zatem potrzebna pamięć robocza jest rzędu <math>\displaystyle \log n</math>.
Dzięki adresacji węzłów drzewa rekurencję można zrealizować, pamiętając jedynie nazwę aktualnego wierzchołka -- adres poprzednika przy powrocie z wywołania rekurencyjnego wyznaczamy przez obcięcie ostatniego bitu w adresie aktualnego węzła. Zatem potrzebna pamięć robocza jest rzędu <math>\log n</math>.
</div></div>
</div></div>
}}
 


{{cwiczenie|6.2||
{{cwiczenie|6.2||
Wykaż, że problem MONOTONE CIRCUIT VALUE, różniący się od CIRCUIT VALUE tylko tym, że nie dopuszcza się w obwodzie bramek negacji, jest P-zupełny.
Wykaż, że problem MONOTONE CIRCUIT VALUE różniący się od CIRCUIT VALUE tylko tym, że nie dopuszcza się w obwodzie bramek negacji, jest P-zupełny.
 
}}
<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">   
<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 zredukować CIRCUIT VALUE do MONOTONE C.V. Wystarcza za pomocą praw de Morgana przesunąć wszystkie negacje w dół, aż do bramek wejściowych. Następnie bramki wejściowe, których następnikami są negacje, zamienić na przeciwne, dodając nowe jeśli trzeba -- gdy bramka wejściowa jest poprzednikiem dwóch bramek, przy czym dokładnie jedna z tych dwóch jest negacją.
Należy zredukować CIRCUIT VALUE do MONOTONE C.V. Wystarcza za pomocą praw de Morgana przesunąć wszystkie negacje w dół, aż do bramek wejściowych. Następnie bramki wejściowe, których następnikami są negacje, zamienić na przeciwne, dodając nowe, jeśli trzeba - gdy bramka wejściowa jest poprzednikiem dwóch bramek, przy czym dokładnie jedna z tych dwóch jest negacją.


Można to zrobić w pamięci logarytmicznej, bo wystarcza przeglądać listę bramek (dla każdej podane jest jej sąsiedztwo), a nie badać struktury obwodu jako grafu.
Można to zrobić w pamięci logarytmicznej, bo wystarcza przeglądać listę bramek (dla każdej podane jest jej sąsiedztwo), a nie badać struktury obwodu jako grafu.
</div></div>
</div></div>
}}


==Testy końcowe==
==Testy końcowe==

Aktualna wersja na dzień 21:57, 15 wrz 2023

Wstęp

W miarę jak technologia zbliża się do wynikających z podstawowych praw fizyki ograniczeń na szybkość obliczeń, wydaje się, że jednym z obiecujących kierunków badań są obliczenia równoległe. W istocie ta idea jest w stanie przynieść nowe możliwości, chociaż należy przyznać, że początkowa fascynacja algorytmami równoległymi nieco zmalała. Tym niemniej teoretyczne zagadnienia, jakie pojawiły się w trakcie badań nad obliczeniami równoległymi, istotnie poszerzyły dziedzinę teorii obliczeń i uczyniły ją jeszcze ciekawszą.

Wprowadzając algorytmy równoległe wraz z odpowiednia technologią, chcielibyśmy uzyskać następujące korzyści:

  • Radykalne przyspieszenie obliczeń. Na ogół wymagamy, by czas był funkcją polilogarytmiczną od rozmiaru wejścia.
  • Liczba procesorów nie była nierozsądnie duża. Sprowadza się to do wymagania, aby była ona wielomianowa od rozmiaru danych.

Modele obliczeń równoległych

Najważniejsze modele obliczeń równoległych to:

  • PRAM -- równoległa maszyna RAM
  • sieci procesorów o ustalonej topologii połączeń: krata, hiperkostka i wiele innych,
  • układy logiczne.

Podstawowym modelem do opisu algorytmów równoległych jest maszyna PRAM, posłużymy się nią, przedstawiając równoległe rozwiązania przykładowych problemów. Technologicznie PRAM nie jest realizowalna, ale abstrahuje od uwarunkowań konstrukcyjnych i pozwala wypowiadać się wystarczająco ogólnie i ściśle o złożoności problemów algorytmicznych. W przeciwieństwie do niej, sieci procesorów o ustalonej topologii praktycznie się produkuje, natomiast poszczególne rozwiązania algorytmiczne dla tych modeli trudniej przenoszą się na inne modele i przez to są mniej ogólne. W naszych rozważaniach ten model pominiemy.

Natomiast układy logiczne stanowią dobrze zbadany model, pozwalający analizować problemy również pod kątem rozwiązań równoległych, i dlatego poświęcimy mu sporo miejsca. Tym bardziej, że na ogół klasy złożoności równoległej definuje się dla tego modelu.

PRAM

Przypomnijmy w skrócie najważniejsze cechy modelu PRAM, znanego czytelnikowi z kursu Zaawansowane algorytmy i struktury danych. W maszynie PRAM (ang. Parallel Random Access Machine mamy:

  • nieograniczoną liczbę procesorów; każdy ma swój numer i swoje własne rejestry,
  • nieograniczoną wspólną pamięć, jak w maszynie RAM,
  • mechanizm (szynę) umożliwiający komunikację każdego procesora z pamięcią w tym samym czasie (o konfliktach dostępu poniżej).

Najczęściej dla modelu PRAM (ale i również modelu sieci procesorów o ustalonej topologii) zakłada się, że procesory wykonują synchronicznie ten sam program, operując być może na różnych danych w tej samej pamięci, ale w każdym momencie wykonując taki sam rozkaz. Odstępstwo może być tylko jedno: procesor może w danym cyklu rozkazowym nie wykonywać żadnej czynności, czyli wyłączać się na skutek spełnienia określonych warunków.

Opuszczając techniczne problemy przydziału procesorów do poszczególnych operacji, zapiszmy przykładowy prosty algorytm równoległy: mnożenie macierzy. Stosujemy język "work/time", w którym opisuje się pracę wykonywaną przez program w kolejnych jednostkach czasu, bez podawania dokładnie które procesory wykonują daną czynność. Słowo kluczowe in-par-do jest skrótem od in parallel do.

Algorytm [Równoległe mnożenie macierzy]


Wejście: Macierze A,B rozmiaru n×n,n=2p.
Wyjście: Iloczyn C=AB.
begin
1.  for 1 <= i,j,k <= n  in-par-do
2.    D[i,j,k]:=A[i,k]*B[k,j]
3.  for q=1,2,\ldots,p do
4.    for 1<=i,j<=n, 1<=k<=n/(2**q) in-par-do
5.      D[i,j,k]:=D[i,j,2k-1]+D[i,j,2k]
6.  for 1<=i,j<=n in-par-do
7.    {C[i,j]:=D[i,j]
end


Algorytm działa na n3 procesorach, w czasie równoległym O(logn). Praca jaką wykonuje jest następująca:

Krok 2: n3.

Krok 5: n3/2+n3/4+n3/n=O(n3).

Krok 7: n2.

W sumie O(n3). Jest to zatem algorytm optymalny pod względem pracy. Można go w łatwy sposób przekształcić, tak aby zachowana była praca oraz czas, natomiast liczba procesorów była optymalna i wynosiła O(n3/logn).

Załóżmy teraz, że na wejściu jest kwadratowa macierz logiczna, A[i,j]=1 oznacza, że w grafie istnieje krawędź z i do j. Interesuje nas rozwiązanie problemu REACHABILITY.

Ćwiczenie 2.1

Naszkicuj algorytm równoległy znajdowania przechodniego domknięcia grafu. Pożądany czas równoległy i praca to odpowiednio O(log2n) oraz O(n3logn).

Wskazówka
Rozwiązanie

Obwody logiczne

Obwody logiczne poznaliśmy już w module 2. Przekonaliśmy się, że stanowią uniwersalny model obliczeń: mogą symulować maszynę Turinga. Ta własność, a jeszcze bardziej jej dowód, przyda nam się podczas omawiania klas złożoności dla obliczeń równoległych.

Ze względu na podobieństwo do rzeczywistej architektury komputera obwody logiczne wydają się być bardzo realistycznym modelem. Z drugiej strony, w "prawdziwych" komputerach równoległych równocześnie działają procesory, a nie tylko bramki logiczne. Tutaj więc każdą bramkę obwodu traktujemy jako procesor, co wydaje się bardzo ograniczającym założeniem. Tak jednak nie jest, a rezultaty złożonościowe dotyczące obwodów przenoszą się na rzeczywiste obliczenia równoległe.

Równoległość w obwodzie logicznym polega na tym, że bramki na kolejnych poziomach, poczynając od bramek wejściowych do wyjściowych, obliczane są równocześnie. Praca algorytmu (odpowiadająca złożoności sekwencyjnej, czyli po rozwinięciu obliczenia na jednym procesorze) to wielkość obwodu, czyli liczba bramek. Czas równoległy to głębokość obwodu, długość najdłuższej ścieżki od bramki wejściowej do wyjściowej. Warto przypomnieć sobie algorytm, który dla zadanego obwodu oblicza głębokość obwodu oraz poszczególne poziomy.

Ćwiczenie 2.2

Napisz algorytm, który dla zadanego grafu G=(V,E) skierowanego acyklicznego wylicza długość d najdłuższej ścieżki w tym grafie oraz dzieli zbiór wierzchołków V na d+1 podzbiorów V0,,Vd takich, że dla każdego i, Vi jest zbiorem niezależnym oraz dla każdej krawędzi (u,v) w G, jeśli uVi,vVj, to i<j.

Wskazówka

Istnieje bardzo ważna różnica między maszyną PRAM a obwodami logicznymi, nie w aspekcie mocy obliczeniowej, a uniwersalności.

  1. Algorytm na maszynie PRAM (podobnie jak dla RAM czy maszyny Turinga) jest skonstruowany dla danych dowolnych rozmiarów.
  2. Obwód logiczny ma ściśle określoną liczbę bramek, a więc rozpoznaje instancje ściśle określonego rozmiaru. Dla innego rozmiaru danych obwód może mieć zupełnie inną "logikę budowy".

Aby upodobnić pod tym względem obwody logiczne do innych modeli, nakładamy dodatkowo wymaganie, by struktura obwodu dla coraz większych rozmiarów danych była obliczalna.


Definicja 2.3

Rodzina (W1,W2,) obwodów logicznych jest jednostajna, jeśli istnieje maszyna Turinga M o złożoności pamięciowej O(logn), która dla danych wejściowych postaci 1n generuje Wn.

Uwaga 2.4

Rodzina układów logicznych, która nie jest jednostajna, może rozwiązać problem nierozstrzygalny! Na przykład, nierozstrzygalny jest język unarny (czyli o słowach nad alfabetem jednoelementowym) L={1<M,w>: M akceptuje w } (<M,w> oznacza kod binarny maszyny M i słowa wejściowego w). Układy dla poszczególnych n są zbudowane w ten sposób, że jeśli 1nL, to układ oblicza koniunkcję wszystkich wejść, więc akceptuje tylko wtedy, gdy są to same jedynki, a dla 1nL ma dodatkową bramkę wyjściową generującą zero i żadnych innych połączeń (ignoruje wejście). Nie potrafimy obliczać takich układów dla wszystkich n, ale wiemy, że one istnieją!

Ćwiczenie 2.5

Skonstruuj obwód logiczny, możliwie o najmniejszej głębokości, rozwiązujący problem REACHABILITY.

Wskazówka
Rozwiązanie

Klasy złożoności

Model obwodów logicznych

Umownie zakładamy, że algorytm równoległy jest efektywny, jeśli działa w czasie polilogarytmicznym, na wielomianowej liczbie procesorów. O problemie mówimy, że można go efektywnie zrównoleglić, jeśli ten problem posiada efektywny algorytm równoległy. Formalnie definiujemy takie algorytmy, wprowadzając klasę NC.

Definicja 3.1

Dla n1 klasa Ni to zbiór języków L takich, że L jest akceptowany przez jednostajną rodzinę układów logicznych rozmiaru wielomianowego i głębokości O(login). Przyjmujemy oznaczenie NC=j>0NCi.

Istnieją ciekawe związki między klasami złożoności równoległej czasowej a klasami złożoności pamięciowej -- przy zbliżonych funkcjach ograniczających dany zasób. Podstawowe z nich to poniższe dwa twierdzenia.

Twierdzenie 3.2

NC1L.

Dowód tego twierdzenia jest jednym z ćwiczeń końcowych.

Twierdzenie 3.3

NLNC2.

Dowód

Niech L będzie językiem nad alfabetem 0,1 akceptowanym przez niedeterministyczna maszynę M o złożoności pamięciowej logn. Aby wykazać, że istnieje jednostajna rodzina obwodów logicznych (W1,W2,) akceptujących L, o głębokości O(log2n), należy skonstruować maszynę Turinga M, działająca w pamięci logarytmicznej, która dla słowa wejściowego 1n generuje obwód Wn akceptujący zbiór L{0,1}n. Najpierw opisujemy procedury składowe:

  1. Generowanie grafu konfiguracji G. Konfiguracja składa się ze stanu, zawartości taśmy roboczej i położenia głowic na obu taśmach. Nie zawiera ona zawartości taśmy wejściowej, zatem wierzchołki tego grafu zależą, przy ustalonej M, tylko od n.
    Niech u,v będą różnymi konfiguracjami, przy czym u zawiera pozycję j na taśmie wejściowej. Definiujemy krawędź (u,v) w G, jeśli v może być osiągnięta z u w 1 ruchu M. Jeśli przejście z u do v ma miejsce tylko gdy i-ty bit wejściowego słowa jest równy 1, to etykietujemy tę krawędź jedynką, jeśli tylko dla 0, to zerem, a jeśli niezależnie od tego bitu, to etykieta jest pusta. Wynikiem jest lista wierzchołków i lista krawędzi, z etykietami.
    Ponieważ liczba możliwych konfiguracji maszyny M wynosi O(n), więc skonstruowanie takiego grafu jest wykonalne w pamięci logarytmicznej.
  2. Konstrukcja obwodu logicznego obliczającego przechodnie domknięcie grafu H o p wierzchołkach. Bramek wejściowych jest p2 i każda informuje o istnieniu - lub nie - jednej krawędzi. Problem przechodniego domknięcia należy do NC2, o czym przekonaliśmy się, analizując algorytm równoległy w modelu PRAM dla tego problemu. Zatem procedura 2 działa w pamięci logarytmicznej od rozmiaru grafu.
Maszyna Turinga M generująca obwód W o n wejściach, działa następująco:
# wywołaj procedurę 1 aby obliczyć rozmiar grafu G.
# wypisz nowe bramki wejściowe b1,,bn.
# wywołaj procedurę 2 zmodyfikowaną następująco:
- za każdym razem, gdy wypisujesz na wyjście bramkę wejściową
(odpowiadającą za jakąś krawędź grafu) wywołuj od początku procedurę
1, aby otrzymać etykietę tej krawędzi i jakich konfiguracji dotyczy,
i w zależności czy etykieta jest równa 0, 1 czy pusta, dodaj
odpowiedni układ pobierający jedną z nowych bramek wejściowych bi,
- dodaj układ sprawdzający na końcu czy istniej ścieżka od
konfiguracji początkowej do akceptującej; jego wynik to
wartość wyliczana przez obwód

Zauważmy jeszcze, że w punkcie 3 maszyna M wielokrotnie wywołuje procedurę 2, gdyż ze względu na ograniczenie pamięciowe nie może sobie pozwolić na zapisanie G na taśmie roboczej. Jest to ten sam chwyt, co zastosowany w dowodzie przechodniości redukcji logarytmicznej, w module 2.

Zakończymy ten fragment rozważań własnością, która nie jest niespodzianką.

Twierdzenie 3.4

NCP.

Ćwiczenie 3.5

Udowodnij powyższe twierdzenie.

Rozwiązanie

Klasy w modelu PRAM

Ważny aspekt dotyczący modelu PRAM, o którym do tej pory nic nie mówiliśmy, to kwestia konfliktów podczas dostępu do pamięci. Czy dana komórkę w tym samym czasie może czytać lub zapisywać więcej niż jeden procesor? Przy równoczesnym zapisie należy jeszcze określić jego semantykę. Wyróżniamy następujące (pod)modele, w kolejności od najsłabszych:

  • EREW (exclusive read/write): algorytmy, w których równoczesny dostęp do tej samej komórki pamięci w ogóle nie występuje,
  • CREW (concurrent read, exclusive write): dopuszczalny jest równoczesny odczyt z tej samej komórki,
  • CRCW: dopuszczalny równoczesny odczyt oraz równoczesny zapis. Z synchroniczności modelu PRAM wynika, że nie jest możliwe, aby jeden procesor czytał, a drugi zapisywał w tym samym czasie do tej samej komórki.

W modelu CRCW wyróżnia się kilka dalszych (pod)modeli, ze względu na sposób rozstrzygania konfliktów zapisu. Dla naszych rozważań są one nieistotne, gdyż możliwe są symulacje między poszczególnymi wariantami modelu CRCW, zmieniające wprawdzie wielomianowo liczbę procesorów (zarazem więc pracę), ale działające w tym samym czasie.

Przyjmijmy oznaczenie następujące: EREWk to zbiór języków akceptowanych przez maszynę EREW o wielomianowej liczbie procesorów i złożoności czasowej O(logkn). Analogiczne oznaczenia wprowadzamy dla modeli CREW i CRCW.

Wspomnijmy jeszcze o jednym modelu oznaczanym przez AC. Jest to wariant jednostajnych obwodów logicznych, w którym pomijamy ograniczenie na stopień wejściowy bramki. Na przykład, alternatywa k bitów może być obliczana obwodem o głębokości 1. ACj z definicji to klasa języków akceptowanych przez takie obwody, o głębokości O(logjn).

Znając techniki konstrukcji maszyn PRAM, nietrudno dowieść, że NCjEREWj. Jeszcze łatwiej pokazać, że ACjNCj+1,j=0,1,. Znacznie bardziej złożony jest dowód trzeciej własności: CRCW(logjn)=ACj.

Z powyższych trzech inkluzji otrzymujemy hierarchię klas złożoności równoległej. Dla j=1,2,:

NCjEREWjCREWjCRCWjACjNCj+1

P-zupełność

Przekonaliśmy się już, że pojęcie NP-zupełności odgrywa fundamentalną rolę w analizie złożoności problemu pod kątem istnienia rowiązań wielomianowych. Okazuje się, że P-zupełność, poza tym, że jest to narzędzie badań teoretycznych nad klasami złożoności, dostarcza analogicznych narzędzi do badania, czy dany problem jest łatwy do zrównoleglenia. To co wiadomo w praktyce, to:

  • nie znaleziono jak dotąd żadnego języka wspólnego dla klasy NC oraz P-zupełnych,
  • uzasadniona jest hipoteza, że NC⊈P.

W tej sytuacji problemy P-zupełne uważa się za trudne do zrównoleglenia.

Przypomnijmy definicję problemu P-zupełnego. Formalnie, pojęcie to definiuje się dla języków - są one odpowiednikami problemów decyzyjnych, powstałymi przez ustalone kodowanie instancji w słowa.

Definicja 4.1

Język L{0,1}* jest P-zupełny, jeśli LP oraz dla każdego języka LP istnieje redukcja logarytmiczna LLL.

NP-zupełność możemy definiować za pomocą redukcji wielomianowej lub redukcji Turinga -- dla P-zupełności nie miałoby to sensu. Dlaczego?

Co więcej, redukcja logarytmiczna zachowuje złożoność równoległą. Związek między redukcją logarytmiczną a przynależnością do klasy NC jest następujący:

Twierdzenie 4.2

Jeśli Q1LQ2 oraz Q2NCj,j2, to Q1NCj.

Ćwiczenie 4.3

Udowodnij powyższe twierdzenie.

Rozwiązanie


Metodologia dowodzenia zupełności w klasie P jest taka sama jak w przypadku klasy NP. Ponieważ praktycznie znaczenie P-zupełności jest jednak dużo mniejsze, repertuar metod pojawiających się tutaj nie ma porównania z wielką gamą technik i gadżetów w dowodach NP-zupełności. Większość znanych dowodów posługuje się redukcją z problemu CIRCUIT VALUE lub którąś z jego modyfikacji.

Przypomnijmy, że aby dowieść, że dany problem Π jest P-zupełny, wystarcza:

  • wykazać, że ΠP,
  • wybrać P-zupełny problem Q i zredukować go logarytmicznie do Π.

Rolę pierwszego problemu zupełnego w P gra na ogół problem wartościowania obwodu logicznego.

Problem [CIRCUIT VALUE]

Wejście: Obwód logiczny z ustalonymi wartościami bramek wejściowych
Wyjście: TAK, jeśli wartość logiczna obwodu jest 1, NIE w przeciwnym przypadku.

Twierdzenie 4.4

Problem CIRCUIT VALUE jest P-zupełny.

Dowód

Dany jest język LP i deterministyczna maszyna Turinga M rozpoznająca L w czasie wielomianowym. Należy skonstruować maszynę Turinga M, która dla zadanego słowa w{0,1}* wygeneruje obwód C(w) z ustalonymi wartościami bramek wejściowych taki, że M akceptuje w wtedy i tylko wtedy, gdy C(w)=1.

Przypomnijmy sobie redukcję maszyny Turinga do obwodu logicznego, skonstruowaną w module 2. Redukcja ta miała na celu wykazanie, że maszyna Turinga działająca w czasie T(n) może być symulowana przez obwód logiczny o O(T2(n)) bramkach.

Korzystamy z tej samej redukcji, co zapewnia nam warunek "wtedy i tylko wtedy". Uzupełnienia wymaga algorytmiczna strona redukcji. Należy wykazać, że obwód symulujący maszynę może być skonstruowany przez algorytm o logarytmicznej złożoności pamięciowej.

Łatwo jednak zauważyć, że to prawda. Dla ustalonej M podukłady stosowane w redukcji są tej samej ustalonej postaci. Algorytm redukcji musi je wyprodukować w odpowiedniej ilości i łączyć w sieć. Ale do tego wystarcza zliczanie -- operacje na indeksach.

Przytoczmy jeszcze dla porządku rzecz oczywistą: problem CIRCUIT VALUE należy do P, co kończy dowód.

Jednym z trudniejszych problemów w klasie P jest problem znajdowania maksymalnego przepływu. Żadnego z wielu algorytmów dla tego problemu nie udało się efektywnie zrównoleglić. Znajduje to odzwierciedlenie w jego P-zupełności. Dowodzimy tej własności dla pewnej szczególnej wersji problemu, mianowicie pytania, czy maksymalny przepływ w sieci z całkowitymi przepustowościami jest nieparzysty.

Przyjmijmy oznaczenie: sieć przedstawiamy jako piątkę N=(V,E,s,t,c), gdzie V i E to zbiór wierzchołków i krawędzi, s i t to źródło i spływ, c to funkcja przepustowości krawędzi.

Problem [PARITY MAX FLOW]

Wejście: Sieć N=(V,E,s,t,c).
Wyjście: TAK, jeśli maksymalny przepływ jest liczbą nieparzystą, NIE w przeciwnym przypadku.

Twierdzenie 4.5

Problem PARITY MAX FLOW jest P-zupełny.

Rysunek 11.1.
Rysunek 11.2.
Rysunek 11.3.
Rysunek 11.4.

Dowód

Do redukcji wybierzmy problem MONOTONE CIRCUIT VALUE. Obwody monotoniczne to takie, w których nie występują negacje. Jest to oczywiście zawężenie problemu CIRCUIT VALUE, dalej jednak P-zupełne (dowód stanowi ćwiczenie). Na wejściu mamy obwód logiczny w postaci grafu skierowanego G=(V,E),|V|=n. Przyjmijmy kilka założeń o tym grafie.

Założenie 1: bramka wyjściowa w G jest typu OR. Jeśli tak nie jest (czyli jest AND), to można ją dać na wejście do nowej wyjściowej bramki OR, której drugim wejściem jest nowa bramka ustalona na stałe na 0.

Założenie 2: każda bramka ma stopień wyjściowy co najwyżej 2. Jeśli tak nie jest, to najpierw przekształcamy obwód, tak jak pokazano na Rysunku 11.1.

Założenie 3: Bramki ponumerowane są w odwrotnym porządku topologicznym -- bramka wyjściowa ma numer 0, poprzedniki każdej bramki mają numery od niej większe. Bramki utożsamiamy z ich numerami. Zobacz kolejny Rysunek 11.2.

Graf G przekształcamy w sieć N=(V,E,s,t,c) następująco:

  • do zbioru wierzchołków dodajemy zródło s i spływ t,
  • ze źródła prowadzimy krawędź do każdego wierzchołka wejściowego u o wartości 1 i ustalamy jej przepustowość na d2u, gdzie d jest stopniem wychodzącym z u,
  • każdej krawędzi (u,v) grafu G dajemy przepustowość 2u,
  • dodajemy krawędź (0,t) z przepustowością 1,
  • dla każdego wierzchołka u typu OR dodajemy krawędź (u,s) z przepustowością S(u), gdzie S(u) to suma pojemności wchodzących minus suma pojemności wychodzących,
  • dla każdego wierzchołka u typu AND dodajemy krawędź (u,t) z przepustowością S(u), gdzie S(u) to suma pojemności wchodzących minus suma pojemności wychodzących.

Zobacz kolejny Rysunek 11.3.

Jeśli rozpatrujemy tylko krawędzie grafu G, to dla każdej bramki typu AND lub OR otrzymujemy przepustowość wchodzącą co najmniej dwa razy większą niż wychodzącą - bo o przepustowości krawędzi decyduje numer jej początku, który jest większy niż numer końca. Zatem krawędzie prowadzące do s i t mają niezerowe przepustowości.

Przepływ F nazywamy standardowym, jeśli przez każdą bramkę, która ma wartość 1, ten przepływ jest maksymalny (równy sumie przepustowości wychodzących) oraz przez każdą bramkę o wartości 0 jest zerowy.

Po pierwsze, przepływ standardowy zawsze istnieje. Najpierw nasycamy wszystkie krawędzie wychodzące ze źródła, co powoduje, że bramki wejściowe z wartością 1 mają pełny przepływ, a bramki wejściowe z wartością 0 mają przepływ zerowy. Indukcyjnie, jeśli bramka v jest typu OR i ma wartość 1, to co najmniej jeden poprzednik ma wartość 1 i przysyła przepływ wystarczający do nasycenia ewentualnych dwóch odpływów z bramki v, ewentualny nadmiar odpłynie do s. Jeśli bramka OR ma wartość 0, to oba poprzedniki mają wartość 0, i z założenia indukcyjnego nic nie przysyłają. Podobne rozumowanie działa dla bramek typu AND.

Zobacz kolejny Rysunek 11.4.

Po drugie, przepływ standardowy jest maksymalny. To łatwo pokazać na podstawie twierdzenia o maksymalnym przepływie i minimalnym przekroju. Wystarczy do jednego podzbioru dać źródło i wszystkie wierzchołki o wartości 1, do drugiego pozostałe.

Na koniec zauważmy, że przepływ standardowy ma wartość nieparzystą wtedy i tylko wtedy, gdy wykorzystuje krawędź z bramki wyjściowej do spływu, a to ma miejsce jedynie, gdy obwód na wyjściu ma wartość 1.

Równoległość i randomizacja

Załóżmy, że bardzo zależy nam, aby dany problem rozwiązać w sposób równoległy, z zachowaniem możliwie najlepszych parametrów złożonościowych. Ustaliwszy jego P-zupełność, zamiast pogodzić się z nieistnieniem (najprawdopodobniej) algorytmu klasy NC, możemy próbować osłabić nie złożoność, a dokładność rozwiązania. Jednak tym razem nie chodzi o podejście aproksymacyjne (jak w przypadku problemów NP-trudnych), a o wykorzystanie randomizacji.

W przypadku obwodów logicznych polega ona na dołożeniu do obwodu Wn o n wejściach kolejnych m(n) bramek wejściowych, które zawierają bity losowe. Zakładamy przy tym, że m(n) jest wielomianem. Taki obwód nazywamy randomizowanym.

Definicja 5.1

Klasą RNCj nazywamy zbiór języków L takich, że L posiada jednostajną rodzinę W1,W2, obwodów logicznych randomizowanych o wysokości O(logj(n)) i wielomianowej liczbie bramek taką, że dla dowolnego x{0,1}n prawdopodobieństwo, że obwód akceptuje x jest:

  • większe lub równe 1/2, jeśli xL,
  • mniejsze niż 1/2, jeśli xL.

Analogią z klasą RP (moduł 10) jest oczywista.

Powyżej wykazaliśmy, że problem maksymalnego przepływu jest P-zupełny, co w praktyce oznacza, że nie jesteśmy w stanie skonstruować algorytmu NC. Blisko związany z maksymalnym przepływem jest problem skojarzenia w grafach. W szczególności, problem znajdowania maksymalnego skojarzenia w grafach dwudzielnych redukuje się do problemu maksymalnego przepływu, na czym zresztą bazuje algorytm Hopcrofta - Karpa dla skojarzeń, który poznaliśmy na kursie Zaawansowane algorytmy i struktury danych.

Zatem wydaje się, że problem znajdowania maksymalnego skojarzenia jest nieco łatwiejszy niż znajdowanie maksymalnego przepływu. Do tej pory jednak nie znaleziono dla niego ani algorytmu o parametrach klasy {NC}, ani dowodu P-zupełności.

Okazuje się jednak, że randomizacja może w tym przypadku pomóc. Naszkicujmy ideę (bardzo skomplikowanego) algorytmu RMATCH znajdującego skojarzenie o maksymalnej liczności w dowolnym grafie.

Załóżmy, że na wejściu mamy graf G=(V,E), o n wierzchołkach i m krawędziach. Tworzymy symboliczną macierz incydencji dla G (macierz Tutte'go), kładąc:

  • jeśli (i,j) jest krawędzią (dowolnie ustalamy porządek wierzchołków na krawędzi), to T(i,j)=xij,T(j,i)=xij,
  • w przeciwnym przypadku T(i,j)=T(j,i)=0.

Na przykład, dla grafu G=(V,E), gdzie V={1,2,3,4}, E={(1,2),(2,3),(2,4),(1,3)}, macierz Tutte'go ma postać:

[0x12x130x210x23x24x31x32000x4200].

Wyznacznik tej macierzy to wielomian wielu zmiennych stopnia n.

Twierdzenie 5.2 [Tutte]

Graf G ma skojarzenie doskonałe wtedy i tylko wtedy, gdy det(T)0.

Pierwszą składową algorytmu RMATCH jest procedura randomizacyjna, która sprawdza, czy det(T) nie jest identycznościowo równe 0. Wykorzystuje ona z kolei szybką metodę randomizacyjną obliczania wyznacznika liczbowego. Złożoność tego fragmentu (w modelu PRAM) opisuje poniższy lemat:

Lemat 5.3

Na pytanie, czy zadany graf G posiada doskonałe skojarzenie, można odpowiedzieć za pomocą równoległego algorytmu randomizacyjnego działającego w czasie O(log2n) i wykonującego pracę O(n3.5).

Bardzo ciekawy jest również następny krok polegający na obliczeniu samego skojarzenia. Podstawowa trudność polega na tym, że graf może mieć wiele skojarzeń doskonałych i wtedy trudno jest "ukierunkować" obliczenie, aby znajdowało jeden z nich (sytuację taka można uznać za wersję problemu łamania symetrii w algorytmach równoległych).

Sposób polega na przypisaniu losowych wag krawędziom, co zapewni z dużym prawdopodobieństwem istnienie unikalnego, minimalnego pod względem wagi, skojarzenia doskonałego. Następnie ponownie korzysta się z macierzy Tutte,go, zastępując w niej symbole zmiennych wylosowanymi wagami. Badając podwyznaczniki tej macierzy ustala się, która krawędź należy do skojarzenia doskonałego.

Ten fragment obliczeń można wykonać algorytmem działającym w takim samym czasie i wykonującym podobną pracę jak poprzedni. Otrzymujemy:

Lemat 5.4

Dla zadanego grafu G można znaleźć skojarzenie doskonałe, o ile takie istnieje, równoległym algorytmem randomizacyjnym działającym w czasie O(log2n) i wykonującym pracę O(mn3.5).

Trzeci i ostatni krok to redukcja problemu znajdowania maksymalnego skojarzenia do problemu znajdowania maksymalnego skojarzenia doskonałego. Jest to bardzo interesujące ćwiczenie, chociaż ono do probabilistyki już się nie odnosi.

Ćwiczenie 5.5

Wykaż, że problem znajdowania maksymalnego skojarzenia redukuje się (w sensie redukcji Turinga) do problemu znajdowania maksymalnego skojarzenia doskonałego.

Wskazówka
Rozwiązanie


Twierdzenie 5.6

Maksymalne pod względem liczności skojarzenie w dowolnym grafie można znaleźć równoległym algorytmem randomizacyjnym o złożoności czasowej O(log3n) i wykonywanej pracy O(mn3.5). A zatem, problem ten należy do klasy RNC.

Ćwiczenia dodatkowe

Ćwiczenie 6.1

Udowodnij, że NC1L.

Wskazówka
Wskazówka
Rozwiązanie


Ćwiczenie 6.2

Wykaż, że problem MONOTONE CIRCUIT VALUE różniący się od CIRCUIT VALUE tylko tym, że nie dopuszcza się w obwodzie bramek negacji, jest P-zupełny.

Rozwiązanie

Testy końcowe