Ugrás a tartalomhoz

Floyd–Warshall-algoritmus

Ellenőrzött
A Wikipédiából, a szabad enciklopédiából
Floyd–Warshall-algoritmus
KategóriaLegrövidebb út probléma (súlyozott gráfok esetében)
AdatstruktúraGráf
Legrosszabb időbonyolultság
Legjobb időbonyolultság
Átlagos idő bonyolultság
Legrosszabb tár bonyolultság

A számítástechnikában a Floyd–Warshall-algoritmus (más néven Floyd–algoritmus, a Roy–Warshall-algoritmus, a Roy–Floyd-algoritmus vagy az ún. WFI-algoritmus ) egy olyan algoritmus, amely a megtalálja legrövidebb útvonalakat egy pozitív vagy negatív élsúlyú súlyozott gráfban . (de negatív körök nélkül).[1][2] Az algoritmus egyetlen végrehajtása megtalálja az összes csúcspár közötti legrövidebb távolságok hosszát (összesített súlyát). Annak ellenére, hogy nem adja vissza az útvonalak részleteit, lehetséges az útvonalak rekonstruálása az algoritmus egyszerű módosításával. Az algoritmus egyes változatai arra is használhatóak, hogy megtaláljunk egy a valós számokkal összefüggésben levő tranzitív lezárást, vagy (a Schulze-módszerrel összefüggésben) a legszélesebb útvonalakat az összes csúcspár között egy súlyozott grafikonon.

Előzmények és elnevezések

[szerkesztés]

A Floyd–Warshall-algoritmus a dinamikus programozás egy jól ismert példája, melyet Robert Floyd publikált 1962-ben.[3] Alapvetően megegyezik azon algoritmusokkal, melyeket korábban Bernard Roy 1959-ben kiadott[4] és továbbá Stephen Warshall 1962-ben [5] egy grafikon tranzitív lezárásának a megállapítására, és szorosan kapcsolódik Kleene algoritmusához (1956-ban lett közzétéve) amely témája egy determinisztikus véges automata konvertálása szabályos kifejezésekké.[6] Az algoritmus modern formuláját azaz a három egymásba ágyazott hurkot (for ciklust) először Peter Ingerman fogalmazta meg, szintén 1962-ben.[7]

Algoritmus

[szerkesztés]

A Floyd–Warshall algoritmus összehasonlítja az összes lehetséges utat a grafikonon az egyes csúcspárok között. Képes ezt megtenni összehasonlítással egy gráfban, bár lehet, hogy akár él van a grafikonon, és az élek minden kombinációját szükséges tesztelni. Ez úgy történik, hogy fokozatosan javítja a becslést a két csúcs közötti legrövidebb útvonalra vonatkozóan, amíg a becslés nem lesz optimális.

Vegyünk egy grafikont, csúcsokkal 1-től -ig számozva. Továbbá egy függvényt az ún. amely visszatér a legrövidebb útvonallal és között adott csúcsok használatával: közbenső pontként a csúcsok mentén. Figyelembe véve az adott függvényt a célunk az, hogy megtaláljuk a legrövidebb utat minden -től minden -ig bármelyik csúcs használatával: .

A csúcspárok mindegyikénél a lehet akár

(1) egy útvonal, amely nem megy át -n (amely csak az adott csúcsokat használja: )

vagy

