Professional Documents
Culture Documents
Algorytmy Grafowe
Algorytmy Grafowe
Jakub Lenart
Matematyka Dyskretna
06.04.2023
Na czym polega kolorowanie grafów?
Kolorowanie grafów to problem polegający na przypisaniu kolorów do wierzchołków grafu
w taki sposób, aby sąsiednie wierzchołki miały różne kolory. Inaczej mówiąc, chodzi o to,
aby każdy wierzchołek otrzymał kolor, a żadne dwa sąsiednie wierzchołki nie otrzymały
tego samego koloru.
Problem kolorowania grafów jest istotny w wielu dziedzinach, takich jak grafika
komputerowa, planowanie harmonogramów, projektowanie sieci telekomunikacyjnych i
wiele innych. W praktyce, problem kolorowania grafów jest zwykle trudny, a jego
rozwiązanie zależy od wielu czynników, takich jak struktura grafu, liczba wierzchołków,
liczba kolorów itp.
Istnieje wiele algorytmów kolorowania grafów, które różnią się skutecznością i złożonością
obliczeniową.
1. Algorytm SLF
Algorytm SLF (ang. Smallest Last Vertex) to algorytm kolorowania grafów, który
wykorzystuje sortowanie wierzchołków względem ich stopni, podobnie jak algorytm LF.
Algorytm SLF przypisuje pierwszy możliwy kolor dla pierwszego wierzchołka, a następnie
przechodzi iteracyjnie przez pozostałe wierzchołki, ustawiając ich kolory na
najwcześniejszy możliwy, pomijając kolory sąsiadujących wierzchołków. Jeśli dla danego
wierzchołka nie ma dostępnych kolorów, algorytm wybiera kolejny wierzchołek z listy "last
vertices", który ma najwięcej sąsiadów w już pokolorowanych wierzchołkach i przypisuje
mu pierwszy dostępny kolor.
Algorytm SLF ma złożoność czasową O(n log n) dla grafów o znanym stopniu, lub O(m log
n) dla grafów o nieznanych stopniach, gdzie n to liczba wierzchołków, a m to liczba
krawędzi. Algorytm ten jest często wykorzystywany w praktyce, ponieważ działa dobrze
dla wielu typów grafów.
Strona 1
2. Algorytm heurystyczny LF kolorowania grafów
Algorytm heurystyczny LF (ang. Heuristic Largest First) to modyfikacja algorytmu LF (ang.
Largest First) kolorowania grafów, która ma na celu poprawienie jakości kolorowania
grafów.
Pozostała część algorytmu jest taka sama jak w przypadku algorytmu LF - wierzchołki są
kolorowane w kolejności ustalonej przez heurystykę, a jeśli dla danego wierzchołka nie ma
dostępnych kolorów, algorytm wybiera kolejny wierzchołek z listy wierzchołków, który ma
najwięcej sąsiadów w już pokolorowanych wierzchołkach i przypisuje mu pierwszy
dostępny kolor.
Strona 2
Algorytm heurystyczny LF pozwala na uzyskanie lepszych kolorowań grafów niż algorytm
LF, szczególnie dla grafów o wysokiej gęstości, ale wymaga dodatkowej implementacji i
czasu wykonania ze względu na zastosowanie heurystyki.
Strona 3
Ważne jest, aby wybierać krawędzie w odpowiedniej kolejności, ponieważ może to
wpłynąć na liczbę wymaganych kolorów. Sortowanie krawędzi malejąco według ich stopni
pozwala na minimalizację liczby wymaganych kolorów.
1. Sortujemy krawędzie grafu malejąco według ich stopni, tzn. według sumy stopni
końcowych.
2. Dla każdej krawędzi wybieramy najmniejszy możliwy kolor, który nie został jeszcze
użyty przez żadną z krawędzi sąsiednich.
Strona 4
3. Jeśli nie ma dostępnych kolorów dla danej krawędzi, to wybieramy krawędź z listy
krawędzi, która ma najwięcej sąsiadujących krawędzi o przypisanych już kolorach,
i przypisujemy jej pierwszy dostępny kolor.
4. Powtarzamy kroki 2-3 dla każdej krawędzi.
Algorytm NTL zapewnia, że żadne dwie sąsiednie krawędzie nie mają tego samego koloru,
co oznacza, że wynikowe kolorowanie grafu będzie poprawne. Algorytm może jednak
zwrócić rozwiązanie nieoptymalne i w niektórych przypadkach może być kosztowny.
Algorytm NTL ma złożoność czasową O(m log m), gdzie m to liczba krawędzi w grafie. Jest
to stosunkowo skuteczny algorytm dla grafów o niskiej gęstości, ale może być kosztowny
dla grafów o wysokiej gęstości lub o dużych rozmiarach.
Strona 5
1. Algorytm działa w następujący sposób:
2. Wybierz dowolny wierzchołek startowy.
3. Przejdź do dowolnego sąsiada tego wierzchołka, usuwając jednocześnie tę krawędź
z grafu.
4. Jeśli usunięcie tej krawędzi nie spowoduje rozspójnienia grafu, przejdź do tego
sąsiada i powtórz ten krok.
5. Jeśli usunięcie tej krawędzi spowoduje rozspójnienie grafu, to należy wybrać inną
krawędź, która nie jest mostem (czyli krawędzią, której usunięcie spowoduje
rozspójnienie grafu).
6. Powtórz kroki 3-4, aż do momentu, gdy nie będzie już możliwe przejście do
żadnego sąsiada.
7. Zakończ algorytm.
Jeśli w wyniku działania algorytmu udało się przejść po każdej krawędzi dokładnie raz, to
graf posiada cykl Eulera. W przypadku, gdy nie udało się przejść po każdej krawędzi
dokładnie raz, należy wykonać powyższy algorytm dla pozostałych nieodwiedzonych
krawędzi, aż do momentu, gdy wszystkie krawędzie zostaną odwiedzone. Wtedy, jeśli graf
posiada ścieżkę Eulera, będzie ona zawierała wszystkie krawędzie, a jeśli nie, to graf nie
posiada cyklu ani ścieżki Eulera.
Strona 6
6. Algorytm Hierholzera znajdowania cyklu Eulera
Algorytm Hierholzera to efektywny algorytm znajdowania cyklu Eulera w spójnym grafie
nieskierowanym. Algorytm składa się z następujących kroków:
Strona 7
• B) Jeśli wierzchołek na szczycie stosu nie ma już krawędzi incydentnych z
wierzchołkami spoza cyklu, usuń go ze stosu i dodaj go do cyklu Eulera w kolejności
odwrotnej do kolejności dodawania na stos.
3. Cykl Eulera otrzymujemy poprzez odwrócenie kolejności wierzchołków na stosie.
Algorytm Hierholzera działa w czasie liniowym względem liczby krawędzi grafu. Jednakże,
aby można było zastosować ten algorytm, graf musi spełniać pewne warunki, a mianowicie
musi być spójny oraz każdy wierzchołek musi mieć parzysty stopień.
Strona 8
7. Algorytm mrówkowy wyszukiwania ścieżki Hamiltona
Algorytm mrówkowy wyszukiwania ścieżki Hamiltona jest heurystycznym algorytmem,
który wykorzystuje zachowanie mrówek w celu znalezienia ścieżki Hamiltona w grafie.
Strona 9
Funkcja ant_colony przyjmuje graf graph jako listę list reprezentującą macierz sąsiedztwa
grafu, współczynniki alpha, beta, rho, określające wpływ feromonów, odległości i wartości
heurystycznej na wybór kolejnych wierzchołków, liczbę mrówek num_ants oraz liczbę
iteracji num_iterations.
Strona 10
1. Inicjalizuje macierz feromonów pheromones o wymiarze len(graph) x len(graph).
2. W pętli for wykonuje się num_iterations iteracji.
3. W pętli for wykonuje się num_ants mrówek, każda z nich zaczyna z losowego
wierzchołka.
4. W pętli while każda mrówka wybiera kolejne wierzchołki w sposób
probabilistyczny, wykorzystując macierz feromonów i wartości heurystyczne.
5. Po zebraniu ścieżki przez każdą mrówkę, aktualizowane są wartości feromonów na
ścieżkach, które przebyły mrówki.
6. Zwracany jest najlepszy znaleziony cykl Hamiltona.
Strona 11