Алгоритм Флойда – Уоршалла
Сорт | Задача о кратчайшем пути для всех пар (для взвешенных графов) |
---|---|
Структура данных | График |
Худшая производительность | |
Лучшая производительность | |
Средняя производительность | |
Наихудшая пространственная сложность |
В информатике алгоритм Флойда-Уоршалла (также известный как алгоритм Флойда , алгоритм Роя-Уоршалла , алгоритм Роя-Флойда или алгоритм WFI ) — это алгоритм поиска кратчайших путей в ориентированном взвешенном графе с положительным или отрицательным краем. веса (но без отрицательных циклов). [ 1 ] [ 2 ] Одно выполнение алгоритма найдет длины (суммированные веса) кратчайших путей между всеми парами вершин. Хотя он не возвращает подробную информацию о самих путях, пути можно восстановить с помощью простых модификаций алгоритма. Версии алгоритма также можно использовать для поиска транзитивного замыкания отношения. , или (в связи с системой голосования Шульце ) широчайшие пути между всеми парами вершин взвешенного графа.
История и именование
[ редактировать ]Алгоритм Флойда-Уоршалла является примером динамического программирования и был опубликован в его ныне признанной форме Робертом Флойдом в 1962 году. [ 3 ] Однако по сути это то же самое, что и алгоритмы, ранее опубликованные Бернаром Роем в 1959 году. [ 4 ] а также Стивеном Уоршаллом в 1962 году. [ 5 ] для нахождения транзитивного замыкания графа, [ 6 ] и тесно связан с алгоритмом Клини (опубликованным в 1956 году) для преобразования детерминированного конечного автомата в регулярное выражение . [ 7 ] Современная формулировка алгоритма в виде трех вложенных циклов for была впервые описана Питером Ингерманом также в 1962 году. [ 8 ]
Алгоритм
[ редактировать ]Алгоритм Флойда-Уоршалла сравнивает множество возможных путей в графе между каждой парой вершин. Он гарантированно находит все кратчайшие пути и может сделать это с помощью сравнения в графике, [ 1 ] [ 9 ] хотя может быть и есть ребра в графе. Это делается путем постепенного улучшения оценки кратчайшего пути между двумя вершинами, пока оценка не станет оптимальной.
Рассмотрим график с вершинами пронумерованы от 1 до . Далее рассмотрим функцию который возвращает длину кратчайшего возможного пути (если он существует) из к использование вершин только из набора как промежуточные точки на этом пути. Теперь, учитывая эту функцию, наша цель — найти длину кратчайшего пути из каждого каждому используя любую вершину в . По определению, это значение , который мы найдем рекурсивно .
Обратите внимание, что должно быть меньше или равно : у нас будет больше гибкости, если нам разрешено использовать вершину . Если на самом деле меньше, чем , то должен существовать путь из к используя вершины который короче любого такого пути, не использующего вершину . Поскольку отрицательных циклов нет, этот путь можно разложить как:
- (1) путь из к который использует вершины , с последующим
- (2) путь из к который использует вершины .
И, конечно же, это должен быть кратчайший такой путь (или несколько из них), иначе мы могли бы еще больше уменьшить длину. Другими словами, мы пришли к рекурсивной формуле:
-
-
- .
-
Базовый случай определяется выражением
где обозначает вес ребра из к если он существует, и ∞ (бесконечность) в противном случае.
Эти формулы составляют основу алгоритма Флойда-Уоршалла. Алгоритм работает, сначала вычисляя для всех пары для , затем , затем , и так далее. Этот процесс продолжается до тех пор, пока , и мы нашли кратчайший путь для всех пары, используя любые промежуточные вершины. Ниже приведен псевдокод для этой базовой версии.
Псевдокод
[ редактировать ]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
Пример
[ редактировать ]Приведенный выше алгоритм выполняется на графике слева ниже:
До первой рекурсии внешнего цикла, обозначенного выше как k = 0 , единственные известные пути соответствовали одиночным ребрам в графе. При k = 1 находятся пути, проходящие через вершину 1: в частности, находится путь [2,1,3], заменяющий путь [2,3], который имеет меньше ребер, но длиннее (по весу ). При k = 2 находятся пути, проходящие через вершины {1,2}. Красные и синие прямоугольники показывают, как путь [4,2,1,3] собирается из двух известных путей [4,2] и [2,1,3], встреченных в предыдущих итерациях, с 2 на пересечении. Путь [4,2,3] не рассматривается, поскольку [2,1,3] — это кратчайший путь от 2 до 3, встреченный на данный момент. При k = 3 пути, проходящие через вершины {1,2,3} найдены. Наконец, при k = 4 найдены все кратчайшие пути.
Матрица расстояний на каждой итерации k с обновленными расстояниями, выделенными жирным шрифтом , будет следующей:
к = 0 | дж | ||||
1 | 2 | 3 | 4 | ||
---|---|---|---|---|---|
я | 1 | 0 | ∞ | −2 | ∞ |
2 | 4 | 0 | 3 | ∞ | |
3 | ∞ | ∞ | 0 | 2 | |
4 | ∞ | −1 | ∞ | 0 |
к = 1 | дж | ||||
1 | 2 | 3 | 4 | ||
---|---|---|---|---|---|
я | 1 | 0 | ∞ | −2 | ∞ |
2 | 4 | 0 | 2 | ∞ | |
3 | ∞ | ∞ | 0 | 2 | |
4 | ∞ | −1 | ∞ | 0 |
к = 2 | дж | ||||
1 | 2 | 3 | 4 | ||
---|---|---|---|---|---|
я | 1 | 0 | ∞ | −2 | ∞ |
2 | 4 | 0 | 2 | ∞ | |
3 | ∞ | ∞ | 0 | 2 | |
4 | 3 | −1 | 1 | 0 |
к = 3 | дж | ||||
1 | 2 | 3 | 4 | ||
---|---|---|---|---|---|
я | 1 | 0 | ∞ | −2 | 0 |
2 | 4 | 0 | 2 | 4 | |
3 | ∞ | ∞ | 0 | 2 | |
4 | 3 | −1 | 1 | 0 |
к = 4 | дж | ||||
1 | 2 | 3 | 4 | ||
---|---|---|---|---|---|
я | 1 | 0 | −1 | −2 | 0 |
2 | 4 | 0 | 2 | 4 | |
3 | 5 | 1 | 0 | 2 | |
4 | 3 | −1 | 1 | 0 |
Поведение при негативных циклах
[ редактировать ]Отрицательный цикл — это цикл, сумма ребер которого дает отрицательное значение. Между любой парой вершин не существует кратчайшего пути , которые составляют часть отрицательного цикла, поскольку длины пути от к может быть сколь угодно малым (отрицательным). Для получения численно значимого результата алгоритм Флойда – Уоршалла предполагает отсутствие отрицательных циклов. Тем не менее, если есть отрицательные циклы, для их обнаружения можно использовать алгоритм Флойда – Уоршалла. Интуиция следующая:
- Алгоритм Флойда – Уоршалла итеративно пересматривает длины путей между всеми парами вершин. , в том числе где ;
- Первоначально длина пути равен нулю;
- Путь можно улучшить только в том случае, если его длина меньше нуля, т.е. обозначает отрицательный цикл;
- Таким образом, после алгоритма будет отрицательным, если существует путь отрицательной длины из вернуться к .
Следовательно, чтобы обнаружить отрицательные циклы с помощью алгоритма Флойда – Уоршалла, можно проверить диагональ матрицы путей, и наличие отрицательного числа указывает на то, что граф содержит хотя бы один отрицательный цикл. [ 9 ] В ходе выполнения алгоритма, если имеется отрицательный цикл, могут появляться экспоненциально большие числа, вплоть до , где — наибольшее абсолютное значение отрицательного ребра на графике. Чтобы избежать проблем переполнения/недополнения, следует проверять наличие отрицательных чисел на диагонали матрицы пути внутри внутреннего цикла алгоритма. [ 10 ] Очевидно, что в неориентированном графе отрицательное ребро создает отрицательный цикл (т. е. замкнутый обход), включающий инцидентные ему вершины. Учитывая, что все ребра приведенного выше примера графа ненаправлены, например, последовательность вершин 4 – 2 – 4 представляет собой цикл с весовой суммой −2.
Реконструкция пути
[ редактировать ]Алгоритм Флойда-Уоршалла обычно предоставляет только длины путей между всеми парами вершин. С помощью простых модификаций можно создать метод для восстановления фактического пути между любыми двумя конечными вершинами. Хотя можно сохранить действительный путь от каждой вершины к другой вершине, в этом нет необходимости, и на самом деле это очень затратно с точки зрения памяти. Вместо этого мы можем использовать дерево кратчайшего пути , которое можно рассчитать для каждого узла в время использования памяти и позволяет нам эффективно восстанавливать направленный путь между любыми двумя соединенными вершинами.
Псевдокод
[ редактировать ]Массив prev[u][v]
содержит предпоследнюю вершину на пути из u
к v
(за исключением случаев prev[v][v]
, где он всегда содержит v
даже если самопетли нет v
): [ 11 ]
let dist be a array of minimum distances initialized to (infinity) let prev 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) prev[u][v] ← u for each vertex v do dist[v][v] ← 0 prev[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] prev[i][j] ← prev[k][j]
procedure Path(u, v) is if prev[u][v] = null then return [] path ← [v] while u ≠ v do v ← prev[u][v] path.prepend(v) return path
Временная сложность
[ редактировать ]Позволять быть , количество вершин. Чтобы найти все из (для всех и ) из тех, требует операции. Поскольку мы начинаем с и вычислить последовательность матрицы , , , , каждый из которых имеет стоимость , общая временная сложность алгоритма равна .
Приложения и обобщения
[ редактировать ]Алгоритм Флойда – Уоршалла можно использовать, среди прочего, для решения следующих задач:
- Кратчайшие пути в ориентированных графах (алгоритм Флойда).
- Транзитивное замыкание ориентированных графов (алгоритм Уоршалла). В исходной формулировке алгоритма Уоршалла граф невзвешен и представлен булевой матрицей смежности . Тогда операция сложения заменяется логической конъюнкцией (И), а операция минимума — логической дизъюнкцией (ИЛИ).
- Поиск регулярного выражения, обозначающего регулярный язык, принимаемый конечным автоматом ( алгоритм Клини , близкое обобщение алгоритма Флойда-Уоршалла) [ 12 ]
- Обращение действительных алгоритм Гаусса – матриц ( Жордана ) [ 13 ]
- Оптимальная маршрутизация. В этом приложении вас интересует поиск пути с максимальным потоком между двумя вершинами. Это означает, что вместо того, чтобы брать минимумы, как в приведенном выше псевдокоде, вместо этого берут максимумы. Веса ребер представляют собой фиксированные ограничения на поток. Веса путей представляют собой узкие места; поэтому описанная выше операция сложения заменяется операцией минимума.
- Быстрое вычисление сетей Pathfinder .
- Самые широкие пути/Пути с максимальной пропускной способностью
- Вычисление канонической формы матриц разностных границ (DBM)
- Вычисление сходства между графиками
- Транзитивное замыкание в графах И/ИЛИ/порог. [ 14 ]
Реализации
[ редактировать ]Реализации доступны для многих языков программирования .
- Для C++ в boost::graph библиотеке
- Для C# в QuikGraph
- Для C# : QuickGraphPCL (вилка QuickGraph с лучшей совместимостью с проектами, использующими переносимые библиотеки классов).
- Для Java в Apache Commons Graph . библиотеке
- Для JavaScript в Cytoscape . библиотеке
- Для Юлии в Graphs.jl пакете
- Для MATLAB в Matlab_bgl. пакете
- Для Perl в Graph модуле
- Для Python в библиотеке SciPy (модуль scipy.sparse.csgraph ) или NetworkX . библиотеке
- Для R в пакетах e1071 и Rfast.
Сравнение с другими алгоритмами кратчайшего пути
[ редактировать ]Для графов с неотрицательными весами ребер алгоритм Дейкстры можно использовать для поиска всех кратчайших путей из одной вершины за время выполнения. . Таким образом, запуск Дейкстры, начиная с каждой вершины, требует времени. . С , это дает наихудшее время выполнения повторения Дейкстры . Хотя это соответствует асимптотическому времени работы алгоритма Флойда-Уоршалла в наихудшем случае, задействованные константы имеют весьма большое значение. Если граф плотный (т. ), алгоритм Флойда-Уоршалла на практике работает лучше. Когда граф разреженный (т. значительно меньше, чем ), Дейкстра имеет тенденцию доминировать.
Для разреженных графов с отрицательными ребрами, но без отрицательных циклов можно использовать алгоритм Джонсона с тем же асимптотическим временем работы, что и повторный подход Дейкстры.
Существуют также известные алгоритмы, использующие быстрое умножение матриц для ускорения вычисления кратчайшего пути для всех пар в плотных графах, но они обычно делают дополнительные предположения о весах ребер (например, требуют, чтобы они были небольшими целыми числами). [ 15 ] [ 16 ] Кроме того, из-за высоких постоянных коэффициентов времени работы они обеспечивают ускорение по сравнению с алгоритмом Флойда-Уоршалла только для очень больших графов.
Ссылки
[ редактировать ]- ^ Jump up to: а б Кормен, Томас Х .; Лейзерсон, Чарльз Э .; Ривест, Рональд Л. (1990). Введение в алгоритмы (1-е изд.). MIT Press и McGraw-Hill. ISBN 0-262-03141-8 . См., в частности, раздел 26.2, «Алгоритм Флойда – Уоршалла», стр. 558–565 и раздел 26.4, «Общая основа решения задач о путях в ориентированных графах», стр. 570–576.
- ^ Кеннет Х. Розен (2003). Дискретная математика и ее приложения, 5-е издание . Эддисон Уэсли. ISBN 978-0-07-119881-3 .
- ^ Флойд, Роберт В. (июнь 1962 г.). «Алгоритм 97: Кратчайший путь» . Коммуникации АКМ . 5 (6): 345. дои : 10.1145/367766.368168 . S2CID 2003382 .
- ^ Рой, Бернард (1959). «Транзитивность и связность» . ЧР акад. наук. Париж (на французском языке). 249 : 216–218.
- ^ Уоршалл, Стивен (январь 1962 г.). «Теорема о булевых матрицах» . Журнал АКМ . 9 (1): 11–12. дои : 10.1145/321105.321107 . S2CID 33763989 .
- ^ Вайсштейн, Эрик В. «Алгоритм Флойда-Уоршалла» . Математический мир .
- ^ Клини, Южная Каролина (1956). «Представление событий в нервных сетях и конечных автоматах». В CE Шеннон и Дж. Маккарти (ред.). Исследования автоматов . Издательство Принстонского университета. стр. 3–42.
- ^ Ингерман, Питер З. (ноябрь 1962 г.). «Алгоритм 141: Матрица путей» . Коммуникации АКМ . 5 (11): 556. дои : 10.1145/368996.369016 . S2CID 29010500 .
- ^ Jump up to: а б Хохбаум, Дорит (2014). «Раздел 8.9: Алгоритм Флойда-Уоршалла для всех пар кратчайших путей» (PDF) . Конспект лекций для IEOR 266: Алгоритмы графов и сетевые потоки . Департамент промышленной инженерии и исследований операций Калифорнийского университета в Беркли . стр. 41–42.
- ^ Стефан Хугарди (апрель 2010 г.). «Алгоритм Флойда – Уоршалла на графах с отрицательными циклами». Письма об обработке информации . 110 (8–9): 279–281. дои : 10.1016/j.ipl.2010.02.001 .
- ^ «Бесплатная книга алгоритмов» .
- ^ Гросс, Джонатан Л.; Йеллен, Джей (2003), Справочник по теории графов , дискретной математике и ее приложениям, CRC Press, стр. 65, ISBN 9780203490204 .
- ^ Пеналоса, Рафаэль. «Алгебраические структуры для транзитивного замыкания». CiteSeerX 10.1.1.71.7650 .
{{cite journal}}
: Для цитирования журнала требуется|journal=
( помощь ) - ^ Гиллис, Дональд (1993). Планирование задач с ограничениями приоритета И/ИЛИ (кандидатская диссертация, Приложение B) (PDF) (Отчет).
- ^ Цвик, Ури (май 2002 г.), «Кратчайшие пути для всех пар с использованием наборов мостов и умножения прямоугольных матриц», Journal of the ACM , 49 (3): 289–317, arXiv : cs/0008011 , doi : 10.1145/567112.567114 , S2CID 1065901 .
- ^ Чан, Тимоти М. (январь 2010 г.), «Дополнительные алгоритмы для кратчайших путей для всех пар во взвешенных графах», SIAM Journal on Computing , 39 (5): 2075–2089, CiteSeerX 10.1.1.153.6864 , doi : 10.1137/08071990x .
Внешние ссылки
[ редактировать ]