Złożoność obliczeniowa/Wykład 7: Algorytmy aproksymacyjne: Różnice pomiędzy wersjami
Nie podano opisu zmian |
|||
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. | ||
# | # 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: | ||
Linia 153: | Linia 153: | ||
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. | ||
}} | }} | ||
Linia 175: | Linia 175: | ||
{{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 | 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 tę 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 | ||
Linia 183: | Linia 183: | ||
a liczba wierzchołków w pokryciu znalezionym przez algorytm wynosi <math>2M</math>, | a liczba wierzchołków w pokryciu znalezionym przez algorytm wynosi <math>2M</math>. To dowodzi, że jest to algorytm <math>2</math>-aproksymacyjny. | ||
}} | }} | ||
Linia 204: | Linia 204: | ||
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> | ||
Linia 210: | Linia 210: | ||
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>\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>. | ||
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>}} | ||
Wersja z 10:01, 20 wrz 2006
Wprowadzenie
W poprzednich modułach pokazaliśmy o wielu problemach, że są Parser nie mógł rozpoznać (nieznana funkcja „\cc”): {\displaystyle \cc{NP}} -zupełne. Jeżeli Parser nie mógł rozpoznać (nieznana funkcja „\cc”): {\displaystyle \cc{P}\neq\cc{NP}} , 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 Parser nie mógł rozpoznać (nieznana funkcja „\cc”): {\displaystyle \cc{NP}} w czasie wielomianowym:
Definicja 2.1
Problem jest problemem Parser nie mógł rozpoznać (nieznana funkcja „\cc”): {\displaystyle \cc{NP}} -optymalizacyjnym, jeżeli składa się z:
- zbioru instancji . Rozmiarem instancji dla jest ilość bitów potrzebnych do zapisania ,
- zbioru rozwiązań dopuszczalnych dla każdej instancji Parser nie mógł rozpoznać (nieznana funkcja „\func”): {\displaystyle \func{S_\Pi}{I}}
. Zbiór ten musi posiadać dodatkowe własności:
- Parser nie mógł rozpoznać (nieznana funkcja „\func”): {\displaystyle \func{S_\Pi}{I} \neq \emptyset} . Dla każdej instancji jest jakieś rozwiązanie dopuszczalne,
- każde Parser nie mógł rozpoznać (nieznana funkcja „\func”): {\displaystyle s \in \func{S_\Pi}{I}} ma rozmiar wielomianowy od i istnieje algorytm wielomianowy, który sprawdza, czy dla pary Parser nie mógł rozpoznać (nieznana funkcja „\braq”): {\displaystyle \braq{I,s}} zachodzi Parser nie mógł rozpoznać (nieznana funkcja „\func”): {\displaystyle s \in \func{S_\Pi}{I}} ,
- funkcji celu Parser nie mógł rozpoznać (błąd składni): {\displaystyle \textnormal{obj}_\Pi} , która przyporządkowuje rozwiązaniom dopuszczalnym nieujemne wartości wymierne. Funkcja ta musi być wielomianowo obliczalna dla każdej pary Parser nie mógł rozpoznać (nieznana funkcja „\braq”): {\displaystyle \braq{I,s}} , gdzie jest instancją , a dopuszczalnym rozwiązaniem .
Definicja 2.2
Rozwiązaniem optymalnym minimalizacji (maksymalizacji) dla instancji problemu Parser nie mógł rozpoznać (nieznana funkcja „\cc”): {\displaystyle \cc{NP}} -optymalizacyjnego jest każde z rozwiązań dopuszczalnych, dla którego funkcja celu jest minimalna (maksymalna).
Wartość minimalną (maksymalną) funkcji celu oznaczamy przez Parser nie mógł rozpoznać (błąd składni): {\displaystyle \textnormal{opt}_\Pi}{I}} i nazywamy optimum. Często będziemy używać skróconej notacji Parser nie mógł rozpoznać (błąd składni): {\displaystyle \textnormal{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 problemu i liczby istnieje rozwiązanie dopuszczalne osiągające wartość funkcji celu mniejszą niż ?".
Znając wartość optimum dla , można natychmiast odpowiadać na pytania . Z drugiej strony, zazwyczaj można łatwo znaleźć wartość Parser nie mógł rozpoznać (błąd składni): {\displaystyle \textnormal{opt}_\Pi{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 Parser nie mógł rozpoznać (nieznana funkcja „\cc”): {\displaystyle \cc{NP}} -zupełny, to skojarzony z nim problem minimalizacji jest Parser nie mógł rozpoznać (nieznana funkcja „\cc”): {\displaystyle \cc{NP}} -trudny. W dalszej części wykładu będziemy analizować tylko problemy, których wersje decyzyjne są Parser nie mógł rozpoznać (nieznana funkcja „\cc”): {\displaystyle \cc{NP}} -zupełne.
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 Parser nie mógł rozpoznać (nieznana funkcja „\cc”): {\displaystyle \cc{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 , taka że:
to jest algorytmem -aproksymacyjnym. Można też powiedzieć, że jest stałą aproksymacji algorytmu .
Jeżeli jest problemem maksymalizacji, to algorytm musi spełniać odwrotną nierówność:
Istotne jest wymaganie, aby , gdyż każdy algorytm aproksymacyjny spełniałby powyższą równość dla .
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:
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 Parser nie mógł rozpoznać (nieznana funkcja „\cc”): {\displaystyle \cc{NP}} -zupełnych problemów decyzyjnych i Parser nie mógł rozpoznać (nieznana funkcja „\cc”): {\displaystyle \cc{NP}} -optymalizacyjnych. Skorzystamy z definicji języka należącego klasy Parser nie mógł rozpoznać (nieznana funkcja „\cc”): {\displaystyle \cc{NP}} :
gdzie jest świadkiem wielomianowo zrównoważonej relacji . Możemy teraz zdefiniować problem optymalizacyjny związany z językiem . Instancją problemu będzie dowolny ciąg bitów . Rozwiązaniami dopuszczalnymi będą dowolne ciągi o długości wielomianowo ograniczonej od (z tym samym wielomianem który decyduje o zrównoważeniu relacji ). Funkcja celu natomiast będzie zdefiniowana następująco:
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:
- Wybierz wierzchołek o największym stopniu.
- Dodaj do pokrycia i usuń z grafu wszystkie krawędzie incydentne z .
Okazuje się jednak, że ten algorytm, nie osiąga stałej aproksymacji. Aby dowieść tego faktu, wystarczy spojrzeć na poniższy przykład:
<flash>file=ZO-7-1.swf|width=300|height=300</flash>
<div.thumbcaption>Pokrycie wierzchołkowe.Przykład 3.2
Algorytm zachłanny najpierw wybierze do pokrycia wierzchołek z grupy (ma on stopień , gdy tymczasem wierzchołki z grupy mają stopień co najwyżej ). Po usunięciu tego wierzchołka stopień wierzchołków z spadnie do co najwyżej , więc algorytm wybierze wszystkie wierzchołki z grupy , itd.
W wyniku działania algorytmu zostanie skonstruowane pokrycie o rozmiarze , gdy tymczasem rozwiązaniem optymalnym jest pokrycie o rozmiarze (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 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 Parser nie mógł rozpoznać (nieznana funkcja „\cc”): {\displaystyle \cc{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 -aproksymacyjny dla problemu pokrycia wierzchołkowego.
Algorytm skojarzeniowy
Algorytm ten jest bardzo prosty w konstrukcji:
Algorytm 3.3 [Algorytm skojarzeniowy]
(animacja Algorytm skojarzeniowy)
- Znajdź dowolne skojarzenie maksymalne (w sensie inkluzji) w grafie .
- Wypisz wszystkie wierzchołki występujące w .
Twierdzenie 3.4
Algorytm skojarzeniowy jest algorytmem -aproksymacyjnym dla problemu minimalizacji rozmiaru pokrycia wierzchołkowego.
Dowód
Najpierw musimy pokazać, że wierzchołki tworzą pokrycie . Gdyby jakaś krawędź nie była pokryta, oznaczałoby to, że żaden z jej końców nie należy do i można by poszerzyć skojarzenie o tę krawędź, co przeczy maksymalności .
Niech będzie optymalnym pokryciem. Zauważmy, że ponieważ jest skojarzeniem, to zawiera krawędzi, z których żadne dwie nie mają wspólnego wierzchołka. Zatem w pokryciu 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 ). Z tego wynika, że
a liczba wierzchołków w pokryciu znalezionym przez algorytm wynosi . To dowodzi, że jest to algorytm -aproksymacyjny.

Ćwiczenie 3.5 [Pesymistyczny przypadek dla algorytmu skojarzeniowego]
Ćwiczenie 3.6 [Konstrukcja rozwiązania optymalnego z wyrocznią podającą optimum]
Problem maksymalnego przekroju - MAX CUT
Ciekawym problemem optymalizacyjnym, który daje się łatwo aproksymować jest problem maksymalnego przekroju.
Mając dany graf Parser nie mógł rozpoznać (nieznana funkcja „\braq”): {\displaystyle G=\braq{V,E}} należy podzielić wierzchołki na dwa podzbiory i tak żeby zmaksymalizować liczbę krawędzi pomiędzy , a .
Podamy od razu dwa różne algorytmy aproksymacyjne dla tego problemu:
Algorytm 4.1 [Algorytm zachłanny]
- Ustaw i .
- Przeglądając wierzchołki w dowolnej kolejności dodawaj każdy z nich do tego ze zbiorów , lub , z którym łączy go mniej krawędzi.
Algorytm 4.2 [Algorytm poszukujący lokalnego optimum]
- Ustaw i .
- Dopóki istnieje w grafie wierzchołek taki, że przesunięcie go z jednego zbioru do drugiego zwiększa rozmiar przekrój dokonuj takiego przesunięcia.
Twierdzenie 4.3
Algorytm zachłanny i poszukujacy lokalnego optimum są algorytmami -aproksymacyjnymi.
Dowód
Dowód dla algorytmu zachłannego jest wyjątkowo prosty. Niech będzie kolejnością w jakiej są przeglądane wierzchołki. Oznaczmy przez liczbę krawędzi dodanych do przekroju kiedy był dodawany wierzchołek , a przez liczbę pozostałych krawędzi łączących z . Algorytm wybiera przyporządkowanie wierzchołka w ten sposób, że . Mamy zatem:
Ponieważ każda z krawędzi albo znajduje się w przekroju, albo nie, to zachodzi:
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 -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 -aproksymacyjny nadajmy wierzchołkom numerację i oznaczmy przez liczbę krawędzi łączących z wierzchołkami z tego samego zbioru, a przez liczbę pozostałych krawędzi z nim incydentnych. Tu również zachodzi . 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:

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
Problem komiwojażera - TSP
Teraz przyjrzymy się innemu klasycznemu problemowi - problemowi komiwojażera. Jest to jeden z najlepiej zbadanych problemów Parser nie mógł rozpoznać (nieznana funkcja „\cc”): {\displaystyle \cc{NP}} -zupełnych ze względu na swoje praktyczne znaczenie. Warto sobie teraz przypomnieć dowód Parser nie mógł rozpoznać (nieznana funkcja „\cc”): {\displaystyle \cc{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 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 Parser nie mógł rozpoznać (nieznana funkcja „\cc”): {\displaystyle \cc{P}\neq\cc{NP}} , to nie ma możliwości skonstruowania dobrego algorytmu aproksymacyjnego. Fakt ten wyraża następujące twierdzenie:
Twierdzenie 5.1
O ile Parser nie mógł rozpoznać (nieznana funkcja „\cc”): {\displaystyle \cc{P}\neq\cc{NP}} , 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 Parser nie mógł rozpoznać (nieznana funkcja „\cc”): {\displaystyle \cc{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 Parser nie mógł rozpoznać (nieznana funkcja „\cc”): {\displaystyle \cc{P}\neq\cc{NP}} .
Załóżmy, że jest algorytmem -aproksymacyjnym dla problemu TSP. Chcąc zredukować problem cyklu Hamiltona dla grafu Parser nie mógł rozpoznać (nieznana funkcja „\braq”): {\displaystyle G=\braq{V,E}} o wierzchołkach tworzymy graf pełny na wierzchołkach . Przypisujemy wagi krawędziom w następujący sposób:
- jeżeli krawędź , to ustalamy jej wagę na ,
- w przeciwnym wypadku ustalamy jej wagę na Parser nie mógł rozpoznać (nieznana funkcja „\func”): {\displaystyle \func{\alpha}{n} \cdot n} .
Zauważmy, że koszt rozwiązania problemu TSP w grafie zależy od tego, czy w grafie był cykl Hamiltona:
- jeżeli graf jest grafem Hamiltonowskim, to koszt optymalnej trasy komiwojażera w wynosi ,
- w przeciwnym wypadku koszt optymalnej trasy jest większy od Parser nie mógł rozpoznać (nieznana funkcja „\func”): {\displaystyle \func{\alpha}{n} \cdot n} (bo została użyta choć jedna krawędź .
Jeżeli teraz podamy graf na wejście algorytmu , to w pierwszym przypadku znajdzie on rozwiązanie o koszcie nie większym niż Parser nie mógł rozpoznać (nieznana funkcja „\func”): {\displaystyle \func{\alpha}{n} \cdot n} , a w drugim przypadku większym od tej wartości. Można zatem rozstrzygnąć, czy w grafie jest cykl Hamiltona porównując koszt rozwiązania znalezionego przez z Parser nie mógł rozpoznać (nieznana funkcja „\func”): {\displaystyle \func{\alpha}{n} \cdot n} .
Pokazany algorytm rozstrzyga Parser nie mógł rozpoznać (nieznana funkcja „\cc”): {\displaystyle \cc{NP}} -zupełny problem HAMILTON CYCLE i działa w czasie wielomianowym. Jest to sprzecznie z założeniem Parser nie mógł rozpoznać (nieznana funkcja „\cc”): {\displaystyle \cc{P}\neq\cc{NP}} .

Wersja metryczna
<flash>file=ZO-7-4.swf|width=300|height=150</flash>
<div.thumbcaption>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 musi zachodzić (rysunek Warunek trójkąta):
Takie zawężenie problemu nazywa się metrycznym problemem komiwojażera i ma ono wiele praktycznych zastosowań. Nawet przy tych dodatkowych warunkach problem pozostaje Parser nie mógł rozpoznać (nieznana funkcja „\cc”): {\displaystyle \cc{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 -aproksymacyjny, który konstruuje cykl komiwojażera w bardzo sprytny sposób:
Algorytm 5.2 [Algorytm drzewowy]
- Znajdź minimalne drzewo rozpinające w grafie odległości.
- Podwój krawędzie drzewa otrzymując graf .
- Znajdź cykl Eulera w grafie .
- Skonstruuj cykl przechodząc po kolei i dodając każdy wierzchołek, który nie został jeszcze dodany do . (porównaj z rysunkiem 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.Twierdzenie 5.3
Algorytm drzewowy jest algorytmem -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 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 jest minimalnym drzewem rozpinającym. Mamy więc
- Parser nie mógł rozpoznać (błąd składni): {\displaystyle \textnormal{cost}(T) \leq \textnormal opt} ,
- Parser nie mógł rozpoznać (błąd składni): {\displaystyle \textnormal{cost}({\mathbb{T}}) = 2 \textnormal{cost}(T) \leq 2 \opt} ,
- Parser nie mógł rozpoznać (błąd składni): {\displaystyle \textnormal{cost}({\mathbb{C}}) = \textnormal{cost}({\mathbb{T}}) \leq 2 \opt} ,

Wyniki osiągane przez ten algorytm można poprawić i dostać algorytm -aproksymacyjny. Szczegóły tego usprawnienia pozostawiamy na ćwiczenia.
Ćwiczenie 5.4 [Algorytm pre-order]
Algorytm 5.5 [Algorytm pre-order]
- Znajdź minimalne drzewo rozpinające w grafie odległości.
- Ukorzeń drzewo i zwróć wierzchołki w kolejności pre-order.
Ćwiczenie 5.6 [-aproksymacja]
Algorytm 5.7 [Algorytm drzewowo-skojarzeniowy]
- Znajdź minimalne drzewo rozpinające w grafie odległości.
- Znajdź najtańsze skojarzenie o maksymalnej liczności w zbiorze wierzchołków o nieparzystym stopniu w .
- .
- Znajdź cykl Eulera w grafie .
- Skonstruuj cykl przechodząc po kolei i dodając każdy wierzchołek, który nie został jeszcze dodany do .
Pokaż, że tak skonstruowany algorytm jest poprawnym -aproksymacyjnym algorytmem rozwiązującym metryczny problem TSP.
Pakowanie - BIN PACKING
Kolejnym istotnym i dzięki temu dobrze zbadanym problemem, którym się zajmiemy jest optymalne pakowanie. Przypomnijmy sformułowanie problemu:
Mając dany zbiór przedmiotów o wagach wymiernych . Należy znaleźć przyporządkowanie ich do jak najmniejszej liczby pojemników. Suma wag przedmiotów w jednym pojemniku nie może przekraczać . Zadaniem optymalizacji jest oczywiście minimalizacja liczby użytych pojemników.
-aproksymacja
Bardzo łatwo jest podać algorytm -aproksymacyjny:
Algorytm 6.1 [Algorytm First-Fit]
(animacja Algorytm First-Fit)
- W liście 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 , 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.
<flashwrap>file=ZO-7-6.swf|size=small</flashwrap>
<div.thumbcaption>Algorytm First-Fit.Twierdzenie 6.2
Algorytm First-Fit jest algorytmem -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 - dwa pojemniki są wypełnione mniej niż w połowie. Zatem wszystkie przedmioty znajdujące się w mogłyby zostać dodane do pojemnika . Zatem algorytm First-Fit tak właśnie by postąpił i pojemnik w ogóle nie byłby potrzebny.
Skoro tak, to liczba pojemników użytych przez algorytm First-Fit spełnia nierówność:
Dla każdego rozwiązania dopuszczalnego, a więc również optymalnego, ilość użytych pojemników spełnia nierówność:
gdyż suma wielkości przedmiotów w jednym pojemniku nie przekracza .
Te dwie nierówności pozwalają stwierdzić, że First-Fit jest algorytmem -aproksymacyjnym.

Teraz pokażemy, że niemożliwe jest osiągnięcie lepszej stałej aproksymacji niż . Fakt ten wyraża następujące twierdzenie:
Twierdzenie 6.3
O ile Parser nie mógł rozpoznać (nieznana funkcja „\cc”): {\displaystyle \cc{P}\neq\cc{NP}} , to dla żadnego algorytmu aproksymacyjnego nie istnieje stała taka, że jest algorytmem -aproksymacyjnym.
Dowód
Dowód oparty jest o redukcję problemu PARTITION. Dla konkretnej instancji problemu PARTITION z elementami i sumą wag Parser nie mógł rozpoznać (nieznana funkcja „\func”): {\displaystyle S=\sum_{i=1}^{n}\func{s}(a_i)} konstruujemy instancję problemu BIN PACKING z wagami Parser nie mógł rozpoznać (nieznana funkcja „\func”): {\displaystyle \frac{2 \func{s}(a_1)}{S},\frac{2 \func{s}(a_2)}{S},\ldots,\frac{2 \func{s}(a_n)}{S}} .
Jeżeli istnieje rozwiązanie problemu PARTITION, to w problemie pakowania wystarczy użyć pojemników. Każdy algorytm aproksymacyjny ze stałą aproksymacji musiałby w takim wypadku znaleźć rozwiązanie używające pojemników i tym samym rozwiązać problem PARTITION.

Zauważmy jeszcze, że przeprowadzone rozumowanie dowodzi również Parser nie mógł rozpoznać (nieznana funkcja „\cc”): {\displaystyle \cc{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 [Parser nie mógł rozpoznać (błąd składni): {\displaystyle \frac{5}{3} \textnormal opt} w algorytmie First-Fit]
Ćwiczenie 6.5 [Algorytm Next-Fit]
Algorytm 6.6 [Algorytm Next-Fit]
- W liście 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 , 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 -aproksymacyjny. Pokaż pesymistyczny przypadek dla tego algorytmu, w którym używa on Parser nie mógł rozpoznać (błąd składni): {\displaystyle 2 \textnormal opt - 1} pojemników.
Ćwiczenie 6.7 [Monotoniczność algorytmów]
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 Parser nie mógł rozpoznać (nieznana funkcja „\set”): {\displaystyle A=\set{a_1,\ldots,a_n}} o rozmiarach Parser nie mógł rozpoznać (nieznana funkcja „\func”): {\displaystyle \func{s}(a_i)} i wartościach Parser nie mógł rozpoznać (nieznana funkcja „\func”): {\displaystyle \func{v}(a_i)} , chcemy wybrać ich podzbiór tak, żeby suma rozmiarów wybranych przedmiotów nie przekraczała zadanej wielkości , 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]
- posortuj przedmioty względem malejącej gęstości Parser nie mógł rozpoznać (nieznana funkcja „\func”): {\displaystyle \func{\varrho}(a_i) = \frac{\func{v}(a_i)}{\func{s}(a_i)}} .
- 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]
- 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ż .
- wybierz lepsze z tych dwóch rozwiązań.
Twierdzenie 7.3
Zmodyfikowany algorytm zachłanny jest algorytmem -aproksymacyjnym dla problemu plecakowego.
Dowód
Załóżmy, że wszystkie przedmioty mają rozmiar mniejszy lub równy . Jeżeli są jakieś większe przedmioty, to i tak nie mają one znaczenia dla żadengo z rozwiązań dopuszczalnych.
Przyjmijmy, że przedmiot maksymalizuje wartość: Parser nie mógł rozpoznać (nieznana funkcja „\func”): {\displaystyle \forall_{i \leq n}\func{v}(b) \geq \func{v}(a_i)} , a przedmioty są już posortowane malejąco względem wartości gęstości (Parser nie mógł rozpoznać (nieznana funkcja „\func”): {\displaystyle \func{\varrho}(a_1) \geq \func{\varrho}(a_2) \geq \ldots \geq \func{\varrho}(a_n)} ).
Niech będzie numerem pierwszego przedmiotu, którego nie ma w rozwiązaniu znajdowanym przez algorytm zachłanny. Zauważmy, że Parser nie mógł rozpoznać (nieznana funkcja „\func”): {\displaystyle \func{s}(a_1) + \func{s}(a_2) + \ldots + \func{s}(a_k) > B} . Gdyby było inaczej, to algorytm zachłanny wybrałby przedmiot do rozwiązania.
Ponieważ przedmioty są posortowane względem , to zachodzi także:
Jest tak dlatego, że zarówno sumaryczny rozmiar przedmiotów jest większy niż w rozwiązaniu optymalnym, jak i średnia gęstość tych przedmiotów jest nie mniejsza.
Zauważmy na koniec, że Parser nie mógł rozpoznać (nieznana funkcja „\func”): {\displaystyle \func{v}{b} > \func{v}{a_k}} . Możemy więc dokonać podstawienia w poprzednim równaniu otrzymując:
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 Parser nie mógł rozpoznać (błąd składni): {\displaystyle \frac{1}{2} \textnormal opt}
.

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]