Złożoność obliczeniowa/Wykład 7: Algorytmy aproksymacyjne: Różnice pomiędzy wersjami

Z Studia Informatyczne
Przejdź do nawigacjiPrzejdź do wyszukiwania
Matiunreal (dyskusja | edycje)
Nie podano opisu zmian
m Zastępowanie tekstu – „ </math>” na „</math>”
 
(Nie pokazano 27 wersji utworzonych przez 2 użytkowników)
Linia 1: Linia 1:
==Wprowadzenie==
==Wprowadzenie==


W poprzednich modułach pokazaliśmy o wielu problemach, że są <math>\cc{NP}</math>-zupełne. Jeżeli <math>\cc{P}\neq\cc{NP}</math>, to żaden z tych problemów nie może mieć rozwiązania, które działałoby w satysfakcjonujący sposób. Jednak wiele z nich to istotne zagadnienia praktyczne i metody choćby częściowego radzenia sobie z nimi są bardzo potrzebne. Konstruowane rozwiązania heurystyczne idą zazwyczaj w dwóch kierunkach:
W poprzednich modułach pokazaliśmy o wielu problemach, że są <math>\mathrm{NP}</math>-zupełne. Jeżeli <math>\mathrm{P}\neq\mathrm{NP}</math>, to żaden z tych problemów nie może mieć rozwiązania, które działałoby w satysfakcjonujący sposób. Jednak wiele z nich to istotne zagadnienia praktyczne i metody choćby częściowego radzenia sobie z nimi są bardzo potrzebne. Konstruowane rozwiązania heurystyczne idą zazwyczaj w dwóch kierunkach:


* wyszukiwanie takich podproblemów, dla których można znaleźć rozwiązanie w czasie wielomianowym,
* wyszukiwanie takich podproblemów, dla których można znaleźć rozwiązanie w czasie wielomianowym,
Linia 11: Linia 11:
==Problem optymalizacyjny==
==Problem optymalizacyjny==


Zwykłe problemy decyzyjne nie nadają się do aproksymowania, bo nie da się przybliżyć rozwiązania konkretnej instancji problemu, którym jest albo "tak", albo "nie". Problemy, które są podatne na aproksymację, to takie, w których odpowiedzią na konkretną instancję problemu jest jakiś kombinatoryczny obiekt z klasy rozwiązań dopuszczalnych. Wprowadzając dodatkowo funkcję celu na obiektach klasy rozwiązań dopuszczalnych możemy żądać, aby znaleziona odpowiedź minimalizowała (lub maksymalizowała) wartość tej funkcji po wszystkich rozwiązaniach dopuszczalnych.
Zwykłe problemy decyzyjne nie nadają się do aproksymowania, bo nie da się przybliżyć rozwiązania konkretnej instancji problemu, którym jest albo "tak", albo "nie". Problemy, które są podatne na aproksymację, to takie, w których odpowiedzią na konkretną instancję problemu jest jakiś kombinatoryczny obiekt z klasy rozwiązań dopuszczalnych. Wprowadzając dodatkowo funkcję celu na obiektach klasy rozwiązań dopuszczalnych, możemy żądać, aby znaleziona odpowiedź minimalizowała (lub maksymalizowała) wartość tej funkcji po wszystkich rozwiązaniach dopuszczalnych.


Problem, który ma powyżej przedstawioną charakterystykę nazywamy problemem optymalizacyjnym i przedstawimy teraz jego formalną definicję w interesującej nas wersji dotyczącej aproksymowania problemów z klasy <math>\cc{NP}</math> w czasie wielomianowym:
Problem, który ma powyżej przedstawioną charakterystykę nazywamy problemem optymalizacyjnym i przedstawimy teraz jego formalną definicję w interesującej nas wersji dotyczącej aproksymowania problemów z klasy <math>\mathrm{NP}</math> w czasie wielomianowym:


{{definicja|2.1|def 1.1|
{{definicja|2.1|def 1.1|
Problem <math>\Pi</math> jest problemem <math>\cc{NP}</math>-optymalizacyjnym, jeżeli składa się z:
Problem <math>\Pi</math> jest problemem <math>\mathrm{NP}</math>-optymalizacyjnym, jeżeli składa się z:


* zbioru instancji <math>D_\Pi</math>. Rozmiarem instancji <math>|I|</math> dla <math>I \in D_\Pi</math> jest ilość bitów potrzebnych do zapisania <math>I</math>,
* zbioru instancji <math>D_\Pi</math>. Rozmiarem instancji <math>|I|</math> dla <math>I \in D_\Pi</math> jest ilość bitów potrzebnych do zapisania <math>I</math>,
* zbioru rozwiązań dopuszczalnych dla każdej instancji <math>\func{S_\Pi}{I}</math>. Zbiór ten musi posiadać dodatkowe własności:
* zbioru rozwiązań dopuszczalnych dla każdej instancji <math>{S_\Pi}{I}</math>. Zbiór ten musi posiadać dodatkowe własności:
** <math>\func{S_\Pi}{I} \neq \emptyset</math> - dla każdej instancji jest jakieś rozwiązanie dopuszczalne,
** <math>{S_\Pi}{I} \neq \emptyset</math>. Dla każdej instancji jest jakieś rozwiązanie dopuszczalne,
** każde <math>s \in \func{S_\Pi}{I}</math> ma rozmiar wielomianowy od <math>|I|</math> i istnieje algorytm wielomianowy, który sprawdza czy dla pary <math>\braq{I,s}</math> zachodzi <math>s \in \func{S_\Pi}{I}</math>,
** każde <math>s \in {S_\Pi}{I}</math> ma rozmiar wielomianowy od <math>|I|</math> i istnieje algorytm wielomianowy, który sprawdza, czy dla pary <math>\mathit{I,s}</math> zachodzi <math>s \in {S_\Pi}{I}</math>,
* funkcji celu <math>\textnormal{obj}_\Pi</math>, która przyporządkowuje rozwiązaniom dopuszczalnym nieujemne wartości wymierne. Funkcja ta musi być wielomianowo obliczalna dla każdej pary <math>\braq{I,s}</math>, gdzie <math>I</math> jest instancją <math>\Pi</math>, a <math>s</math> dopuszczalnym rozwiązaniem <math>I</math>.
* funkcji celu <math>\text{obj}_\Pi</math>, która przyporządkowuje rozwiązaniom dopuszczalnym nieujemne wartości wymierne. Funkcja ta musi być wielomianowo obliczalna dla każdej pary <math>\mathit{I,s}</math>, gdzie <math>I</math> jest instancją <math>\Pi</math>, a <math>s</math> dopuszczalnym rozwiązaniem <math>I</math>.
}}
}}


{{definicja|2.2|def 1.2|
{{definicja|2.2|def 1.2|
Rozwiązaniem optymalnym minimalizacji (maksymalizacji) dla instancji <math>I</math> problemu <math>\cc{NP}</math>-optymalizacyjnego <math>\Pi</math> jest każde z rozwiązań dopuszczalnych, dla którego funkcja celu jest minimalna (maksymalna).
Rozwiązaniem optymalnym minimalizacji (maksymalizacji) dla instancji <math>I</math> problemu <math>\mathrm{NP}</math>-optymalizacyjnego <math>\Pi</math> jest każde z rozwiązań dopuszczalnych, dla którego funkcja celu jest minimalna (maksymalna).
}}
}}


Wartość minimalną (maksymalną) funkcji celu oznaczamy przez <math>\textnormal{opt}_\Pi}{I}</math> i nazywamy optimum. Często będziemy używać skróconej notacji <math>\textnormal{opt}</math>, kiedy nie będzie wątpliwości jaki problem i jego instancję mamy na myśli.
Wartość minimalną (maksymalną) funkcji celu oznaczamy przez <math>\text{opt}_{\Pi}{I}</math> i nazywamy optimum. Często będziemy używać skróconej notacji <math>\text{opt}</math>, kiedy nie będzie wątpliwości, jaki problem i jego instancję mamy na myśli.


===Problemy optymalizacyjne, a problemy decyzyjne===
===Problemy optymalizacyjne a problemy decyzyjne===


Załóżmy, że mamy problem minimalizacji <math>\Pi</math>. Dla problemów maksymalizacyjnych całe rozumowanie jest analogiczne.
Załóżmy, że mamy problem minimalizacji <math>\Pi</math>. Dla problemów maksymalizacyjnych całe rozumowanie jest analogiczne.
Linia 37: Linia 37:
Z problemem <math>\Pi</math> w naturalny sposób jest związany problem decyzyjny <math>\Sigma</math> równoważny pytaniu: "Czy dla zadanej instancji <math>I</math> problemu <math>\Pi</math> i liczby <math>B</math> istnieje rozwiązanie dopuszczalne osiągające wartość funkcji celu mniejszą niż <math>B</math>?".
Z problemem <math>\Pi</math> w naturalny sposób jest związany problem decyzyjny <math>\Sigma</math> równoważny pytaniu: "Czy dla zadanej instancji <math>I</math> problemu <math>\Pi</math> i liczby <math>B</math> istnieje rozwiązanie dopuszczalne osiągające wartość funkcji celu mniejszą niż <math>B</math>?".


Znając wartość optimum dla <math>I</math> można natychmiast odpowiadać na pytania <math>\Sigma</math>. Z drugiej strony, zazwyczaj można łatwo znaleźć wartość <math>\textnormal{opt}_\Pi{I}</math> używając algorytmu rozwiązującego <math>\Sigma</math>. Wystarczy użyć odpowiednio dobranego wyszukiwania binarnego.
Znając wartość optimum dla <math>I</math>, można natychmiast odpowiadać na pytania <math>\Sigma</math>. Z drugiej strony, zazwyczaj można łatwo znaleźć wartość <math>\text{opt}_\Pi{I}</math>, używając algorytmu rozwiązującego <math>\Sigma</math>. Wystarczy użyć odpowiednio dobranego wyszukiwania binarnego.


Dość oczywistą i ważną własnością jest, że jeżeli problem <math>\Sigma</math> jest <math>\cc{NP}</math>-zupełny, to skojarzony z nim problem minimalizacji jest <math>\cc{NP}</math>-trudny. W dalszej części wykładu będziemy analizować tylko problemy, których wersje decyzyjne są <math>\cc{NP}</math>-zupełne.
Dość oczywistą i ważną własnością jest, że jeżeli problem <math>\Sigma</math> jest <math>\mathrm{NP}</math>-zupełny, to skojarzony z nim problem minimalizacji jest <math>\mathrm{NP}</math>-trudny. W dalszej części wykładu będziemy analizować tylko problemy, których wersje decyzyjne są <math>\mathrm{NP}</math>-zupełne.


{{uwaga|2.3|uw 1.3|
{{uwaga|2.3|uw 1.3|
Dla wielu problemów sama tylko umiejętność znajdowania wartości optimum wystarcza, aby w czasie wielomianowym znaleźć również rozwiązanie optymalne. Nie jest to jednak reguła - są problemy, o których zostało pokazane, że nie mają tej własności. Dlatego trzeba rozróżniać problem znalezienia wartości optimum i znalezienia rozwiązania optymalnego. Oczywiście ten drugi jest dla nas znacznie ciekawszy.
Dla wielu problemów sama tylko umiejętność znajdowania wartości optimum wystarcza, aby w czasie wielomianowym znaleźć również rozwiązanie optymalne. Nie jest to jednak reguła i są problemy, o których zostało pokazane, że nie mają tej własności. Dlatego trzeba rozróżniać problem znalezienia wartości optimum i znalezienia rozwiązania optymalnego. Oczywiście ten drugi jest dla nas znacznie ciekawszy.
}}
}}


===Rozwiązania aproksymacyjne===
===Rozwiązania aproksymacyjne===


Wprowadzimy teraz pojęcie algorytmu aproksymacyjnego. Nie będzie ona zbyt restrykcyjna i będzie obejmować każdy algorytm znajdujący jakiekolwiek rozwiązania. Dopiero później zdefiniujemy pojęcia, które pozwolą mówić o skuteczności takich algorytmów.
Wprowadzimy teraz pojęcie algorytmu aproksymacyjnego. Nie będzie ono zbyt restrykcyjne i będzie obejmować każdy algorytm znajdujący jakiekolwiek rozwiązania. Dopiero później zdefiniujemy pojęcia, które pozwolą mówić o skuteczności takich algorytmów.


{{definicja|2.4|def 1.4|
{{definicja|2.4|def 1.4|
Algorytmem aproksymacyjnym <math>\mathcal{A}</math> dla minimalizacji (maksymalizacji) problemu <math>\cc{NP}</math>-optymalizacyjnego <math>\Pi</math> nazywamy algorytm, który działa w czasie wielomianowym i dla każdej instancji problemu <math>\Pi</math> znajduje rozwiązanie dopuszczalne.
Algorytmem aproksymacyjnym <math>\mathcal{A}</math> dla minimalizacji (maksymalizacji) problemu <math>\mathrm{NP}</math>-optymalizacyjnego <math>\Pi</math> nazywamy algorytm, który działa w czasie wielomianowym i dla każdej instancji problemu <math>\Pi</math> znajduje rozwiązanie dopuszczalne.
}}
}}


Linia 60: Linia 60:


<center><math>a \geq 1 \wedge \forall_{I \in D_\Pi}
<center><math>a \geq 1 \wedge \forall_{I \in D_\Pi}
\textnormal{obj}_\Pi(I,\func{\mathcal{A}}(I)) \leq a \cdot
\text{obj}_\Pi(I,{\mathcal{A}}(I)) \leq a \cdot
\textnormal{opt}_\Pi(I),
\text{opt}_\Pi(I)\text{,}
</math></center>
</math></center>


Linia 68: Linia 68:
}}
}}


Jeżeli <math>\Pi</math> jest problemem maksymalizacji, to Algorytm <math>\mathcal{A}</math> musi spełniać odwrotną nierówność:
Jeżeli <math>\Pi</math> jest problemem maksymalizacji, to algorytm <math>\mathcal{A}</math> musi spełniać odwrotną nierówność:




<center><math>a \leq 1 \wedge \forall_{I \in D_\Pi} \textnormal{obj}_\Pi(I,\func{\mathcal{A}}(I)) \geq a \cdot \textnormal{opt}_\Pi(I)
<center><math>a \leq 1 \wedge \forall_{I \in D_\Pi} \text{obj}_\Pi(I,{\mathcal{A}}(I)) \geq a \cdot \text{opt}_\Pi(I)\text{.}
</math></center>
</math></center>


Linia 80: Linia 80:


{{definicja|2.6|def 2.6|
{{definicja|2.6|def 2.6|
Jeżeli dla algorytmu <math>\mathcal{A}</math> rozwiązującego problem minimalizacji <math>\Pi</math> istnieje funkcja <math>\alpha : \mathbb N \rightarrow \mathbb R ^+</math>, taka że
Jeżeli dla algorytmu <math>\mathcal{A}</math> rozwiązującego problem minimalizacji <math>\Pi</math> istnieje funkcja <math>\alpha : \mathbb N \rightarrow \mathbb R ^+</math>, taka że:




<center><math>\forall_{n \in \mathbb N} \func{\alpha}(n) \geq 1 \wedge \forall_{I\in D_\Pi} \textnormal{obj}_\Pi(I,\func{\mathcal{A}}(I)) \leq
<center><math>\forall_{n \in \mathbb N} {\alpha}(n) \geq 1 \wedge \forall_{I\in D_\Pi} \text{obj}_\Pi(I,{\mathcal{A}}(I)) \leq
\func{\alpha|I|} \cdot \textnormal{opt}_\Pi(I),
{\alpha|I|} \cdot \text{opt}_\Pi(I)\text{,}
</math></center>
</math></center>


Linia 96: Linia 96:


{{cwiczenie|2.7 [Problemy decyzyjne jako problemy optymalizacyjne]|cw 2.7|
{{cwiczenie|2.7 [Problemy decyzyjne jako problemy optymalizacyjne]|cw 2.7|
Przyjrzyjmy się bliżej związkom <math>\cc{NP}</math>-zupełnych problemów decyzyjnych i <math>\cc{NP}</math>-optymalizacyjnych. Skorzystamy z definicji języka <math>L</math> należącego klasy <math>\cc{NP}</math>:
Przyjrzyjmy się bliżej związkom <math>\mathrm{NP}</math>-zupełnych problemów decyzyjnych i <math>\mathrm{NP}</math>-optymalizacyjnych. Skorzystamy z definicji języka <math>L</math> należącego klasy <math>\mathrm{NP}</math>:




<center><math>L = \{\defset{x}:{\exists_y (x,y) \in R}\}
<center><math>L = \{{x}:{\exists_y (x,y) \in R}\}\text{,}
</math></center>
</math></center>


Linia 106: Linia 106:




<center><math>\textnormal{obj}_{\Pi_L}(x,y) =
<center><math>\text{obj}_{\Pi_L}(x,y) =
\begin{cases}  
\begin{cases}  
0\quad (x,y) \notin R \\
0\quad (x,y) \notin R \\
1\quad (x,y) \in R
1\quad (x,y) \in R
\end{cases}
\end{cases}\text{.}
</math></center>
</math></center>




Pokaż, że jest to dobrze zdefiniowany problem <math>\cc{NP}</math>-optymalizacyjny i że o ile problem <math>L</math> jest <math>\cc{NP}</math>-zupełny i <math>\cc{P}\neq\cc{NP}</math>, to dla problemu maksymalizacji <math>\Pi_L</math> nie ma algorytmu <math>a</math>-aproksymacyjnego.}}
Pokaż, że jest to dobrze zdefiniowany problem <math>\mathrm{NP}</math>-optymalizacyjny i że o ile problem <math>L</math> jest <math>\mathrm{NP}</math>-zupełny i <math>\mathrm{P}\neq\mathrm{NP}</math>, to dla problemu maksymalizacji <math>\Pi_L</math> nie ma algorytmu <math>a</math>-aproksymacyjnego.}}


<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"> Użyj algorytmu <math>a</math>-aproksymacyjnego do znalezienia świadka relacji <math>R</math> lub stwierdzenia, że taki świadek nie istnieje.
<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"> Użyj algorytmu <math>a</math>-aproksymacyjnego do znalezienia świadka relacji <math>R</math> lub stwierdzenia, że taki świadek nie istnieje.
</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"> Żeby uzasadnić dobre postawienie problemu wystarczy powiedzieć, że dziedzina instancji jest dobrze określona, dla każdej instancji istnieją rozwiązania i są one wielomianowego rozmiaru, oraz że zarówno funkcja sprawdzająca  dopuszczalność rozwiązania, jak i funkcja celu są obliczalne w czasie wielomianowym. Wszystkie te własności są zapewnione przez wielomianowe zrównoważenie relacji <math>R</math>.
<div class="mw-collapsible mw-made=collapsible mw-collapsed"><span class="mw-collapsible-toogle mw-collapsible-toogle-default style="font-variant:small-caps">Rozwiązanie </span><div class="mw-collapsible-content" style="display:none"> Żeby uzasadnić dobre postawienie problemu wystarczy powiedzieć, że dziedzina instancji jest dobrze określona, dla każdej instancji istnieją rozwiązania i są one wielomianowego rozmiaru oraz że zarówno funkcja sprawdzająca  dopuszczalność rozwiązania, jak i funkcja celu, są obliczalne w czasie wielomianowym. Wszystkie te własności są zapewnione przez wielomianowe zrównoważenie relacji <math>R</math>.


Załóżmy teraz, że <math>\mathcal{A}</math> jest algorytmem <math>a</math>-aproksymacyjnym dla problemu <math>\Pi_L</math>. Jeżeli <math>x \in L</math>, to <math>\textnormal{opt}_{\Pi_L}(x) = 1</math>, a w przeciwnym wypadku <math>\textnormal{opt}_{\Pi_L}(x) = 0</math>. W związku z tym rozwiązanie znajdowane przez algorytm <math>\func{\mathcal{A}}(x)</math> musi mieć wartość funkcji celu nie mniejszą niż <math>a > 0</math> dla <math>x \in L</math>. Oznacza to, że dla <math>x \in L</math> musi zachodzić <math>(x,\func{\mathcal{A}}(x)) \in R</math>, bo w przeciwnym wypadku <math>\textnormal{obj}_{\Pi_L}(x,\func{\mathcal{A}}(x))=0</math>. Dla dowolnego ciągu <math>x</math> możemy zatem uruchomić algorytm <math>\mathcal{A}</math>, który działa w czasie wielomianowym i sprawdzić, czy znalezione rozwiązanie jest świadkiem relacji <math>R</math> dla <math>x</math>.
Załóżmy teraz, że <math>\mathcal{A}</math> jest algorytmem <math>a</math>-aproksymacyjnym dla problemu <math>\Pi_L</math>. Jeżeli <math>x \in L</math>, to <math>\text{opt}_{\Pi_L}(x) = 1</math>, a w przeciwnym wypadku <math>\text{opt}_{\Pi_L}(x) = 0</math>. W związku z tym rozwiązanie znajdowane przez algorytm <math>{\mathcal{A}}(x)</math> musi mieć wartość funkcji celu nie mniejszą niż <math>a > 0</math> dla <math>x \in L</math>. Oznacza to, że dla <math>x \in L</math> musi zachodzić <math>(x,{\mathcal{A}}(x)) \in R</math>, bo w przeciwnym wypadku <math>\text{obj}_{\Pi_L}(x,{\mathcal{A}}(x))=0</math>. Dla dowolnego ciągu <math>x</math> możemy zatem uruchomić algorytm <math>\mathcal{A}</math>, który działa w czasie wielomianowym i sprawdzić, czy znalezione rozwiązanie jest świadkiem relacji <math>R</math> dla <math>x</math>.


Pokazaliśmy właśnie algorytm wielomianowy rozwiązujący <math>\cc{NP}</math>-zupełny problem <math>L</math>, co jest sprzeczne z założeniem <math>\cc{P}\neq\cc{NP}</math>.
Pokazaliśmy właśnie algorytm wielomianowy rozwiązujący <math>\mathrm{NP}</math>-zupełny problem <math>L</math>, co jest sprzeczne z założeniem <math>\mathrm{P}\neq\mathrm{NP}</math>.
</div></div>
</div></div>


==Pokrycie wierzchołkowe - NODE COVER==
==Pokrycie wierzchołkowe NODE COVER==


Pierwszym problemem, którego możliwość aproksymacji zbadamy jest problem minimalizacji rozmiaru pokrycia wierzchołkowego grafu. Jest to optymalizacyjna wersja problemu NODE COVER. Instancją problemu jest pojedynczy graf. Rozwiązaniami dopuszczalnymi są pokrycia wierzchołkowe tego grafu, a funkcją celu jest rozmiar znalezionego pokrycia. Interesuje nas oczywiście minimalizacja rozmiaru pokrycia.
Pierwszym problemem, którego możliwość aproksymacji zbadamy jest problem minimalizacji rozmiaru pokrycia wierzchołkowego grafu. Jest to optymalizacyjna wersja problemu NODE COVER. Instancją problemu jest pojedynczy graf. Rozwiązaniami dopuszczalnymi są pokrycia wierzchołkowe tego grafu, a funkcją celu jest rozmiar znalezionego pokrycia. Interesuje nas oczywiście minimalizacja rozmiaru pokrycia.
Linia 139: Linia 139:
Dopóki w grafie są krawędzie:
Dopóki w grafie są krawędzie:


# wybierz wierzchołek <math>v</math> o największym stopniu.
# Wybierz wierzchołek <math>v</math> o największym stopniu.
# dodaj <math>v</math> do pokrycia i usuń z grafu wszystkie krawędzie incydentne z <math>v</math>.}}
# Dodaj <math>v</math> do pokrycia i usuń z grafu wszystkie krawędzie incydentne z <math>v</math>.}}


Okazuje się jednak, że ten algorytm, nie osiąga stałej aproksymacji. Aby dowieść tego faktu, wystarczy spojrzeć na poniższy przykład:
Okazuje się jednak, że ten algorytm, nie osiąga stałej aproksymacji. Aby dowieść tego faktu, wystarczy spojrzeć na poniższy przykład:
<div class="thumb tright"><div style="width:300px;">
[[File:ZO-7-1.svg|300x300px|thumb|right|Pokrycie wierzchołkowe.]]
<flash>file=ZO-7-1.swf|width=300|height=300</flash>
<div.thumbcaption>Pokrycie wierzchołkowe.</div>
</div></div>
<!-- [[pokrycie wierzchołkowe - ZO-7.1]] -->
<!-- [[pokrycie wierzchołkowe - ZO-7.1]] -->
{{przyklad|3.2|przy 2.2|
{{przyklad|3.2|przy 2.2|
Linia 153: Linia 150:
W wyniku działania algorytmu zostanie skonstruowane pokrycie <math>B_n \cup B_{n-1} \cup \ldots \cup B_2</math> o rozmiarze <math>\lfloor{\frac{n}{n}}\rfloor+\lfloor{\frac{n}{n-1}}\rfloor+\ldots+\lfloor{\frac{n}{2}}\rfloor</math>, gdy tymczasem rozwiązaniem optymalnym jest pokrycie <math>A</math> o rozmiarze <math>n</math> (rysunek [http://osilek.mimuw.edu.pl/images/3/39/ZO-7-1.swf Pokrycie wierzchołkowe]).
W wyniku działania algorytmu zostanie skonstruowane pokrycie <math>B_n \cup B_{n-1} \cup \ldots \cup B_2</math> o rozmiarze <math>\lfloor{\frac{n}{n}}\rfloor+\lfloor{\frac{n}{n-1}}\rfloor+\ldots+\lfloor{\frac{n}{2}}\rfloor</math>, gdy tymczasem rozwiązaniem optymalnym jest pokrycie <math>A</math> o rozmiarze <math>n</math> (rysunek [http://osilek.mimuw.edu.pl/images/3/39/ZO-7-1.swf Pokrycie wierzchołkowe]).


Używając prostej analizy z wykorzystaniem sumy ciągu harmonicznego można pokazać, że dla instancji z tej konkretnej rodziny rozwiązanie znajdowane przez algorytm jest <math>\Theta(\log n)</math> razy gorsze od rozwiązania optymalnego.
Używając prostej analizy z wykorzystaniem sumy ciągu harmonicznego, można pokazać, że dla instancji z tej konkretnej rodziny rozwiązanie znajdowane przez algorytm jest <math>\Theta(\log n)</math> razy gorsze od rozwiązania optymalnego.
}}
}}


Pierwsze, bardzo naturalne, podejście do problemu nie doprowadziło nas do algorytmu ze stałą aproksymacji. Niestety, regułą jest, że nie da się osiągnąć aproksymacji problemów <math>\cc{NP}</math>-zupełnych tak prostymi sposobami i trzeba szukać bardziej wyrafinowanych metod. Oczywiście są od tej reguły wyjątki, które pokażemy. Teraz skonstruujemy algorytm <math>2</math>-aproksymacyjny dla problemu pokrycia wierzchołkowego.
Pierwsze, bardzo naturalne, podejście do problemu nie doprowadziło nas do algorytmu ze stałą aproksymacji. Niestety, regułą jest, że nie da się osiągnąć aproksymacji problemów <math>\mathrm{NP}</math>-zupełnych tak prostymi sposobami i trzeba szukać bardziej wyrafinowanych metod. Oczywiście są od tej reguły wyjątki, które pokażemy. Teraz skonstruujemy algorytm <math>2</math>-aproksymacyjny dla problemu pokrycia wierzchołkowego.


===Algorytm skojarzeniowy===
===Algorytm skojarzeniowy===
Linia 166: Linia 163:
# Znajdź dowolne skojarzenie maksymalne (w sensie inkluzji) <math>M</math> w grafie <math>G</math>.
# Znajdź dowolne skojarzenie maksymalne (w sensie inkluzji) <math>M</math> w grafie <math>G</math>.
# Wypisz wszystkie wierzchołki występujące w <math>M</math>.}}
# Wypisz wszystkie wierzchołki występujące w <math>M</math>.}}
<div class="thumb tright"><div style="width:250px;"><flashwrap>file=ZO-7-2.swf|size=small</flashwrap>
[[File:ZO-7-2.mp4|250x250px|thumb|right|Algorytm skojarzeniowy.]]<!-- [[Animacja:algorytm skojarzeniowy - ZO-7.2]] -->
<div.thumbcaption>Algorytm skojarzeniowy.</div></div></div>
<!-- [[Animacja:algorytm skojarzeniowy - ZO-7.2]] -->


{{twierdzenie|3.4|tw 2.4|
{{twierdzenie|3.4|tw 2.4|
Linia 175: Linia 170:


{{dowod|||
{{dowod|||
Najpierw musimy pokazać, że wierzchołki <math>M</math> tworzą pokrycie <math>G</math>. Gdyby jakaś krawędź nie była pokryta, oznaczałoby to, że żaden z jej końców nie należy do <math>M</math> i można by poszerzyć skojarzenie o krawędź, co przeczy maksymalności <math>M</math>.
Najpierw musimy pokazać, że wierzchołki <math>M</math> tworzą pokrycie <math>G</math>. Gdyby jakaś krawędź nie była pokryta, oznaczałoby to, że żaden z jej końców nie należy do <math>M</math> i można by poszerzyć skojarzenie o krawędź, co przeczy maksymalności <math>M</math>.


Niech <math>O</math> będzie optymalnym pokryciem. Zauważmy, że ponieważ <math>M</math> jest skojarzeniem, to zawiera <math>|M|</math> krawędzi, z których żadne dwie nie mają wspólnego wierzchołka. Zatem w pokryciu <math>O</math> musi się znajdować przynajmniej jeden z końców każdej z tych krawędzi (w przeciwnym wypadku, krawędź ta byłaby niepokryta przez <math>O</math>). Z tego wynika, że
Niech <math>O</math> będzie optymalnym pokryciem. Zauważmy, że ponieważ <math>M</math> jest skojarzeniem, to zawiera <math>|M|</math> krawędzi, z których żadne dwie nie mają wspólnego wierzchołka. Zatem w pokryciu <math>O</math> musi się znajdować przynajmniej jeden z końców każdej z tych krawędzi (w przeciwnym wypadku, krawędź ta byłaby niepokryta przez <math>O</math>). Z tego wynika, że




<center><math>|M| \leq |O|,</math></center>
<center><math>|M| \leq |O|\text{,}</math></center>




a liczba wierzchołków w pokryciu znalezionym przez algorytm wynosi <math>2M</math>, co dowodzi że jest to algorytm <math>2</math>-aproksymacyjny.
a liczba wierzchołków w pokryciu znalezionym przez algorytm wynosi <math>2M</math>. To dowodzi, że jest to algorytm <math>2</math>-aproksymacyjny.
}}
}}


{{cwiczenie|3.5 [Pesymistyczny przypadek dla algorytmu skojarzeniowego]|cw 2.5|
{{cwiczenie|3.5 [Pesymistyczny przypadek dla algorytmu skojarzeniowego]|cw 2.5|
Pokaż rodzinę grafów, dla których wynik algorytmu skojarzeniowego jest dokładnie <math>2</math> razy gorszy od optymalnego.
Pokaż rodzinę grafów, dla których wynik algorytmu skojarzeniowego jest dokładnie <math>2</math> razy gorszy od optymalnego.
 
}}
<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"> Dla grafów z tej rodziny pokrycie wierzchołkowe musi zawierać dokładnie po jednym wierzchołku z każdej krawędzi skojarzenia maksymalnego.
<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"> Dla grafów z tej rodziny pokrycie wierzchołkowe musi zawierać dokładnie po jednym wierzchołku z każdej krawędzi skojarzenia maksymalnego.
</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">  
<div class="thumb tright"><div style="width:250px;">
[[File:ZO-7-3.svg|250x250px|thumb|right|Graf K(n,n).]]
<flash>file=ZO-7-3.swf|width=250|height=250</flash>
<div.thumbcaption>Graf K(n,n).</div>
</div></div>
Przykładem takiej rodziny grafów są pełne grafy dwudzielne <math>K_{n,n}</math> z <math>2n</math> wierzchołkami. Każde skojarzenie maksymalne w takim grafie ma <math>n</math> krawędzi, a więc <math>2n</math> wierzchołków. Tymczasem minimalne pokrycie wierzchołkowe składa się z dokładnie <math>n</math> wierzchołków.
Przykładem takiej rodziny grafów są pełne grafy dwudzielne <math>K_{n,n}</math> z <math>2n</math> wierzchołkami. Każde skojarzenie maksymalne w takim grafie ma <math>n</math> krawędzi, a więc <math>2n</math> wierzchołków. Tymczasem minimalne pokrycie wierzchołkowe składa się z dokładnie <math>n</math> wierzchołków.


</div></div>}}
</div></div>


{{cwiczenie|3.6 [Konstrukcja rozwiązania optymalnego z wyrocznią podającą optimum]|cw 2.6|
{{cwiczenie|3.6 [Konstrukcja rozwiązania optymalnego z wyrocznią podającą optimum]|cw 2.6|
Pokaż, że używając wyroczni podającej rozmiar najmniejszego pokrycia wierzchołkowego dla zadanego grafu, można znaleźć rozwiązanie optymalne problemu NODE COVER w czasie wielomianowym.
Pokaż, że używając wyroczni podającej rozmiar najmniejszego pokrycia wierzchołkowego dla zadanego grafu, można znaleźć rozwiązanie optymalne problemu NODE COVER w czasie wielomianowym.
 
}}
<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"> Użyj wyroczni do stwierdzenia czy konkretny wierzchołek należy do jakiegoś rozwiązania optymalnego.
<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"> Użyj wyroczni do stwierdzenia, czy konkretny wierzchołek należy do jakiegoś rozwiązania optymalnego.
</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"> Oznaczmy odpowiedź wyroczni dla grafu <math>G</math> przez <math>\func{\mathcal{A}}(G)</math>.
<div class="mw-collapsible mw-made=collapsible mw-collapsed"><span class="mw-collapsible-toogle mw-collapsible-toogle-default style="font-variant:small-caps">Rozwiązanie </span><div class="mw-collapsible-content" style="display:none"> Oznaczmy odpowiedź wyroczni dla grafu <math>G</math> przez <math>{\mathcal{A}}(G)</math>.
Dla danego wierzchołka <math>x</math> możemy przy pomocy wyroczni <math>\mathcal{A}</math> stwierdzić, czy istnieje pokrycie wierzchołkowe minimalnego rozmiaru zawierające <math>x</math>. Wystarczy porównać wartości <math>\func{\mathcal{A}}(G)</math> i <math>\func{\mathcal{A}}(G-x)</math>. Druga z nich jest mniejsza od pierwszej wtedy i tylko wtedy, gdy istnieje pokrycie wierzchołkowe minimalnego rozmiaru zawierające <math>x</math>.
Dla danego wierzchołka <math>x</math> możemy przy pomocy wyroczni <math>\mathcal{A}</math> stwierdzić, czy istnieje pokrycie wierzchołkowe minimalnego rozmiaru zawierające <math>x</math>. Wystarczy porównać wartości <math>{\mathcal{A}}(G)</math> i <math>{\mathcal{A}}(G-x)</math>. Druga z nich jest mniejsza od pierwszej wtedy i tylko wtedy, gdy istnieje pokrycie wierzchołkowe minimalnego rozmiaru zawierające <math>x</math>.


Po znalezieniu takiego wierzchołka <math>x</math> wystarczy go dodać do konstruowanego pokrycia, usunąć z grafu i kontynuować proces dopóki w grafie są jeszcze jakieś krawędzie.
Po znalezieniu takiego wierzchołka <math>x</math> wystarczy go dodać do konstruowanego pokrycia, usunąć z grafu i kontynuować proces, dopóki w grafie są jeszcze jakieś krawędzie.
</div></div>}}
</div></div>


==Problem maksymalnego przekroju - MAX CUT==
==Problem maksymalnego przekroju MAX CUT==


Ciekawym problemem optymalizacyjnym, który daje się łatwo aproksymować jest problem maksymalnego przekroju.
Ciekawym problemem optymalizacyjnym, który daje się łatwo aproksymować jest problem maksymalnego przekroju.


{{problem| [Maksymalny przekrój - MAX CUT]||
{{problem| [Maksymalny przekrój MAX CUT]||
Mając dany graf <math>G=\braq{V,E}</math> należy podzielić wierzchołki <math>V</math> na dwa podzbiory <math>V_1</math> i <math>V_2</math> tak żeby zmaksymalizować liczbę krawędzi pomiędzy <math>V_1</math>, a <math>V_2</math>.
Mając dany graf <math>G=\mathit{V,E}</math> należy podzielić wierzchołki <math>V</math> na dwa podzbiory <math>V_1</math> i <math>V_2</math>, tak żeby zmaksymalizować liczbę krawędzi pomiędzy <math>V_1</math>, a <math>V_2</math>.
}}
}}


Linia 225: Linia 217:
{{algorytm|4.1 [Algorytm zachłanny]|al 3.1|
{{algorytm|4.1 [Algorytm zachłanny]|al 3.1|
# Ustaw <math>V_1 = \emptyset</math> i <math>V_2 = \emptyset</math>.
# Ustaw <math>V_1 = \emptyset</math> i <math>V_2 = \emptyset</math>.
# Przeglądając wierzchołki <math>V</math> w dowolnej kolejności dodawaj każdy z nich do tego ze zbiorów <math>V_1</math>, lub <math>V_2</math>, z którym łączy go mniej krawędzi.}}
# Przeglądając wierzchołki <math>V</math> w dowolnej kolejności, dodawaj każdy z nich do tego ze zbiorów <math>V_1</math> lub <math>V_2</math>, z którym łączy go mniej krawędzi.}}


{{algorytm|4.2 [Algorytm poszukujący lokalnego optimum]|al 3.2|
{{algorytm|4.2 [Algorytm poszukujący lokalnego optimum]|al 3.2|
# Ustaw <math>V_1 = V</math> i <math>V_2 = \emptyset</math>.
# Ustaw <math>V_1 = V</math> i <math>V_2 = \emptyset</math>.
# Dopóki istnieje w grafie wierzchołek <math>x</math> taki, że przesunięcie go z jednego zbioru do drugiego zwiększa rozmiar przekrój dokonuj takiego przesunięcia.}}
# Dopóki istnieje w grafie wierzchołek <math>x</math> taki, że przesunięcie go z jednego zbioru do drugiego zwiększa rozmiar przekroju, dokonuj takiego przesunięcia.}}


{{twierdzenie|4.3|tw 3.3|
{{twierdzenie|4.3|tw 3.3|
Algorytm zachłanny i poszukujacy lokalnego optimum są algorytmami <math>\frac{1}{2}</math>-aproksymacyjnymi.
Algorytm zachłanny i poszukujący lokalnego optimum są algorytmami <math>\frac{1}{2}</math>-aproksymacyjnymi.
}}
}}


{{dowod|||
{{dowod|||
Dowód dla algorytmu zachłannego jest wyjątkowo prosty. Niech <math>v_1,v_2,\ldots,v_n</math> będzie kolejnością w jakiej są przeglądane wierzchołki. Oznaczmy przez <math>e_i</math> liczbę krawędzi dodanych do przekroju kiedy był dodawany wierzchołek <math>v_i</math>, a przez <math>\bar{e_i}</math> liczbę pozostałych krawędzi łączących <math>v_i</math> z <math>v_1,v_2,\ldots,v_{i-1}</math>. Algorytm wybiera przyporządkowanie wierzchołka <math>v_i</math> w ten sposób, że <math>e_i \geq \bar{e_i}</math>. Mamy zatem:
Dowód dla algorytmu zachłannego jest wyjątkowo prosty. Niech <math>v_1,v_2,\ldots,v_n</math> będzie kolejnością w jakiej są przeglądane wierzchołki. Oznaczmy przez <math>e_i</math> liczbę krawędzi dodanych do przekroju, kiedy był dodawany wierzchołek <math>v_i</math>, a przez <math>\bar{e_i}</math> liczbę pozostałych krawędzi łączących <math>v_i</math> z <math>v_1,v_2,\ldots,v_{i-1}</math>. Algorytm wybiera przyporządkowanie wierzchołka <math>v_i</math> w ten sposób, że <math>e_i \geq \bar{e_i}</math>. Mamy zatem:




<center><math>\sum_{i=1}^n e_i \geq \sum_{i=1}^n \bar{e_i}
<center><math>\sum_{i=1}^n e_i \geq \sum_{i=1}^n \bar{e_i}\text{.}
</math></center>
</math></center>


Linia 252: Linia 244:
W związku z tym mamy, że przynajmniej połowa wszystkich krawędzi jest w przekroju znalezionym przez algorytm zachłanny. To oczywiście dowodzi <math>\frac{1}{2}</math>-aproksymowalności, gdyż w rozwiązaniu optymalnym nie może być więcej krawędzi niż w całym grafie.
W związku z tym mamy, że przynajmniej połowa wszystkich krawędzi jest w przekroju znalezionym przez algorytm zachłanny. To oczywiście dowodzi <math>\frac{1}{2}</math>-aproksymowalności, gdyż w rozwiązaniu optymalnym nie może być więcej krawędzi niż w całym grafie.


Żeby pokazać, że algorytm poszukujący lokalnego optimum jest <math>\frac{1}{2}</math>-aproksymacyjny nadajmy wierzchołkom numerację <math>v_1,v_2,\ldots,v_n</math> i oznaczmy przez <math>\bar{e_i}</math> liczbę krawędzi łączących <math>v_i</math> z wierzchołkami z tego samego zbioru, a przez <math>e_i</math> liczbę pozostałych krawędzi z nim incydentnych. Tu również zachodzi <math>e_i \geq \bar{e_i}</math>. Gdyby dla któregoś z wierzchołków było przeciwnie, to przeniesienie go do drugiego zbioru zwiekszyłoby rozmiar przekroju. Dalsza analiza jest taka sama jak poprzednio z tą różnicą, że:
Żeby pokazać, że algorytm poszukujący lokalnego optimum jest <math>\frac{1}{2}</math>-aproksymacyjny, nadajmy wierzchołkom numerację <math>v_1,v_2,\ldots,v_n</math> i oznaczmy przez <math>\bar{e_i}</math> liczbę krawędzi łączących <math>v_i</math> z wierzchołkami z tego samego zbioru, a przez <math>e_i</math> liczbę pozostałych krawędzi z nim incydentnych. Tu również zachodzi <math>e_i \geq \bar{e_i}</math>. Gdyby dla któregoś z wierzchołków było przeciwnie, to przeniesienie go do drugiego zbioru zwiększyłoby rozmiar przekroju. Dalsza analiza jest taka sama jak poprzednio z tą różnicą, że:




<center><math>\sum_{i=1}^n (e_i + \bar{e_i}) = 2|E|
<center><math>\sum_{i=1}^n (e_i + \bar{e_i}) = 2|E|\text{.}
</math></center>}}
</math></center>}}




W przeciwieństwie do problemu NODE COVER udało nam się skonstruować algorytmy ze stałą aproksymacji dla MAX CUT używając bardzo prostych technik - techniki zachłannej i lokalnych ulepszeń. Pokazuje to, że czasem zanim zaczniemy głębiej analizować jakiś problem, warto sprawdzić takie najprostsze podejścia.
W przeciwieństwie do problemu NODE COVER udało nam się skonstruować algorytmy ze stałą aproksymacji dla MAX CUT, używając bardzo prostych technik: techniki zachłannej i lokalnych ulepszeń. Pokazuje to, że czasem zanim zaczniemy głębiej analizować jakiś problem, warto sprawdzić takie najprostsze podejścia.


{{cwiczenie|4.4|cw 3.4|
{{cwiczenie|4.4|cw 3.4|
Pokaż, że decyzyjna wersja problemu MAX CUT jest <math>\cc{NP}</math>-zupełna.
Pokaż, że decyzyjna wersja problemu MAX CUT jest <math>\mathrm{NP}</math>-zupełna.
 
}}
<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"> Skonstruuj redukcję problemu NAE<math>3</math>SAT do MAXCUT. Stwórz po jednym wierzchołku dla każdego literału.
<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"> Skonstruuj redukcję problemu NAE<math>3</math>SAT do MAXCUT. Stwórz po jednym wierzchołku dla każdego literału.
</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">   
Pokażemy redukcję logarytmiczną problemu NAE<math>3</math>SAT do MAXCUT. Niech <math>\phi</math> będzie formułą problemu NAE<math>3</math>SAT. Musimy dokonać pewnej modyfikacji <math>\phi</math>. Po pierwsze usuwamy wszystkie klauzule zawierające literał <math>x</math> i jednocześnie jego zaprzeczenie <math>\neg x</math> - takie klauzule i tak są spełnione przez każde wartościowanie.
Pokażemy redukcję logarytmiczną problemu NAE<math>3</math>SAT do MAXCUT. Niech <math>\phi</math> będzie formułą problemu NAE<math>3</math>SAT. Musimy dokonać pewnej modyfikacji <math>\phi</math>. Po pierwsze, usuwamy wszystkie klauzule zawierające literał <math>x</math> i jednocześnie jego zaprzeczenie <math>\neg x</math>. Takie klauzule i tak są spełnione przez każde wartościowanie.


Druga modyfikacja formuły <math>\phi</math> polega na takiej zamianie klauzul, żeby żadne dwie nie miały dwóch wspólnych literałów. Można to osiągnąć w następujący sposób, że zamiast dwóch klauzul postaci <math>(a \vee b \vee c)</math> i <math>(a \vee b \vee d)</math> tworzymy cztery klauzule z dwoma nowymi zmiennymi <math>x</math> i <math>y</math>:
Druga modyfikacja formuły <math>\phi</math> polega na takiej zamianie klauzul, żeby żadne dwie nie miały dwóch wspólnych literałów. Można to osiągnąć w następujący sposób, że zamiast dwóch klauzul postaci <math>(a \vee b \vee c)</math> i <math>(a \vee b \vee d)</math> tworzymy cztery klauzule z dwiema nowymi zmiennymi <math>x</math> i <math>y</math>:




<center><math>\aligned a \vee b \vee c \\
<center><math>\begin{align} a \vee b \vee c\text{,} \\
a \vee x \vee d \\
a \vee x \vee d\text{,} \\
b \vee \neg x \vee y \\
b \vee \neg x \vee y\text{,} \\
\neg b \vee x \vee y
\neg b \vee x \vee y\text{.}
\endaligned</math></center>
\end{align}</math></center>




Dwie ostatnie klauzule są NAE-spełnione wtedy i tylko wtedy, gdy zmienna <math>x</math> ma samą wartość co <math>b</math>.
Dwie ostatnie klauzule są NAE-spełnione wtedy i tylko wtedy, gdy zmienna <math>x</math> ma samą wartość co <math>b</math>.


Po tych modyfikacjach <math>\phi</math> możemy skonstruować instancję problemu MAX CUT. Niech <math>\phi</math> ma <math>n</math> zmiennych i <math>m</math> klauzul. Stworzymy graf o <math>2n</math> wierzchołkach i <math>n+3m</math> krawędziach. Dla każdej zmiennej <math>x</math> mamy dwa wierzchołki odpowiadające literałom <math>x</math> i <math>\neg x</math>. Dodajemy następujące krawędzie:
Po tych modyfikacjach <math>\phi</math> możemy skonstruować instancję problemu MAX CUT. Niech <math>\phi</math> ma <math>n</math> zmiennych i <math>m</math> klauzul. Stworzymy graf o <math>2n</math> wierzchołkach i <math>n+3m</math> krawędziach. Dla każdej zmiennej <math>x</math> mamy dwa wierzchołki odpowiadające literałom <math>x</math> i <math>\neg x</math>. Dodajemy następujące krawędzie:
Linia 291: Linia 283:
Udowodnimy teraz, że formuła <math>\phi</math> jest NAE-spełnialna wtedy i tylko wtedy, gdy w skonstruowanym grafie jest przekrój rozmiaru <math>n+2m</math>.
Udowodnimy teraz, że formuła <math>\phi</math> jest NAE-spełnialna wtedy i tylko wtedy, gdy w skonstruowanym grafie jest przekrój rozmiaru <math>n+2m</math>.


Jeżeli <math>\phi</math> jest spełnialna, to niech <math>S</math> będzie zbiorem literałów, które są prawdziwe w wartościowaniu spełniającym <math>\phi</math>. Przekrój pomiędzy zbiorem wierzchołków <math>S</math>, a resztą grafu ma dokładnie <math>n+2m</math> krawędzi - <math>n</math> krawędzi łączących <math>x</math> z <math>\neg x</math> i po dwie krawędzi z każdego trójkąta.
Jeżeli <math>\phi</math> jest spełnialna, to niech <math>S</math> będzie zbiorem literałów, które są prawdziwe w wartościowaniu spełniającym <math>\phi</math>. Przekrój pomiędzy zbiorem wierzchołków <math>S</math> a resztą grafu ma dokładnie <math>n+2m</math> krawędzi - <math>n</math> krawędzi łączących <math>x</math> z <math>\neg x</math> i po dwie krawędzi z każdego trójkąta.


Jeżeli jakiś przekrój <math>C</math> w skonstruowanym grafie ma rozmiar <math>n+2m</math>, to zauważmy, że wyznacza on pewne wartościowanie zmiennych. Ponieważ w każdym przekroju mogą występować co najwyżej dwie krawędzie z jednego trójkąta, to oznacza to, że przekrój <math>C</math> ma dokładnie dwie krawędzie z każdego trójkąta i wszystkie krawędzie łączące przeciwne literały. Zatem przeciwne literały są w przeciwnych zbiorach podziału i możemy podać takie wartościowanie zmiennych, aby literały z jednego podzbioru wierzchołków były wartościowane pozytywnie, a te z drugiego negatywnie.
Jeżeli jakiś przekrój <math>C</math> w skonstruowanym grafie ma rozmiar <math>n+2m</math>, to zauważmy, że wyznacza on pewne wartościowanie zmiennych. Ponieważ w każdym przekroju mogą występować co najwyżej dwie krawędzie z jednego trójkąta, oznacza to, że przekrój <math>C</math> ma dokładnie dwie krawędzie z każdego trójkąta i wszystkie krawędzie łączące przeciwne literały. Zatem przeciwne literały są w przeciwnych zbiorach podziału i możemy podać takie wartościowanie zmiennych, aby literały z jednego podzbioru wierzchołków były wartościowane pozytywnie, a te z drugiego negatywnie.


Ponieważ każdy z trójkątów ma dwie krawędzie w przekroju, to odpowiada to dokładnie temu, że każda z klauzul jest NAE-spełniona.
Ponieważ każdy z trójkątów ma dwie krawędzie w przekroju, zatem odpowiada to dokładnie temu, że każda z klauzul jest NAE-spełniona.
</div></div>
</div></div>


}}
==Problem komiwojażera TSP==


==Problem komiwojażera - TSP==
Teraz przyjrzymy się innemu klasycznemu problemowi. Problem komiwojażera jest jednym z najlepiej zbadanych problemów <math>\mathrm{NP}</math>-zupełnych ze względu na swoje praktyczne znaczenie. Warto sobie teraz przypomnieć dowód <math>\mathrm{NP}</math>-zupełności jego decyzyjnej wersji. Użyjemy ponownie tych samych redukcji w analizie możliwości aproksymacji.


Teraz przyjrzymy się innemu klasycznemu problemowi - problemowi komiwojażera. Jest to jeden z najlepiej zbadanych problemów <math>\cc{NP}</math>-zupełnych ze względu na swoje praktyczne znaczenie. Warto sobie teraz przypomnieć dowód <math>\cc{NP}</math>-zupełności jego decyzyjnej wersji. Użyjemy ponownie tych samych redukcji w analizie możliwości aproksymacji.
Optymalizacyjna wersja problemu TSP powstaje w naturalny sposób. Wejściem jest opis odległości pomiędzy <math>n</math> miastami, rozwiązaniami dopuszczalnymi są cykle przechodzące przez wszystkie miasta, a funkcją celu, której wartość chcemy zminimalizować, jest sumaryczna długość cyklu.


Optymalizacyjna wersja problemu TSP powstaje w naturalny sposób. Wejściem jest opis odległości pomiędzy <math>n</math> miastami, rozwiązaniami dopuszczalnymi są cykle przechodzące przez wszystkie miasta, a funkcją celu, której wartość chcemy zminimalizować jest sumaryczna długość cyklu.
Pierwsze smutne spostrzeżenie jest takie, że o ile <math>\mathrm{P}\neq\mathrm{NP}</math>, to nie ma możliwości skonstruowania dobrego algorytmu aproksymacyjnego. Fakt ten wyraża następujące twierdzenie:
 
Pierwsze smutne spostrzeżenie jest takie, że o ile <math>\cc{P}\neq\cc{NP}</math>, to nie ma możliwości skonstruowania dobrego algorytmu aproksymacyjnego. Fakt ten wyraża następujące twierdzenie:


{{twierdzenie|5.1|tw 4.1|
{{twierdzenie|5.1|tw 4.1|
O ile <math>\cc{P}\neq\cc{NP}</math>, to dla żadnego algorytmu aproksymacyjnego <math>\mathcal{A}</math> nie istnieje funkcja obliczalna w czasie wielomianowym <math>\alpha</math> taka, że <math>\mathcal{A}</math> jest algorytmem <math>\alpha</math>-aproksymacyjnym dla problemu TSP.
O ile <math>\mathrm{P}\neq\mathrm{NP}</math>, to dla żadnego algorytmu aproksymacyjnego <math>\mathcal{A}</math> nie istnieje funkcja obliczalna w czasie wielomianowym <math>\alpha</math> taka, że <math>\mathcal{A}</math> jest algorytmem <math>\alpha</math>-aproksymacyjnym dla problemu TSP.
}}
}}


{{dowod|||
{{dowod|||
Dowód wynika bezpośrednio z dowodu <math>\cc{NP}</math>-zupełności decyzyjnego problemu TSP. Przypomnijmy, że polegał on na redukcji problemu HAMILTON CYCLE. Wykorzystamy teraz redukcję do pokazania, że dowolny <math>\alpha</math>-aproksymacyjny algorytm pozwoliłby rozstrzygać problem cyklu Hamiltona, co przeczyłoby <math>\cc{P}\neq\cc{NP}</math>.
Dowód wynika bezpośrednio z dowodu <math>\mathrm{NP}</math>-zupełności decyzyjnego problemu TSP. Przypomnijmy, że polegał on na redukcji problemu HAMILTON CYCLE. Wykorzystamy teraz redukcję do pokazania, że dowolny <math>\alpha</math>-aproksymacyjny algorytm pozwoliłby rozstrzygać problem cyklu Hamiltona, co przeczyłoby <math>\mathrm{P}\neq\mathrm{NP}</math>.


Załóżmy, że <math>\mathcal{A}</math> jest algorytmem <math>\alpha</math>-aproksymacyjnym dla problemu TSP. Chcąc zredukować problem cyklu Hamiltona dla grafu <math>G=\braq{V,E}</math> o <math>n</math> wierzchołkach tworzymy graf pełny <math>H</math> na wierzchołkach <math>V</math>. Przypisujemy wagi krawędziom w następujący sposób:
Załóżmy, że <math>\mathcal{A}</math> jest algorytmem <math>\alpha</math>-aproksymacyjnym dla problemu TSP. Chcąc zredukować problem cyklu Hamiltona dla grafu <math>G=\mathit{V,E}</math> o <math>n</math> wierzchołkach, tworzymy graf pełny <math>H</math> na wierzchołkach <math>V</math>. Przypisujemy wagi krawędziom w następujący sposób:


* jeżeli krawędź <math>xy \in E</math>, to ustalamy jej wagę na <math>1</math>,
* jeżeli krawędź <math>xy \in E</math>, to ustalamy jej wagę na <math>1</math>,
* w przeciwnym wypadku ustalamy jej wagę na <math>\func{\alpha}{n} \cdot n</math>.
* w przeciwnym wypadku ustalamy jej wagę na <math>{\alpha}{n} \cdot n</math>.


Zauważmy, że koszt rozwiązania problemu TSP w grafie <math>H</math> zależy od tego, czy w grafie <math>G</math> był cykl Hamiltona:
Zauważmy, że koszt rozwiązania problemu TSP w grafie <math>H</math> zależy od tego, czy w grafie <math>G</math> był cykl Hamiltona:


* jeżeli graf <math>G</math> jest grafem Hamiltonowskim, to koszt optymalnej trasy komiwojażera w <math>H</math> wynosi <math>n</math>,
* jeżeli graf <math>G</math> jest grafem Hamiltonowskim, to koszt optymalnej trasy komiwojażera w <math>H</math> wynosi <math>n</math>,
* w przeciwnym wypadku koszt optymalnej trasy jest większy od <math>\func{\alpha}{n} \cdot n</math> (bo została użyta choć jedna krawędź <math>xy \notin E</math>.
* w przeciwnym wypadku koszt optymalnej trasy jest większy od <math>{\alpha}{n} \cdot n</math> (bo została użyta choć jedna krawędź <math>xy \notin E</math>).


Jeżeli teraz podamy graf <math>H</math> na wejście algorytmu <math>\mathcal{A}</math>, to w pierwszym przypadku znajdzie on rozwiązanie o koszcie nie większym niż <math>\func{\alpha}{n} \cdot n</math>, a w drugim przypadku większym od tej wartości. Można zatem rozstrzygnąć, czy w grafie <math>G</math> jest cykl Hamiltona porównując koszt rozwiązania znalezionego przez <math>\mathcal{A}</math> z <math>\func{\alpha}{n} \cdot n</math>.
Jeżeli teraz podamy graf <math>H</math> na wejście algorytmu <math>\mathcal{A}</math>, to w pierwszym przypadku znajdzie on rozwiązanie o koszcie nie większym niż <math>{\alpha}{n} \cdot n</math>, a w drugim przypadku większym od tej wartości. Można zatem rozstrzygnąć, czy w grafie <math>G</math> jest cykl Hamiltona, porównując koszt rozwiązania znalezionego przez <math>\mathcal{A}</math> z <math>{\alpha}{n} \cdot n</math>.


Pokazany algorytm rozstrzyga <math>\cc{NP}</math>-zupełny problem HAMILTON CYCLE i działa w czasie wielomianowym. Jest to sprzecznie z założeniem <math>\cc{P}\neq\cc{NP}</math>.
Pokazany algorytm rozstrzyga <math>\mathrm{NP}</math>-zupełny problem HAMILTON CYCLE i działa w czasie wielomianowym. Jest to sprzecznie z założeniem <math>\mathrm{P}\neq\mathrm{NP}</math>.
}}
}}


===Wersja metryczna===
===Wersja metryczna===
<div class="thumb tright"><div style="width:300px;">
[[File:ZO-7-4.svg|300x150px|thumb|right|Warunek trójkąta.]]
<flash>file=ZO-7-4.swf|width=300|height=150</flash>
<div.thumbcaption>Warunek trójkąta.</div>
</div></div>
<!-- [[warunek trójkąta - ZO-7.4]] -->
<!-- [[warunek trójkąta - ZO-7.4]] -->
Pokazaliśmy, że nie ma nadziei na efektywny algorytm dla ogólnego przypadku problemu komiwojażera. Poddamy teraz analizie naturalne zawężenie problemu i odkryjemy, że jest wtedy możliwa dobra aproksymacja. Zawężeniem problemu, o którym mowa, jest nałożenie dodatkowego wymagania na odległości podawane na wejściu. Żądamy, aby spełniały one warunek trójkąta. Dla każdych trzech miast <math>x,y,z</math> musi zachodzić (rysunek [http://osilek.mimuw.edu.pl/images/0/02/ZO-7-4.swf Warunek trójkąta]):
Pokazaliśmy, że nie ma nadziei na efektywny algorytm dla ogólnego przypadku problemu komiwojażera. Poddamy teraz analizie naturalne zawężenie problemu i odkryjemy, że jest wtedy możliwa dobra aproksymacja. Zawężeniem problemu, o którym mowa, jest nałożenie dodatkowego wymagania na odległości podawane na wejściu. Żądamy, aby spełniały one warunek trójkąta. Dla każdych trzech miast <math>x,y,z</math> musi zachodzić (rysunek [http://osilek.mimuw.edu.pl/images/0/02/ZO-7-4.swf Warunek trójkąta]):


<center><math>\func{d}(x,y) \leq \func{d}(x,z) + \func{d}(z,y)
<center><math>{d}(x,y) \leq {d}(x,z) + {d}(z,y)\text{.}
</math></center>
</math></center>




Takie zawężenie problemu nazywa się metrycznym problemem komiwojażera i ma ono wiele praktycznych zastosowań. Nawet przy tych dodatkowych warunkach problem pozostaje <math>\cc{NP}</math>-zupełny (zwykła redukcja problemu HAMILTON CYCLE tworzy instancję metrycznego problemu komiwojażera).
Takie zawężenie problemu nazywa się metrycznym problemem komiwojażera i ma ono wiele praktycznych zastosowań. Nawet przy tych dodatkowych warunkach problem pozostaje <math>\mathrm{NP}</math>-zupełny (zwykła redukcja problemu HAMILTON CYCLE tworzy instancję metrycznego problemu komiwojażera).


Zauważmy, że konstrukcja, która pokazywała, że ogólny problem komiwojażera nie może być dobrze aproksymowany tworzyła wejścia, które zdecydowanie nie zachowywały warunku trójkąta. Daje to nadzieję na istnienie algorytmu aproksymacyjnego dla tego podproblemu.
Zauważmy, że konstrukcja, która pokazywała, że ogólny problem komiwojażera nie może być dobrze aproksymowany, tworzyła wejścia, które zdecydowanie nie zachowywały warunku trójkąta. Daje to nadzieję na istnienie algorytmu aproksymacyjnego dla tego podproblemu.


Najpierw pokażemy algorytm <math>2</math>-aproksymacyjny, który konstruuje cykl komiwojażera w bardzo sprytny sposób:
Najpierw pokażemy algorytm <math>2</math>-aproksymacyjny, który konstruuje cykl komiwojażera w bardzo sprytny sposób:
Linia 351: Linia 338:


# Znajdź minimalne drzewo rozpinające <math>T</math> w grafie odległości.
# Znajdź minimalne drzewo rozpinające <math>T</math> w grafie odległości.
# Podwój krawędzie drzewa <math>T</math> otrzymując graf <math>\mathbb{T}</math>.
# Podwój krawędzie drzewa <math>T</math>, otrzymując graf <math>\mathbb{T}</math>.
# Znajdź cykl Eulera <math>\mathbb{C}</math> w grafie <math>\mathbb{T}</math>.
# Znajdź cykl Eulera <math>\mathbb{C}</math> w grafie <math>\mathbb{T}</math>.
# Skonstruuj cykl <math>C</math> przechodząc <math>\mathbb{C}</math> po kolei i dodając każdy wierzchołek, który nie został jeszcze dodany do <math>C</math>. (porównaj z rysunkiem [http://osilek.mimuw.edu.pl/images/5/5b/ZO-7-5.swf Zamiana drzewa rozpinającego na cykl komiwojażera])
# Skonstruuj cykl <math>C</math>, przechodząc <math>\mathbb{C}</math> po kolei i dodając każdy wierzchołek, który nie został jeszcze dodany do <math>C</math>. (porównaj z rysunkiem [http://osilek.mimuw.edu.pl/images/5/5b/ZO-7-5.swf Zamiana drzewa rozpinającego na cykl komiwojażera])
}}
}}
<div class="thumb tright"><div style="width:300px;">
[[File:ZO-7-5.svg|300x300px|thumb|right|Zamiana drzewa rozpinającego na cykl komiwojażera.]]
<flash>file=ZO-7-5.swf|width=300|height=300</flash>
<div.thumbcaption>Zamiana drzewa rozpinającego na cykl komiwojażera.</div>
</div></div>
<!-- [[zamiana drzewa rozpinającego na cykl komiwojażera - ZO-7.5]] -->
<!-- [[zamiana drzewa rozpinającego na cykl komiwojażera - ZO-7.5]] -->


Linia 366: Linia 350:


{{dowod|||
{{dowod|||
Dowód przeprowadzimy porównując koszt struktur konstruowanych w kolejnych krokach algorytmu względem optymalnego rozwiązania problemu. Tak więc:
Dowód przeprowadzimy, porównując koszt struktur konstruowanych w kolejnych krokach algorytmu względem optymalnego rozwiązania problemu. Tak więc:


* suma wag krawędzi drzewa <math>T</math> jest mniejsza lub równa kosztowi optymalnego rozwiązania problemu. Jest tak dlatego, gdyż usuwając dowolną krawędź z rozwiązania optymalnego otrzymujemy drzewo (a raczej ścieżkę) rozpinające grafu. Tymczasem <math>T</math> jest minimalnym drzewem rozpinającym. Mamy więc
* suma wag krawędzi drzewa <math>T</math> jest mniejsza lub równa kosztowi optymalnego rozwiązania problemu. Jest tak dlatego, gdyż usuwając dowolną krawędź z rozwiązania optymalnego, otrzymujemy drzewo (a raczej ścieżkę) rozpinające grafu. Tymczasem <math>T</math> jest minimalnym drzewem rozpinającym. Mamy więc
* <math>\textnormal{cost}(T) \leq \textnormal opt</math>,
* <math>\text{cost}(T) \leq \text{opt}</math>,
* <math>\textnormal{cost}({\mathbb{T}}) = 2 \textnormal{cost}(T) \leq 2 \opt</math>,
* <math>\text{cost}({\mathbb{T}}) = 2 \text{cost}(T) \leq 2 </math>,
* <math>\textnormal{cost}({\mathbb{C}}) = \textnormal{cost}({\mathbb{T}}) \leq 2 \opt</math>,
* <math>\text{cost}({\mathbb{C}}) = \text{cost}({\mathbb{T}}) \leq 2</math>,
musimy teraz pokazać, że konstruując <math>C</math> nie pogorszymy oszacowania na koszt <math>\mathbb{C}</math>. Tutaj właśnie skorzystamy z tego, że odległości zachowują warunek trójkąta. Sprawia to, że pomijając wierzchołki i dodając krawędź bezpośrednią pomiędzy końcami usuniętego fragmentu możemy tylko zmniejszyć całkowity koszt rozwiązania. W związku z tym <math>\textnormal{cost}(C) \leq \textnormal{cost}({\mathbb{C}}) \leq 2 \textnormal{opt}</math>.}}
musimy teraz pokazać, że konstruując <math>C</math>, nie pogorszymy oszacowania na koszt <math>\mathbb{C}</math>. Tutaj właśnie skorzystamy z tego, że odległości zachowują warunek trójkąta. Sprawia to, że pomijając wierzchołki i dodając krawędź bezpośrednią pomiędzy końcami usuniętego fragmentu, możemy tylko zmniejszyć całkowity koszt rozwiązania. W związku z tym <math>\text{cost}(C) \leq \text{cost}({\mathbb{C}}) \leq 2 \text{opt}</math>.}}


Wyniki osiągane przez ten algorytm można poprawić i dostać algorytm <math>\frac{3}{2}</math>-aproksymacyjny. Szczegóły tego usprawnienia pozostawiamy na ćwiczenia.
Wyniki osiągane przez ten algorytm można poprawić i otrzymać algorytm <math>\frac{3}{2}</math>-aproksymacyjny. Szczegóły tego usprawnienia pozostawiamy na ćwiczenia.


{{cwiczenie|5.4 [Algorytm pre-order]|cw 4.4|
{{cwiczenie|5.4 [Algorytm pre-order]|cw 4.4|
Linia 409: Linia 393:
<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"> Aby udowodnić poprawność algorytmu musimy pokazać, że graf <math>T+M</math> jest Eulerowski. Wystarczy zauważyć, że w każdym drzewie jest parzysta liczba wierzchołków o nieparzystym stopniu. W związku z tym skojarzenie <math>M</math> doda każdemu takiemu wierzchołkowi jedną krawędź i w powstałym grafie każdy wierzchołek będzie miał stopień parzysty.
<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"> Aby udowodnić poprawność algorytmu musimy pokazać, że graf <math>T+M</math> jest Eulerowski. Wystarczy zauważyć, że w każdym drzewie jest parzysta liczba wierzchołków o nieparzystym stopniu. W związku z tym skojarzenie <math>M</math> doda każdemu takiemu wierzchołkowi jedną krawędź i w powstałym grafie każdy wierzchołek będzie miał stopień parzysty.


Pokażemy, że sumaryczny koszt krawędzi w skojarzeniu spełnia nierówność <math>\textnormal{cost}(M) < \frac{1}{2} \opt</math>. Niech <math>W</math> będzie zbiorem wierzchołków o nieparzystym stopniu w <math>T</math>. Niech <math>O_W</math> oznacza cykl przechodzący przez wierzchołki <math>W</math> powstały przez zawężenie cyklu optymalnego <math>O</math> do wierzchołków <math>W</math>. Warunek trójkąta pozwala nam stwierdzić  <math>\textnormal{cost}(O_W) \leq \textnormal{cost}(O) = \textnormal opt</math>.
Pokażemy, że sumaryczny koszt krawędzi w skojarzeniu spełnia nierówność <math>\text{cost}(M) < \frac{1}{2} \text{opt}</math>. Niech <math>W</math> będzie zbiorem wierzchołków o nieparzystym stopniu w <math>T</math>. Niech <math>O_W</math> oznacza cykl przechodzący przez wierzchołki <math>W</math> powstały przez zawężenie cyklu optymalnego <math>O</math> do wierzchołków <math>W</math>. Warunek trójkąta pozwala nam stwierdzić  <math>\text{cost}(O_W) \leq \text{cost}(O) = \text{opt}</math>.


Ponieważ wybór co drugiej krawędzi na cyklu definiuje skojarzenie o maksymalnej liczności, to cykl <math>O_W</math> wyznacza dwa takie rozłączne skojarzenia na wierzchołkach <math>W</math>. Tańsze z nich ma koszt nie większy niż połowa <math>\textnormal{cost}(O_W)</math> i jest to koszt nie mniejszy od kosztu najtańszego skojarzenia <math>M</math>. W związku z tym:
Ponieważ wybór co drugiej krawędzi na cyklu definiuje skojarzenie o maksymalnej liczności, to cykl <math>O_W</math> wyznacza dwa takie rozłączne skojarzenia na wierzchołkach <math>W</math>. Tańsze z nich ma koszt nie większy niż połowa <math>\text{cost}(O_W)</math> i jest to koszt nie mniejszy od kosztu najtańszego skojarzenia <math>M</math>. W związku z tym:




<center><math>\textnormal{cost}(M) \leq \frac{1}{2} \textnormal{cost}(O_W) \leq \frac{1}{2} \textnormal opt
<center><math>\text{cost}(M) \leq \frac{1}{2} \text{cost}(O_W) \leq \frac{1}{2} \text{opt}\text{.}
</math></center>
</math></center>




Zatem sumaryczny koszt krawędzi grafu <math>T+M</math> jest nie większy niż <math>\frac{3}{2} \textnormal opt</math> i algorytm osiąga stałą aproksymacji równą <math>\frac{3}{2}</math>.
Zatem sumaryczny koszt krawędzi grafu <math>T+M</math> jest nie większy niż <math>\frac{3}{2} \text{opt}</math> i algorytm osiąga stałą aproksymacji równą <math>\frac{3}{2}</math>.
</div></div>
</div></div>


==Pakowanie - BIN PACKING==
==Pakowanie BIN PACKING==


Kolejnym istotnym i dzięki temu dobrze zbadanym problemem, którym się zajmiemy jest optymalne pakowanie. Przypomnijmy sformułowanie problemu:
Kolejnym istotnym i dzięki temu dobrze zbadanym problemem, którym się zajmiemy, jest optymalne pakowanie. Przypomnijmy sformułowanie problemu:


{{problem|[Pakowanie - BIN PACKING]||
{{problem|[Pakowanie BIN PACKING]||
Mając dany zbiór <math>n</math> przedmiotów o wagach wymiernych <math>w_1, w_2, \ldots, w_n \in \left(0,1\right]</math>. Należy znaleźć przyporządkowanie ich do jak najmniejszej liczby pojemników. Suma wag przedmiotów w jednym pojemniku nie może przekraczać <math>1</math>. Zadaniem optymalizacji jest oczywiście minimalizacja liczby użytych pojemników.
Mając dany zbiór <math>n</math> przedmiotów o wagach wymiernych <math>w_1, w_2, \ldots, w_n \in \left(0,1\right]</math>, należy znaleźć przyporządkowanie ich do jak najmniejszej liczby pojemników. Suma wag przedmiotów w jednym pojemniku nie może przekraczać <math>1</math>. Zadaniem optymalizacji jest oczywiście minimalizacja liczby użytych pojemników.
}}
}}


Linia 436: Linia 420:
(animacja [http://osilek.mimuw.edu.pl/images/a/ac/ZO-7-6.swf Algorytm First-Fit])
(animacja [http://osilek.mimuw.edu.pl/images/a/ac/ZO-7-6.swf Algorytm First-Fit])
# W liście <math>B</math> przechowuj częściowo wypełnione pojemniki. Na początku lista jest pusta.
# W liście <math>B</math> przechowuj częściowo wypełnione pojemniki. Na początku lista jest pusta.
# Przeglądając przedmioty w kolejności dodawaj je do pierwszego pojemnika na liście <math>B</math>, w którym jest jeszcze wystarczająco dużo "miejsca". Jeżeli nie można przedmiotu dodać do żadnego z pojemników, to dodaj nowy pojemnik do listy i włóż przedmiot właśnie do niego.}}
# Przeglądając przedmioty w kolejności, dodawaj je do pierwszego pojemnika na liście <math>B</math>, w którym jest jeszcze wystarczająco dużo "miejsca". Jeżeli nie można przedmiotu dodać do żadnego z pojemników, to dodaj nowy pojemnik do listy i włóż przedmiot właśnie do niego.}}


<div class="thumb tright"><div style="width:250px;">
[[File:ZO-7-6.mp4|250x250px|thumb|right|Algorytm First-Fit.]]
<flashwrap>file=ZO-7-6.swf|size=small</flashwrap>
<div.thumbcaption>Algorytm First-Fit.</div>
</div></div>
<!-- [[algorytm First-Fit - ZO-7.6 (animacja)]] -->
<!-- [[algorytm First-Fit - ZO-7.6 (animacja)]] -->


Linia 449: Linia 430:


{{dowod|||
{{dowod|||
Zauważmy, że po zakończeniu algorytmu co najwyżej jeden z pojemników jest wypełniony mniej niż w połowie. Załóżmy że jest przeciwnie - dwa pojemniki <math>B_i, B_j, i < j</math> są wypełnione mniej niż w połowie. Zatem wszystkie przedmioty znajdujące się w <math>B_j</math> mogłyby zostać dodane do pojemnika <math>B_i</math>. Zatem algorytm First-Fit tak właśnie by postąpił i pojemnik <math>B_j</math> w ogóle nie byłby potrzebny.
Zauważmy, że po zakończeniu algorytmu co najwyżej jeden z pojemników jest wypełniony mniej niż w połowie. Załóżmy, że jest przeciwnie i dwa pojemniki <math>B_i, B_j, i < j</math> są wypełnione mniej niż w połowie. Zatem wszystkie przedmioty znajdujące się w <math>B_j</math> mogłyby zostać dodane do pojemnika <math>B_i</math>. Zatem algorytm First-Fit tak właśnie by postąpił i pojemnik <math>B_j</math> w ogóle nie byłby potrzebny.


Skoro tak, to liczba pojemników użytych przez algorytm First-Fit <math>m</math> spełnia nierówność:
Skoro tak, to liczba pojemników użytych przez algorytm First-Fit <math>m</math> spełnia nierówność:




<center><math>m \leq 2  \sum_{i=1}^{n}w_i
<center><math>m \leq 2  \sum_{i=1}^{n}w_i\text{.}
</math></center>
</math></center>


Linia 461: Linia 442:




<center><math>u \geq \sum_{i=1}^{n}w_i\textnormal{,}
<center><math>u \geq \sum_{i=1}^{n}w_i\text{,}
</math></center>
</math></center>


Linia 473: Linia 454:


{{twierdzenie|6.3|tw 5.3|
{{twierdzenie|6.3|tw 5.3|
O ile <math>\cc{P}\neq\cc{NP}</math>, to dla żadnego algorytmu aproksymacyjnego <math>\mathcal{A}</math> nie istnieje stała <math>a < \frac{3}{2}</math> taka, że <math>\mathcal{A}</math> jest algorytmem <math>a</math>-aproksymacyjnym.
O ile <math>\mathrm{P}\neq\mathrm{NP}</math>, to dla żadnego algorytmu aproksymacyjnego <math>\mathcal{A}</math> nie istnieje stała <math>a < \frac{3}{2}</math> taka, że <math>\mathcal{A}</math> jest algorytmem <math>a</math>-aproksymacyjnym.
}}
}}


{{dowod|||
{{dowod|||
Dowód oparty jest o redukcję problemu PARTITION. Dla konkretnej instancji problemu PARTITION z elementami <math>a_1,a_2,\ldots,a_n</math> i sumą wag <math>S=\sum_{i=1}^{n}\func{s}(a_i)</math> konstruujemy instancję problemu BIN PACKING z wagami <math>\frac{2 \func{s}(a_1)}{S},\frac{2 \func{s}(a_2)}{S},\ldots,\frac{2 \func{s}(a_n)}{S}</math>.
Dowód oparty jest o redukcję problemu PARTITION. Dla konkretnej instancji problemu PARTITION z elementami <math>a_1,a_2,\ldots,a_n</math> i sumą wag <math>S=\sum_{i=1}^{n}{s}(a_i)</math> konstruujemy instancję problemu BIN PACKING z wagami <math>\frac{2 {s}(a_1)}{S},\frac{2 {s}(a_2)}{S},\ldots,\frac{2 {s}(a_n)}{S}</math>.


Jeżeli istnieje rozwiązanie problemu PARTITION, to w problemie pakowania wystarczy użyć <math>2</math> pojemników. Każdy algorytm aproksymacyjny <math>\mathcal{A}</math> ze stałą aproksymacji <math>a < \frac{3}{2}</math> musiałby w takim wypadku znaleźć rozwiązanie używające <math>2</math> pojemników i tym samym rozwiązać problem PARTITION.
Jeżeli istnieje rozwiązanie problemu PARTITION, to w problemie pakowania wystarczy użyć <math>2</math> pojemników. Każdy algorytm aproksymacyjny <math>\mathcal{A}</math> ze stałą aproksymacji <math>a < \frac{3}{2}</math> musiałby w takim wypadku znaleźć rozwiązanie używające <math>2</math> pojemników i tym samym rozwiązać problem PARTITION.
}}
}}


Zauważmy jeszcze, że przeprowadzone rozumowanie dowodzi również <math>\cc{NP}</math>-zupełności decyzyjnej wersji problemu BIN-PACKING.
Zauważmy jeszcze, że przeprowadzone rozumowanie dowodzi również <math>\mathrm{NP}</math>-zupełności decyzyjnej wersji problemu BIN-PACKING.


Do problemu pakowania i jego aproksymacji powrócimy jeszcze w następnym rozdziale, aby przyjrzeć mu się z trochę innej perspektywy.
Do problemu pakowania i jego aproksymacji powrócimy jeszcze w następnym rozdziale, aby przyjrzeć mu się z trochę innej perspektywy.


{{cwiczenie|6.4 [<math>\frac{5}{3} \textnormal opt</math> w algorytmie First-Fit]|cw 5.4|
{{cwiczenie|6.4 [<math>\frac{5}{3} \text{opt}</math> w algorytmie First-Fit]|cw 5.4|
Podaj przykład danych wejściowych, dla których algorytm First-Fit używa <math>\frac{5}{3} \textnormal opt</math> pojemników.
Podaj przykład danych wejściowych, dla których algorytm First-Fit używa <math>\frac{5}{3} \text{opt}</math> pojemników.
 
}}
<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"> Można skonstruować taki przykład korzystając tylko z przedmiotów rozmiaru <math>\frac{1}{2}+\epsilon</math>, <math>\frac{1}{3}+\epsilon</math> oraz <math>\frac{1}{7} + \epsilon</math>, gdzie <math>\epsilon = \frac{1}{1000}</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"> Można skonstruować taki przykład, korzystając tylko z przedmiotów rozmiaru <math>\frac{1}{2}+\epsilon</math>, <math>\frac{1}{3}+\epsilon</math> oraz <math>\frac{1}{7} + \epsilon</math>, gdzie <math>\epsilon = \frac{1}{1000}</math>.
</div></div>
</div></div>


Linia 495: Linia 476:




<center><math>6 \times \braq(\frac{1}{7}+\epsilon), 6 \times \braq(\frac{1}{3}+\epsilon), 6 \times \braq(\frac{1}{2}+\epsilon)
<center><math>6 \times (\frac{1}{7}+\epsilon), 6 \times (\frac{1}{3}+\epsilon), 6 \times (\frac{1}{2}+\epsilon)\text{,}
</math></center>
</math></center>




, to użyje on <math>10</math> pojemników. Jeden zostanie wypełniony przez przedmioty rozmiaru <math>\frac{1}{7}+\epsilon</math>, trzy przez <math>\frac{1}{3}+\epsilon</math>, a kolejne sześć przez <math>\frac{1}{2}+\epsilon</math>.
to użyje on <math>10</math> pojemników. Jeden zostanie wypełniony przez przedmioty rozmiaru <math>\frac{1}{7}+\epsilon</math>, trzy przez <math>\frac{1}{3}+\epsilon</math>, a kolejne sześć przez <math>\frac{1}{2}+\epsilon</math>.


Tymczasem rozwiązanie optymalne używa <math>6</math> pojemników umieszczając w nich po jednym z przedmiotów każdego rozmiaru.
Tymczasem rozwiązanie optymalne używa <math>6</math> pojemników, umieszczając w nich po jednym z przedmiotów każdego rozmiaru.


Możemy te same dane zwielokrotnić - podać po <math>12,18,\ldots</math> przedmiotów każdego rozmiaru. Otrzymamy w ten sposób całą rodzinę egzemplarzy dla których rozwiązanie First-Fit jest <math>\frac{5}{3}</math> razy gorsze od optymlanego.
Możemy te same dane zwielokrotnić. Podać po <math>12,18,\ldots</math> przedmiotów każdego rozmiaru. Otrzymamy w ten sposób całą rodzinę przykładów dla których rozwiązanie First-Fit jest <math>\frac{5}{3}</math> razy gorsze od optymlanego.


</div></div>
</div></div>


}}
 


{{cwiczenie|6.5 [Algorytm Next-Fit]|cw 5.5|
{{cwiczenie|6.5 [Algorytm Next-Fit]|cw 5.5|
Linia 515: Linia 496:


# W liście <math>B</math> przechowuj częściowo wypełnione pojemniki. Na początku lista jest pusta.
# W liście <math>B</math> przechowuj częściowo wypełnione pojemniki. Na początku lista jest pusta.
# Przeglądając przedmioty w kolejności dodawaj je do ostatniego pojemnika na liście <math>B</math>, jeżeli jest w nim jeszcze wystarczająco dużo "miejsca". Jeżeli nie można przedmiotu dodać do ostatniego pojemnika, to dodaj nowy pojemnik na koniec listy i włóż przedmiot właśnie do niego.}}
# Przeglądając przedmioty w kolejności, dodawaj je do ostatniego pojemnika na liście <math>B</math>, jeżeli jest w nim jeszcze wystarczająco dużo "miejsca". Jeżeli nie można przedmiotu dodać do ostatniego pojemnika, to dodaj nowy pojemnik na koniec listy i włóż przedmiot właśnie do niego.}}


Pokaż, że jest to algorytm <math>2</math>-aproksymacyjny. Pokaż pesymistyczny przypadek dla tego algorytmu, w którym używa on <math>2 \textnormal opt - 1</math> pojemników.
Pokaż, że jest to algorytm <math>2</math>-aproksymacyjny. Pokaż pesymistyczny przypadek dla tego algorytmu, w którym używa on <math>2 \text{opt} - 1</math> pojemników.


<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"> Zauważ, że suma wielkości przedmiotów w każdych dwóch kolejnych pojemnikach zawsze przekracza <math>1</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"> Zauważ, że suma wielkości przedmiotów w każdych dwóch kolejnych pojemnikach zawsze przekracza <math>1</math>.
Linia 524: Linia 505:
<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"> Pokażemy, że jeżeli algorytm użył <math>m</math> pojemników, to suma wielkości przedmiotów <math>W = \sum_{i=1}^{n} w_i</math> spełnia nierówność:
<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"> Pokażemy, że jeżeli algorytm użył <math>m</math> pojemników, to suma wielkości przedmiotów <math>W = \sum_{i=1}^{n} w_i</math> spełnia nierówność:


<center><math>W > \lfloor{\frac{m}{2}}\rfloor
<center><math>W > \lfloor{\frac{m}{2}}\rfloor\text{.}
</math></center>
</math></center>


Dowód tej nierówności przeprowadzimy indukcyjnie ze względu na <math>m</math>. Dla <math>m=1,2</math> dowód jest oczywisty. Dla <math>m>2</math> możemy założyć, że <math>k</math> przedmiotów zostało upakowanych w pierwszych <math>m-2</math> pojemnikach, a pozostałe w ostatnich dwóch. Możemy wtedy rozbić <math>W</math> na dwie części <math>W_1 = \sum_{i=1}^{k} w_i</math> i <math>W_2 = \sum_{i=k+1}^{n} w_i</math>. Z założenia indukcyjnego mamy <math>W_1 > \lfloor{\frac{m-2}{2}}\rfloor</math> i <math>W_2 > 1</math>, co po zsumowaniu daje <math>W = W_1 + W_2 > \lfloor{\frac{m}{2}}\rfloor</math>. W związku z tym optymalne upakowanie musi użyć co najmniej <math>\lceil{\frac{m}{2}}\rceil</math> pojemników.
Dowód tej nierówności przeprowadzimy indukcyjnie ze względu na <math>m</math>. Dla <math>m=1,2</math> dowód jest oczywisty. Dla <math>m>2</math> możemy założyć, że <math>k</math> przedmiotów zostało upakowanych w pierwszych <math>m-2</math> pojemnikach, a pozostałe w ostatnich dwóch. Możemy wtedy rozbić <math>W</math> na dwie części <math>W_1 = \sum_{i=1}^{k} w_i</math> i <math>W_2 = \sum_{i=k+1}^{n} w_i</math>. Z założenia indukcyjnego mamy <math>W_1 > \lfloor{\frac{m-2}{2}}\rfloor</math> i <math>W_2 > 1</math>, co po zsumowaniu daje <math>W = W_1 + W_2 > \lfloor{\frac{m}{2}}\rfloor</math>. W związku z tym optymalne upakowanie musi użyć co najmniej <math>\lceil{\frac{m}{2}}\rceil</math> pojemników.


Konstrukcja przypadku pesymistycznego przebiega w następujący sposób, że na wejście algorytmu podajemy ciąg przedmiotów o następujących wielkościach:
Konstrukcja przypadku pesymistycznego przebiega w taki sposób, że na wejście algorytmu podajemy ciąg przedmiotów o następujących wielkościach:




<center><math>\frac{n+1}{2n}, \frac{n+2}{2n}, \frac{n-1}{2n}, \frac{n+3}{2n}, \frac{n-2}{2n}, \ldots, \frac{n+\braq(n-2)}{2n}, \frac{n-\braq(n-3)}{2n}, \frac{n+\braq(n-1)}{2n}, \frac{n-\braq(n-2)}{2n}
<center><math>\frac{n+1}{2n}, \frac{n+2}{2n}, \frac{n-1}{2n}, \frac{n+3}{2n}, \frac{n-2}{2n}, \ldots, \frac{n+(n-2)}{2n}, \frac{n-(n-3)}{2n}, \frac{n+(n-1)}{2n}, \frac{n-(n-2)}{2n}
</math></center>
</math></center>




Algorytm Next-Fit upakuje każdy z przedmiotów w osobnym pojemniku, gdyż suma każdych dwóch kolejnych wielkości przekracza <math>1</math>. Zatem użyje on <math>2n-3</math> pojemników. Tymczasem rozwiązanie optymalne używa <math>n-1</math> pojemników łącząc przedmioty <math>\frac{n+a}{2n}</math> i <math>\frac{n-a}{2n}</math> w <math>n-2</math> par i umieszczając przedmiot o wadze <math>\frac{n+\braq(n-1)}{2n}</math> w osobnym pojemniku.
Algorytm Next-Fit upakuje każdy z przedmiotów w osobnym pojemniku, gdyż suma każdych dwóch kolejnych wielkości przekracza <math>1</math>. Zatem użyje on <math>2n-3</math> pojemników. Tymczasem rozwiązanie optymalne używa <math>n-1</math> pojemników, łącząc przedmioty <math>\frac{n+a}{2n}</math> i <math>\frac{n-a}{2n}</math> w <math>n-2</math> par i umieszczając przedmiot o wadze <math>\frac{n+(n-1)}{2n}</math> w osobnym pojemniku.
</div></div>
</div></div>




{{cwiczenie|6.7 [Monotoniczność algorytmów]|cw 5.7|
{{cwiczenie|6.7 [Monotoniczność algorytmów]|cw 5.7|
O algorytmie aproksymacyjnym <math>\mathcal{A}</math> dla problemu BIN PACKING powiemy, że jest monotoniczny, jeżeli liczba pojemników użytych przez <math>\mathcal{A}</math> do upakowania dowolnego podciągu <math>a_{i_1},a_{i_2},\ldots,a_{i_k} \braq(i_1<i_2<\ldots<i_k)</math> ciągu przedmiotów <math>a_1,a_2,\ldots,a_n</math> jest nie większa niż liczba pojemników potrzebnych do upakowania całego ciągu.
O algorytmie aproksymacyjnym <math>\mathcal{A}</math> dla problemu BIN PACKING powiemy, że jest monotoniczny, jeżeli liczba pojemników użytych przez <math>\mathcal{A}</math> do upakowania dowolnego podciągu <math>a_{i_1},a_{i_2},\ldots,a_{i_k} (i_1<i_2<\ldots<i_k)</math> ciągu przedmiotów <math>a_1,a_2,\ldots,a_n</math> jest nie większa niż liczba pojemników potrzebnych do upakowania całego ciągu.


Pokaż, że algorytm First-Fit nie jest monotoniczny, a algorytm Next-Fit jest.
Pokaż, że algorytm First-Fit nie jest monotoniczny, a algorytm Next-Fit jest.
 
}}
<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"> Przykładem ciągu i podciągu dla których First-Fit zachowuje się niemonotonicznie jest na przykład:
<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"> Przykładem ciągu i podciągu dla których First-Fit zachowuje się niemonotonicznie jest na przykład:


Linia 554: Linia 535:
Gdzie podciąg został oznaczony podkreśleniem. Łatwo zauważyć, że First-Fit użyje <math>3</math> pojemników do upakowania całego ciągu i <math>4</math> pojemników do upakowania podciągu.
Gdzie podciąg został oznaczony podkreśleniem. Łatwo zauważyć, że First-Fit użyje <math>3</math> pojemników do upakowania całego ciągu i <math>4</math> pojemników do upakowania podciągu.


Pokażemy, że Next-Fit jest monotoniczny oraz, że jeżeli dla jakiegoś podciągu używa tyle samo pojemników, co dla całego ciągu, to w ostatnim pojemniku pozostawia co najmniej tyle samo miejsca. Dowód poprowadzimy indukcyjnie ze względu na długość ciągu.
Pokażemy, że Next-Fit jest monotoniczny oraz że jeżeli dla jakiegoś podciągu używa tyle samo pojemników, co dla całego ciągu, to w ostatnim pojemniku pozostawia co najmniej tyle samo miejsca. Dowód poprowadzimy indukcyjnie ze względu na długość ciągu.


Dla ciągów jednoelementowych sprawa jest oczywista, a dodatkowe założenie o pozostawianiu co najmniej tyle samo miejsca w ostatnim pojemniku pozwala udowodnić krok indukcyjny.
Dla ciągów jednoelementowych sprawa jest oczywista, a dodatkowe założenie o pozostawianiu co najmniej tyle samo miejsca w ostatnim pojemniku pozwala udowodnić krok indukcyjny.
</div></div>
</div></div>


}}
==Problem plecakowy KNAPSACK==


==Problem plecakowy - KNAPSACK==
Pokażemy teraz prosty algorytm aproksymacyjny dla problemu KNAPSACK. Wersja decyzyjna problemu została już przestawiona wcześniej. Przypomnijmy, że mając zbiór przedmiotów <math>A={a_1,\ldots,a_n}</math> o rozmiarach <math>{s}(a_i)</math> i wartościach <math>{v}(a_i)</math>, chcemy wybrać ich podzbiór tak, żeby suma rozmiarów wybranych przedmiotów nie przekraczała zadanej wielkości <math>B</math>, jednocześnie maksymalizując sumę wartości.
 
Pokażemy teraz prosty algorytm aproksymacyjny dla problemu KNAPSACK. Wersja decyzyjna problemu została już przestawiona wcześniej. Przypomnijmy, że mając zbiór przedmiotów <math>A=\set{a_1,\ldots,a_n}</math> o rozmiarach <math>\func{s}(a_i)</math> i wartościach <math>\func{v}(a_i)</math>, chcemy wybrać ich podzbiór tak, żeby suma rozmiarów wybranych przedmiotów nie przekraczała zadanej wielkości <math>B</math>, jednocześnie maksymalizując sumę wartości.


Najprostsza próba konstrukcji rozwiązania przybliżającego optymalne polega na zastosowaniu algorytmu dla ciągłego problemu plecakowego do sytuacji dyskretnej. Oto algorytm:
Najprostsza próba konstrukcji rozwiązania przybliżającego optymalne polega na zastosowaniu algorytmu dla ciągłego problemu plecakowego do sytuacji dyskretnej. Oto algorytm:


{{algorytm|7.1 [Algorytm zachłanny]|al 6.1|
{{algorytm|7.1 [Algorytm zachłanny]|al 6.1|
# posortuj przedmioty względem malejącej gęstości <math>\func{\varrho}(a_i) = \frac{\func{v}(a_i)}{\func{s}(a_i)}</math>.
# Posortuj przedmioty względem malejącej gęstości <math>{\varrho}(a_i) = \frac{{v}(a_i)}{{s}(a_i)}</math>.
# wybieraj przedmioty po kolei i dodawaj je do rozwiązania, jeżeli tylko jest jeszcze wystarczająco dużo miejsca w plecaku.}}
# Wybieraj przedmioty po kolei i dodawaj je do rozwiązania, jeżeli tylko jest jeszcze wystarczająco dużo miejsca w plecaku.}}


Nie jest trudno pokazać, że ten algorytm nie osiąga żadnej stałej aproksymacji. Dowód tego faktu pozostawiamy jako ćwiczenie.
Nie jest trudno pokazać, że ten algorytm nie osiąga żadnej stałej aproksymacji. Dowód tego faktu pozostawiamy jako ćwiczenie.


Na szczęście da się poprawić wyniki osiągane przez ten algorytm wprowadzając niewielką modyfikację:
Na szczęście da się poprawić wyniki osiągane przez ten algorytm, wprowadzając niewielką modyfikację:


{{algorytm|7.2 [Zmodyfikowany algorytm zachłanny]|al 6.2|
{{algorytm|7.2 [Zmodyfikowany algorytm zachłanny]|al 6.2|
# oblicz rozwiązanie metodą zachłanną.
# Oblicz rozwiązanie metodą zachłanną.
# skonstruuj rozwiązanie zawierające tylko jeden przedmiot - wybierz ten, który ma największą wartość wśród przedmiotów o rozmiarze nie większym niż <math>B</math>.
# Skonstruuj rozwiązanie zawierające tylko jeden przedmiot - wybierz ten, który ma największą wartość wśród przedmiotów o rozmiarze nie większym niż <math>B</math>.
# wybierz lepsze z tych dwóch rozwiązań.}}
# Wybierz lepsze z tych dwóch rozwiązań.}}


{{twierdzenie|7.3|tw 6.3|
{{twierdzenie|7.3|tw 6.3|
Linia 587: Linia 566:
Załóżmy, że wszystkie przedmioty mają rozmiar mniejszy lub równy <math>B</math>. Jeżeli są jakieś większe przedmioty, to i tak nie mają one znaczenia dla żadengo z rozwiązań dopuszczalnych.
Załóżmy, że wszystkie przedmioty mają rozmiar mniejszy lub równy <math>B</math>. Jeżeli są jakieś większe przedmioty, to i tak nie mają one znaczenia dla żadengo z rozwiązań dopuszczalnych.


Przyjmijmy, że przedmiot <math>b</math> maksymalizuje wartość: <math>\forall_{i \leq n}\func{v}(b) \geq \func{v}(a_i)</math>, a przedmioty są już posortowane malejąco względem wartości gęstości (<math>\func{\varrho}(a_1) \geq \func{\varrho}(a_2) \geq \ldots \geq \func{\varrho}(a_n)</math>).
Przyjmijmy, że przedmiot <math>b</math> maksymalizuje wartość: <math>\forall_{i \leq n}{v}(b) \geq {v}(a_i)</math>, a przedmioty są już posortowane malejąco względem wartości gęstości (<math>{\varrho}(a_1) \geq {\varrho}(a_2) \geq \ldots \geq {\varrho}(a_n)</math>).


Niech <math>k</math> będzie numerem pierwszego przedmiotu, którego nie ma w rozwiązaniu znajdowanym przez algorytm zachłanny. Zauważmy, że <math>\func{s}(a_1) + \func{s}(a_2) + \ldots + \func{s}(a_k) > B</math>. Gdyby było inaczej, to algorytm zachłanny wybrałby przedmiot <math>a_k</math> do rozwiązania.
Niech <math>k</math> będzie numerem pierwszego przedmiotu, którego nie ma w rozwiązaniu znajdowanym przez algorytm zachłanny. Zauważmy, że <math>{s}(a_1) + {s}(a_2) + \ldots + {s}(a_k) > B</math>. Gdyby było inaczej, to algorytm zachłanny wybrałby przedmiot <math>a_k</math> do rozwiązania.


Ponieważ przedmioty są posortowane względem <math>\varrho</math>, to zachodzi także:
Ponieważ przedmioty są posortowane względem <math>\varrho</math>, to zachodzi także:




<center><math>\func{v}(a_1) + \func{v}(a_2) + \ldots + \func{v}(a_k) > \textnormal opt
<center><math>{v}(a_1) + {v}(a_2) + \ldots + {v}(a_k) > \text{opt}.
</math></center>
</math></center>


Linia 600: Linia 579:
Jest tak dlatego, że zarówno sumaryczny rozmiar przedmiotów <math>a_1,a_2,\ldots,a_k</math> jest większy niż w rozwiązaniu optymalnym, jak i średnia gęstość tych przedmiotów jest nie mniejsza.
Jest tak dlatego, że zarówno sumaryczny rozmiar przedmiotów <math>a_1,a_2,\ldots,a_k</math> jest większy niż w rozwiązaniu optymalnym, jak i średnia gęstość tych przedmiotów jest nie mniejsza.


Zauważmy na koniec, że <math>\func{v}{b} > \func{v}{a_k}</math>. Możemy więc dokonać podstawienia w poprzednim równaniu otrzymując:
Zauważmy na koniec, że <math>{v}{b} > {v}{a_k}</math>. Możemy więc dokonać podstawienia w poprzednim równaniu otrzymując:




<center><math>\func{v}(a_1) + \func{v}(a_2) + \ldots + \func{v}(a_{k-1}) + \func{v}(b) > \textnormal opt
<center><math>{v}(a_1) + {v}(a_2) + \ldots + {v}(a_{k-1}) + {v}(b) > \text{opt}.
</math></center>
</math></center>




Lewa strona jest teraz mniejsza od sumy obu rozwiązań rozważanych przez zmodyfikowany algorytm zachłanny. Ponieważ algorytm wybiera lepsze z nich, więc jego wartość musi być większa od <math>\frac{1}{2} \textnormal opt</math>.
Lewa strona jest teraz mniejsza od sumy obu rozwiązań rozważanych przez zmodyfikowany algorytm zachłanny. Ponieważ algorytm wybiera lepsze z nich, więc jego wartość musi być większa od <math>\frac{1}{2} \text{opt}</math>.
}}
}}


Linia 614: Linia 593:
{{cwiczenie|7.4 [Algorytm zachłanny dla problemu KNAPSACK]|cw 6.4|
{{cwiczenie|7.4 [Algorytm zachłanny dla problemu KNAPSACK]|cw 6.4|
Pokaż, że zaprezentowany algorytm zachłanny nie jest algorytmem <math>a</math>-aproksymacyjnym dla żadnego <math>a</math>.
Pokaż, że zaprezentowany algorytm zachłanny nie jest algorytmem <math>a</math>-aproksymacyjnym dla żadnego <math>a</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"> Użyj małego przedmiotu o dużej gęstości do "zablokowania" droższego przedmiotu.
<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"> Użyj małego przedmiotu o dużej gęstości do "zablokowania" droższego przedmiotu.
</div></div>
</div></div>
Linia 621: Linia 600:




<center><math>\aligned n & = & 2 \\
<center><math>\begin{align} n & = & 2\text{,} \\
\func{v}(a_1) & = & 2 \\
{v}(a_1) & = & 2\text{,} \\
\func{s}(a_1) & = & 1 \\
{s}(a_1) & = & 1\text{,} \\
\func{\varrho}(a_1) & = & 2 \\
{\varrho}(a_1) & = & 2\text{,} \\
\func{v}(a_2) & = & k \\
{v}(a_2) & = & k\text{,} \\
\func{s}(a_2) & = &  k \\
{s}(a_2) & = &  k\text{,} \\
\func{\varrho}(a_2) & = & 1 \\
{\varrho}(a_2) & = & 1\text{,} \\
B & = & k \\
B & = & k\text{.} \\
\endaligned</math></center>
\end{align}</math></center>




Nietrudno stwierdzić, że rozwiązaniem optymalnym dającym wynik <math>k</math> jest wybranie drugiego przedmiotu. Algorytm zachłanny tymczasem wybierze przedmiot pierwszy, gdyż ma on większą gęstość. Osiągnie tym samym wynik równy <math>2</math>. Dobierając odpowiednio parametr <math>k > 2a</math> możemy pokazać, że nie jest to algorytm <math>a</math>-aproksymacyjny dla żadnego <math>a</math>.
Nietrudno stwierdzić, że rozwiązaniem optymalnym dającym wynik <math>k</math> jest wybranie drugiego przedmiotu. Algorytm zachłanny tymczasem wybierze przedmiot pierwszy, gdyż ma on większą gęstość. Osiągnie tym samym wynik równy <math>2</math>. Dobierając odpowiednio parametr <math>k > 2a</math>, możemy pokazać, że nie jest to algorytm <math>a</math>-aproksymacyjny dla żadnego <math>a</math>.
</div></div>
</div></div>
}}


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

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

Wprowadzenie

W poprzednich modułach pokazaliśmy o wielu problemach, że są NP-zupełne. Jeżeli PNP, to żaden z tych problemów nie może mieć rozwiązania, które działałoby w satysfakcjonujący sposób. Jednak wiele z nich to istotne zagadnienia praktyczne i metody choćby częściowego radzenia sobie z nimi są bardzo potrzebne. Konstruowane rozwiązania heurystyczne idą zazwyczaj w dwóch kierunkach:

  • wyszukiwanie takich podproblemów, dla których można znaleźć rozwiązanie w czasie wielomianowym,
  • szukanie algorytmów aproksymacyjnych, które nie rozwiązują problemu dokładnie, ale podają rozwiązania przybliżone do poprawnych.

W tym i w dwóch następnych modułach zajmiemy się właśnie tym drugim podejściem. Przedstawimy formalizmy, które służą do opisu algorytmów aproksymacyjnych i przeanalizujemy najistotniejsze przykłady.

Problem optymalizacyjny

Zwykłe problemy decyzyjne nie nadają się do aproksymowania, bo nie da się przybliżyć rozwiązania konkretnej instancji problemu, którym jest albo "tak", albo "nie". Problemy, które są podatne na aproksymację, to takie, w których odpowiedzią na konkretną instancję problemu jest jakiś kombinatoryczny obiekt z klasy rozwiązań dopuszczalnych. Wprowadzając dodatkowo funkcję celu na obiektach klasy rozwiązań dopuszczalnych, możemy żądać, aby znaleziona odpowiedź minimalizowała (lub maksymalizowała) wartość tej funkcji po wszystkich rozwiązaniach dopuszczalnych.

Problem, który ma powyżej przedstawioną charakterystykę nazywamy problemem optymalizacyjnym i przedstawimy teraz jego formalną definicję w interesującej nas wersji dotyczącej aproksymowania problemów z klasy NP w czasie wielomianowym:

Definicja 2.1

Problem Π jest problemem NP-optymalizacyjnym, jeżeli składa się z:

  • zbioru instancji DΠ. Rozmiarem instancji |I| dla IDΠ jest ilość bitów potrzebnych do zapisania I,
  • zbioru rozwiązań dopuszczalnych dla każdej instancji SΠI. Zbiór ten musi posiadać dodatkowe własności:
    • SΠI. Dla każdej instancji jest jakieś rozwiązanie dopuszczalne,
    • każde sSΠI ma rozmiar wielomianowy od |I| i istnieje algorytm wielomianowy, który sprawdza, czy dla pary I,s zachodzi sSΠI,
  • funkcji celu objΠ, która przyporządkowuje rozwiązaniom dopuszczalnym nieujemne wartości wymierne. Funkcja ta musi być wielomianowo obliczalna dla każdej pary I,s, gdzie I jest instancją Π, a s dopuszczalnym rozwiązaniem I.

Definicja 2.2

Rozwiązaniem optymalnym minimalizacji (maksymalizacji) dla instancji I problemu NP-optymalizacyjnego Π jest każde z rozwiązań dopuszczalnych, dla którego funkcja celu jest minimalna (maksymalna).

Wartość minimalną (maksymalną) funkcji celu oznaczamy przez optΠI i nazywamy optimum. Często będziemy używać skróconej notacji opt, kiedy nie będzie wątpliwości, jaki problem i jego instancję mamy na myśli.

Problemy optymalizacyjne a problemy decyzyjne

Załóżmy, że mamy problem minimalizacji Π. Dla problemów maksymalizacyjnych całe rozumowanie jest analogiczne.

Z problemem Π w naturalny sposób jest związany problem decyzyjny Σ równoważny pytaniu: "Czy dla zadanej instancji I problemu Π i liczby B istnieje rozwiązanie dopuszczalne osiągające wartość funkcji celu mniejszą niż B?".

Znając wartość optimum dla I, można natychmiast odpowiadać na pytania Σ. Z drugiej strony, zazwyczaj można łatwo znaleźć wartość optΠI, używając algorytmu rozwiązującego Σ. Wystarczy użyć odpowiednio dobranego wyszukiwania binarnego.

Dość oczywistą i ważną własnością jest, że jeżeli problem Σ jest NP-zupełny, to skojarzony z nim problem minimalizacji jest NP-trudny. W dalszej części wykładu będziemy analizować tylko problemy, których wersje decyzyjne są NP-zupełne.

Uwaga 2.3

Dla wielu problemów sama tylko umiejętność znajdowania wartości optimum wystarcza, aby w czasie wielomianowym znaleźć również rozwiązanie optymalne. Nie jest to jednak reguła i są problemy, o których zostało pokazane, że nie mają tej własności. Dlatego trzeba rozróżniać problem znalezienia wartości optimum i znalezienia rozwiązania optymalnego. Oczywiście ten drugi jest dla nas znacznie ciekawszy.

Rozwiązania aproksymacyjne

Wprowadzimy teraz pojęcie algorytmu aproksymacyjnego. Nie będzie ono zbyt restrykcyjne i będzie obejmować każdy algorytm znajdujący jakiekolwiek rozwiązania. Dopiero później zdefiniujemy pojęcia, które pozwolą mówić o skuteczności takich algorytmów.

Definicja 2.4

Algorytmem aproksymacyjnym 𝒜 dla minimalizacji (maksymalizacji) problemu NP-optymalizacyjnego Π nazywamy algorytm, który działa w czasie wielomianowym i dla każdej instancji problemu Π znajduje rozwiązanie dopuszczalne.

W domyśle interesują nas algorytmy, które znajdują rozwiązania przybliżające rozwiązanie optymalne. W związku z tym chcemy ograniczyć błąd jaki może popełnić algorytm. Stąd definicja:

Definicja 2.5

Jeżeli dla problemu minimalizacji Π i algorytmu 𝒜 istnieje stała a+, taka że:


a1IDΠobjΠ(I,𝒜(I))aoptΠ(I),


to 𝒜 jest algorytmem a-aproksymacyjnym. Można też powiedzieć, że a jest stałą aproksymacji algorytmu 𝒜.

Jeżeli Π jest problemem maksymalizacji, to algorytm 𝒜 musi spełniać odwrotną nierówność:


a1IDΠobjΠ(I,𝒜(I))aoptΠ(I).


Istotne jest wymaganie, aby a+, gdyż każdy algorytm aproksymacyjny spełniałby powyższą równość dla a0.

Czasem algorytm nie ma stałej aproksymacji, ale różnicę pomiędzy rozwiązaniami znajdowanymi, a optymalnymi można ograniczyć przez funkcję zależną od rozmiaru instancji. Chcemy mieć możliwość uchwycenia również takich zależności.

Definicja 2.6

Jeżeli dla algorytmu 𝒜 rozwiązującego problem minimalizacji Π istnieje funkcja α:+, taka że:


nα(n)1IDΠobjΠ(I,𝒜(I))α|I|optΠ(I),


to 𝒜 jest algorytmem α-aproksymacyjnym.

Definicja dla problemu maksymalizacji jest analogiczna.

Zaprezentowane definicje pozwalają badać pesymistyczne zachowanie algorytmów. Często można również przeprowadzić analizę przypadku średniego, w którym znalezione rozwiązania są zazwyczaj znacząco lepsze od tych, które występują w przypadku pesymistycznym. My jednak skupimy się poszukiwaniu algorytmów, które dają gwarancję ograniczonego błędu dla dowolnej instancji.

Ćwiczenie 2.7 [Problemy decyzyjne jako problemy optymalizacyjne]

Przyjrzyjmy się bliżej związkom NP-zupełnych problemów decyzyjnych i NP-optymalizacyjnych. Skorzystamy z definicji języka L należącego klasy NP:


L={x:y(x,y)R},


gdzie y jest świadkiem wielomianowo zrównoważonej relacji R. Możemy teraz zdefiniować problem optymalizacyjny związany z językiem L. Instancją problemu ΠL będzie dowolny ciąg bitów x. Rozwiązaniami dopuszczalnymi będą dowolne ciągi y o długości wielomianowo ograniczonej od |x| (z tym samym wielomianem który decyduje o zrównoważeniu relacji R). Funkcja celu natomiast będzie zdefiniowana następująco:


objΠL(x,y)={0(x,y)R1(x,y)R.


Pokaż, że jest to dobrze zdefiniowany problem NP-optymalizacyjny i że o ile problem L jest NP-zupełny i PNP, to dla problemu maksymalizacji ΠL nie ma algorytmu a-aproksymacyjnego.
Wskazówka
Rozwiązanie

Pokrycie wierzchołkowe NODE COVER

Pierwszym problemem, którego możliwość aproksymacji zbadamy jest problem minimalizacji rozmiaru pokrycia wierzchołkowego grafu. Jest to optymalizacyjna wersja problemu NODE COVER. Instancją problemu jest pojedynczy graf. Rozwiązaniami dopuszczalnymi są pokrycia wierzchołkowe tego grafu, a funkcją celu jest rozmiar znalezionego pokrycia. Interesuje nas oczywiście minimalizacja rozmiaru pokrycia.

Zarówno sprawdzenia dopuszczalności rozwiązania, jak i obliczenia funkcji celu można łatwo dokonać w czasie liniowym od rozmiaru grafu.

Algorytm zachłanny

Na początek przeanalizujemy najbardziej naturalne podejście do rozwiązania. Wykorzystamy metodę zachłanną konstruowania algorytmów. Wydaje się, że wybieranie do pokrycia wierzchołków, które mają największy stopień (a więc pokrywają najwięcej krawędzi), pozwala najszybciej pokryć cały graf. Prowadzi to do następującego algorytmu:

Algorytm 3.1 [Algorytm zachłanny]


Dopóki w grafie są krawędzie:

  1. Wybierz wierzchołek v o największym stopniu.
  2. Dodaj v do pokrycia i usuń z grafu wszystkie krawędzie incydentne z v.

Okazuje się jednak, że ten algorytm, nie osiąga stałej aproksymacji. Aby dowieść tego faktu, wystarczy spojrzeć na poniższy przykład:

Pokrycie wierzchołkowe.

Przykład 3.2

Algorytm zachłanny najpierw wybierze do pokrycia wierzchołek z grupy Bn (ma on stopień n, gdy tymczasem wierzchołki z grupy A mają stopień co najwyżej n1). Po usunięciu tego wierzchołka stopień wierzchołków z A spadnie do co najwyżej n2, więc algorytm wybierze wszystkie wierzchołki z grupy Bn1, itd.

W wyniku działania algorytmu zostanie skonstruowane pokrycie BnBn1B2 o rozmiarze nn+nn1++n2, gdy tymczasem rozwiązaniem optymalnym jest pokrycie A o rozmiarze n (rysunek Pokrycie wierzchołkowe).

Używając prostej analizy z wykorzystaniem sumy ciągu harmonicznego, można pokazać, że dla instancji z tej konkretnej rodziny rozwiązanie znajdowane przez algorytm jest Θ(logn) razy gorsze od rozwiązania optymalnego.

Pierwsze, bardzo naturalne, podejście do problemu nie doprowadziło nas do algorytmu ze stałą aproksymacji. Niestety, regułą jest, że nie da się osiągnąć aproksymacji problemów NP-zupełnych tak prostymi sposobami i trzeba szukać bardziej wyrafinowanych metod. Oczywiście są od tej reguły wyjątki, które pokażemy. Teraz skonstruujemy algorytm 2-aproksymacyjny dla problemu pokrycia wierzchołkowego.

Algorytm skojarzeniowy

Algorytm ten jest bardzo prosty w konstrukcji:

Algorytm 3.3 [Algorytm skojarzeniowy]


(animacja Algorytm skojarzeniowy)

  1. Znajdź dowolne skojarzenie maksymalne (w sensie inkluzji) M w grafie G.
  2. Wypisz wszystkie wierzchołki występujące w M.
Algorytm skojarzeniowy.

Twierdzenie 3.4

Algorytm skojarzeniowy jest algorytmem 2-aproksymacyjnym dla problemu minimalizacji rozmiaru pokrycia wierzchołkowego.

Dowód

Najpierw musimy pokazać, że wierzchołki M tworzą pokrycie G. Gdyby jakaś krawędź nie była pokryta, oznaczałoby to, że żaden z jej końców nie należy do M i można by poszerzyć skojarzenie o tę krawędź, co przeczy maksymalności M.

Niech O będzie optymalnym pokryciem. Zauważmy, że ponieważ M jest skojarzeniem, to zawiera |M| krawędzi, z których żadne dwie nie mają wspólnego wierzchołka. Zatem w pokryciu O musi się znajdować przynajmniej jeden z końców każdej z tych krawędzi (w przeciwnym wypadku, krawędź ta byłaby niepokryta przez O). Z tego wynika, że


|M||O|,


a liczba wierzchołków w pokryciu znalezionym przez algorytm wynosi 2M. To dowodzi, że jest to algorytm 2-aproksymacyjny.

Ćwiczenie 3.5 [Pesymistyczny przypadek dla algorytmu skojarzeniowego]

Pokaż rodzinę grafów, dla których wynik algorytmu skojarzeniowego jest dokładnie 2 razy gorszy od optymalnego.

Wskazówka
Rozwiązanie

Ćwiczenie 3.6 [Konstrukcja rozwiązania optymalnego z wyrocznią podającą optimum]

Pokaż, że używając wyroczni podającej rozmiar najmniejszego pokrycia wierzchołkowego dla zadanego grafu, można znaleźć rozwiązanie optymalne problemu NODE COVER w czasie wielomianowym.

Wskazówka
Rozwiązanie

Problem maksymalnego przekroju MAX CUT

Ciekawym problemem optymalizacyjnym, który daje się łatwo aproksymować jest problem maksymalnego przekroju.

Problem [Maksymalny przekrój MAX CUT]

Mając dany graf G=V,E należy podzielić wierzchołki V na dwa podzbiory V1 i V2, tak żeby zmaksymalizować liczbę krawędzi pomiędzy V1, a V2.

Podamy od razu dwa różne algorytmy aproksymacyjne dla tego problemu:

Algorytm 4.1 [Algorytm zachłanny]


  1. Ustaw V1= i V2=.
  2. Przeglądając wierzchołki V w dowolnej kolejności, dodawaj każdy z nich do tego ze zbiorów V1 lub V2, z którym łączy go mniej krawędzi.

Algorytm 4.2 [Algorytm poszukujący lokalnego optimum]


  1. Ustaw V1=V i V2=.
  2. Dopóki istnieje w grafie wierzchołek x taki, że przesunięcie go z jednego zbioru do drugiego zwiększa rozmiar przekroju, dokonuj takiego przesunięcia.

Twierdzenie 4.3

Algorytm zachłanny i poszukujący lokalnego optimum są algorytmami 12-aproksymacyjnymi.

Dowód

Dowód dla algorytmu zachłannego jest wyjątkowo prosty. Niech v1,v2,,vn będzie kolejnością w jakiej są przeglądane wierzchołki. Oznaczmy przez ei liczbę krawędzi dodanych do przekroju, kiedy był dodawany wierzchołek vi, a przez ei¯ liczbę pozostałych krawędzi łączących vi z v1,v2,,vi1. Algorytm wybiera przyporządkowanie wierzchołka vi w ten sposób, że eiei¯. Mamy zatem:


i=1neii=1nei¯.


Ponieważ każda z krawędzi albo znajduje się w przekroju, albo nie, to zachodzi:


i=1n(ei+ei¯)=|E|


W związku z tym mamy, że przynajmniej połowa wszystkich krawędzi jest w przekroju znalezionym przez algorytm zachłanny. To oczywiście dowodzi 12-aproksymowalności, gdyż w rozwiązaniu optymalnym nie może być więcej krawędzi niż w całym grafie.

Żeby pokazać, że algorytm poszukujący lokalnego optimum jest 12-aproksymacyjny, nadajmy wierzchołkom numerację v1,v2,,vn i oznaczmy przez ei¯ liczbę krawędzi łączących vi z wierzchołkami z tego samego zbioru, a przez ei liczbę pozostałych krawędzi z nim incydentnych. Tu również zachodzi eiei¯. Gdyby dla któregoś z wierzchołków było przeciwnie, to przeniesienie go do drugiego zbioru zwiększyłoby rozmiar przekroju. Dalsza analiza jest taka sama jak poprzednio z tą różnicą, że:


i=1n(ei+ei¯)=2|E|.


W przeciwieństwie do problemu NODE COVER udało nam się skonstruować algorytmy ze stałą aproksymacji dla MAX CUT, używając bardzo prostych technik: techniki zachłannej i lokalnych ulepszeń. Pokazuje to, że czasem zanim zaczniemy głębiej analizować jakiś problem, warto sprawdzić takie najprostsze podejścia.

Ćwiczenie 4.4

Pokaż, że decyzyjna wersja problemu MAX CUT jest NP-zupełna.

Wskazówka
Rozwiązanie

Problem komiwojażera TSP

Teraz przyjrzymy się innemu klasycznemu problemowi. Problem komiwojażera jest jednym z najlepiej zbadanych problemów NP-zupełnych ze względu na swoje praktyczne znaczenie. Warto sobie teraz przypomnieć dowód NP-zupełności jego decyzyjnej wersji. Użyjemy ponownie tych samych redukcji w analizie możliwości aproksymacji.

Optymalizacyjna wersja problemu TSP powstaje w naturalny sposób. Wejściem jest opis odległości pomiędzy n miastami, rozwiązaniami dopuszczalnymi są cykle przechodzące przez wszystkie miasta, a funkcją celu, której wartość chcemy zminimalizować, jest sumaryczna długość cyklu.

Pierwsze smutne spostrzeżenie jest takie, że o ile PNP, to nie ma możliwości skonstruowania dobrego algorytmu aproksymacyjnego. Fakt ten wyraża następujące twierdzenie:

Twierdzenie 5.1

O ile PNP, to dla żadnego algorytmu aproksymacyjnego 𝒜 nie istnieje funkcja obliczalna w czasie wielomianowym α taka, że 𝒜 jest algorytmem α-aproksymacyjnym dla problemu TSP.

Dowód

Dowód wynika bezpośrednio z dowodu NP-zupełności decyzyjnego problemu TSP. Przypomnijmy, że polegał on na redukcji problemu HAMILTON CYCLE. Wykorzystamy teraz tę redukcję do pokazania, że dowolny α-aproksymacyjny algorytm pozwoliłby rozstrzygać problem cyklu Hamiltona, co przeczyłoby PNP.

Załóżmy, że 𝒜 jest algorytmem α-aproksymacyjnym dla problemu TSP. Chcąc zredukować problem cyklu Hamiltona dla grafu G=V,E o n wierzchołkach, tworzymy graf pełny H na wierzchołkach V. Przypisujemy wagi krawędziom w następujący sposób:

  • jeżeli krawędź xyE, to ustalamy jej wagę na 1,
  • w przeciwnym wypadku ustalamy jej wagę na αnn.

Zauważmy, że koszt rozwiązania problemu TSP w grafie H zależy od tego, czy w grafie G był cykl Hamiltona:

  • jeżeli graf G jest grafem Hamiltonowskim, to koszt optymalnej trasy komiwojażera w H wynosi n,
  • w przeciwnym wypadku koszt optymalnej trasy jest większy od αnn (bo została użyta choć jedna krawędź xyE).

Jeżeli teraz podamy graf H na wejście algorytmu 𝒜, to w pierwszym przypadku znajdzie on rozwiązanie o koszcie nie większym niż αnn, a w drugim przypadku większym od tej wartości. Można zatem rozstrzygnąć, czy w grafie G jest cykl Hamiltona, porównując koszt rozwiązania znalezionego przez 𝒜 z αnn.

Pokazany algorytm rozstrzyga NP-zupełny problem HAMILTON CYCLE i działa w czasie wielomianowym. Jest to sprzecznie z założeniem PNP.

Wersja metryczna

Warunek trójkąta.

Pokazaliśmy, że nie ma nadziei na efektywny algorytm dla ogólnego przypadku problemu komiwojażera. Poddamy teraz analizie naturalne zawężenie problemu i odkryjemy, że jest wtedy możliwa dobra aproksymacja. Zawężeniem problemu, o którym mowa, jest nałożenie dodatkowego wymagania na odległości podawane na wejściu. Żądamy, aby spełniały one warunek trójkąta. Dla każdych trzech miast x,y,z musi zachodzić (rysunek Warunek trójkąta):

d(x,y)d(x,z)+d(z,y).


Takie zawężenie problemu nazywa się metrycznym problemem komiwojażera i ma ono wiele praktycznych zastosowań. Nawet przy tych dodatkowych warunkach problem pozostaje NP-zupełny (zwykła redukcja problemu HAMILTON CYCLE tworzy instancję metrycznego problemu komiwojażera).

Zauważmy, że konstrukcja, która pokazywała, że ogólny problem komiwojażera nie może być dobrze aproksymowany, tworzyła wejścia, które zdecydowanie nie zachowywały warunku trójkąta. Daje to nadzieję na istnienie algorytmu aproksymacyjnego dla tego podproblemu.

Najpierw pokażemy algorytm 2-aproksymacyjny, który konstruuje cykl komiwojażera w bardzo sprytny sposób:

Algorytm 5.2 [Algorytm drzewowy]



  1. Znajdź minimalne drzewo rozpinające T w grafie odległości.
  2. Podwój krawędzie drzewa T, otrzymując graf 𝕋.
  3. Znajdź cykl Eulera w grafie 𝕋.
  4. Skonstruuj cykl C, przechodząc po kolei i dodając każdy wierzchołek, który nie został jeszcze dodany do C. (porównaj z rysunkiem Zamiana drzewa rozpinającego na cykl komiwojażera)
Zamiana drzewa rozpinającego na cykl komiwojażera.

Twierdzenie 5.3

Algorytm drzewowy jest algorytmem 2-aproksymacyjnym.

Dowód

Dowód przeprowadzimy, porównując koszt struktur konstruowanych w kolejnych krokach algorytmu względem optymalnego rozwiązania problemu. Tak więc:

  • suma wag krawędzi drzewa T jest mniejsza lub równa kosztowi optymalnego rozwiązania problemu. Jest tak dlatego, gdyż usuwając dowolną krawędź z rozwiązania optymalnego, otrzymujemy drzewo (a raczej ścieżkę) rozpinające grafu. Tymczasem T jest minimalnym drzewem rozpinającym. Mamy więc
  • cost(T)opt,
  • cost(𝕋)=2cost(T)2,
  • cost()=cost(𝕋)2,
musimy teraz pokazać, że konstruując C, nie pogorszymy oszacowania na koszt . Tutaj właśnie skorzystamy z tego, że odległości zachowują warunek trójkąta. Sprawia to, że pomijając wierzchołki i dodając krawędź bezpośrednią pomiędzy końcami usuniętego fragmentu, możemy tylko zmniejszyć całkowity koszt rozwiązania. W związku z tym cost(C)cost()2opt.

Wyniki osiągane przez ten algorytm można poprawić i otrzymać algorytm 32-aproksymacyjny. Szczegóły tego usprawnienia pozostawiamy na ćwiczenia.

Ćwiczenie 5.4 [Algorytm pre-order]

Poddaj analizie następujący algorytm dla metrycznego problemu komiwojażera:

Algorytm 5.5 [Algorytm pre-order]



  1. Znajdź minimalne drzewo rozpinające T w grafie odległości.
  2. Ukorzeń drzewo T i zwróć wierzchołki w kolejności pre-order.
Wskazówka
Rozwiązanie

Ćwiczenie 5.6 [32-aproksymacja]

Możemy zmodyfikować algorytm tak, żeby osiągał znacznie lepsze oszacowanie aproksymacji. Zauważmy, że punktem, który wymaga poprawienia jest podwajanie drzewa rozpinającego. To podwojenie sprawia, że graf staje się grafem Eulerowskim. Osiągniemy teraz ten sam efekt mniejszym kosztem.

Algorytm 5.7 [Algorytm drzewowo-skojarzeniowy]



  1. Znajdź minimalne drzewo rozpinające T w grafie odległości.
  2. Znajdź najtańsze skojarzenie o maksymalnej liczności M w zbiorze wierzchołków o nieparzystym stopniu w T.
  3. 𝕋=T+M.
  4. Znajdź cykl Eulera w grafie 𝕋.
  5. Skonstruuj cykl C przechodząc po kolei i dodając każdy wierzchołek, który nie został jeszcze dodany do C.

Pokaż, że tak skonstruowany algorytm jest poprawnym 32-aproksymacyjnym algorytmem rozwiązującym metryczny problem TSP.

Wskazówka
Rozwiązanie

Pakowanie BIN PACKING

Kolejnym istotnym i dzięki temu dobrze zbadanym problemem, którym się zajmiemy, jest optymalne pakowanie. Przypomnijmy sformułowanie problemu:

Problem [Pakowanie BIN PACKING]

Mając dany zbiór n przedmiotów o wagach wymiernych w1,w2,,wn(0,1], należy znaleźć przyporządkowanie ich do jak najmniejszej liczby pojemników. Suma wag przedmiotów w jednym pojemniku nie może przekraczać 1. Zadaniem optymalizacji jest oczywiście minimalizacja liczby użytych pojemników.

2-aproksymacja

Bardzo łatwo jest podać algorytm 2-aproksymacyjny:

Algorytm 6.1 [Algorytm First-Fit]


(animacja Algorytm First-Fit)

  1. W liście B przechowuj częściowo wypełnione pojemniki. Na początku lista jest pusta.
  2. Przeglądając przedmioty w kolejności, dodawaj je do pierwszego pojemnika na liście B, w którym jest jeszcze wystarczająco dużo "miejsca". Jeżeli nie można przedmiotu dodać do żadnego z pojemników, to dodaj nowy pojemnik do listy i włóż przedmiot właśnie do niego.
Algorytm First-Fit.

Twierdzenie 6.2

Algorytm First-Fit jest algorytmem 2-aproksymacyjnym.

Dowód

Zauważmy, że po zakończeniu algorytmu co najwyżej jeden z pojemników jest wypełniony mniej niż w połowie. Załóżmy, że jest przeciwnie i dwa pojemniki Bi,Bj,i<j są wypełnione mniej niż w połowie. Zatem wszystkie przedmioty znajdujące się w Bj mogłyby zostać dodane do pojemnika Bi. Zatem algorytm First-Fit tak właśnie by postąpił i pojemnik Bj w ogóle nie byłby potrzebny.

Skoro tak, to liczba pojemników użytych przez algorytm First-Fit m spełnia nierówność:


m2i=1nwi.


Dla każdego rozwiązania dopuszczalnego, a więc również optymalnego, ilość użytych pojemników u spełnia nierówność:


ui=1nwi,


gdyż suma wielkości przedmiotów w jednym pojemniku nie przekracza 1.

Te dwie nierówności pozwalają stwierdzić, że First-Fit jest algorytmem 2-aproksymacyjnym.

Teraz pokażemy, że niemożliwe jest osiągnięcie lepszej stałej aproksymacji niż 32. Fakt ten wyraża następujące twierdzenie:

Twierdzenie 6.3

O ile PNP, to dla żadnego algorytmu aproksymacyjnego 𝒜 nie istnieje stała a<32 taka, że 𝒜 jest algorytmem a-aproksymacyjnym.

Dowód

Dowód oparty jest o redukcję problemu PARTITION. Dla konkretnej instancji problemu PARTITION z elementami a1,a2,,an i sumą wag S=i=1ns(ai) konstruujemy instancję problemu BIN PACKING z wagami 2s(a1)S,2s(a2)S,,2s(an)S.

Jeżeli istnieje rozwiązanie problemu PARTITION, to w problemie pakowania wystarczy użyć 2 pojemników. Każdy algorytm aproksymacyjny 𝒜 ze stałą aproksymacji a<32 musiałby w takim wypadku znaleźć rozwiązanie używające 2 pojemników i tym samym rozwiązać problem PARTITION.

Zauważmy jeszcze, że przeprowadzone rozumowanie dowodzi również NP-zupełności decyzyjnej wersji problemu BIN-PACKING.

Do problemu pakowania i jego aproksymacji powrócimy jeszcze w następnym rozdziale, aby przyjrzeć mu się z trochę innej perspektywy.

Ćwiczenie 6.4 [53opt w algorytmie First-Fit]

Podaj przykład danych wejściowych, dla których algorytm First-Fit używa 53opt pojemników.

Wskazówka
Rozwiązanie


Ćwiczenie 6.5 [Algorytm Next-Fit]

Rozważ następujący algorytm:

Algorytm 6.6 [Algorytm Next-Fit]



  1. W liście B przechowuj częściowo wypełnione pojemniki. Na początku lista jest pusta.
  2. Przeglądając przedmioty w kolejności, dodawaj je do ostatniego pojemnika na liście B, jeżeli jest w nim jeszcze wystarczająco dużo "miejsca". Jeżeli nie można przedmiotu dodać do ostatniego pojemnika, to dodaj nowy pojemnik na koniec listy i włóż przedmiot właśnie do niego.

Pokaż, że jest to algorytm 2-aproksymacyjny. Pokaż pesymistyczny przypadek dla tego algorytmu, w którym używa on 2opt1 pojemników.

Wskazówka
Rozwiązanie


Ćwiczenie 6.7 [Monotoniczność algorytmów]

O algorytmie aproksymacyjnym 𝒜 dla problemu BIN PACKING powiemy, że jest monotoniczny, jeżeli liczba pojemników użytych przez 𝒜 do upakowania dowolnego podciągu ai1,ai2,,aik(i1<i2<<ik) ciągu przedmiotów a1,a2,,an jest nie większa niż liczba pojemników potrzebnych do upakowania całego ciągu.

Pokaż, że algorytm First-Fit nie jest monotoniczny, a algorytm Next-Fit jest.

Rozwiązanie

Problem plecakowy KNAPSACK

Pokażemy teraz prosty algorytm aproksymacyjny dla problemu KNAPSACK. Wersja decyzyjna problemu została już przestawiona wcześniej. Przypomnijmy, że mając zbiór przedmiotów A=a1,,an o rozmiarach s(ai) i wartościach v(ai), chcemy wybrać ich podzbiór tak, żeby suma rozmiarów wybranych przedmiotów nie przekraczała zadanej wielkości B, jednocześnie maksymalizując sumę wartości.

Najprostsza próba konstrukcji rozwiązania przybliżającego optymalne polega na zastosowaniu algorytmu dla ciągłego problemu plecakowego do sytuacji dyskretnej. Oto algorytm:

Algorytm 7.1 [Algorytm zachłanny]


  1. Posortuj przedmioty względem malejącej gęstości ϱ(ai)=v(ai)s(ai).
  2. Wybieraj przedmioty po kolei i dodawaj je do rozwiązania, jeżeli tylko jest jeszcze wystarczająco dużo miejsca w plecaku.

Nie jest trudno pokazać, że ten algorytm nie osiąga żadnej stałej aproksymacji. Dowód tego faktu pozostawiamy jako ćwiczenie.

Na szczęście da się poprawić wyniki osiągane przez ten algorytm, wprowadzając niewielką modyfikację:

Algorytm 7.2 [Zmodyfikowany algorytm zachłanny]


  1. Oblicz rozwiązanie metodą zachłanną.
  2. Skonstruuj rozwiązanie zawierające tylko jeden przedmiot - wybierz ten, który ma największą wartość wśród przedmiotów o rozmiarze nie większym niż B.
  3. Wybierz lepsze z tych dwóch rozwiązań.

Twierdzenie 7.3

Zmodyfikowany algorytm zachłanny jest algorytmem 12-aproksymacyjnym dla problemu plecakowego.

Dowód

Załóżmy, że wszystkie przedmioty mają rozmiar mniejszy lub równy B. Jeżeli są jakieś większe przedmioty, to i tak nie mają one znaczenia dla żadengo z rozwiązań dopuszczalnych.

Przyjmijmy, że przedmiot b maksymalizuje wartość: inv(b)v(ai), a przedmioty są już posortowane malejąco względem wartości gęstości (ϱ(a1)ϱ(a2)ϱ(an)).

Niech k będzie numerem pierwszego przedmiotu, którego nie ma w rozwiązaniu znajdowanym przez algorytm zachłanny. Zauważmy, że s(a1)+s(a2)++s(ak)>B. Gdyby było inaczej, to algorytm zachłanny wybrałby przedmiot ak do rozwiązania.

Ponieważ przedmioty są posortowane względem ϱ, to zachodzi także:


v(a1)+v(a2)++v(ak)>opt.


Jest tak dlatego, że zarówno sumaryczny rozmiar przedmiotów a1,a2,,ak jest większy niż w rozwiązaniu optymalnym, jak i średnia gęstość tych przedmiotów jest nie mniejsza.

Zauważmy na koniec, że vb>vak. Możemy więc dokonać podstawienia w poprzednim równaniu otrzymując:


v(a1)+v(a2)++v(ak1)+v(b)>opt.


Lewa strona jest teraz mniejsza od sumy obu rozwiązań rozważanych przez zmodyfikowany algorytm zachłanny. Ponieważ algorytm wybiera lepsze z nich, więc jego wartość musi być większa od 12opt.

Do problemu plecakowego powrócimy jeszcze w następnym rozdziale, aby pokazać, że można osiągnąć znacznie lepszy wynik, niż tylko aproksymacja ze stałą. Problem plecakowy jest przykładem problemu, który można aproksymować praktycznie z dowolną dokładnością.

Ćwiczenie 7.4 [Algorytm zachłanny dla problemu KNAPSACK]

Pokaż, że zaprezentowany algorytm zachłanny nie jest algorytmem a-aproksymacyjnym dla żadnego a.

Wskazówka
Rozwiązanie

Testy końcowe