(2) egy útvonal, amely végigmegy -n (-től -ig és aztán -tól -ig, mindkét esetben az adott közbenső csúcsokat használva:  

Tudjuk, hogy a legjobb útvonal -től -ig az amely csak azon csúcsokat használja amik -en keresztül vannak meghatározva a által, és egyértelmű, hogy ha jobb útvonal lenne -től -ig majd onnan -ig, akkor ezen útvonalnak a hossza lenne a legrövidebb út láncolata az -től a -ig (csak a közbenső csúcsok használatával ) és a legrövidebb a -tól -ig (csak a közbenső csúcsok használatával  ).

Ha az él súlya az adott és csúcsok között, akkor meghatározhatjuk a függvényt a következő rekurzív képlet szerint:

a rekurzív eset a következő:

.

Ez a képlet a Floyd–Warshall algoritmus szive. Az algoritmus futása során először kiszámolja a alapján az pároknak a , majd és így tovább. Ez a folyamat addig folytatódik, amíg , és megtaláltuk a legrövidebb utat mindegyik páros számára bármilyen közbenső csúcs használatával. Az alapváltozat pszeudókódja a következő:

Legyen az ún. 'tavolsag' a |V| × |V| minimális távolságok tömbje, amely inicializálva ∞-ig (végtelen)
for each el (u, v) do
    tavolsag[u][v] ← w(u, v)  // Az adott él súlya (u, v)
for each csucs v do
    tavolsag[v][v] ← 0
for k from 1 to |V|
    for i from 1 to |V|
        for j from 1 to |V|
            if tavolsag[i][j] > tavolsag[i][k] + tavolsag[k][j] 
                tavolsag[i][j] ← tavolsag[i][k] + tavolsag[k][j]
            end if

Példa

[szerkesztés]

A fenti algoritmust az alább látható bal oldali grafikonon láthatjuk:

A külső hurok első rekurziója előtt, a fenti k = 0 jelöléssel láthatjuk, az egyetlen ismert útvonalat amely megfelel a grafikon egyes széleinek. k = 1 esetén mindössze 1 útvonal található amely áthalad a csúcson: a [2,1,3] útvonal, amely helyettesíti a [2,3] útvonalat, amelynek kevesebb éle van, de hosszabb (súly szempontjából). A k = 2 esetén az {1,2} csúcsokon átmenő utak találhatók. A piros és a kék négyzet megmutatja, hogy a [4,2,1,3] út, hogy állt össze a korábbi iterációkban felismert két útvonalból a [4,2] és [2,1,3]-ból 2-vel a metszéspontban. A [4,2,3] elérési utat nem vesszük figyelembe, mivel a [2,1,3] a legrövidebb út, amelyet eddig a 2-től 3-ig megfigyeltünk. A k = 3 esetén a {1,2,3} csúcsokon átmenő utak találhatók. Végül, k = 4 -nél az összes legrövidebb útvonal megtalálható.

A távolság mátrixa minden k iterációnál, a frissített távolságokkal (vastag betűvel jelölve):

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


Viselkedés negatív körökkel

[szerkesztés]

A gráfelméletben értelmezett negatív kör egy olyan kör, ahol az élek összege negatív értékhez vezet. Legrövidebb út nem fellelhető egyetlen , csúcspár között sem, amelyek egy negatív kör részét képezik, mert az út hossza -től -ig tetszőlegesen kicsi (negatív). Numerikusan értelmezhető kimeneti értékhez a Floyd – Warshall algoritmus feltételezi, hogy nincs negatív kör. Mindazonáltal, ha vannak negatív körök, a Floyd – Warshall algoritmus felhasználható arra, hogy felismerje ezeket. Az intuíció a következő:

  • A Floyd–Warshall algoritmus iteratív módon felülvizsgálja az út hosszát az összes csúcspár között , beleértve azon eseteket ahol  ;
  • Az út hossza kezdetben nulla;
  • Egy adott út csak javulhat, ha a hossza kisebb mint nulla, vagyis negatív kört jelöl;
  • Az algoritmus után negatív lesz, ha létezik negatív hosszúságú útvonal az és között.

Ennélfogva a negatív körök, Floyd – Warshall algoritmussal történő felismeréséhez meg kell vizsgálni az út mátrix átlóját, a vizsgálat során negatív szám jelenléte jelzi, hogy a grafikon legalább egy negatív kört tartalmaz.[8] A numerikus problémák elkerülése érdekében ellenőrizni kell, hogy vannak-e negatív számok az útvonal mátrixának átlójában az algoritmus belső ciklusán belül.[9] Nyilvánvalóan egy irányítatlan gráfban a negatív él negatív kört (azaz zárt bejárást) hoz létre az érintett csúcsokkal. Figyelembe véve a fenti példa gráfjának minden éle irányítatlan, pl. a 4 - 2 - 4 csúcsszekvencia egy kör, amelynek súlya −2.

Útvonal helyreállítása

[szerkesztés]

A Floyd–Warshall algoritmus általában a csúcspárok közötti útvonalakat adja meg. Azonban egyszerű módosításokkal lehetséges olyan eljárást készíteni ami helyreállítja az útvonalat bármely két végpont csúcsa között. Van rá lehetőség, hogy eltároljuk a tényleges útvonalat az egyik csúcstól egy adott másik csúcshoz, de ez nem szükséges, sőt tárhelyfelhasználás (memória) szempontjából eléggé költséges. Ehelyett a legrövidebb útvonal kiszámítható minden egyes csomópontoknak, idő alatti tárhely felhasználásával amely az egyes fák tárolására szolgáló memória, amely lehetővé teszi számunkra, hogy hatékonyan rekonstruáljunk egy utat bármely két csatlakoztatott csúcsból.

Pszeudókód [10]

[szerkesztés]
Legyen az ún. 'tavolsag'  minimális távolságok tömbje, inicializálva -ig(végtelen)
Legyen a 'kovetkezo' a  csúcsindexek tömbje amely null értékkel inicializálódik.

procedure FloydWarshallUtvonalHelyreallitassal() is
    for each el (u, v) do
        tavolsag[u][v] ← w(u, v)  // Az adott él súlya (u, v)
        kovetkezo[u][v] ← v
    for each csucs v do
        tavolsag[v][v] ← 0
        kovetkezo[v][v] ← v
    for k from 1 to |V| do // általános Floyd-Warshall implementáció
        for i from 1 to |V|
            for j from 1 to |V|
                if tavolsag[i][j] > tavolsag[i][k] + tavolsag[k][j] then
                    tavolsag[i][j] ← tavolsag[i][k] + tavolsagg[k][j]
                    kovetkezo[i][j] ← kovetkezo[i][k]
procedure Utvonal(u, v)
    if tavolsag[u][v] = null then
        return []
    ut = [u]
    while uv
        u ← kovetkezo[u][v]
        ut.append(u)
    return ut

Elemzés

[szerkesztés]

Legyen a , azaz a csúcsok száma . Ahhoz, hogy megtaláljuk az összes értéket a -hoz tartozóan (minden és ) azokból ahol a , számú műveletet igényel. Mivel úgy kezdünk, hogy a és kiszámítjuk az adott mátrixok , , , , összes használt műveletnek a számát, ami: . Ezért az algoritmus bonyolultsága: .

Alkalmazások és általánosítások

[szerkesztés]

A Floyd – Warshall algoritmus felhasználható többek között a következő problémák megoldására:

  • A legrövidebb útvonal számítására irányított gráfokban (Floyd algoritmusa).
  • Irányított gráfok tranzitív lezárására (Warshall algoritmus). Eredeti megfogalmazásában a Warshall algoritmusban a gráf nem súlyozott, és egy logikai szomszédsági mátrix képviseli. Az összeadási műveletet helyettesíti a logikai összekapcsolás (ÉS), a minimális művelet pedig logikus diszjunció (VAGY).
  • Véges automata által elfogadott szabályos nyelvet jelölő reguláris kifejezés keresése ( Kleene algoritmusa, amely egy szorosan kapcsolódó általánosítása a Floyd – Warshall algoritmusnak) [11]
  • Valós mátrixok inverziója ( Gauss – Jordan algoritmus ) [12]
  • Optimális útvonal választás. Ebben az alkalmazásban az érdekesség megtalálni az utat a két csúcs között, maximális áramlással. Ahelyett, hogy a minimumokat vennénk mint a fentebb látható pszeudókódban is, inkább a maximumokat vesszük. Az élek súlya rögzített kényszert reprezentál az áramlásban. Az útvonal súlya ún. szűkületet ábrázol; így a fenti összeadás műveletet a minimális művelet váltja fel.
  • A Pathfinder (útvonal-kereső) hálózatok gyors kiszámítása.
  • Legszélesebb útvonalak / Maximális sávszélesség-útvonalak
  • A különbséghez kötött mátrixok (DBM) kanonikus formájának kiszámítása
  • A gráfok közötti hasonlóság kiszámítása

Megvalósítások

[szerkesztés]

Az algoritmus megvalósításai megannyi programozási nyelven rendelkezésre állnak.

Összehasonlítás más legrövidebb út alapú algoritmusokkal

[szerkesztés]

A Floyd – Warshall algoritmus jó választás az útvonal kiszámításához az összes csúcspár között sűrű grafikonokban, amelyekben a csúcsok többségét vagy az összeset élek kötik össze. A nem negatív élsúlyú ritka gráfok esetében jobb választás, ha Dijkstra algoritmusát használjuk minden lehetséges kezdőpontból, mivel az ismételt Dijkstra futási ideje ( (Fibonacci halom) jobb, mint a Floyd – Warshall algoritmus futási ideje, amikor jelentősen kisebb, mint . A negatív élekkel rendelkező, de negatív körök nélküli ritka gráfoknál Johnson algoritmusa használható, ugyanolyan futási idővel, mint az ismételt Dijkstra megközelítésnél.

Vannak ismert algoritmusok, amelyek gyors mátrixszorzást használnak az összes pár legrövidebb útjának kiszámításához sűrű grafikonokban, ám ezek általában további kikötéseket fogalmaznak meg az élsúlyokhoz (például előírják, hogy kis egész számok legyenek).[13][14] Ezen túlmenően a futási idejükben fellelhető állandó tényezők miatt csak a nagyon nagy grafikonok esetében lennének gyorsabbak mint a Floyd – Warshall algoritmus.

Irodalom

[szerkesztés]
  1. Cormen, Thomas H.; Leiserson, Charles E.; Rivest, Ronald L. (1990). Introduction to Algorithms (1st ed.). MIT Press and McGraw-Hill. ISBN 0-262-03141-8. See in particular Section 26.2, "The Floyd–Warshall algorithm", pp. 558–565 and Section 26.4, "A general framework for solving path problems in directed graphs", pp. 570–576.
  2. Kenneth H. Rosen. Discrete Mathematics and Its Applications, 5th Edition. Addison Wesley (2003). ISBN 978-0-07-119881-3 
  3. Floyd (1962. június 1.). „Algorithm 97: Shortest Path”. Communications of the ACM 5 (6), 345. o. DOI:10.1145/367766.368168. 
  4. Roy (1959). „Transitivité et connexité.” (french nyelven). C. R. Acad. Sci. Paris 249, 216–218. o. 
  5. Warshall (1962. január 1.). „A theorem on Boolean matrices”. Journal of the ACM 9 (1), 11–12. o. DOI:10.1145/321105.321107. 
  6. Kleene, S. C..szerk.: C. E. Shannon and J. McCarthy: Representation of events in nerve nets and finite automata, Automata Studies. Princeton University Press, 3–42. o. (1956) 
  7. Ingerman (1962. november 1.). „Algorithm 141: Path Matrix”. Communications of the ACM 5, 556. o. DOI:10.1145/368996.369016. 
  8. Hochbaum: Section 8.9: Floyd-Warshall algorithm for all pairs shortest paths (PDF). Lecture Notes for IEOR 266: Graph Algorithms and Network Flows. Department of Industrial Engineering and Operations Research, University of California, Berkeley, 2014 [2016. október 20-i dátummal az eredetiből archiválva]. (Hozzáférés: 2020. június 11.)
  9. Stefan Hougardy (2010. április 1.). „The Floyd–Warshall algorithm on graphs with negative cycles”. Information Processing Letters 110, 279–281. o. DOI:10.1016/j.ipl.2010.02.001. 
  10. https://books.goalkicker.com/AlgorithmsBook/
  11. Gross, Jonathan L. & Yellen, Jay (2003), Handbook of Graph Theory, Discrete Mathematics and Its Applications, CRC Press, p. 65, ISBN 9780203490204, <https://books.google.com/books?id=mKkIGIea_BkC&pg=PA65>.
  12. Penaloza. „Algebraic Structures for Transitive Closure”. 
  13. Zwick, Uri (May 2002), "All pairs shortest paths using bridging sets and rectangular matrix multiplication", Journal of the ACM 49 (3): 289–317, DOI 10.1145/567112.567114.
  14. Chan, Timothy M. (January 2010), "More algorithms for all-pairs shortest paths in weighted graphs", SIAM Journal on Computing 39 (5): 2075–2089, DOI 10.1137/08071990x.

Külső linkek

[szerkesztés]

Fordítás

[szerkesztés]

Ez a szócikk részben vagy egészben a Floyd–Warshall algorithm című angol Wikipédia-szócikk fordításán alapul. Az eredeti cikk szerkesztőit annak laptörténete sorolja fel. Ez a jelzés csupán a megfogalmazás eredetét és a szerzői jogokat jelzi, nem szolgál a cikkben szereplő információk forrásmegjelöléseként.