Algoritmus Floyd – Warshall - Floyd–Warshall algorithm

Algoritmus Floyd – Warshall
Třída Problém s nejkratší cestou všech párů (pro vážené grafy)
Datová struktura Graf
Nejhorší výkon
Nejlepší výkon
Průměrný výkon
Nejhorší prostorová složitost

V informatice je Floyd – Warshallův algoritmus (také známý jako Floydův algoritmus , Roy – Warshallův algoritmus , Roy – Floydův algoritmus nebo algoritmus WFI ) algoritmus pro hledání nejkratších cest v orientovaném váženém grafu s kladnou nebo zápornou hranou váhy (ale bez negativních cyklů). Jediným provedením algoritmu se zjistí délky (součtové hmotnosti) nejkratších cest mezi všemi páry vrcholů. Přestože nevrací podrobnosti o samotných cestách, je možné cesty rekonstruovat jednoduchými úpravami algoritmu. Verze algoritmu lze také použít k nalezení přechodného uzavření vztahu nebo (ve spojení s hlasovacím systémem Schulze ) nejširších cest mezi všemi páry vrcholů ve váženém grafu.

Historie a pojmenování

Algoritmus Floyd – Warshall je příkladem dynamického programování a byl publikován ve své aktuálně uznávané podobě Robertem Floydem v roce 1962. Je však v podstatě stejný jako algoritmy, které dříve publikoval Bernard Roy v roce 1959 a také Stephen Warshall v roce 1962 pro nalezení tranzitivního uzavření grafu a je v těsném spojení s Kleeneovým algoritmem (publikovaným v roce 1956) pro převod deterministického konečného automatu na regulární výraz . Moderní formulaci algoritmu jako tří vnořených smyček poprvé popsal Peter Ingerman, také v roce 1962.

Algoritmus

Algoritmus Floyd – Warshall porovnává všechny možné cesty v grafu mezi každou dvojicí vrcholů. Dokáže to pomocí srovnání v grafu, přestože v grafu může být až hran a testuje se každá kombinace hran. Činí tak postupným zlepšováním odhadu na nejkratší cestě mezi dvěma vrcholy, dokud není odhad optimální.

Zvažte graf s vrcholy očíslovanými od 1 do  . Dále zvažte funkci, která vrací nejkratší možnou cestu z do pomocí vrcholů pouze ze sady jako mezilehlých bodů na cestě. Vzhledem k této funkci je nyní naším cílem najít nejkratší cestu od každého ke každému pomocí libovolného vrcholu v .

Pro každý z těchto párů vrcholů může být buď

(1) cesta, která neprochází (používá pouze vrcholy v sadě .)

nebo

(2) cesta, která prochází (od do a poté od do , oba pouze pomocí mezilehlých vrcholů v  )

Víme, že nejlepší cesta od k, která používá pouze vrcholy skrz, je definována a je jasné, že pokud by existovala lepší cesta od do do , pak by délka této cesty byla zřetězení nejkratší cesty od do (pouze pomocí mezilehlých vrcholů v ) a nejkratší cestou od do (pouze pomocí mezilehlých vrcholů v  ).

Pokud je váha hrany mezi vrcholy a , můžeme definovat pomocí následujícího rekurzivního vzorce: základní případ je

a rekurzivní případ je

.

Tento vzorec je srdcem algoritmu Floyd -Warshall. Algoritmus funguje tak, že nejprve vypočítá pro všechny páry pro , potom a tak dále. Tento proces pokračuje, dokud jsme nenašli nejkratší cestu pro všechny páry pomocí jakýchkoli mezilehlých vrcholů. Následuje pseudokód pro tuto základní verzi:

let dist be a |V| × |V| array of minimum distances initialized to ∞ (infinity)
for each edge (u, v) do
    dist[u][v] ← w(u, v)  // The weight of the edge (u, v)
for each vertex v do
    dist[v][v] ← 0
for k from 1 to |V|
    for i from 1 to |V|
        for j from 1 to |V|
            if dist[i][j] > dist[i][k] + dist[k][j] 
                dist[i][j] ← dist[i][k] + dist[k][j]
            end if

Příklad

Algoritmus výše je proveden na grafu vlevo dole:

Příklad Floyd-Warshall.svg

Před první rekurzí vnější smyčky, označené výše k = 0 , odpovídají jediné známé cesty jednotlivým hranám v grafu. Při k = 1 jsou nalezeny cesty, které procházejí vrcholem 1: zejména je nalezena cesta [2,1,3], která nahrazuje cestu [2,3], která má méně hran, ale je delší (pokud jde o hmotnost ). Při k = 2 jsou nalezeny cesty procházející vrcholy {1,2}. Červené a modré pole ukazuje, jak je cesta [4,2,1,3] sestavena ze dvou známých cest [4,2] a [2,1,3], se kterými se setkáváme v předchozích iteracích, přičemž 2 jsou v průsečíku. Cesta [4,2,3] není brána v úvahu, protože [2,1,3] je dosud nejkratší cestou od 2 do 3. Při k = 3 cesty procházející vrcholy {1,2,3} Jsou nalezeny. Nakonec při k = 4 jsou nalezeny všechny nejkratší cesty.

Matice vzdálenosti při každé iteraci k , s aktualizovanými vzdálenostmi tučně , bude:

