Algorytmy i struktury danych

Transkrypt

Algorytmy i struktury danych
Algorytmy i struktury danych
ĆWICZENIE 4 – ALGORYTM Z POWRACANIEM - (16.04.2012)
Prowadząca: dr hab. inż. Małgorzata Sterna
Informatyka i3, poniedziałek godz. 11:45
Adam Matuszewski, nr 106550
Oliver Kostera , nr 106552
1. Implementacja oraz testowanie.
Do implementacji algorytmów posłużyliśmy się językiem C. Najpierw
zaczęliśmy testować wszystkie algorytmy dla gęstości d = 0,4 od n = 6
(najmniejszy możliwy graf spójny o takiej gęstości). Przy n = 20 algorytm
poszukiwania wszystkich cykli Hamiltona stał się zbyt długi i zaniechaliśmy
jego testowanie kontynuując badanie czasu poszukiwania cyklu Eulera i
pojedynczego cyklu Hamiltona z krokiem co 20 do n = 400. Odrębnie
przetestowaliśmy algorytm wyszukiwania cyklu Eulera dla 3 różnych
gęstości d = 0,2; 0,4; 0,6 zaczynając od n = 100, kończąc na n = 750. Dla
tych samych gęstości również sprawdzaliśmy czasy poszukiwania
pojedynczego oraz wszystkich cykli Hamiltona i liczbę wszystkich
możliwych cykli Hamiltona w grafie przerywając testowanie dla danych n i
poszczególnych gęstości gdy czas się stawał się zbyt długi.
2. Porównanie algorytmów poszukujących cykl Eulera i cykl
Hamiltona.
d = 0.4
350
300
250
czas[s]
200
150
100
50
0
7
6
9
8
11
10
13
12
15
14
17
16
19
18
40
20
80
60
120 160 200 240 280 320 360 400
100 140 180 220 260 300 340 380
n
cykl Eulera
Wykres.1
pojedynczy cykl Hamiltona
wszystkie cykle Hamiltona
d = 0,4
n
tE [s]
tH1 [s]
tH [s]
6
0,00
0,00
0,00
7
0,00
0,00
0,00
8
0,00
0,00
0,00
9
0,00
0,00
0,00
10
0,00
0,00
0,00
11
0,00
0,00
0,00
12
0,00
0,00
0,00
13
0,00
0,00
0,00
14
0,00
0,00
0,04
15
0,00
0,00
0,16
16
0,00
0,00
0,96
17
0,00
0,00
5,55
18
0,00
0,00
59,55
19
0,00
0,00
331,58
20
0,00
0,00
-------
40
0,00
0,00
-------
60
0,00
0,00
-------
80
0,00
0,00
-------
100
0,00
0,00
-------
120
0,00
0,00
-------
140
0,00
13,62
-------
160
0,00
0,00
-------
180
0,00
0,00
-------
200
0,00
0,00
-------
220
0,00
0,00
-------
240
0,00
0,00
-------
260
0,01
0,00
-------
280
0,01
0,01
-------
300
0,02
0,00
-------
320
0,02
0,04
-------
340
0,02
0,00
-------
360
0,03
47,00
-------
380
0,04
0,00
-------
400
0,05
0,00
-------
Tab.1
tE - czas poszukiwania cyklu Eulera, tH1 – czas poszukiwania pojedynczego cyklu
Hamiltona, tH – czas poszukiwania wszystkich cykli Hamiltona.
Wyniki testowania wszystkich algorytmów dla gęstości d = 0,4 zostały
przedstawione w tabeli (Tab.1) i na wykresie (Wykres.1) powyżej.
Problem znajdowania cyklu Eulera należy do klasy problemów łatwych (P –
klasy problemów), czyli takich, które są rozwiązywalne przez DTM
(deterministyczną maszynę Turinga) w wielomianowym czasie. Klasyfikacja
ta została dokonana na podstawie tego, że istnieje algorytm, który znajduje
cykl Eulera w czasie rzędu wielomianowego. Złożoność obliczeniowa tego
algorytmu wyniesie O(m), jeżeli graf jest reprezentowany poprzez listę
sąsiedztwa, czyli jest to algorytm wielomianowy.
Problem znajdowania cyklu Hamiltona należy do klasy problemów trudnych
(NP-zupełnych) czyli takich, które nie są rozwiązywalne przez DTM w czasie
wielomianowym. Nie istnieje wielomianowy algorytm poszukujący cykl
Hamiltona. Złożoność obliczeniowa poszukiwania pojedynczego, jak i
wszystkich cykli jest wykładnicza.
3. Poszukiwanie cyklu Eulera.
n
d = 0,2
d = 0,4
d = 0,6
[s]
[s]
[s]
100
0,00
0,00
0,00
200
0,00
0,00
0,00
300
0,00
0,02
0,03
400
0,02
0,05
0,08
500
0,04
0,09
0,14
600
0,08
0,16
0,24
700
0,13
0,25
0,38
720
0,14
0,28
0,41
740
0,15
0,30
0,45
750
0,16
0,31
0,46
Tab.2
Poszukiwanie cyklu Eulera
0.5
0.45
0.4
0.35
czas [s]
0.3
0.25
0.2
0.15
0.1
0.05
0
100
200
300
400
500
600
700
720
740
n
d = 0,2
d = 0,4
d = 0,6
Wykres.2
Wyniki testów algorytmu poszukiwania cyklu Eulera dla 3 różnych gęstości
d = 0,2; 0,4; 0,6 zostały przedstawione powyżej w tabeli (Tab.2) i na
wykresie (Wykres.2).
Metoda wyszukiwania cyklu Eulera oparta jest na algorytmie
przeszukiwania DFS. Z tą różnicą że analizowane są krawędzie zamiast
wierzchołków. Po odwiedzeniu krawędzi, zostaje ona usunięta.
Warunkiem koniecznym i dostatecznym jest spójność grafu, oraz parzysty
stopień wierzchołków. W testowanych grafach istniał cykl ponieważ
generowaliśmy spójne grafy o parzystych stopniach wierzchołków. Proces
generowania grafu zaczynał się od generowania losowego grafu
nieskierowanego o n wierzchołkach i m krawędziach, bez pętli własnych.
Następnie sprawdzany był stopień kolejnych wierzchołków i gdy był on
nieparzysty, tworzono (lub usuwano gdy krawędź istniała) krawędź z
losowym wierzchołkiem o wyższym indeksie. W wyniku takich działań mógł
powstać graf niespójny, więc w tym celu został sprawdzany metodą DFS.
Gdy graf okazał się niespójny, proces tworzenia grafu został rozpoczęty od
nowa. W ten sposób powstały graf był spójny, a stopień wszystkich
wierzchołków był parzysty.
750
Algorytm poszukujący cyklu Eulera przechodzi co najmniej raz przez każdą
z m krawędzi (czas O(m)). Przy użyciu macierzy sąsiedztwa poszukanie
następnika jest O(n). Więc dla n elementów ostatecznie algorytm jest
O(n2+m). Trzeba jeszcze uwzględnić czas usuwania krawędzi po przejściu
przez nią, jednak w macierzy sąsiedztwa jest on symboliczny.
Do reprezentowania grafu wykorzystana została macierz sąsiedztwa, która
posiada dobry czas przejścia do następnego elementu. Najlepszą
reprezentacją pod tym względem byłaby lista następników, jednak
możliwość usuwania krawędzi zadecydowała o tym, że wybrana została
macierz sąsiedztwa. Atut w postaci zajętości pamięci też nie był by aż tak
widoczny, ponieważ dla jednej krawędzi musiałyby być zapamiętywane
dwa następniki.
Z wykresu powyżej można zauważyć, że algorytm zachowuje się
naturalnie, im większa gęstość tym dłuższy czas wykonywania algorytmu,
podobnie jak dla ilości wierzchołków.
4. Poszukiwanie cyklu Hamiltona
n
d = 0,2
d = 0,4
d = 0,6
[s]
[s]
[s]
20
0,00
0,00
0,00
25
1,88
0,00
0,00
30
2,36
0,00
0,00
35
0,05
0,02
0,00
40
0,00
0,00
0,00
45
0,01
0,00
0,00
50
0,00
0,00
0,00
55
0,00
0,00
0,00
60
0,00
0,01
0,00
65
0,36
0,02
0,00
Tab.3a
Poszukiwanie pojedyńczego cyklu Hamiltona
2.5
czas [s]
2
1.5
1
0.5
0
20
25
30
35
40
45
50
55
60
n
d = 0.2
d = 0.4
d = 0.6
Wykres.3a
n
d = 0,2
d = 0,4
d = 0,6
[s]
[s]
[s]
11
0,00
0,00
0,00
12
0,00
0,00
0,07
13
0,00
0,00
0,37
14
0,00
0,02
2,62
15
0,00
0,08
24,65
16
0,00
0,32
214,24
17
0,00
4,82
--------
18
0,00
32,74
--------
19
0,01
--------
--------
20
0,35
--------
--------
Tab.3b
65
Poszukiwanie wszystkich cykli Hamiltona
250
czas [s]
200
150
100
50
0
11
12
13
14
15
16
17
18
19
n
d = 0.2
d = 0.4
d = 0.6
Wykres.3b
n
d = 0,2
d = 0,4
d = 0,6
11
1
5
2140
12
0
2
36585
13
0
878
79571
14
1
651
881646
15
0
182
4237339
16
0
3231
48265006
17
2
57817
-------
18
0
1443467
-------
19
0
-------
-------
20
0
-------
-------
Tab.4
20
Wyniki testowania czasu poszukiwania pojedynczego cyklu Hamiltona
zostały przedstawione w tabeli (Tab.3a) i na wykresie (Wykres.3a) powyżej.
Podobnie jak testy czasu poszukiwania wszystkich cykli Hamiltona (Tab.3b i
Wykres.3b) oraz liczba cykli Hamiltona (Tab.4).
Do poszukiwania cykli Hamiltona wykorzystuje się algorytm z
powracaniem. Algorytm ten generuje wszystkie przypadki odrzucając te,
które nie spełniają wymagań. W ten sposób może wyszukiwać pojedyncze
lub wszystkie rozwiązania.
Algorytm z powracaniem może być wykorzystywany również dla innych
problemów niż poszukiwaniu cyklu Hamiltona, lecz często nie będzie on
najszybszy. Stosuje się go dla problemów NP-zupełnych.
Dla wyszukiwania jednego, jak i wszystkich cykli Hamiltona złożoność
obliczeniowa algorytmu jest wykładnicza i wynosi O(n!), gdzie n! stanowi
liczbę permutacji wierzchołków grafu. Algorytm z powracaniem działa
szybciej niż dokonywania pełnego przeglądu wszystkich możliwych
rozwiązań, gdyż błędne ścieżki zostają wykryte i odrzucone.
Dla wyszukiwania pojedynczego i wszystkich cykli algorytm jest taki sam.
Jednak w poszukiwaniu pojedynczego cyklu po jego znalezieniu algorytm
kończy pracę, więc poszukiwanie wszystkich cykli jest pesymistycznym
przypadkiem poszukiwania pojedynczego rozwiązania. Poszukiwanie
wszystkich cykli jest bardziej „stabilna” od poszukiwania pojedynczego
cyklu, jednak w obu przypadkach czas jest zależny od budowy grafu.
Poszukiwanie pojedynczego cyklu może zakończyć się szybko gdy
znajdziemy cykl na początku poszukiwań, lub wolniej gdy pod koniec.
Do implementacji wykorzystana została macierz sąsiedztwa, z tych samych
powodów jak wyszukiwanie cyklu Eulera.
Ilość wierzchołków i krawędzi ma duży wpływ na czas działania
algorytmów. Dla obu przypadków liczba wierzchołków wpływa na liczbę
różnych przypadków. Im więcej wierzchołków tym większa ilość
przypadków do przeanalizowania (przede wszystkim dla poszukiwania
wszystkich cykli). Ilość krawędzi również ma wpływ, dla poszukiwania
pojedynczego cyklu większa gęstość grafu przyspieszy znalezienie
rozwiązania, ponieważ z każdego wierzchołka będziemy mieli więcej
możliwości przejścia do następnego, dlatego też wraz z gęstością zwiększa
się liczba cykli Hamiltona. Z drugiej strony w poszukiwaniu wszystkich
cykli, mniejsza gęstość pozwoli na szybsze odrzucenie złych rozwiązań.