k = 0 j
1 2 3 4
1 0 −2
2 4 0 3
3 0 2
4 -1 0
k = 1 j
1 2 3 4
1 0 −2
2 4 0 2
3 0 2
4 -1 0
k = 2 j
1 2 3 4
1 0 −2
2 4 0 2
3 0 2
4 3 -1 1 0
k = 3 j
1 2 3 4
1 0 −2 0
2 4 0 2 4
3 0 2
4 3 -1 1 0
k = 4 j
1 2 3 4
1 0 -1 −2 0
2 4 0 2 4
3 5 1 0 2
4 3 -1 1 0

Chování s negativními cykly

Negativní cyklus je cyklus, jehož hrany se sčítají se zápornou hodnotou. Mezi dvojicí vrcholů , které jsou součástí negativního cyklu, neexistuje nejkratší cesta , protože délky cest od do mohou být libovolně malé (záporné). U číselně smysluplného výstupu algoritmus Floyd – Warshall předpokládá, že neexistují žádné negativní cykly. Pokud však existují negativní cykly, lze k jejich detekci použít algoritmus Floyd – Warshall. Intuice je následující:

  • Algoritmus Floyd – Warshall iterativně reviduje délky dráhy mezi všemi páry vrcholů , včetně kde ;
  • Zpočátku je délka cesty nulová;
  • Cesta se na tom může zlepšit, pouze pokud má délku menší než nula, tj. Označuje negativní cyklus;
  • Po algoritmu tedy bude záporné, pokud existuje cesta záporné délky zezadu do .

K detekci negativních cyklů pomocí algoritmu Floyd -Warshall lze tedy zkontrolovat úhlopříčku matice dráhy a přítomnost záporného čísla naznačuje, že graf obsahuje alespoň jeden negativní cyklus. Pokud během provádění algoritmu existuje záporný cyklus, mohou se objevit exponenciálně velká čísla, stejně velká jako kde je největší absolutní hodnota záporné hrany v grafu. Abyste se vyhnuli problémům s přetečením/podtečením, měli byste zkontrolovat záporná čísla na úhlopříčce matice cesty ve vnitřní smyčce for algoritmu. Je zřejmé, že v neorientovaném grafu vytváří negativní hrana negativní cyklus (tj. Uzavřená procházka) zahrnující jeho dopadající vrcholy. Vzhledem k tomu, že všechny hrany výše uvedeného příkladového grafu jsou neorientované, např. Vrcholová posloupnost 4 - 2 - 4 je cyklus se součtem hmotnosti −2.

Rekonstrukce cesty

Algoritmus Floyd – Warshall obvykle poskytuje pouze délky cest mezi všemi páry vrcholů. Pomocí jednoduchých úprav je možné vytvořit metodu pro rekonstrukci skutečné cesty mezi libovolnými dvěma vrcholy koncových bodů. I když lze mít sklon ukládat skutečnou cestu z každého vrcholu k druhému vrcholu, není to nutné a ve skutečnosti je to velmi nákladné z hlediska paměti. Místo toho lze pro každý uzel vypočítat strom nejkratší cesty v čase pomocí paměti pro uložení každého stromu, což nám umožňuje efektivně rekonstruovat cestu z libovolných dvou spojených vrcholů.

Pseudo kód

let dist be a  array of minimum distances initialized to  (infinity)
let next be a  array of vertex indices initialized to null

procedure FloydWarshallWithPathReconstruction() is
    for each edge (u, v) do
        dist[u][v] ← w(u, v)  // The weight of the edge (u, v)
        next[u][v] ← v
    for each vertex v do
        dist[v][v] ← 0
        next[v][v] ← v
    for k from 1 to |V| do // standard Floyd-Warshall implementation
        for i from 1 to |V|
            for j from 1 to |V|
                if dist[i][j] > dist[i][k] + dist[k][j] then
                    dist[i][j] ← dist[i][k] + dist[k][j]
                    next[i][j] ← next[i][k]
procedure Path(u, v)
    if next[u][v] = null then
        return []
    path = [u]
    while uv
        u ← next[u][v]
        path.append(u)
    return path

Analýza

Dovolit být počet vrcholů. Chcete-li najít vše o (pro všechny a ) od těch vyžaduje operace. Vzhledem k tomu, začneme a spočítat pořadí matic , , , celkový počet operací používá . Proto je složitost algoritmu je .

Aplikace a zobecnění

Algoritmus Floyd – Warshall lze použít mimo jiné k řešení následujících problémů:

Implementace

Implementace jsou k dispozici pro mnoho programovacích jazyků .

Porovnání s jinými algoritmy nejkratších cest

Algoritmus Floyd – Warshall je dobrou volbou pro výpočet cest mezi všemi páry vrcholů v hustých grafech , ve kterých je většina nebo všechny páry vrcholů spojeny hranami. U řídkých grafů s nezápornými váhovými hranami lze dosáhnout nižší asymptotické složitosti spuštěním Dijkstraova algoritmu z každého možného počátečního vrcholu, protože doba nejhoršího případu opakování Dijkstra ( pomocí haldy Fibonacci ) je menší než doba běhu Floyd –Warshallův algoritmus, když je výrazně menší než . Pro řídké grafy s negativními hranami, ale bez negativních cyklů, lze použít Johnsonův algoritmus se stejnou asymptotickou dobou běhu jako opakovaný Dijkstra přístup.

Existují také známé algoritmy využívající rychlé násobení matic ke zrychlení výpočtu nejkratší cesty všech párů v hustých grafech, ale ty obvykle vytvářejí další předpoklady o hraničních váhách (například vyžadují, aby to byla malá celá čísla). Kromě toho by kvůli vysokým konstantním faktorům v jejich době běhu poskytovaly zrychlení přes algoritmus Floyd – Warshall pouze pro velmi velké grafy.

Reference

externí odkazy