<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="ru">
	<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=EkaterinaShevchenko</id>
	<title>Алговики - Вклад [ru]</title>
	<link rel="self" type="application/atom+xml" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=EkaterinaShevchenko"/>
	<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/ru/%D0%A1%D0%BB%D1%83%D0%B6%D0%B5%D0%B1%D0%BD%D0%B0%D1%8F:%D0%92%D0%BA%D0%BB%D0%B0%D0%B4/EkaterinaShevchenko"/>
	<updated>2026-10-23T02:46:27Z</updated>
	<subtitle>Вклад</subtitle>
	<generator>MediaWiki 1.43.5</generator>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%A4%D0%BB%D0%BE%D0%B9%D0%B4%D0%B0-%D0%A3%D0%BE%D1%80%D1%88%D0%B5%D0%BB%D0%BB%D0%B0&amp;diff=24794</id>
		<title>Алгоритм Флойда-Уоршелла</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%A4%D0%BB%D0%BE%D0%B9%D0%B4%D0%B0-%D0%A3%D0%BE%D1%80%D1%88%D0%B5%D0%BB%D0%BB%D0%B0&amp;diff=24794"/>
		<updated>2017-12-01T08:11:29Z</updated>

		<summary type="html">&lt;p&gt;EkaterinaShevchenko: /* Масштабируемость реализации алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Автор: Екатерина Шевченко&lt;br /&gt;
== Свойства и структура алгоритма ==&lt;br /&gt;
=== Общее описание алгоритма ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Алгоритм Флойда-Уоршелла&#039;&#039;&#039;&amp;lt;ref&amp;gt;Roy, Bernard. “Transitivité Et Connexité.” Comptes Rendus De l&#039;Académie Des Sciences 249 (1959): 216–218.&amp;lt;/ref&amp;gt;&amp;lt;ref&amp;gt;Warshall, Stephen. “A Theorem on Boolean Matrices.” Journal of the ACM 9, no. 1 (January 1, 1962): 11–12. doi:10.1145/321105.321107.&amp;lt;/ref&amp;gt;&amp;lt;ref&amp;gt;Floyd, Robert W. “Algorithm 97: Shortest Path.” Communications of the ACM 5, no. 6 (June 1, 1962): 345. doi:10.1145/367766.368168.&amp;lt;/ref&amp;gt; предназначен для решения [[Поиск кратчайшего пути для всех пар вершин (APSP)|задачи поиска всех кратчайших путей на графе]]. Для заданного ориентированного взвешенного графа алгоритм находит кратчайшие расстояния между всеми парами вершин за время &amp;lt;math&amp;gt;O(n^3)&amp;lt;/math&amp;gt;. Алгоритм применим к графам с произвольными, в том числе с отрицательными, весами. Таким образом, он является более общим в сравнении с [[Алгоритм Дейкстры|алгоритмом Дейкстры]], который не работает с отрицательными весами ребер. Также алгоритм распознаёт наличие отрицательных циклов.&lt;br /&gt;
&lt;br /&gt;
=== Математическое описание алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Имеем граф &amp;lt;math&amp;gt;G=(V,E)&amp;lt;/math&amp;gt;, в котором каждая вершина пронумерована от &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt; до &amp;lt;math&amp;gt;|V|&amp;lt;/math&amp;gt;. Сформируем матрицу смежности &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt;. Эта матрица имеет размер &amp;lt;math&amp;gt;|V|*|V|&amp;lt;/math&amp;gt; и каждому ее элементу &amp;lt;math&amp;gt;D_{ij}&amp;lt;/math&amp;gt; присвоен вес ребра, соединяющего вершину &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; с вершиной &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt;. Заметим, что в силу ориентированности графа &amp;lt;math&amp;gt;G&amp;lt;/math&amp;gt; матрица &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt; может быть несимметрична. &lt;br /&gt;
&lt;br /&gt;
По мере выполнения алгоритма данная матрица будет перезаписываться: в каждую из ее ячеек внесется значение, определяющее оптимальную длину пути из вершины &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; в вершину &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Полагаем диагональные элементы &amp;lt;math&amp;gt;D_{ii}&amp;lt;/math&amp;gt; равными нулю, а недиагональные элементы, соответствующие не инцидентным вершинам (не имеющим общего ребра), положим равными бесконечности или числу, заведомо большему возможного расстояния между ребрами.&lt;br /&gt;
&lt;br /&gt;
Ключевая часть алгоритма состоит из трех циклов:&amp;lt;br&amp;gt;&lt;br /&gt;
Для k от 1 до |V| выполнять &amp;lt;br&amp;gt;&lt;br /&gt;
Для i от 1 до |V| выполнять &amp;lt;br&amp;gt;&lt;br /&gt;
Для j от 1 до |V| выполнять &amp;lt;br&amp;gt;&lt;br /&gt;
Если &amp;lt;math&amp;gt;{D_{ik}+D_{kj} &amp;lt; D_{ij}}&amp;lt;/math&amp;gt;, то &amp;lt;math&amp;gt;{D_{ij} := D_{ik}+D_{kj}}&amp;lt;/math&amp;gt;. &amp;lt;br&amp;gt;&lt;br /&gt;
=== Вычислительное ядро алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Основной операцией алгоритма является релаксация элементов матрицы смежности: если &amp;lt;math&amp;gt;{D_{ik}+D_{kj} &amp;lt; D_{ij}}&amp;lt;/math&amp;gt;, то производится присваивание &amp;lt;math&amp;gt;{D_{ij} := D_{ik}+D_{kj}}&amp;lt;/math&amp;gt;. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Макроструктура алгоритма ===&lt;br /&gt;
Ключевая часть алгоритма состоит из трех циклов:&amp;lt;br&amp;gt;&lt;br /&gt;
Для k от 1 до |V| выполнять &amp;lt;br&amp;gt;&lt;br /&gt;
Для i от 1 до |V| выполнять &amp;lt;br&amp;gt;&lt;br /&gt;
Для j от 1 до |V| выполнять &amp;lt;br&amp;gt;&lt;br /&gt;
Если &amp;lt;math&amp;gt;{D_{ik}+D_{kj} &amp;lt; D_{ij}}&amp;lt;/math&amp;gt;, то &amp;lt;math&amp;gt;{D_{ij} := D_{ik}+D_{kj}}&amp;lt;/math&amp;gt;. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
При этом вычисляются минимумы из двух чисел  &amp;lt;math&amp;gt;min({D_{ik}+D_{kj}}, D_{ij})&amp;lt;/math&amp;gt; и их значения становятся новыми значениями элементов смежной матрицы. &amp;lt;br&amp;gt;&lt;br /&gt;
=== Схема реализации последовательного алгоритма ===&lt;br /&gt;
matrix - матрица смежности, numberOfVert - число вершин в графе&lt;br /&gt;
&lt;br /&gt;
    //Пробегаемся по всем вершинам и ищем более короткий путь&lt;br /&gt;
    //через вершину k&lt;br /&gt;
    for(int k = 0; k &amp;lt; numberOfVert; k++) {&lt;br /&gt;
        for(int i = 0; i &amp;lt; numberOfVert; i++) {&lt;br /&gt;
           for(int j = 0; j &amp;lt; numberOfVert; j++) {&lt;br /&gt;
                //Новое значение ребра равно минимальному между старым&lt;br /&gt;
                //и суммой ребер i &amp;lt;-&amp;gt; k + k &amp;lt;-&amp;gt; j (если через k пройти быстрее)&lt;br /&gt;
                matrix[i][j] = min(matrix[i][j], matrix[i][k] + matrix[k][j]);&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
=== Последовательная сложность алгоритма ===&lt;br /&gt;
Время выполнения этой программы, очевидно, имеет порядок &amp;lt;math&amp;gt;O(n^3)&amp;lt;/math&amp;gt;, поскольку в ней практически нет ничего, кроме вложенных друг в друга трех циклов.&lt;br /&gt;
&lt;br /&gt;
=== Информационный граф ===&lt;br /&gt;
[[file:Graphforfloyd.png|thumb|center|300px|Рис.1. Информационная структура предельной параллелизации алгоритма Флойда-Уоршелла]]&lt;br /&gt;
&lt;br /&gt;
На приведенном далее информационном графе нижний уровень параллелизма обозначен в горизонтальных плоскостях. Множество всех плоскостей представляет собой верхний уровень параллелизма (операции в каждой плоскости могут выполняться параллельно). Верхний уровень параллелизма заключается в параллельном подсчете дистанций для различных элементов матрицы смежности, и на рисунке отмечен разными плоскостями.&lt;br /&gt;
&lt;br /&gt;
=== Ресурс параллелизма алгоритма ===&lt;br /&gt;
В последовательном алгоритме единственная операция - это нахождение минимума, ее нет смысла распараллеливать. Вся сложность алгоритма заключается в полном переборе «матрицы смежности». Идея параллельных схем алгоритма Флойда-Уоршелла состоит в том, чтобы модифицировать матрицу смежности одновременно несколькими процессорами. Можно выделить два основных подхода.&lt;br /&gt;
&lt;br /&gt;
Первый подход. В распоряжении имеется такое количество процессоров, что можно отдать каждому ровно по одному элементу &amp;lt;math&amp;gt;D_{ij}&amp;lt;/math&amp;gt;, чтобы он считал для этого элемента минимум.&lt;br /&gt;
&lt;br /&gt;
Второй подход. В распоряжении ограниченное количество процессов. В этом случае грамотным решением будет отдать каждому процессору(или процессу) по одной строке матрицы смежности. Пусть каждый процесс посчитает минимумы в своей строке матрицы и отдаст результаты корневому процессу, это прилично ускорит работу алгоритма.&lt;br /&gt;
&lt;br /&gt;
Для параллельного алгоритма на отдельной итерации каждый процессор выполняет обновление элементов матрицы &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt;. Всего в подзадачах &amp;lt;math&amp;gt;{n^2/p}&amp;lt;/math&amp;gt; таких элементов, число итераций алгоритма равно &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;, таким образом, показатели ускорения и эффективности параллельного алгоритма Флойда имеют вид (&amp;lt;math&amp;gt;p&amp;lt;/math&amp;gt; – число процессоров): &amp;lt;math&amp;gt;{Sp = n^3/(n^3/p) = p}&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;{Ep = n^3/(p(n^3⁄p)) = 1}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Входные и выходные данные алгоритма ===&lt;br /&gt;
Входные данные: Матрица смежности D. Перед работой алгоритма матрица D заполняется длинами рёбер графа (или запредельно большим числом M, если ребра нет). &amp;lt;br&amp;gt;&lt;br /&gt;
Выходные данные: Матрица кратчайших расстояний D.&lt;br /&gt;
&lt;br /&gt;
=== Свойства алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Алгоритм может распознавать наличие отрицательных циклов: такой цикл существует, если один из диагональных элементов матрицы расстояний становится меньше нуля.&lt;br /&gt;
&lt;br /&gt;
== Программная реализация алгоритма ==&lt;br /&gt;
=== Особенности реализации последовательного алгоритма ===&lt;br /&gt;
=== Локальность данных и вычислений ===&lt;br /&gt;
==== Локальность реализации алгоритма ====&lt;br /&gt;
===== Структура обращений в память и качественная оценка локальности =====&lt;br /&gt;
===== Количественная оценка локальности =====&lt;br /&gt;
=== Возможные способы и особенности параллельной реализации алгоритма ===&lt;br /&gt;
=== Масштабируемость алгоритма и его реализации ===&lt;br /&gt;
==== Масштабируемость алгоритма ====&lt;br /&gt;
Возможность обрабатывать фрагменты независимо означает хорошую масштабируемость алгоритма. Сдерживающие факторы: &amp;lt;br&amp;gt;&lt;br /&gt;
1)Пропускная способность памяти при чтении данных графа.&amp;lt;br&amp;gt;&lt;br /&gt;
2)Соперничество потоков при выполнении атомарных операций с памятью. &amp;lt;br&amp;gt;&lt;br /&gt;
3)Синхронизация после каждого подшага алгоритма. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Алгоритм Флойда-Уоршелла обладает большим потенциалом масштабируемости, так как вычисление кратчайших путей можно распределить между независимыми процессами вплоть до вычисления каждым отдельным процессом одного элемента матрицы смежности.&lt;br /&gt;
&lt;br /&gt;
==== Масштабируемость реализации алгоритма ====&lt;br /&gt;
Проведём исследование масштабируемости параллельной реализации алгоритма. Работа выполнена с использованием оборудования Центра коллективного пользования сверхвысокопроизводительными вычислительными ресурсами МГУ имени М.В. Ломоносова.&lt;br /&gt;
Сильная масштабируемость показывает, как меняется время решения задачи с увеличением количества процессоров (или вычислительных узлов) при неизменном общем объёме задачи.&lt;br /&gt;
&lt;br /&gt;
[[file: Pic1.jpg|thumb|center|700px|Сравнение времени параллельной работы алгоритма Флойда-Уоршелла в зависимости от количества процессоров.]]&lt;br /&gt;
&lt;br /&gt;
[[file: Pic3.jpg|thumb|center|700px|Ускорение параллельного алгоритма Флойда-Уоршелла с ростом числа процессоров.]]&lt;br /&gt;
&lt;br /&gt;
Как видно из представленных графиков параллельный алгоритм сильно масштабируем.&lt;br /&gt;
&lt;br /&gt;
=== Динамические характеристики и эффективность реализации алгоритма ===&lt;br /&gt;
=== Выводы для классов архитектур ===&lt;br /&gt;
=== Существующие реализации алгоритма ===&lt;br /&gt;
&lt;br /&gt;
* C++: [http://www.boost.org/libs/graph/doc/ Boost Graph Library] (функция &amp;lt;code&amp;gt;[http://www.boost.org/libs/graph/doc/floyd_warshall_shortest.html floyd_warshall_shortest]&amp;lt;/code&amp;gt;).&lt;br /&gt;
* Python: [https://networkx.github.io NetworkX] (функция &amp;lt;code&amp;gt;[http://networkx.github.io/documentation/networkx-1.9.1/reference/generated/networkx.algorithms.shortest_paths.dense.floyd_warshall.html floyd_warshall]&amp;lt;/code&amp;gt;).&lt;br /&gt;
* Java: [http://jgrapht.org JGraphT] (класс &amp;lt;code&amp;gt;[http://jgrapht.org/javadoc/org/jgrapht/alg/FloydWarshallShortestPaths.html FloydWarshallShortestPaths]&amp;lt;/code&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
== Литература ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;references /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Категория:Начатые статьи]]&lt;/div&gt;</summary>
		<author><name>EkaterinaShevchenko</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%A4%D0%BB%D0%BE%D0%B9%D0%B4%D0%B0-%D0%A3%D0%BE%D1%80%D1%88%D0%B5%D0%BB%D0%BB%D0%B0&amp;diff=24793</id>
		<title>Алгоритм Флойда-Уоршелла</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%A4%D0%BB%D0%BE%D0%B9%D0%B4%D0%B0-%D0%A3%D0%BE%D1%80%D1%88%D0%B5%D0%BB%D0%BB%D0%B0&amp;diff=24793"/>
		<updated>2017-12-01T08:11:06Z</updated>

		<summary type="html">&lt;p&gt;EkaterinaShevchenko: /* Масштабируемость реализации алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Автор: Екатерина Шевченко&lt;br /&gt;
== Свойства и структура алгоритма ==&lt;br /&gt;
=== Общее описание алгоритма ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Алгоритм Флойда-Уоршелла&#039;&#039;&#039;&amp;lt;ref&amp;gt;Roy, Bernard. “Transitivité Et Connexité.” Comptes Rendus De l&#039;Académie Des Sciences 249 (1959): 216–218.&amp;lt;/ref&amp;gt;&amp;lt;ref&amp;gt;Warshall, Stephen. “A Theorem on Boolean Matrices.” Journal of the ACM 9, no. 1 (January 1, 1962): 11–12. doi:10.1145/321105.321107.&amp;lt;/ref&amp;gt;&amp;lt;ref&amp;gt;Floyd, Robert W. “Algorithm 97: Shortest Path.” Communications of the ACM 5, no. 6 (June 1, 1962): 345. doi:10.1145/367766.368168.&amp;lt;/ref&amp;gt; предназначен для решения [[Поиск кратчайшего пути для всех пар вершин (APSP)|задачи поиска всех кратчайших путей на графе]]. Для заданного ориентированного взвешенного графа алгоритм находит кратчайшие расстояния между всеми парами вершин за время &amp;lt;math&amp;gt;O(n^3)&amp;lt;/math&amp;gt;. Алгоритм применим к графам с произвольными, в том числе с отрицательными, весами. Таким образом, он является более общим в сравнении с [[Алгоритм Дейкстры|алгоритмом Дейкстры]], который не работает с отрицательными весами ребер. Также алгоритм распознаёт наличие отрицательных циклов.&lt;br /&gt;
&lt;br /&gt;
=== Математическое описание алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Имеем граф &amp;lt;math&amp;gt;G=(V,E)&amp;lt;/math&amp;gt;, в котором каждая вершина пронумерована от &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt; до &amp;lt;math&amp;gt;|V|&amp;lt;/math&amp;gt;. Сформируем матрицу смежности &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt;. Эта матрица имеет размер &amp;lt;math&amp;gt;|V|*|V|&amp;lt;/math&amp;gt; и каждому ее элементу &amp;lt;math&amp;gt;D_{ij}&amp;lt;/math&amp;gt; присвоен вес ребра, соединяющего вершину &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; с вершиной &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt;. Заметим, что в силу ориентированности графа &amp;lt;math&amp;gt;G&amp;lt;/math&amp;gt; матрица &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt; может быть несимметрична. &lt;br /&gt;
&lt;br /&gt;
По мере выполнения алгоритма данная матрица будет перезаписываться: в каждую из ее ячеек внесется значение, определяющее оптимальную длину пути из вершины &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; в вершину &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Полагаем диагональные элементы &amp;lt;math&amp;gt;D_{ii}&amp;lt;/math&amp;gt; равными нулю, а недиагональные элементы, соответствующие не инцидентным вершинам (не имеющим общего ребра), положим равными бесконечности или числу, заведомо большему возможного расстояния между ребрами.&lt;br /&gt;
&lt;br /&gt;
Ключевая часть алгоритма состоит из трех циклов:&amp;lt;br&amp;gt;&lt;br /&gt;
Для k от 1 до |V| выполнять &amp;lt;br&amp;gt;&lt;br /&gt;
Для i от 1 до |V| выполнять &amp;lt;br&amp;gt;&lt;br /&gt;
Для j от 1 до |V| выполнять &amp;lt;br&amp;gt;&lt;br /&gt;
Если &amp;lt;math&amp;gt;{D_{ik}+D_{kj} &amp;lt; D_{ij}}&amp;lt;/math&amp;gt;, то &amp;lt;math&amp;gt;{D_{ij} := D_{ik}+D_{kj}}&amp;lt;/math&amp;gt;. &amp;lt;br&amp;gt;&lt;br /&gt;
=== Вычислительное ядро алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Основной операцией алгоритма является релаксация элементов матрицы смежности: если &amp;lt;math&amp;gt;{D_{ik}+D_{kj} &amp;lt; D_{ij}}&amp;lt;/math&amp;gt;, то производится присваивание &amp;lt;math&amp;gt;{D_{ij} := D_{ik}+D_{kj}}&amp;lt;/math&amp;gt;. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Макроструктура алгоритма ===&lt;br /&gt;
Ключевая часть алгоритма состоит из трех циклов:&amp;lt;br&amp;gt;&lt;br /&gt;
Для k от 1 до |V| выполнять &amp;lt;br&amp;gt;&lt;br /&gt;
Для i от 1 до |V| выполнять &amp;lt;br&amp;gt;&lt;br /&gt;
Для j от 1 до |V| выполнять &amp;lt;br&amp;gt;&lt;br /&gt;
Если &amp;lt;math&amp;gt;{D_{ik}+D_{kj} &amp;lt; D_{ij}}&amp;lt;/math&amp;gt;, то &amp;lt;math&amp;gt;{D_{ij} := D_{ik}+D_{kj}}&amp;lt;/math&amp;gt;. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
При этом вычисляются минимумы из двух чисел  &amp;lt;math&amp;gt;min({D_{ik}+D_{kj}}, D_{ij})&amp;lt;/math&amp;gt; и их значения становятся новыми значениями элементов смежной матрицы. &amp;lt;br&amp;gt;&lt;br /&gt;
=== Схема реализации последовательного алгоритма ===&lt;br /&gt;
matrix - матрица смежности, numberOfVert - число вершин в графе&lt;br /&gt;
&lt;br /&gt;
    //Пробегаемся по всем вершинам и ищем более короткий путь&lt;br /&gt;
    //через вершину k&lt;br /&gt;
    for(int k = 0; k &amp;lt; numberOfVert; k++) {&lt;br /&gt;
        for(int i = 0; i &amp;lt; numberOfVert; i++) {&lt;br /&gt;
           for(int j = 0; j &amp;lt; numberOfVert; j++) {&lt;br /&gt;
                //Новое значение ребра равно минимальному между старым&lt;br /&gt;
                //и суммой ребер i &amp;lt;-&amp;gt; k + k &amp;lt;-&amp;gt; j (если через k пройти быстрее)&lt;br /&gt;
                matrix[i][j] = min(matrix[i][j], matrix[i][k] + matrix[k][j]);&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
=== Последовательная сложность алгоритма ===&lt;br /&gt;
Время выполнения этой программы, очевидно, имеет порядок &amp;lt;math&amp;gt;O(n^3)&amp;lt;/math&amp;gt;, поскольку в ней практически нет ничего, кроме вложенных друг в друга трех циклов.&lt;br /&gt;
&lt;br /&gt;
=== Информационный граф ===&lt;br /&gt;
[[file:Graphforfloyd.png|thumb|center|300px|Рис.1. Информационная структура предельной параллелизации алгоритма Флойда-Уоршелла]]&lt;br /&gt;
&lt;br /&gt;
На приведенном далее информационном графе нижний уровень параллелизма обозначен в горизонтальных плоскостях. Множество всех плоскостей представляет собой верхний уровень параллелизма (операции в каждой плоскости могут выполняться параллельно). Верхний уровень параллелизма заключается в параллельном подсчете дистанций для различных элементов матрицы смежности, и на рисунке отмечен разными плоскостями.&lt;br /&gt;
&lt;br /&gt;
=== Ресурс параллелизма алгоритма ===&lt;br /&gt;
В последовательном алгоритме единственная операция - это нахождение минимума, ее нет смысла распараллеливать. Вся сложность алгоритма заключается в полном переборе «матрицы смежности». Идея параллельных схем алгоритма Флойда-Уоршелла состоит в том, чтобы модифицировать матрицу смежности одновременно несколькими процессорами. Можно выделить два основных подхода.&lt;br /&gt;
&lt;br /&gt;
Первый подход. В распоряжении имеется такое количество процессоров, что можно отдать каждому ровно по одному элементу &amp;lt;math&amp;gt;D_{ij}&amp;lt;/math&amp;gt;, чтобы он считал для этого элемента минимум.&lt;br /&gt;
&lt;br /&gt;
Второй подход. В распоряжении ограниченное количество процессов. В этом случае грамотным решением будет отдать каждому процессору(или процессу) по одной строке матрицы смежности. Пусть каждый процесс посчитает минимумы в своей строке матрицы и отдаст результаты корневому процессу, это прилично ускорит работу алгоритма.&lt;br /&gt;
&lt;br /&gt;
Для параллельного алгоритма на отдельной итерации каждый процессор выполняет обновление элементов матрицы &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt;. Всего в подзадачах &amp;lt;math&amp;gt;{n^2/p}&amp;lt;/math&amp;gt; таких элементов, число итераций алгоритма равно &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;, таким образом, показатели ускорения и эффективности параллельного алгоритма Флойда имеют вид (&amp;lt;math&amp;gt;p&amp;lt;/math&amp;gt; – число процессоров): &amp;lt;math&amp;gt;{Sp = n^3/(n^3/p) = p}&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;{Ep = n^3/(p(n^3⁄p)) = 1}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Входные и выходные данные алгоритма ===&lt;br /&gt;
Входные данные: Матрица смежности D. Перед работой алгоритма матрица D заполняется длинами рёбер графа (или запредельно большим числом M, если ребра нет). &amp;lt;br&amp;gt;&lt;br /&gt;
Выходные данные: Матрица кратчайших расстояний D.&lt;br /&gt;
&lt;br /&gt;
=== Свойства алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Алгоритм может распознавать наличие отрицательных циклов: такой цикл существует, если один из диагональных элементов матрицы расстояний становится меньше нуля.&lt;br /&gt;
&lt;br /&gt;
== Программная реализация алгоритма ==&lt;br /&gt;
=== Особенности реализации последовательного алгоритма ===&lt;br /&gt;
=== Локальность данных и вычислений ===&lt;br /&gt;
==== Локальность реализации алгоритма ====&lt;br /&gt;
===== Структура обращений в память и качественная оценка локальности =====&lt;br /&gt;
===== Количественная оценка локальности =====&lt;br /&gt;
=== Возможные способы и особенности параллельной реализации алгоритма ===&lt;br /&gt;
=== Масштабируемость алгоритма и его реализации ===&lt;br /&gt;
==== Масштабируемость алгоритма ====&lt;br /&gt;
Возможность обрабатывать фрагменты независимо означает хорошую масштабируемость алгоритма. Сдерживающие факторы: &amp;lt;br&amp;gt;&lt;br /&gt;
1)Пропускная способность памяти при чтении данных графа.&amp;lt;br&amp;gt;&lt;br /&gt;
2)Соперничество потоков при выполнении атомарных операций с памятью. &amp;lt;br&amp;gt;&lt;br /&gt;
3)Синхронизация после каждого подшага алгоритма. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Алгоритм Флойда-Уоршелла обладает большим потенциалом масштабируемости, так как вычисление кратчайших путей можно распределить между независимыми процессами вплоть до вычисления каждым отдельным процессом одного элемента матрицы смежности.&lt;br /&gt;
&lt;br /&gt;
==== Масштабируемость реализации алгоритма ====&lt;br /&gt;
Проведём исследование масштабируемости параллельной реализации алгоритма. Работа выполнена с использованием оборудования Центра коллективного пользования сверхвысокопроизводительными вычислительными ресурсами МГУ имени М.В. Ломоносова.&lt;br /&gt;
Сильная масштабируемость показывает, как меняется время решения задачи с увеличением количества процессоров (или вычислительных узлов) при неизменном общем объёме задачи. Исследование показало, что параллельный алгоритм Флойда-Уоршелла сильно масштабируем.&lt;br /&gt;
&lt;br /&gt;
[[file: Pic1.jpg|thumb|center|700px|Сравнение времени параллельной работы алгоритма Флойда-Уоршелла в зависимости от количества процессоров.]]&lt;br /&gt;
&lt;br /&gt;
[[file: Pic3.jpg|thumb|center|700px|Ускорение параллельного алгоритма Флойда-Уоршелла с ростом числа процессоров.]]&lt;br /&gt;
&lt;br /&gt;
Как видно из представленных графиков параллельный алгоритм сильно масштабируем.&lt;br /&gt;
&lt;br /&gt;
=== Динамические характеристики и эффективность реализации алгоритма ===&lt;br /&gt;
=== Выводы для классов архитектур ===&lt;br /&gt;
=== Существующие реализации алгоритма ===&lt;br /&gt;
&lt;br /&gt;
* C++: [http://www.boost.org/libs/graph/doc/ Boost Graph Library] (функция &amp;lt;code&amp;gt;[http://www.boost.org/libs/graph/doc/floyd_warshall_shortest.html floyd_warshall_shortest]&amp;lt;/code&amp;gt;).&lt;br /&gt;
* Python: [https://networkx.github.io NetworkX] (функция &amp;lt;code&amp;gt;[http://networkx.github.io/documentation/networkx-1.9.1/reference/generated/networkx.algorithms.shortest_paths.dense.floyd_warshall.html floyd_warshall]&amp;lt;/code&amp;gt;).&lt;br /&gt;
* Java: [http://jgrapht.org JGraphT] (класс &amp;lt;code&amp;gt;[http://jgrapht.org/javadoc/org/jgrapht/alg/FloydWarshallShortestPaths.html FloydWarshallShortestPaths]&amp;lt;/code&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
== Литература ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;references /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Категория:Начатые статьи]]&lt;/div&gt;</summary>
		<author><name>EkaterinaShevchenko</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%A4%D0%BB%D0%BE%D0%B9%D0%B4%D0%B0-%D0%A3%D0%BE%D1%80%D1%88%D0%B5%D0%BB%D0%BB%D0%B0&amp;diff=24763</id>
		<title>Алгоритм Флойда-Уоршелла</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%A4%D0%BB%D0%BE%D0%B9%D0%B4%D0%B0-%D0%A3%D0%BE%D1%80%D1%88%D0%B5%D0%BB%D0%BB%D0%B0&amp;diff=24763"/>
		<updated>2017-11-30T22:24:26Z</updated>

		<summary type="html">&lt;p&gt;EkaterinaShevchenko: /* Свойства и структура алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Автор: Екатерина Шевченко&lt;br /&gt;
== Свойства и структура алгоритма ==&lt;br /&gt;
=== Общее описание алгоритма ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Алгоритм Флойда-Уоршелла&#039;&#039;&#039;&amp;lt;ref&amp;gt;Roy, Bernard. “Transitivité Et Connexité.” Comptes Rendus De l&#039;Académie Des Sciences 249 (1959): 216–218.&amp;lt;/ref&amp;gt;&amp;lt;ref&amp;gt;Warshall, Stephen. “A Theorem on Boolean Matrices.” Journal of the ACM 9, no. 1 (January 1, 1962): 11–12. doi:10.1145/321105.321107.&amp;lt;/ref&amp;gt;&amp;lt;ref&amp;gt;Floyd, Robert W. “Algorithm 97: Shortest Path.” Communications of the ACM 5, no. 6 (June 1, 1962): 345. doi:10.1145/367766.368168.&amp;lt;/ref&amp;gt; предназначен для решения [[Поиск кратчайшего пути для всех пар вершин (APSP)|задачи поиска всех кратчайших путей на графе]]. Для заданного ориентированного взвешенного графа алгоритм находит кратчайшие расстояния между всеми парами вершин за время &amp;lt;math&amp;gt;O(n^3)&amp;lt;/math&amp;gt;. Алгоритм применим к графам с произвольными, в том числе с отрицательными, весами. Таким образом, он является более общим в сравнении с [[Алгоритм Дейкстры|алгоритмом Дейкстры]], который не работает с отрицательными весами ребер. Также алгоритм распознаёт наличие отрицательных циклов.&lt;br /&gt;
&lt;br /&gt;
=== Математическое описание алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Имеем граф &amp;lt;math&amp;gt;G=(V,E)&amp;lt;/math&amp;gt;, в котором каждая вершина пронумерована от &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt; до &amp;lt;math&amp;gt;|V|&amp;lt;/math&amp;gt;. Сформируем матрицу смежности &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt;. Эта матрица имеет размер &amp;lt;math&amp;gt;|V|*|V|&amp;lt;/math&amp;gt; и каждому ее элементу &amp;lt;math&amp;gt;D_{ij}&amp;lt;/math&amp;gt; присвоен вес ребра, соединяющего вершину &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; с вершиной &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt;. Заметим, что в силу ориентированности графа &amp;lt;math&amp;gt;G&amp;lt;/math&amp;gt; матрица &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt; может быть несимметрична. &lt;br /&gt;
&lt;br /&gt;
По мере выполнения алгоритма данная матрица будет перезаписываться: в каждую из ее ячеек внесется значение, определяющее оптимальную длину пути из вершины &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; в вершину &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Полагаем диагональные элементы &amp;lt;math&amp;gt;D_{ii}&amp;lt;/math&amp;gt; равными нулю, а недиагональные элементы, соответствующие не инцидентным вершинам (не имеющим общего ребра), положим равными бесконечности или числу, заведомо большему возможного расстояния между ребрами.&lt;br /&gt;
&lt;br /&gt;
Ключевая часть алгоритма состоит из трех циклов:&amp;lt;br&amp;gt;&lt;br /&gt;
Для k от 1 до |V| выполнять &amp;lt;br&amp;gt;&lt;br /&gt;
Для i от 1 до |V| выполнять &amp;lt;br&amp;gt;&lt;br /&gt;
Для j от 1 до |V| выполнять &amp;lt;br&amp;gt;&lt;br /&gt;
Если &amp;lt;math&amp;gt;{D_{ik}+D_{kj} &amp;lt; D_{ij}}&amp;lt;/math&amp;gt;, то &amp;lt;math&amp;gt;{D_{ij} := D_{ik}+D_{kj}}&amp;lt;/math&amp;gt;. &amp;lt;br&amp;gt;&lt;br /&gt;
=== Вычислительное ядро алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Основной операцией алгоритма является релаксация элементов матрицы смежности: если &amp;lt;math&amp;gt;{D_{ik}+D_{kj} &amp;lt; D_{ij}}&amp;lt;/math&amp;gt;, то производится присваивание &amp;lt;math&amp;gt;{D_{ij} := D_{ik}+D_{kj}}&amp;lt;/math&amp;gt;. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Макроструктура алгоритма ===&lt;br /&gt;
Ключевая часть алгоритма состоит из трех циклов:&amp;lt;br&amp;gt;&lt;br /&gt;
Для k от 1 до |V| выполнять &amp;lt;br&amp;gt;&lt;br /&gt;
Для i от 1 до |V| выполнять &amp;lt;br&amp;gt;&lt;br /&gt;
Для j от 1 до |V| выполнять &amp;lt;br&amp;gt;&lt;br /&gt;
Если &amp;lt;math&amp;gt;{D_{ik}+D_{kj} &amp;lt; D_{ij}}&amp;lt;/math&amp;gt;, то &amp;lt;math&amp;gt;{D_{ij} := D_{ik}+D_{kj}}&amp;lt;/math&amp;gt;. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
При этом вычисляются минимумы из двух чисел  &amp;lt;math&amp;gt;min({D_{ik}+D_{kj}}, D_{ij})&amp;lt;/math&amp;gt; и их значения становятся новыми значениями элементов смежной матрицы. &amp;lt;br&amp;gt;&lt;br /&gt;
=== Схема реализации последовательного алгоритма ===&lt;br /&gt;
matrix - матрица смежности, numberOfVert - число вершин в графе&lt;br /&gt;
&lt;br /&gt;
    //Пробегаемся по всем вершинам и ищем более короткий путь&lt;br /&gt;
    //через вершину k&lt;br /&gt;
    for(int k = 0; k &amp;lt; numberOfVert; k++) {&lt;br /&gt;
        for(int i = 0; i &amp;lt; numberOfVert; i++) {&lt;br /&gt;
           for(int j = 0; j &amp;lt; numberOfVert; j++) {&lt;br /&gt;
                //Новое значение ребра равно минимальному между старым&lt;br /&gt;
                //и суммой ребер i &amp;lt;-&amp;gt; k + k &amp;lt;-&amp;gt; j (если через k пройти быстрее)&lt;br /&gt;
                matrix[i][j] = min(matrix[i][j], matrix[i][k] + matrix[k][j]);&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
=== Последовательная сложность алгоритма ===&lt;br /&gt;
Время выполнения этой программы, очевидно, имеет порядок &amp;lt;math&amp;gt;O(n^3)&amp;lt;/math&amp;gt;, поскольку в ней практически нет ничего, кроме вложенных друг в друга трех циклов.&lt;br /&gt;
&lt;br /&gt;
=== Информационный граф ===&lt;br /&gt;
[[file:Graphforfloyd.png|thumb|center|300px|Рис.1. Информационная структура предельной параллелизации алгоритма Флойда-Уоршелла]]&lt;br /&gt;
&lt;br /&gt;
На приведенном далее информационном графе нижний уровень параллелизма обозначен в горизонтальных плоскостях. Множество всех плоскостей представляет собой верхний уровень параллелизма (операции в каждой плоскости могут выполняться параллельно). Верхний уровень параллелизма заключается в параллельном подсчете дистанций для различных элементов матрицы смежности, и на рисунке отмечен разными плоскостями.&lt;br /&gt;
&lt;br /&gt;
=== Ресурс параллелизма алгоритма ===&lt;br /&gt;
В последовательном алгоритме единственная операция - это нахождение минимума, ее нет смысла распараллеливать. Вся сложность алгоритма заключается в полном переборе «матрицы смежности». Идея параллельных схем алгоритма Флойда-Уоршелла состоит в том, чтобы модифицировать матрицу смежности одновременно несколькими процессорами. Можно выделить два основных подхода.&lt;br /&gt;
&lt;br /&gt;
Первый подход. В распоряжении имеется такое количество процессоров, что можно отдать каждому ровно по одному элементу &amp;lt;math&amp;gt;D_{ij}&amp;lt;/math&amp;gt;, чтобы он считал для этого элемента минимум.&lt;br /&gt;
&lt;br /&gt;
Второй подход. В распоряжении ограниченное количество процессов. В этом случае грамотным решением будет отдать каждому процессору(или процессу) по одной строке матрицы смежности. Пусть каждый процесс посчитает минимумы в своей строке матрицы и отдаст результаты корневому процессу, это прилично ускорит работу алгоритма.&lt;br /&gt;
&lt;br /&gt;
Для параллельного алгоритма на отдельной итерации каждый процессор выполняет обновление элементов матрицы &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt;. Всего в подзадачах &amp;lt;math&amp;gt;{n^2/p}&amp;lt;/math&amp;gt; таких элементов, число итераций алгоритма равно &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;, таким образом, показатели ускорения и эффективности параллельного алгоритма Флойда имеют вид (&amp;lt;math&amp;gt;p&amp;lt;/math&amp;gt; – число процессоров): &amp;lt;math&amp;gt;{Sp = n^3/(n^3/p) = p}&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;{Ep = n^3/(p(n^3⁄p)) = 1}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Входные и выходные данные алгоритма ===&lt;br /&gt;
Входные данные: Матрица смежности D. Перед работой алгоритма матрица D заполняется длинами рёбер графа (или запредельно большим числом M, если ребра нет). &amp;lt;br&amp;gt;&lt;br /&gt;
Выходные данные: Матрица кратчайших расстояний D.&lt;br /&gt;
&lt;br /&gt;
=== Свойства алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Алгоритм может распознавать наличие отрицательных циклов: такой цикл существует, если один из диагональных элементов матрицы расстояний становится меньше нуля.&lt;br /&gt;
&lt;br /&gt;
== Программная реализация алгоритма ==&lt;br /&gt;
=== Особенности реализации последовательного алгоритма ===&lt;br /&gt;
=== Локальность данных и вычислений ===&lt;br /&gt;
==== Локальность реализации алгоритма ====&lt;br /&gt;
===== Структура обращений в память и качественная оценка локальности =====&lt;br /&gt;
===== Количественная оценка локальности =====&lt;br /&gt;
=== Возможные способы и особенности параллельной реализации алгоритма ===&lt;br /&gt;
=== Масштабируемость алгоритма и его реализации ===&lt;br /&gt;
==== Масштабируемость алгоритма ====&lt;br /&gt;
Возможность обрабатывать фрагменты независимо означает хорошую масштабируемость алгоритма. Сдерживающие факторы: &amp;lt;br&amp;gt;&lt;br /&gt;
1)Пропускная способность памяти при чтении данных графа.&amp;lt;br&amp;gt;&lt;br /&gt;
2)Соперничество потоков при выполнении атомарных операций с памятью. &amp;lt;br&amp;gt;&lt;br /&gt;
3)Синхронизация после каждого подшага алгоритма. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Алгоритм Флойда-Уоршелла обладает большим потенциалом масштабируемости, так как вычисление кратчайших путей можно распределить между независимыми процессами вплоть до вычисления каждым отдельным процессом одного элемента матрицы смежности.&lt;br /&gt;
&lt;br /&gt;
==== Масштабируемость реализации алгоритма ====&lt;br /&gt;
Проведём исследование масштабируемости параллельной реализации алгоритма. Работа выполнена с использованием оборудования Центра коллективного пользования сверхвысокопроизводительными вычислительными ресурсами МГУ имени М.В. Ломоносова.&lt;br /&gt;
&lt;br /&gt;
[[file: Pic1.jpg|thumb|center|700px|Сравнение времени параллельной работы алгоритма Флойда-Уоршелла в зависимости от количества процессоров.]]&lt;br /&gt;
&lt;br /&gt;
[[file: Pic3.jpg|thumb|center|700px|Ускорение параллельного алгоритма Флойда-Уоршелла с ростом числа процессоров.]]&lt;br /&gt;
&lt;br /&gt;
Как видно из представленных графиков параллельный алгоритм сильно масштабируем.&lt;br /&gt;
&lt;br /&gt;
=== Динамические характеристики и эффективность реализации алгоритма ===&lt;br /&gt;
=== Выводы для классов архитектур ===&lt;br /&gt;
=== Существующие реализации алгоритма ===&lt;br /&gt;
&lt;br /&gt;
* C++: [http://www.boost.org/libs/graph/doc/ Boost Graph Library] (функция &amp;lt;code&amp;gt;[http://www.boost.org/libs/graph/doc/floyd_warshall_shortest.html floyd_warshall_shortest]&amp;lt;/code&amp;gt;).&lt;br /&gt;
* Python: [https://networkx.github.io NetworkX] (функция &amp;lt;code&amp;gt;[http://networkx.github.io/documentation/networkx-1.9.1/reference/generated/networkx.algorithms.shortest_paths.dense.floyd_warshall.html floyd_warshall]&amp;lt;/code&amp;gt;).&lt;br /&gt;
* Java: [http://jgrapht.org JGraphT] (класс &amp;lt;code&amp;gt;[http://jgrapht.org/javadoc/org/jgrapht/alg/FloydWarshallShortestPaths.html FloydWarshallShortestPaths]&amp;lt;/code&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
== Литература ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;references /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Категория:Начатые статьи]]&lt;/div&gt;</summary>
		<author><name>EkaterinaShevchenko</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%A4%D0%BB%D0%BE%D0%B9%D0%B4%D0%B0-%D0%A3%D0%BE%D1%80%D1%88%D0%B5%D0%BB%D0%BB%D0%B0&amp;diff=24762</id>
		<title>Алгоритм Флойда-Уоршелла</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%A4%D0%BB%D0%BE%D0%B9%D0%B4%D0%B0-%D0%A3%D0%BE%D1%80%D1%88%D0%B5%D0%BB%D0%BB%D0%B0&amp;diff=24762"/>
		<updated>2017-11-30T22:23:02Z</updated>

		<summary type="html">&lt;p&gt;EkaterinaShevchenko: /* Масштабируемость реализации алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Свойства и структура алгоритма ==&lt;br /&gt;
=== Общее описание алгоритма ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Алгоритм Флойда-Уоршелла&#039;&#039;&#039;&amp;lt;ref&amp;gt;Roy, Bernard. “Transitivité Et Connexité.” Comptes Rendus De l&#039;Académie Des Sciences 249 (1959): 216–218.&amp;lt;/ref&amp;gt;&amp;lt;ref&amp;gt;Warshall, Stephen. “A Theorem on Boolean Matrices.” Journal of the ACM 9, no. 1 (January 1, 1962): 11–12. doi:10.1145/321105.321107.&amp;lt;/ref&amp;gt;&amp;lt;ref&amp;gt;Floyd, Robert W. “Algorithm 97: Shortest Path.” Communications of the ACM 5, no. 6 (June 1, 1962): 345. doi:10.1145/367766.368168.&amp;lt;/ref&amp;gt; предназначен для решения [[Поиск кратчайшего пути для всех пар вершин (APSP)|задачи поиска всех кратчайших путей на графе]]. Для заданного ориентированного взвешенного графа алгоритм находит кратчайшие расстояния между всеми парами вершин за время &amp;lt;math&amp;gt;O(n^3)&amp;lt;/math&amp;gt;. Алгоритм применим к графам с произвольными, в том числе с отрицательными, весами. Таким образом, он является более общим в сравнении с [[Алгоритм Дейкстры|алгоритмом Дейкстры]], который не работает с отрицательными весами ребер. Также алгоритм распознаёт наличие отрицательных циклов.&lt;br /&gt;
&lt;br /&gt;
=== Математическое описание алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Имеем граф &amp;lt;math&amp;gt;G=(V,E)&amp;lt;/math&amp;gt;, в котором каждая вершина пронумерована от &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt; до &amp;lt;math&amp;gt;|V|&amp;lt;/math&amp;gt;. Сформируем матрицу смежности &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt;. Эта матрица имеет размер &amp;lt;math&amp;gt;|V|*|V|&amp;lt;/math&amp;gt; и каждому ее элементу &amp;lt;math&amp;gt;D_{ij}&amp;lt;/math&amp;gt; присвоен вес ребра, соединяющего вершину &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; с вершиной &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt;. Заметим, что в силу ориентированности графа &amp;lt;math&amp;gt;G&amp;lt;/math&amp;gt; матрица &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt; может быть несимметрична. &lt;br /&gt;
&lt;br /&gt;
По мере выполнения алгоритма данная матрица будет перезаписываться: в каждую из ее ячеек внесется значение, определяющее оптимальную длину пути из вершины &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; в вершину &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Полагаем диагональные элементы &amp;lt;math&amp;gt;D_{ii}&amp;lt;/math&amp;gt; равными нулю, а недиагональные элементы, соответствующие не инцидентным вершинам (не имеющим общего ребра), положим равными бесконечности или числу, заведомо большему возможного расстояния между ребрами.&lt;br /&gt;
&lt;br /&gt;
Ключевая часть алгоритма состоит из трех циклов:&amp;lt;br&amp;gt;&lt;br /&gt;
Для k от 1 до |V| выполнять &amp;lt;br&amp;gt;&lt;br /&gt;
Для i от 1 до |V| выполнять &amp;lt;br&amp;gt;&lt;br /&gt;
Для j от 1 до |V| выполнять &amp;lt;br&amp;gt;&lt;br /&gt;
Если &amp;lt;math&amp;gt;{D_{ik}+D_{kj} &amp;lt; D_{ij}}&amp;lt;/math&amp;gt;, то &amp;lt;math&amp;gt;{D_{ij} := D_{ik}+D_{kj}}&amp;lt;/math&amp;gt;. &amp;lt;br&amp;gt;&lt;br /&gt;
=== Вычислительное ядро алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Основной операцией алгоритма является релаксация элементов матрицы смежности: если &amp;lt;math&amp;gt;{D_{ik}+D_{kj} &amp;lt; D_{ij}}&amp;lt;/math&amp;gt;, то производится присваивание &amp;lt;math&amp;gt;{D_{ij} := D_{ik}+D_{kj}}&amp;lt;/math&amp;gt;. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Макроструктура алгоритма ===&lt;br /&gt;
Ключевая часть алгоритма состоит из трех циклов:&amp;lt;br&amp;gt;&lt;br /&gt;
Для k от 1 до |V| выполнять &amp;lt;br&amp;gt;&lt;br /&gt;
Для i от 1 до |V| выполнять &amp;lt;br&amp;gt;&lt;br /&gt;
Для j от 1 до |V| выполнять &amp;lt;br&amp;gt;&lt;br /&gt;
Если &amp;lt;math&amp;gt;{D_{ik}+D_{kj} &amp;lt; D_{ij}}&amp;lt;/math&amp;gt;, то &amp;lt;math&amp;gt;{D_{ij} := D_{ik}+D_{kj}}&amp;lt;/math&amp;gt;. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
При этом вычисляются минимумы из двух чисел  &amp;lt;math&amp;gt;min({D_{ik}+D_{kj}}, D_{ij})&amp;lt;/math&amp;gt; и их значения становятся новыми значениями элементов смежной матрицы. &amp;lt;br&amp;gt;&lt;br /&gt;
=== Схема реализации последовательного алгоритма ===&lt;br /&gt;
matrix - матрица смежности, numberOfVert - число вершин в графе&lt;br /&gt;
&lt;br /&gt;
    //Пробегаемся по всем вершинам и ищем более короткий путь&lt;br /&gt;
    //через вершину k&lt;br /&gt;
    for(int k = 0; k &amp;lt; numberOfVert; k++) {&lt;br /&gt;
        for(int i = 0; i &amp;lt; numberOfVert; i++) {&lt;br /&gt;
           for(int j = 0; j &amp;lt; numberOfVert; j++) {&lt;br /&gt;
                //Новое значение ребра равно минимальному между старым&lt;br /&gt;
                //и суммой ребер i &amp;lt;-&amp;gt; k + k &amp;lt;-&amp;gt; j (если через k пройти быстрее)&lt;br /&gt;
                matrix[i][j] = min(matrix[i][j], matrix[i][k] + matrix[k][j]);&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
=== Последовательная сложность алгоритма ===&lt;br /&gt;
Время выполнения этой программы, очевидно, имеет порядок &amp;lt;math&amp;gt;O(n^3)&amp;lt;/math&amp;gt;, поскольку в ней практически нет ничего, кроме вложенных друг в друга трех циклов.&lt;br /&gt;
&lt;br /&gt;
=== Информационный граф ===&lt;br /&gt;
[[file:Graphforfloyd.png|thumb|center|300px|Рис.1. Информационная структура предельной параллелизации алгоритма Флойда-Уоршелла]]&lt;br /&gt;
&lt;br /&gt;
На приведенном далее информационном графе нижний уровень параллелизма обозначен в горизонтальных плоскостях. Множество всех плоскостей представляет собой верхний уровень параллелизма (операции в каждой плоскости могут выполняться параллельно). Верхний уровень параллелизма заключается в параллельном подсчете дистанций для различных элементов матрицы смежности, и на рисунке отмечен разными плоскостями.&lt;br /&gt;
&lt;br /&gt;
=== Ресурс параллелизма алгоритма ===&lt;br /&gt;
В последовательном алгоритме единственная операция - это нахождение минимума, ее нет смысла распараллеливать. Вся сложность алгоритма заключается в полном переборе «матрицы смежности». Идея параллельных схем алгоритма Флойда-Уоршелла состоит в том, чтобы модифицировать матрицу смежности одновременно несколькими процессорами. Можно выделить два основных подхода.&lt;br /&gt;
&lt;br /&gt;
Первый подход. В распоряжении имеется такое количество процессоров, что можно отдать каждому ровно по одному элементу &amp;lt;math&amp;gt;D_{ij}&amp;lt;/math&amp;gt;, чтобы он считал для этого элемента минимум.&lt;br /&gt;
&lt;br /&gt;
Второй подход. В распоряжении ограниченное количество процессов. В этом случае грамотным решением будет отдать каждому процессору(или процессу) по одной строке матрицы смежности. Пусть каждый процесс посчитает минимумы в своей строке матрицы и отдаст результаты корневому процессу, это прилично ускорит работу алгоритма.&lt;br /&gt;
&lt;br /&gt;
Для параллельного алгоритма на отдельной итерации каждый процессор выполняет обновление элементов матрицы &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt;. Всего в подзадачах &amp;lt;math&amp;gt;{n^2/p}&amp;lt;/math&amp;gt; таких элементов, число итераций алгоритма равно &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;, таким образом, показатели ускорения и эффективности параллельного алгоритма Флойда имеют вид (&amp;lt;math&amp;gt;p&amp;lt;/math&amp;gt; – число процессоров): &amp;lt;math&amp;gt;{Sp = n^3/(n^3/p) = p}&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;{Ep = n^3/(p(n^3⁄p)) = 1}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Входные и выходные данные алгоритма ===&lt;br /&gt;
Входные данные: Матрица смежности D. Перед работой алгоритма матрица D заполняется длинами рёбер графа (или запредельно большим числом M, если ребра нет). &amp;lt;br&amp;gt;&lt;br /&gt;
Выходные данные: Матрица кратчайших расстояний D.&lt;br /&gt;
&lt;br /&gt;
=== Свойства алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Алгоритм может распознавать наличие отрицательных циклов: такой цикл существует, если один из диагональных элементов матрицы расстояний становится меньше нуля.&lt;br /&gt;
&lt;br /&gt;
== Программная реализация алгоритма ==&lt;br /&gt;
=== Особенности реализации последовательного алгоритма ===&lt;br /&gt;
=== Локальность данных и вычислений ===&lt;br /&gt;
==== Локальность реализации алгоритма ====&lt;br /&gt;
===== Структура обращений в память и качественная оценка локальности =====&lt;br /&gt;
===== Количественная оценка локальности =====&lt;br /&gt;
=== Возможные способы и особенности параллельной реализации алгоритма ===&lt;br /&gt;
=== Масштабируемость алгоритма и его реализации ===&lt;br /&gt;
==== Масштабируемость алгоритма ====&lt;br /&gt;
Возможность обрабатывать фрагменты независимо означает хорошую масштабируемость алгоритма. Сдерживающие факторы: &amp;lt;br&amp;gt;&lt;br /&gt;
1)Пропускная способность памяти при чтении данных графа.&amp;lt;br&amp;gt;&lt;br /&gt;
2)Соперничество потоков при выполнении атомарных операций с памятью. &amp;lt;br&amp;gt;&lt;br /&gt;
3)Синхронизация после каждого подшага алгоритма. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Алгоритм Флойда-Уоршелла обладает большим потенциалом масштабируемости, так как вычисление кратчайших путей можно распределить между независимыми процессами вплоть до вычисления каждым отдельным процессом одного элемента матрицы смежности.&lt;br /&gt;
&lt;br /&gt;
==== Масштабируемость реализации алгоритма ====&lt;br /&gt;
Проведём исследование масштабируемости параллельной реализации алгоритма. Работа выполнена с использованием оборудования Центра коллективного пользования сверхвысокопроизводительными вычислительными ресурсами МГУ имени М.В. Ломоносова.&lt;br /&gt;
&lt;br /&gt;
[[file: Pic1.jpg|thumb|center|700px|Сравнение времени параллельной работы алгоритма Флойда-Уоршелла в зависимости от количества процессоров.]]&lt;br /&gt;
&lt;br /&gt;
[[file: Pic3.jpg|thumb|center|700px|Ускорение параллельного алгоритма Флойда-Уоршелла с ростом числа процессоров.]]&lt;br /&gt;
&lt;br /&gt;
Как видно из представленных графиков параллельный алгоритм сильно масштабируем.&lt;br /&gt;
&lt;br /&gt;
=== Динамические характеристики и эффективность реализации алгоритма ===&lt;br /&gt;
=== Выводы для классов архитектур ===&lt;br /&gt;
=== Существующие реализации алгоритма ===&lt;br /&gt;
&lt;br /&gt;
* C++: [http://www.boost.org/libs/graph/doc/ Boost Graph Library] (функция &amp;lt;code&amp;gt;[http://www.boost.org/libs/graph/doc/floyd_warshall_shortest.html floyd_warshall_shortest]&amp;lt;/code&amp;gt;).&lt;br /&gt;
* Python: [https://networkx.github.io NetworkX] (функция &amp;lt;code&amp;gt;[http://networkx.github.io/documentation/networkx-1.9.1/reference/generated/networkx.algorithms.shortest_paths.dense.floyd_warshall.html floyd_warshall]&amp;lt;/code&amp;gt;).&lt;br /&gt;
* Java: [http://jgrapht.org JGraphT] (класс &amp;lt;code&amp;gt;[http://jgrapht.org/javadoc/org/jgrapht/alg/FloydWarshallShortestPaths.html FloydWarshallShortestPaths]&amp;lt;/code&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
== Литература ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;references /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Категория:Начатые статьи]]&lt;/div&gt;</summary>
		<author><name>EkaterinaShevchenko</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%A4%D0%BB%D0%BE%D0%B9%D0%B4%D0%B0-%D0%A3%D0%BE%D1%80%D1%88%D0%B5%D0%BB%D0%BB%D0%B0&amp;diff=24734</id>
		<title>Алгоритм Флойда-Уоршелла</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%A4%D0%BB%D0%BE%D0%B9%D0%B4%D0%B0-%D0%A3%D0%BE%D1%80%D1%88%D0%B5%D0%BB%D0%BB%D0%B0&amp;diff=24734"/>
		<updated>2017-11-30T20:54:52Z</updated>

		<summary type="html">&lt;p&gt;EkaterinaShevchenko: /* Масштабируемость алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Свойства и структура алгоритма ==&lt;br /&gt;
=== Общее описание алгоритма ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Алгоритм Флойда-Уоршелла&#039;&#039;&#039;&amp;lt;ref&amp;gt;Roy, Bernard. “Transitivité Et Connexité.” Comptes Rendus De l&#039;Académie Des Sciences 249 (1959): 216–218.&amp;lt;/ref&amp;gt;&amp;lt;ref&amp;gt;Warshall, Stephen. “A Theorem on Boolean Matrices.” Journal of the ACM 9, no. 1 (January 1, 1962): 11–12. doi:10.1145/321105.321107.&amp;lt;/ref&amp;gt;&amp;lt;ref&amp;gt;Floyd, Robert W. “Algorithm 97: Shortest Path.” Communications of the ACM 5, no. 6 (June 1, 1962): 345. doi:10.1145/367766.368168.&amp;lt;/ref&amp;gt; предназначен для решения [[Поиск кратчайшего пути для всех пар вершин (APSP)|задачи поиска всех кратчайших путей на графе]]. Для заданного ориентированного взвешенного графа алгоритм находит кратчайшие расстояния между всеми парами вершин за время &amp;lt;math&amp;gt;O(n^3)&amp;lt;/math&amp;gt;. Алгоритм применим к графам с произвольными, в том числе с отрицательными, весами. Таким образом, он является более общим в сравнении с [[Алгоритм Дейкстры|алгоритмом Дейкстры]], который не работает с отрицательными весами ребер. Также алгоритм распознаёт наличие отрицательных циклов.&lt;br /&gt;
&lt;br /&gt;
=== Математическое описание алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Имеем граф &amp;lt;math&amp;gt;G=(V,E)&amp;lt;/math&amp;gt;, в котором каждая вершина пронумерована от &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt; до &amp;lt;math&amp;gt;|V|&amp;lt;/math&amp;gt;. Сформируем матрицу смежности &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt;. Эта матрица имеет размер &amp;lt;math&amp;gt;|V|*|V|&amp;lt;/math&amp;gt; и каждому ее элементу &amp;lt;math&amp;gt;D_{ij}&amp;lt;/math&amp;gt; присвоен вес ребра, соединяющего вершину &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; с вершиной &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt;. Заметим, что в силу ориентированности графа &amp;lt;math&amp;gt;G&amp;lt;/math&amp;gt; матрица &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt; может быть несимметрична. &lt;br /&gt;
&lt;br /&gt;
По мере выполнения алгоритма данная матрица будет перезаписываться: в каждую из ее ячеек внесется значение, определяющее оптимальную длину пути из вершины &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; в вершину &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Полагаем диагональные элементы &amp;lt;math&amp;gt;D_{ii}&amp;lt;/math&amp;gt; равными нулю, а недиагональные элементы, соответствующие не инцидентным вершинам (не имеющим общего ребра), положим равными бесконечности или числу, заведомо большему возможного расстояния между ребрами.&lt;br /&gt;
&lt;br /&gt;
Ключевая часть алгоритма состоит из трех циклов:&amp;lt;br&amp;gt;&lt;br /&gt;
Для k от 1 до |V| выполнять &amp;lt;br&amp;gt;&lt;br /&gt;
Для i от 1 до |V| выполнять &amp;lt;br&amp;gt;&lt;br /&gt;
Для j от 1 до |V| выполнять &amp;lt;br&amp;gt;&lt;br /&gt;
Если &amp;lt;math&amp;gt;{D_{ik}+D_{kj} &amp;lt; D_{ij}}&amp;lt;/math&amp;gt;, то &amp;lt;math&amp;gt;{D_{ij} := D_{ik}+D_{kj}}&amp;lt;/math&amp;gt;. &amp;lt;br&amp;gt;&lt;br /&gt;
=== Вычислительное ядро алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Основной операцией алгоритма является релаксация элементов матрицы смежности: если &amp;lt;math&amp;gt;{D_{ik}+D_{kj} &amp;lt; D_{ij}}&amp;lt;/math&amp;gt;, то производится присваивание &amp;lt;math&amp;gt;{D_{ij} := D_{ik}+D_{kj}}&amp;lt;/math&amp;gt;. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Макроструктура алгоритма ===&lt;br /&gt;
Ключевая часть алгоритма состоит из трех циклов:&amp;lt;br&amp;gt;&lt;br /&gt;
Для k от 1 до |V| выполнять &amp;lt;br&amp;gt;&lt;br /&gt;
Для i от 1 до |V| выполнять &amp;lt;br&amp;gt;&lt;br /&gt;
Для j от 1 до |V| выполнять &amp;lt;br&amp;gt;&lt;br /&gt;
Если &amp;lt;math&amp;gt;{D_{ik}+D_{kj} &amp;lt; D_{ij}}&amp;lt;/math&amp;gt;, то &amp;lt;math&amp;gt;{D_{ij} := D_{ik}+D_{kj}}&amp;lt;/math&amp;gt;. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
При этом вычисляются минимумы из двух чисел  &amp;lt;math&amp;gt;min({D_{ik}+D_{kj}}, D_{ij})&amp;lt;/math&amp;gt; и их значения становятся новыми значениями элементов смежной матрицы. &amp;lt;br&amp;gt;&lt;br /&gt;
=== Схема реализации последовательного алгоритма ===&lt;br /&gt;
matrix - матрица смежности, numberOfVert - число вершин в графе&lt;br /&gt;
&lt;br /&gt;
    //Пробегаемся по всем вершинам и ищем более короткий путь&lt;br /&gt;
    //через вершину k&lt;br /&gt;
    for(int k = 0; k &amp;lt; numberOfVert; k++) {&lt;br /&gt;
        for(int i = 0; i &amp;lt; numberOfVert; i++) {&lt;br /&gt;
           for(int j = 0; j &amp;lt; numberOfVert; j++) {&lt;br /&gt;
                //Новое значение ребра равно минимальному между старым&lt;br /&gt;
                //и суммой ребер i &amp;lt;-&amp;gt; k + k &amp;lt;-&amp;gt; j (если через k пройти быстрее)&lt;br /&gt;
                matrix[i][j] = min(matrix[i][j], matrix[i][k] + matrix[k][j]);&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
=== Последовательная сложность алгоритма ===&lt;br /&gt;
Время выполнения этой программы, очевидно, имеет порядок &amp;lt;math&amp;gt;O(n^3)&amp;lt;/math&amp;gt;, поскольку в ней практически нет ничего, кроме вложенных друг в друга трех циклов.&lt;br /&gt;
&lt;br /&gt;
=== Информационный граф ===&lt;br /&gt;
[[file:Graphforfloyd.png|thumb|center|300px|Рис.1. Информационная структура предельной параллелизации алгоритма Флойда-Уоршелла]]&lt;br /&gt;
&lt;br /&gt;
На приведенном далее информационном графе нижний уровень параллелизма обозначен в горизонтальных плоскостях. Множество всех плоскостей представляет собой верхний уровень параллелизма (операции в каждой плоскости могут выполняться параллельно). Верхний уровень параллелизма заключается в параллельном подсчете дистанций для различных элементов матрицы смежности, и на рисунке отмечен разными плоскостями.&lt;br /&gt;
&lt;br /&gt;
=== Ресурс параллелизма алгоритма ===&lt;br /&gt;
В последовательном алгоритме единственная операция - это нахождение минимума, ее нет смысла распараллеливать. Вся сложность алгоритма заключается в полном переборе «матрицы смежности». Идея параллельных схем алгоритма Флойда-Уоршелла состоит в том, чтобы модифицировать матрицу смежности одновременно несколькими процессорами. Можно выделить два основных подхода.&lt;br /&gt;
&lt;br /&gt;
Первый подход. В распоряжении имеется такое количество процессоров, что можно отдать каждому ровно по одному элементу &amp;lt;math&amp;gt;D_{ij}&amp;lt;/math&amp;gt;, чтобы он считал для этого элемента минимум.&lt;br /&gt;
&lt;br /&gt;
Второй подход. В распоряжении ограниченное количество процессов. В этом случае грамотным решением будет отдать каждому процессору(или процессу) по одной строке матрицы смежности. Пусть каждый процесс посчитает минимумы в своей строке матрицы и отдаст результаты корневому процессу, это прилично ускорит работу алгоритма.&lt;br /&gt;
&lt;br /&gt;
Для параллельного алгоритма на отдельной итерации каждый процессор выполняет обновление элементов матрицы &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt;. Всего в подзадачах &amp;lt;math&amp;gt;{n^2/p}&amp;lt;/math&amp;gt; таких элементов, число итераций алгоритма равно &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;, таким образом, показатели ускорения и эффективности параллельного алгоритма Флойда имеют вид (&amp;lt;math&amp;gt;p&amp;lt;/math&amp;gt; – число процессоров): &amp;lt;math&amp;gt;{Sp = n^3/(n^3/p) = p}&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;{Ep = n^3/(p(n^3⁄p)) = 1}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Входные и выходные данные алгоритма ===&lt;br /&gt;
Входные данные: Матрица смежности D. Перед работой алгоритма матрица D заполняется длинами рёбер графа (или запредельно большим числом M, если ребра нет). &amp;lt;br&amp;gt;&lt;br /&gt;
Выходные данные: Матрица кратчайших расстояний D.&lt;br /&gt;
&lt;br /&gt;
=== Свойства алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Алгоритм может распознавать наличие отрицательных циклов: такой цикл существует, если один из диагональных элементов матрицы расстояний становится меньше нуля.&lt;br /&gt;
&lt;br /&gt;
== Программная реализация алгоритма ==&lt;br /&gt;
=== Особенности реализации последовательного алгоритма ===&lt;br /&gt;
=== Локальность данных и вычислений ===&lt;br /&gt;
==== Локальность реализации алгоритма ====&lt;br /&gt;
===== Структура обращений в память и качественная оценка локальности =====&lt;br /&gt;
===== Количественная оценка локальности =====&lt;br /&gt;
=== Возможные способы и особенности параллельной реализации алгоритма ===&lt;br /&gt;
=== Масштабируемость алгоритма и его реализации ===&lt;br /&gt;
==== Масштабируемость алгоритма ====&lt;br /&gt;
Возможность обрабатывать фрагменты независимо означает хорошую масштабируемость алгоритма. Сдерживающие факторы: &amp;lt;br&amp;gt;&lt;br /&gt;
1)Пропускная способность памяти при чтении данных графа.&amp;lt;br&amp;gt;&lt;br /&gt;
2)Соперничество потоков при выполнении атомарных операций с памятью. &amp;lt;br&amp;gt;&lt;br /&gt;
3)Синхронизация после каждого подшага алгоритма. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Алгоритм Флойда-Уоршелла обладает большим потенциалом масштабируемости, так как вычисление кратчайших путей можно распределить между независимыми процессами вплоть до вычисления каждым отдельным процессом одного элемента матрицы смежности.&lt;br /&gt;
&lt;br /&gt;
==== Масштабируемость реализации алгоритма ====&lt;br /&gt;
=== Динамические характеристики и эффективность реализации алгоритма ===&lt;br /&gt;
=== Выводы для классов архитектур ===&lt;br /&gt;
=== Существующие реализации алгоритма ===&lt;br /&gt;
&lt;br /&gt;
* C++: [http://www.boost.org/libs/graph/doc/ Boost Graph Library] (функция &amp;lt;code&amp;gt;[http://www.boost.org/libs/graph/doc/floyd_warshall_shortest.html floyd_warshall_shortest]&amp;lt;/code&amp;gt;).&lt;br /&gt;
* Python: [https://networkx.github.io NetworkX] (функция &amp;lt;code&amp;gt;[http://networkx.github.io/documentation/networkx-1.9.1/reference/generated/networkx.algorithms.shortest_paths.dense.floyd_warshall.html floyd_warshall]&amp;lt;/code&amp;gt;).&lt;br /&gt;
* Java: [http://jgrapht.org JGraphT] (класс &amp;lt;code&amp;gt;[http://jgrapht.org/javadoc/org/jgrapht/alg/FloydWarshallShortestPaths.html FloydWarshallShortestPaths]&amp;lt;/code&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
== Литература ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;references /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Категория:Начатые статьи]]&lt;/div&gt;</summary>
		<author><name>EkaterinaShevchenko</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%A4%D0%BB%D0%BE%D0%B9%D0%B4%D0%B0-%D0%A3%D0%BE%D1%80%D1%88%D0%B5%D0%BB%D0%BB%D0%B0&amp;diff=24710</id>
		<title>Алгоритм Флойда-Уоршелла</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%A4%D0%BB%D0%BE%D0%B9%D0%B4%D0%B0-%D0%A3%D0%BE%D1%80%D1%88%D0%B5%D0%BB%D0%BB%D0%B0&amp;diff=24710"/>
		<updated>2017-11-30T20:13:00Z</updated>

		<summary type="html">&lt;p&gt;EkaterinaShevchenko: /* Информационный граф */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Свойства и структура алгоритма ==&lt;br /&gt;
=== Общее описание алгоритма ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Алгоритм Флойда-Уоршелла&#039;&#039;&#039;&amp;lt;ref&amp;gt;Roy, Bernard. “Transitivité Et Connexité.” Comptes Rendus De l&#039;Académie Des Sciences 249 (1959): 216–218.&amp;lt;/ref&amp;gt;&amp;lt;ref&amp;gt;Warshall, Stephen. “A Theorem on Boolean Matrices.” Journal of the ACM 9, no. 1 (January 1, 1962): 11–12. doi:10.1145/321105.321107.&amp;lt;/ref&amp;gt;&amp;lt;ref&amp;gt;Floyd, Robert W. “Algorithm 97: Shortest Path.” Communications of the ACM 5, no. 6 (June 1, 1962): 345. doi:10.1145/367766.368168.&amp;lt;/ref&amp;gt; предназначен для решения [[Поиск кратчайшего пути для всех пар вершин (APSP)|задачи поиска всех кратчайших путей на графе]]. Для заданного ориентированного взвешенного графа алгоритм находит кратчайшие расстояния между всеми парами вершин за время &amp;lt;math&amp;gt;O(n^3)&amp;lt;/math&amp;gt;. Алгоритм применим к графам с произвольными, в том числе с отрицательными, весами. Таким образом, он является более общим в сравнении с [[Алгоритм Дейкстры|алгоритмом Дейкстры]], который не работает с отрицательными весами ребер. Также алгоритм распознаёт наличие отрицательных циклов.&lt;br /&gt;
&lt;br /&gt;
=== Математическое описание алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Имеем граф &amp;lt;math&amp;gt;G=(V,E)&amp;lt;/math&amp;gt;, в котором каждая вершина пронумерована от &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt; до &amp;lt;math&amp;gt;|V|&amp;lt;/math&amp;gt;. Сформируем матрицу смежности &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt;. Эта матрица имеет размер &amp;lt;math&amp;gt;|V|*|V|&amp;lt;/math&amp;gt; и каждому ее элементу &amp;lt;math&amp;gt;D_{ij}&amp;lt;/math&amp;gt; присвоен вес ребра, соединяющего вершину &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; с вершиной &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt;. Заметим, что в силу ориентированности графа &amp;lt;math&amp;gt;G&amp;lt;/math&amp;gt; матрица &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt; может быть несимметрична. &lt;br /&gt;
&lt;br /&gt;
По мере выполнения алгоритма данная матрица будет перезаписываться: в каждую из ее ячеек внесется значение, определяющее оптимальную длину пути из вершины &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; в вершину &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Полагаем диагональные элементы &amp;lt;math&amp;gt;D_{ii}&amp;lt;/math&amp;gt; равными нулю, а недиагональные элементы, соответствующие не инцидентным вершинам (не имеющим общего ребра), положим равными бесконечности или числу, заведомо большему возможного расстояния между ребрами.&lt;br /&gt;
&lt;br /&gt;
Ключевая часть алгоритма состоит из трех циклов:&amp;lt;br&amp;gt;&lt;br /&gt;
Для k от 1 до |V| выполнять &amp;lt;br&amp;gt;&lt;br /&gt;
Для i от 1 до |V| выполнять &amp;lt;br&amp;gt;&lt;br /&gt;
Для j от 1 до |V| выполнять &amp;lt;br&amp;gt;&lt;br /&gt;
Если &amp;lt;math&amp;gt;{D_{ik}+D_{kj} &amp;lt; D_{ij}}&amp;lt;/math&amp;gt;, то &amp;lt;math&amp;gt;{D_{ij} := D_{ik}+D_{kj}}&amp;lt;/math&amp;gt;. &amp;lt;br&amp;gt;&lt;br /&gt;
=== Вычислительное ядро алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Основной операцией алгоритма является релаксация элементов матрицы смежности: если &amp;lt;math&amp;gt;{D_{ik}+D_{kj} &amp;lt; D_{ij}}&amp;lt;/math&amp;gt;, то производится присваивание &amp;lt;math&amp;gt;{D_{ij} := D_{ik}+D_{kj}}&amp;lt;/math&amp;gt;. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Макроструктура алгоритма ===&lt;br /&gt;
Ключевая часть алгоритма состоит из трех циклов:&amp;lt;br&amp;gt;&lt;br /&gt;
Для k от 1 до |V| выполнять &amp;lt;br&amp;gt;&lt;br /&gt;
Для i от 1 до |V| выполнять &amp;lt;br&amp;gt;&lt;br /&gt;
Для j от 1 до |V| выполнять &amp;lt;br&amp;gt;&lt;br /&gt;
Если &amp;lt;math&amp;gt;{D_{ik}+D_{kj} &amp;lt; D_{ij}}&amp;lt;/math&amp;gt;, то &amp;lt;math&amp;gt;{D_{ij} := D_{ik}+D_{kj}}&amp;lt;/math&amp;gt;. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
При этом вычисляются минимумы из двух чисел  &amp;lt;math&amp;gt;min({D_{ik}+D_{kj}}, D_{ij})&amp;lt;/math&amp;gt; и их значения становятся новыми значениями элементов смежной матрицы. &amp;lt;br&amp;gt;&lt;br /&gt;
=== Схема реализации последовательного алгоритма ===&lt;br /&gt;
matrix - матрица смежности, numberOfVert - число вершин в графе&lt;br /&gt;
&lt;br /&gt;
    //Пробегаемся по всем вершинам и ищем более короткий путь&lt;br /&gt;
    //через вершину k&lt;br /&gt;
    for(int k = 0; k &amp;lt; numberOfVert; k++) {&lt;br /&gt;
        for(int i = 0; i &amp;lt; numberOfVert; i++) {&lt;br /&gt;
           for(int j = 0; j &amp;lt; numberOfVert; j++) {&lt;br /&gt;
                //Новое значение ребра равно минимальному между старым&lt;br /&gt;
                //и суммой ребер i &amp;lt;-&amp;gt; k + k &amp;lt;-&amp;gt; j (если через k пройти быстрее)&lt;br /&gt;
                matrix[i][j] = min(matrix[i][j], matrix[i][k] + matrix[k][j]);&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
=== Последовательная сложность алгоритма ===&lt;br /&gt;
Время выполнения этой программы, очевидно, имеет порядок &amp;lt;math&amp;gt;O(n^3)&amp;lt;/math&amp;gt;, поскольку в ней практически нет ничего, кроме вложенных друг в друга трех циклов.&lt;br /&gt;
&lt;br /&gt;
=== Информационный граф ===&lt;br /&gt;
[[file:Graphforfloyd.png|thumb|center|300px|Рис.1. Информационная структура предельной параллелизации алгоритма Флойда-Уоршелла]]&lt;br /&gt;
&lt;br /&gt;
На приведенном далее информационном графе нижний уровень параллелизма обозначен в горизонтальных плоскостях. Множество всех плоскостей представляет собой верхний уровень параллелизма (операции в каждой плоскости могут выполняться параллельно). Верхний уровень параллелизма заключается в параллельном подсчете дистанций для различных элементов матрицы смежности, и на рисунке отмечен разными плоскостями.&lt;br /&gt;
&lt;br /&gt;
=== Ресурс параллелизма алгоритма ===&lt;br /&gt;
В последовательном алгоритме единственная операция - это нахождение минимума, ее нет смысла распараллеливать. Вся сложность алгоритма заключается в полном переборе «матрицы смежности». Идея параллельных схем алгоритма Флойда-Уоршелла состоит в том, чтобы модифицировать матрицу смежности одновременно несколькими процессорами. Можно выделить два основных подхода.&lt;br /&gt;
&lt;br /&gt;
Первый подход. В распоряжении имеется такое количество процессоров, что можно отдать каждому ровно по одному элементу &amp;lt;math&amp;gt;D_{ij}&amp;lt;/math&amp;gt;, чтобы он считал для этого элемента минимум.&lt;br /&gt;
&lt;br /&gt;
Второй подход. В распоряжении ограниченное количество процессов. В этом случае грамотным решением будет отдать каждому процессору(или процессу) по одной строке матрицы смежности. Пусть каждый процесс посчитает минимумы в своей строке матрицы и отдаст результаты корневому процессу, это прилично ускорит работу алгоритма.&lt;br /&gt;
&lt;br /&gt;
Для параллельного алгоритма на отдельной итерации каждый процессор выполняет обновление элементов матрицы &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt;. Всего в подзадачах &amp;lt;math&amp;gt;{n^2/p}&amp;lt;/math&amp;gt; таких элементов, число итераций алгоритма равно &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;, таким образом, показатели ускорения и эффективности параллельного алгоритма Флойда имеют вид (&amp;lt;math&amp;gt;p&amp;lt;/math&amp;gt; – число процессоров): &amp;lt;math&amp;gt;{Sp = n^3/(n^3/p) = p}&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;{Ep = n^3/(p(n^3⁄p)) = 1}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Входные и выходные данные алгоритма ===&lt;br /&gt;
Входные данные: Матрица смежности D. Перед работой алгоритма матрица D заполняется длинами рёбер графа (или запредельно большим числом M, если ребра нет). &amp;lt;br&amp;gt;&lt;br /&gt;
Выходные данные: Матрица кратчайших расстояний D.&lt;br /&gt;
&lt;br /&gt;
=== Свойства алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Алгоритм может распознавать наличие отрицательных циклов: такой цикл существует, если один из диагональных элементов матрицы расстояний становится меньше нуля.&lt;br /&gt;
&lt;br /&gt;
== Программная реализация алгоритма ==&lt;br /&gt;
=== Особенности реализации последовательного алгоритма ===&lt;br /&gt;
=== Локальность данных и вычислений ===&lt;br /&gt;
==== Локальность реализации алгоритма ====&lt;br /&gt;
===== Структура обращений в память и качественная оценка локальности =====&lt;br /&gt;
===== Количественная оценка локальности =====&lt;br /&gt;
=== Возможные способы и особенности параллельной реализации алгоритма ===&lt;br /&gt;
=== Масштабируемость алгоритма и его реализации ===&lt;br /&gt;
==== Масштабируемость алгоритма ====&lt;br /&gt;
==== Масштабируемость реализации алгоритма ====&lt;br /&gt;
=== Динамические характеристики и эффективность реализации алгоритма ===&lt;br /&gt;
=== Выводы для классов архитектур ===&lt;br /&gt;
=== Существующие реализации алгоритма ===&lt;br /&gt;
&lt;br /&gt;
* C++: [http://www.boost.org/libs/graph/doc/ Boost Graph Library] (функция &amp;lt;code&amp;gt;[http://www.boost.org/libs/graph/doc/floyd_warshall_shortest.html floyd_warshall_shortest]&amp;lt;/code&amp;gt;).&lt;br /&gt;
* Python: [https://networkx.github.io NetworkX] (функция &amp;lt;code&amp;gt;[http://networkx.github.io/documentation/networkx-1.9.1/reference/generated/networkx.algorithms.shortest_paths.dense.floyd_warshall.html floyd_warshall]&amp;lt;/code&amp;gt;).&lt;br /&gt;
* Java: [http://jgrapht.org JGraphT] (класс &amp;lt;code&amp;gt;[http://jgrapht.org/javadoc/org/jgrapht/alg/FloydWarshallShortestPaths.html FloydWarshallShortestPaths]&amp;lt;/code&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
== Литература ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;references /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Категория:Начатые статьи]]&lt;/div&gt;</summary>
		<author><name>EkaterinaShevchenko</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%A4%D0%BB%D0%BE%D0%B9%D0%B4%D0%B0-%D0%A3%D0%BE%D1%80%D1%88%D0%B5%D0%BB%D0%BB%D0%B0&amp;diff=24700</id>
		<title>Алгоритм Флойда-Уоршелла</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%A4%D0%BB%D0%BE%D0%B9%D0%B4%D0%B0-%D0%A3%D0%BE%D1%80%D1%88%D0%B5%D0%BB%D0%BB%D0%B0&amp;diff=24700"/>
		<updated>2017-11-30T19:03:50Z</updated>

		<summary type="html">&lt;p&gt;EkaterinaShevchenko: /* Свойства и структура алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Свойства и структура алгоритма ==&lt;br /&gt;
=== Общее описание алгоритма ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Алгоритм Флойда-Уоршелла&#039;&#039;&#039;&amp;lt;ref&amp;gt;Roy, Bernard. “Transitivité Et Connexité.” Comptes Rendus De l&#039;Académie Des Sciences 249 (1959): 216–218.&amp;lt;/ref&amp;gt;&amp;lt;ref&amp;gt;Warshall, Stephen. “A Theorem on Boolean Matrices.” Journal of the ACM 9, no. 1 (January 1, 1962): 11–12. doi:10.1145/321105.321107.&amp;lt;/ref&amp;gt;&amp;lt;ref&amp;gt;Floyd, Robert W. “Algorithm 97: Shortest Path.” Communications of the ACM 5, no. 6 (June 1, 1962): 345. doi:10.1145/367766.368168.&amp;lt;/ref&amp;gt; предназначен для решения [[Поиск кратчайшего пути для всех пар вершин (APSP)|задачи поиска всех кратчайших путей на графе]]. Для заданного ориентированного взвешенного графа алгоритм находит кратчайшие расстояния между всеми парами вершин за время &amp;lt;math&amp;gt;O(n^3)&amp;lt;/math&amp;gt;. Алгоритм применим к графам с произвольными, в том числе с отрицательными, весами. Таким образом, он является более общим в сравнении с [[Алгоритм Дейкстры|алгоритмом Дейкстры]], который не работает с отрицательными весами ребер. Также алгоритм распознаёт наличие отрицательных циклов.&lt;br /&gt;
&lt;br /&gt;
=== Математическое описание алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Имеем граф &amp;lt;math&amp;gt;G=(V,E)&amp;lt;/math&amp;gt;, в котором каждая вершина пронумерована от &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt; до &amp;lt;math&amp;gt;|V|&amp;lt;/math&amp;gt;. Сформируем матрицу смежности &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt;. Эта матрица имеет размер &amp;lt;math&amp;gt;|V|*|V|&amp;lt;/math&amp;gt; и каждому ее элементу &amp;lt;math&amp;gt;D_{ij}&amp;lt;/math&amp;gt; присвоен вес ребра, соединяющего вершину &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; с вершиной &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt;. Заметим, что в силу ориентированности графа &amp;lt;math&amp;gt;G&amp;lt;/math&amp;gt; матрица &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt; может быть несимметрична. &lt;br /&gt;
&lt;br /&gt;
По мере выполнения алгоритма данная матрица будет перезаписываться: в каждую из ее ячеек внесется значение, определяющее оптимальную длину пути из вершины &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; в вершину &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Полагаем диагональные элементы &amp;lt;math&amp;gt;D_{ii}&amp;lt;/math&amp;gt; равными нулю, а недиагональные элементы, соответствующие не инцидентным вершинам (не имеющим общего ребра), положим равными бесконечности или числу, заведомо большему возможного расстояния между ребрами.&lt;br /&gt;
&lt;br /&gt;
Ключевая часть алгоритма состоит из трех циклов:&amp;lt;br&amp;gt;&lt;br /&gt;
Для k от 1 до |V| выполнять &amp;lt;br&amp;gt;&lt;br /&gt;
Для i от 1 до |V| выполнять &amp;lt;br&amp;gt;&lt;br /&gt;
Для j от 1 до |V| выполнять &amp;lt;br&amp;gt;&lt;br /&gt;
Если &amp;lt;math&amp;gt;{D_{ik}+D_{kj} &amp;lt; D_{ij}}&amp;lt;/math&amp;gt;, то &amp;lt;math&amp;gt;{D_{ij} := D_{ik}+D_{kj}}&amp;lt;/math&amp;gt;. &amp;lt;br&amp;gt;&lt;br /&gt;
=== Вычислительное ядро алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Основной операцией алгоритма является релаксация элементов матрицы смежности: если &amp;lt;math&amp;gt;{D_{ik}+D_{kj} &amp;lt; D_{ij}}&amp;lt;/math&amp;gt;, то производится присваивание &amp;lt;math&amp;gt;{D_{ij} := D_{ik}+D_{kj}}&amp;lt;/math&amp;gt;. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Макроструктура алгоритма ===&lt;br /&gt;
Ключевая часть алгоритма состоит из трех циклов:&amp;lt;br&amp;gt;&lt;br /&gt;
Для k от 1 до |V| выполнять &amp;lt;br&amp;gt;&lt;br /&gt;
Для i от 1 до |V| выполнять &amp;lt;br&amp;gt;&lt;br /&gt;
Для j от 1 до |V| выполнять &amp;lt;br&amp;gt;&lt;br /&gt;
Если &amp;lt;math&amp;gt;{D_{ik}+D_{kj} &amp;lt; D_{ij}}&amp;lt;/math&amp;gt;, то &amp;lt;math&amp;gt;{D_{ij} := D_{ik}+D_{kj}}&amp;lt;/math&amp;gt;. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
При этом вычисляются минимумы из двух чисел  &amp;lt;math&amp;gt;min({D_{ik}+D_{kj}}, D_{ij})&amp;lt;/math&amp;gt; и их значения становятся новыми значениями элементов смежной матрицы. &amp;lt;br&amp;gt;&lt;br /&gt;
=== Схема реализации последовательного алгоритма ===&lt;br /&gt;
matrix - матрица смежности, numberOfVert - число вершин в графе&lt;br /&gt;
&lt;br /&gt;
    //Пробегаемся по всем вершинам и ищем более короткий путь&lt;br /&gt;
    //через вершину k&lt;br /&gt;
    for(int k = 0; k &amp;lt; numberOfVert; k++) {&lt;br /&gt;
        for(int i = 0; i &amp;lt; numberOfVert; i++) {&lt;br /&gt;
           for(int j = 0; j &amp;lt; numberOfVert; j++) {&lt;br /&gt;
                //Новое значение ребра равно минимальному между старым&lt;br /&gt;
                //и суммой ребер i &amp;lt;-&amp;gt; k + k &amp;lt;-&amp;gt; j (если через k пройти быстрее)&lt;br /&gt;
                matrix[i][j] = min(matrix[i][j], matrix[i][k] + matrix[k][j]);&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
=== Последовательная сложность алгоритма ===&lt;br /&gt;
Время выполнения этой программы, очевидно, имеет порядок &amp;lt;math&amp;gt;O(n^3)&amp;lt;/math&amp;gt;, поскольку в ней практически нет ничего, кроме вложенных друг в друга трех циклов.&lt;br /&gt;
&lt;br /&gt;
=== Информационный граф ===&lt;br /&gt;
=== Ресурс параллелизма алгоритма ===&lt;br /&gt;
В последовательном алгоритме единственная операция - это нахождение минимума, ее нет смысла распараллеливать. Вся сложность алгоритма заключается в полном переборе «матрицы смежности». Идея параллельных схем алгоритма Флойда-Уоршелла состоит в том, чтобы модифицировать матрицу смежности одновременно несколькими процессорами. Можно выделить два основных подхода.&lt;br /&gt;
&lt;br /&gt;
Первый подход. В распоряжении имеется такое количество процессоров, что можно отдать каждому ровно по одному элементу &amp;lt;math&amp;gt;D_{ij}&amp;lt;/math&amp;gt;, чтобы он считал для этого элемента минимум.&lt;br /&gt;
&lt;br /&gt;
Второй подход. В распоряжении ограниченное количество процессов. В этом случае грамотным решением будет отдать каждому процессору(или процессу) по одной строке матрицы смежности. Пусть каждый процесс посчитает минимумы в своей строке матрицы и отдаст результаты корневому процессу, это прилично ускорит работу алгоритма.&lt;br /&gt;
&lt;br /&gt;
Для параллельного алгоритма на отдельной итерации каждый процессор выполняет обновление элементов матрицы &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt;. Всего в подзадачах &amp;lt;math&amp;gt;{n^2/p}&amp;lt;/math&amp;gt; таких элементов, число итераций алгоритма равно &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;, таким образом, показатели ускорения и эффективности параллельного алгоритма Флойда имеют вид (&amp;lt;math&amp;gt;p&amp;lt;/math&amp;gt; – число процессоров): &amp;lt;math&amp;gt;{Sp = n^3/(n^3/p) = p}&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;{Ep = n^3/(p(n^3⁄p)) = 1}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Входные и выходные данные алгоритма ===&lt;br /&gt;
Входные данные: Матрица смежности D. Перед работой алгоритма матрица D заполняется длинами рёбер графа (или запредельно большим числом M, если ребра нет). &amp;lt;br&amp;gt;&lt;br /&gt;
Выходные данные: Матрица кратчайших расстояний D.&lt;br /&gt;
&lt;br /&gt;
=== Свойства алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Алгоритм может распознавать наличие отрицательных циклов: такой цикл существует, если один из диагональных элементов матрицы расстояний становится меньше нуля.&lt;br /&gt;
&lt;br /&gt;
== Программная реализация алгоритма ==&lt;br /&gt;
=== Особенности реализации последовательного алгоритма ===&lt;br /&gt;
=== Локальность данных и вычислений ===&lt;br /&gt;
==== Локальность реализации алгоритма ====&lt;br /&gt;
===== Структура обращений в память и качественная оценка локальности =====&lt;br /&gt;
===== Количественная оценка локальности =====&lt;br /&gt;
=== Возможные способы и особенности параллельной реализации алгоритма ===&lt;br /&gt;
=== Масштабируемость алгоритма и его реализации ===&lt;br /&gt;
==== Масштабируемость алгоритма ====&lt;br /&gt;
==== Масштабируемость реализации алгоритма ====&lt;br /&gt;
=== Динамические характеристики и эффективность реализации алгоритма ===&lt;br /&gt;
=== Выводы для классов архитектур ===&lt;br /&gt;
=== Существующие реализации алгоритма ===&lt;br /&gt;
&lt;br /&gt;
* C++: [http://www.boost.org/libs/graph/doc/ Boost Graph Library] (функция &amp;lt;code&amp;gt;[http://www.boost.org/libs/graph/doc/floyd_warshall_shortest.html floyd_warshall_shortest]&amp;lt;/code&amp;gt;).&lt;br /&gt;
* Python: [https://networkx.github.io NetworkX] (функция &amp;lt;code&amp;gt;[http://networkx.github.io/documentation/networkx-1.9.1/reference/generated/networkx.algorithms.shortest_paths.dense.floyd_warshall.html floyd_warshall]&amp;lt;/code&amp;gt;).&lt;br /&gt;
* Java: [http://jgrapht.org JGraphT] (класс &amp;lt;code&amp;gt;[http://jgrapht.org/javadoc/org/jgrapht/alg/FloydWarshallShortestPaths.html FloydWarshallShortestPaths]&amp;lt;/code&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
== Литература ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;references /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Категория:Начатые статьи]]&lt;/div&gt;</summary>
		<author><name>EkaterinaShevchenko</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%A4%D0%BB%D0%BE%D0%B9%D0%B4%D0%B0-%D0%A3%D0%BE%D1%80%D1%88%D0%B5%D0%BB%D0%BB%D0%B0&amp;diff=24698</id>
		<title>Алгоритм Флойда-Уоршелла</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%A4%D0%BB%D0%BE%D0%B9%D0%B4%D0%B0-%D0%A3%D0%BE%D1%80%D1%88%D0%B5%D0%BB%D0%BB%D0%B0&amp;diff=24698"/>
		<updated>2017-11-30T18:56:33Z</updated>

		<summary type="html">&lt;p&gt;EkaterinaShevchenko: /* Свойства и структура алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Свойства и структура алгоритма ==&lt;br /&gt;
=== Общее описание алгоритма ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Алгоритм Флойда-Уоршелла&#039;&#039;&#039;&amp;lt;ref&amp;gt;Roy, Bernard. “Transitivité Et Connexité.” Comptes Rendus De l&#039;Académie Des Sciences 249 (1959): 216–218.&amp;lt;/ref&amp;gt;&amp;lt;ref&amp;gt;Warshall, Stephen. “A Theorem on Boolean Matrices.” Journal of the ACM 9, no. 1 (January 1, 1962): 11–12. doi:10.1145/321105.321107.&amp;lt;/ref&amp;gt;&amp;lt;ref&amp;gt;Floyd, Robert W. “Algorithm 97: Shortest Path.” Communications of the ACM 5, no. 6 (June 1, 1962): 345. doi:10.1145/367766.368168.&amp;lt;/ref&amp;gt; предназначен для решения [[Поиск кратчайшего пути для всех пар вершин (APSP)|задачи поиска всех кратчайших путей на графе]]. Для заданного ориентированного взвешенного графа алгоритм находит кратчайшие расстояния между всеми парами вершин за время &amp;lt;math&amp;gt;O(n^3)&amp;lt;/math&amp;gt;. Алгоритм применим к графам с произвольными, в том числе с отрицательными, весами. Таким образом, он является более общим в сравнении с [[Алгоритм Дейкстры|алгоритмом Дейкстры]], который не работает с отрицательными весами ребер. Также алгоритм распознаёт наличие отрицательных циклов.&lt;br /&gt;
&lt;br /&gt;
=== Математическое описание алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Имеем граф &amp;lt;math&amp;gt;G=(V,E)&amp;lt;/math&amp;gt;, в котором каждая вершина пронумерована от &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt; до &amp;lt;math&amp;gt;|V|&amp;lt;/math&amp;gt;. Сформируем матрицу смежности &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt;. Эта матрица имеет размер &amp;lt;math&amp;gt;|V|*|V|&amp;lt;/math&amp;gt; и каждому ее элементу &amp;lt;math&amp;gt;D_{ij}&amp;lt;/math&amp;gt; присвоен вес ребра, соединяющего вершину &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; с вершиной &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt;. Заметим, что в силу ориентированности графа &amp;lt;math&amp;gt;G&amp;lt;/math&amp;gt; матрица &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt; может быть несимметрична. &lt;br /&gt;
&lt;br /&gt;
По мере выполнения алгоритма данная матрица будет перезаписываться: в каждую из ее ячеек внесется значение, определяющее оптимальную длину пути из вершины &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; в вершину &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Полагаем диагональные элементы &amp;lt;math&amp;gt;D_{ii}&amp;lt;/math&amp;gt; равными нулю, а недиагональные элементы, соответствующие не инцидентным вершинам (не имеющим общего ребра), положим равными бесконечности или числу, заведомо большему возможного расстояния между ребрами.&lt;br /&gt;
&lt;br /&gt;
Ключевая часть алгоритма состоит из трех циклов:&amp;lt;br&amp;gt;&lt;br /&gt;
Для k от 1 до |V| выполнять &amp;lt;br&amp;gt;&lt;br /&gt;
Для i от 1 до |V| выполнять &amp;lt;br&amp;gt;&lt;br /&gt;
Для j от 1 до |V| выполнять &amp;lt;br&amp;gt;&lt;br /&gt;
Если &amp;lt;math&amp;gt;{D_{ik}+D_{kj} &amp;lt; D_{ij}}&amp;lt;/math&amp;gt;, то &amp;lt;math&amp;gt;{D_{ij} := D_{ik}+D_{kj}}&amp;lt;/math&amp;gt;. &amp;lt;br&amp;gt;&lt;br /&gt;
=== Вычислительное ядро алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Основной операцией алгоритма является релаксация элементов матрицы смежности: если &amp;lt;math&amp;gt;{D_{ik}+D_{kj} &amp;lt; D_{ij}}&amp;lt;/math&amp;gt;, то производится присваивание &amp;lt;math&amp;gt;{D_{ij} := D_{ik}+D_{kj}}&amp;lt;/math&amp;gt;. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Макроструктура алгоритма ===&lt;br /&gt;
=== Схема реализации последовательного алгоритма ===&lt;br /&gt;
matrix - матрица смежности, numberOfVert - число вершин в графе&lt;br /&gt;
&lt;br /&gt;
    //Пробегаемся по всем вершинам и ищем более короткий путь&lt;br /&gt;
    //через вершину k&lt;br /&gt;
    for(int k = 0; k &amp;lt; numberOfVert; k++) {&lt;br /&gt;
        for(int i = 0; i &amp;lt; numberOfVert; i++) {&lt;br /&gt;
           for(int j = 0; j &amp;lt; numberOfVert; j++) {&lt;br /&gt;
                //Новое значение ребра равно минимальному между старым&lt;br /&gt;
                //и суммой ребер i &amp;lt;-&amp;gt; k + k &amp;lt;-&amp;gt; j (если через k пройти быстрее)&lt;br /&gt;
                matrix[i][j] = min(matrix[i][j], matrix[i][k] + matrix[k][j]);&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
=== Последовательная сложность алгоритма ===&lt;br /&gt;
Время выполнения этой программы, очевидно, имеет порядок &amp;lt;math&amp;gt;O(n^3)&amp;lt;/math&amp;gt;, поскольку в ней практически нет ничего, кроме вложенных друг в друга трех циклов.&lt;br /&gt;
&lt;br /&gt;
=== Информационный граф ===&lt;br /&gt;
=== Ресурс параллелизма алгоритма ===&lt;br /&gt;
В последовательном алгоритме единственная операция - это нахождение минимума, ее нет смысла распараллеливать. Вся сложность алгоритма заключается в полном переборе «матрицы смежности». Идея параллельных схем алгоритма Флойда-Уоршелла состоит в том, чтобы модифицировать матрицу смежности одновременно несколькими процессорами. Можно выделить два основных подхода.&lt;br /&gt;
&lt;br /&gt;
Первый подход. В распоряжении имеется такое количество процессоров, что можно отдать каждому ровно по одному элементу &amp;lt;math&amp;gt;D_{ij}&amp;lt;/math&amp;gt;, чтобы он считал для этого элемента минимум.&lt;br /&gt;
&lt;br /&gt;
Второй подход. В распоряжении ограниченное количество процессов. В этом случае грамотным решением будет отдать каждому процессору(или процессу) по одной строке матрицы смежности. Пусть каждый процесс посчитает минимумы в своей строке матрицы и отдаст результаты корневому процессу, это прилично ускорит работу алгоритма.&lt;br /&gt;
&lt;br /&gt;
Для параллельного алгоритма на отдельной итерации каждый процессор выполняет обновление элементов матрицы &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt;. Всего в подзадачах &amp;lt;math&amp;gt;{n^2/p}&amp;lt;/math&amp;gt; таких элементов, число итераций алгоритма равно &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;, таким образом, показатели ускорения и эффективности параллельного алгоритма Флойда имеют вид (&amp;lt;math&amp;gt;p&amp;lt;/math&amp;gt; – число процессоров): &amp;lt;math&amp;gt;{Sp = n^3/(n^3/p) = p}&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;{Ep = n^3/(p(n^3⁄p)) = 1}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Входные и выходные данные алгоритма ===&lt;br /&gt;
Входные данные: Матрица смежности D. Перед работой алгоритма матрица D заполняется длинами рёбер графа (или запредельно большим числом M, если ребра нет). &amp;lt;br&amp;gt;&lt;br /&gt;
Выходные данные: Матрица кратчайших расстояний D.&lt;br /&gt;
&lt;br /&gt;
=== Свойства алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Алгоритм может распознавать наличие отрицательных циклов: такой цикл существует, если один из диагональных элементов матрицы расстояний становится меньше нуля.&lt;br /&gt;
&lt;br /&gt;
== Программная реализация алгоритма ==&lt;br /&gt;
=== Особенности реализации последовательного алгоритма ===&lt;br /&gt;
=== Локальность данных и вычислений ===&lt;br /&gt;
==== Локальность реализации алгоритма ====&lt;br /&gt;
===== Структура обращений в память и качественная оценка локальности =====&lt;br /&gt;
===== Количественная оценка локальности =====&lt;br /&gt;
=== Возможные способы и особенности параллельной реализации алгоритма ===&lt;br /&gt;
=== Масштабируемость алгоритма и его реализации ===&lt;br /&gt;
==== Масштабируемость алгоритма ====&lt;br /&gt;
==== Масштабируемость реализации алгоритма ====&lt;br /&gt;
=== Динамические характеристики и эффективность реализации алгоритма ===&lt;br /&gt;
=== Выводы для классов архитектур ===&lt;br /&gt;
=== Существующие реализации алгоритма ===&lt;br /&gt;
&lt;br /&gt;
* C++: [http://www.boost.org/libs/graph/doc/ Boost Graph Library] (функция &amp;lt;code&amp;gt;[http://www.boost.org/libs/graph/doc/floyd_warshall_shortest.html floyd_warshall_shortest]&amp;lt;/code&amp;gt;).&lt;br /&gt;
* Python: [https://networkx.github.io NetworkX] (функция &amp;lt;code&amp;gt;[http://networkx.github.io/documentation/networkx-1.9.1/reference/generated/networkx.algorithms.shortest_paths.dense.floyd_warshall.html floyd_warshall]&amp;lt;/code&amp;gt;).&lt;br /&gt;
* Java: [http://jgrapht.org JGraphT] (класс &amp;lt;code&amp;gt;[http://jgrapht.org/javadoc/org/jgrapht/alg/FloydWarshallShortestPaths.html FloydWarshallShortestPaths]&amp;lt;/code&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
== Литература ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;references /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Категория:Начатые статьи]]&lt;/div&gt;</summary>
		<author><name>EkaterinaShevchenko</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%A4%D0%BB%D0%BE%D0%B9%D0%B4%D0%B0-%D0%A3%D0%BE%D1%80%D1%88%D0%B5%D0%BB%D0%BB%D0%B0&amp;diff=24688</id>
		<title>Алгоритм Флойда-Уоршелла</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%A4%D0%BB%D0%BE%D0%B9%D0%B4%D0%B0-%D0%A3%D0%BE%D1%80%D1%88%D0%B5%D0%BB%D0%BB%D0%B0&amp;diff=24688"/>
		<updated>2017-11-30T18:32:24Z</updated>

		<summary type="html">&lt;p&gt;EkaterinaShevchenko: /* Свойства и структура алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Свойства и структура алгоритма ==&lt;br /&gt;
=== Общее описание алгоритма ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Алгоритм Флойда-Уоршелла&#039;&#039;&#039;&amp;lt;ref&amp;gt;Roy, Bernard. “Transitivité Et Connexité.” Comptes Rendus De l&#039;Académie Des Sciences 249 (1959): 216–218.&amp;lt;/ref&amp;gt;&amp;lt;ref&amp;gt;Warshall, Stephen. “A Theorem on Boolean Matrices.” Journal of the ACM 9, no. 1 (January 1, 1962): 11–12. doi:10.1145/321105.321107.&amp;lt;/ref&amp;gt;&amp;lt;ref&amp;gt;Floyd, Robert W. “Algorithm 97: Shortest Path.” Communications of the ACM 5, no. 6 (June 1, 1962): 345. doi:10.1145/367766.368168.&amp;lt;/ref&amp;gt; предназначен для решения [[Поиск кратчайшего пути для всех пар вершин (APSP)|задачи поиска всех кратчайших путей на графе]]. Для заданного ориентированного взвешенного графа алгоритм находит кратчайшие расстояния между всеми парами вершин за время &amp;lt;math&amp;gt;O(n^3)&amp;lt;/math&amp;gt;. Алгоритм применим к графам с произвольными, в том числе с отрицательными, весами. Таким образом, он является более общим в сравнении с [[Алгоритм Дейкстры|алгоритмом Дейкстры]], который не работает с отрицательными весами ребер. Также алгоритм распознаёт наличие отрицательных циклов.&lt;br /&gt;
&lt;br /&gt;
=== Математическое описание алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Имеем граф &amp;lt;math&amp;gt;G=(V,E)&amp;lt;/math&amp;gt;, в котором каждая вершина пронумерована от &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt; до &amp;lt;math&amp;gt;|V|&amp;lt;/math&amp;gt;. Сформируем матрицу смежности &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt;. Эта матрица имеет размер &amp;lt;math&amp;gt;|V|*|V|&amp;lt;/math&amp;gt; и каждому ее элементу &amp;lt;math&amp;gt;D_{ij}&amp;lt;/math&amp;gt; присвоен вес ребра, соединяющего вершину &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; с вершиной &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt;. Заметим, что в силу ориентированности графа &amp;lt;math&amp;gt;G&amp;lt;/math&amp;gt; матрица &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt; может быть несимметрична. &lt;br /&gt;
&lt;br /&gt;
По мере выполнения алгоритма данная матрица будет перезаписываться: в каждую из ее ячеек внесется значение, определяющее оптимальную длину пути из вершины &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; в вершину &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Полагаем диагональные элементы &amp;lt;math&amp;gt;D_{ii}&amp;lt;/math&amp;gt; равными нулю, а недиагональные элементы, соответствующие не инцидентным вершинам (не имеющим общего ребра), положим равными бесконечности или числу, заведомо большему возможного расстояния между ребрами.&lt;br /&gt;
&lt;br /&gt;
Ключевая часть алгоритма состоит из трех циклов:&amp;lt;br&amp;gt;&lt;br /&gt;
Для k от 1 до |V| выполнять &amp;lt;br&amp;gt;&lt;br /&gt;
Для i от 1 до |V| выполнять &amp;lt;br&amp;gt;&lt;br /&gt;
Для j от 1 до |V| выполнять &amp;lt;br&amp;gt;&lt;br /&gt;
Если &amp;lt;math&amp;gt;{D_{ik}+D_{kj} &amp;lt; D_{ij}}&amp;lt;/math&amp;gt;, то &amp;lt;math&amp;gt;{D_{ij} := D_{ik}+D_{kj}}&amp;lt;/math&amp;gt;. &amp;lt;br&amp;gt;&lt;br /&gt;
=== Вычислительное ядро алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Основной операцией алгоритма является релаксация элементов матрицы смежности: если &amp;lt;math&amp;gt;{D_{ik}+D_{kj} &amp;lt; D_{ij}}&amp;lt;/math&amp;gt;, то производится присваивание &amp;lt;math&amp;gt;{D_{ij} := D_{ik}+D_{kj}}&amp;lt;/math&amp;gt;. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Макроструктура алгоритма ===&lt;br /&gt;
=== Схема реализации последовательного алгоритма ===&lt;br /&gt;
=== Последовательная сложность алгоритма ===&lt;br /&gt;
Время выполнения этой программы, очевидно, имеет порядок &amp;lt;math&amp;gt;O(n^3)&amp;lt;/math&amp;gt;, поскольку в ней практически нет ничего, кроме вложенных друг в друга трех циклов.&lt;br /&gt;
&lt;br /&gt;
=== Информационный граф ===&lt;br /&gt;
=== Ресурс параллелизма алгоритма ===&lt;br /&gt;
В последовательном алгоритме единственная операция - это нахождение минимума, ее нет смысла распараллеливать. Вся сложность алгоритма заключается в полном переборе «матрицы смежности». Идея параллельных схем алгоритма Флойда-Уоршелла состоит в том, чтобы модифицировать матрицу смежности одновременно несколькими процессорами. Можно выделить два основных подхода.&lt;br /&gt;
&lt;br /&gt;
Первый подход. В распоряжении имеется такое количество процессоров, что можно отдать каждому ровно по одному элементу &amp;lt;math&amp;gt;D_{ij}&amp;lt;/math&amp;gt;, чтобы он считал для этого элемента минимум.&lt;br /&gt;
&lt;br /&gt;
Второй подход. В распоряжении ограниченное количество процессов. В этом случае грамотным решением будет отдать каждому процессору(или процессу) по одной строке матрицы смежности. Пусть каждый процесс посчитает минимумы в своей строке матрицы и отдаст результаты корневому процессу, это прилично ускорит работу алгоритма.&lt;br /&gt;
&lt;br /&gt;
Для параллельного алгоритма на отдельной итерации каждый процессор выполняет обновление элементов матрицы &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt;. Всего в подзадачах &amp;lt;math&amp;gt;{n^2/p}&amp;lt;/math&amp;gt; таких элементов, число итераций алгоритма равно &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;, таким образом, показатели ускорения и эффективности параллельного алгоритма Флойда имеют вид (&amp;lt;math&amp;gt;p&amp;lt;/math&amp;gt; – число процессоров): &amp;lt;math&amp;gt;{Sp = n^3/(n^3/p) = p}&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;{Ep = n^3/(p(n^3⁄p)) = 1}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Входные и выходные данные алгоритма ===&lt;br /&gt;
Входные данные: Матрица смежности D. Перед работой алгоритма матрица D заполняется длинами рёбер графа (или запредельно большим числом M, если ребра нет). &amp;lt;br&amp;gt;&lt;br /&gt;
Выходные данные: Матрица кратчайших расстояний D.&lt;br /&gt;
&lt;br /&gt;
=== Свойства алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Алгоритм может распознавать наличие отрицательных циклов: такой цикл существует, если один из диагональных элементов матрицы расстояний становится меньше нуля.&lt;br /&gt;
&lt;br /&gt;
== Программная реализация алгоритма ==&lt;br /&gt;
=== Особенности реализации последовательного алгоритма ===&lt;br /&gt;
=== Локальность данных и вычислений ===&lt;br /&gt;
==== Локальность реализации алгоритма ====&lt;br /&gt;
===== Структура обращений в память и качественная оценка локальности =====&lt;br /&gt;
===== Количественная оценка локальности =====&lt;br /&gt;
=== Возможные способы и особенности параллельной реализации алгоритма ===&lt;br /&gt;
=== Масштабируемость алгоритма и его реализации ===&lt;br /&gt;
==== Масштабируемость алгоритма ====&lt;br /&gt;
==== Масштабируемость реализации алгоритма ====&lt;br /&gt;
=== Динамические характеристики и эффективность реализации алгоритма ===&lt;br /&gt;
=== Выводы для классов архитектур ===&lt;br /&gt;
=== Существующие реализации алгоритма ===&lt;br /&gt;
&lt;br /&gt;
* C++: [http://www.boost.org/libs/graph/doc/ Boost Graph Library] (функция &amp;lt;code&amp;gt;[http://www.boost.org/libs/graph/doc/floyd_warshall_shortest.html floyd_warshall_shortest]&amp;lt;/code&amp;gt;).&lt;br /&gt;
* Python: [https://networkx.github.io NetworkX] (функция &amp;lt;code&amp;gt;[http://networkx.github.io/documentation/networkx-1.9.1/reference/generated/networkx.algorithms.shortest_paths.dense.floyd_warshall.html floyd_warshall]&amp;lt;/code&amp;gt;).&lt;br /&gt;
* Java: [http://jgrapht.org JGraphT] (класс &amp;lt;code&amp;gt;[http://jgrapht.org/javadoc/org/jgrapht/alg/FloydWarshallShortestPaths.html FloydWarshallShortestPaths]&amp;lt;/code&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
== Литература ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;references /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Категория:Начатые статьи]]&lt;/div&gt;</summary>
		<author><name>EkaterinaShevchenko</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%A4%D0%BB%D0%BE%D0%B9%D0%B4%D0%B0-%D0%A3%D0%BE%D1%80%D1%88%D0%B5%D0%BB%D0%BB%D0%B0&amp;diff=24687</id>
		<title>Алгоритм Флойда-Уоршелла</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%A4%D0%BB%D0%BE%D0%B9%D0%B4%D0%B0-%D0%A3%D0%BE%D1%80%D1%88%D0%B5%D0%BB%D0%BB%D0%B0&amp;diff=24687"/>
		<updated>2017-11-30T18:10:52Z</updated>

		<summary type="html">&lt;p&gt;EkaterinaShevchenko: /* Ресурс параллелизма алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Свойства и структура алгоритма ==&lt;br /&gt;
=== Общее описание алгоритма ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Алгоритм Флойда-Уоршелла&#039;&#039;&#039;&amp;lt;ref&amp;gt;Roy, Bernard. “Transitivité Et Connexité.” Comptes Rendus De l&#039;Académie Des Sciences 249 (1959): 216–218.&amp;lt;/ref&amp;gt;&amp;lt;ref&amp;gt;Warshall, Stephen. “A Theorem on Boolean Matrices.” Journal of the ACM 9, no. 1 (January 1, 1962): 11–12. doi:10.1145/321105.321107.&amp;lt;/ref&amp;gt;&amp;lt;ref&amp;gt;Floyd, Robert W. “Algorithm 97: Shortest Path.” Communications of the ACM 5, no. 6 (June 1, 1962): 345. doi:10.1145/367766.368168.&amp;lt;/ref&amp;gt; предназначен для решения [[Поиск кратчайшего пути для всех пар вершин (APSP)|задачи поиска всех кратчайших путей на графе]]. Для заданного ориентированного взвешенного графа алгоритм находит кратчайшие расстояния между всеми парами вершин за время &amp;lt;math&amp;gt;O(n^3)&amp;lt;/math&amp;gt;. Алгоритм применим к графам с произвольными, в том числе с отрицательными, весами. Таким образом, он является более общим в сравнении с [[Алгоритм Дейкстры|алгоритмом Дейкстры]], который не работает с отрицательными весами ребер. Также алгоритм распознаёт наличие отрицательных циклов.&lt;br /&gt;
&lt;br /&gt;
=== Математическое описание алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Имеем граф &amp;lt;math&amp;gt;G=(V,E)&amp;lt;/math&amp;gt;, в котором каждая вершина пронумерована от &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt; до &amp;lt;math&amp;gt;|V|&amp;lt;/math&amp;gt;. Сформируем матрицу смежности &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt;. Эта матрица имеет размер &amp;lt;math&amp;gt;|V|*|V|&amp;lt;/math&amp;gt; и каждому ее элементу &amp;lt;math&amp;gt;D_{ij}&amp;lt;/math&amp;gt; присвоен вес ребра, соединяющего вершину &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; с вершиной &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt;. Заметим, что в силу ориентированности графа &amp;lt;math&amp;gt;G&amp;lt;/math&amp;gt; матрица &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt; может быть несимметрична. &lt;br /&gt;
&lt;br /&gt;
По мере выполнения алгоритма данная матрица будет перезаписываться: в каждую из ее ячеек внесется значение, определяющее оптимальную длину пути из вершины &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; в вершину &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Полагаем диагональные элементы &amp;lt;math&amp;gt;D_{ii}&amp;lt;/math&amp;gt; равными нулю, а недиагональные элементы, соответствующие не инцидентным вершинам (не имеющим общего ребра), положим равными бесконечности или числу, заведомо большему возможного расстояния между ребрами.&lt;br /&gt;
&lt;br /&gt;
Ключевая часть алгоритма состоит из трех циклов:&amp;lt;br&amp;gt;&lt;br /&gt;
Для k от 1 до |V| выполнять &amp;lt;br&amp;gt;&lt;br /&gt;
Для i от 1 до |V| выполнять &amp;lt;br&amp;gt;&lt;br /&gt;
Для j от 1 до |V| выполнять &amp;lt;br&amp;gt;&lt;br /&gt;
Если &amp;lt;math&amp;gt;{D_{ik}+D_{kj} &amp;lt; D_{ij}}&amp;lt;/math&amp;gt;, то &amp;lt;math&amp;gt;{D_{ij} := D_{ik}+D_{kj}}&amp;lt;/math&amp;gt;. &amp;lt;br&amp;gt;&lt;br /&gt;
=== Вычислительное ядро алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Основной операцией алгоритма является релаксация элементов матрицы смежности: если &amp;lt;math&amp;gt;{D_{ik}+D_{kj} &amp;lt; D_{ij}}&amp;lt;/math&amp;gt;, то производится присваивание &amp;lt;math&amp;gt;{D_{ij} := D_{ik}+D_{kj}}&amp;lt;/math&amp;gt;. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Макроструктура алгоритма ===&lt;br /&gt;
=== Схема реализации последовательного алгоритма ===&lt;br /&gt;
=== Последовательная сложность алгоритма ===&lt;br /&gt;
Время выполнения этой программы, очевидно, имеет порядок &amp;lt;math&amp;gt;O(n^3)&amp;lt;/math&amp;gt;, поскольку в ней практически нет ничего, кроме вложенных друг в друга трех циклов.&lt;br /&gt;
&lt;br /&gt;
=== Информационный граф ===&lt;br /&gt;
=== Ресурс параллелизма алгоритма ===&lt;br /&gt;
В последовательном алгоритме единственная операция это нахождение минимума, ее нет смысла распараллеливать. Вся сложность алгоритма заключается в полном переборе «матрицы смежности». Идея параллельных схем алгоритма Флойда-Уоршелла состоит в том, чтобы модифицировать матрицу смежности одновременно несколькими процессорами. Можно выделить два основных подхода.&lt;br /&gt;
&lt;br /&gt;
Первый подход. В распоряжении имеется такое количество процессоров, что можно отдать каждому ровно по одному элементу &amp;lt;math&amp;gt;{D_{ij}}&amp;lt;math&amp;gt;, чтобы он считал для этого элемента минимум.&lt;br /&gt;
&lt;br /&gt;
Второй подход. В распоряжении ограниченное количество процессов. В этом случае грамотным решением будет отдать каждому процессору(или процессу) по одной строке матрицы смежности. Пусть каждый процесс посчитает минимумы в своей строке матрицы и отдаст результаты корневому процессу, это прилично ускорит работу алгоритма.&lt;br /&gt;
&lt;br /&gt;
Для параллельного алгоритма на отдельной итерации каждый процессор выполняет обновление элементов матрицы &amp;lt;math&amp;gt;{D}&amp;lt;math&amp;gt;. Всего в подзадачах &amp;lt;math&amp;gt;{n^2/p}&amp;lt;math&amp;gt; таких элементов, число итераций алгоритма равно &amp;lt;math&amp;gt;{n}&amp;lt;math&amp;gt;, таким образом, показатели ускорения и эффективности параллельного алгоритма Флойда имеют вид (&amp;lt;math&amp;gt;{p}&amp;lt;math&amp;gt; – число процессоров): &amp;lt;math&amp;gt;{Sp = n^3/(n^3/p) = p}&amp;lt;math&amp;gt;, &amp;lt;math&amp;gt;{Ep = n^3/(p(n^3⁄p)) = 1}&amp;lt;math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Входные и выходные данные алгоритма ===&lt;br /&gt;
Входные данные: Матрица смежности D. Перед работой алгоритма матрица D заполняется длинами рёбер графа (или запредельно большим числом M, если ребра нет). &amp;lt;br&amp;gt;&lt;br /&gt;
Выходные данные: Матрица кратчайших расстояний D.&lt;br /&gt;
&lt;br /&gt;
=== Свойства алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Алгоритм может распознавать наличие отрицательных циклов: такой цикл существует, если один из диагональных элементов матрицы расстояний становится меньше нуля.&lt;br /&gt;
&lt;br /&gt;
== Программная реализация алгоритма ==&lt;br /&gt;
=== Особенности реализации последовательного алгоритма ===&lt;br /&gt;
=== Локальность данных и вычислений ===&lt;br /&gt;
==== Локальность реализации алгоритма ====&lt;br /&gt;
===== Структура обращений в память и качественная оценка локальности =====&lt;br /&gt;
===== Количественная оценка локальности =====&lt;br /&gt;
=== Возможные способы и особенности параллельной реализации алгоритма ===&lt;br /&gt;
=== Масштабируемость алгоритма и его реализации ===&lt;br /&gt;
==== Масштабируемость алгоритма ====&lt;br /&gt;
==== Масштабируемость реализации алгоритма ====&lt;br /&gt;
=== Динамические характеристики и эффективность реализации алгоритма ===&lt;br /&gt;
=== Выводы для классов архитектур ===&lt;br /&gt;
=== Существующие реализации алгоритма ===&lt;br /&gt;
&lt;br /&gt;
* C++: [http://www.boost.org/libs/graph/doc/ Boost Graph Library] (функция &amp;lt;code&amp;gt;[http://www.boost.org/libs/graph/doc/floyd_warshall_shortest.html floyd_warshall_shortest]&amp;lt;/code&amp;gt;).&lt;br /&gt;
* Python: [https://networkx.github.io NetworkX] (функция &amp;lt;code&amp;gt;[http://networkx.github.io/documentation/networkx-1.9.1/reference/generated/networkx.algorithms.shortest_paths.dense.floyd_warshall.html floyd_warshall]&amp;lt;/code&amp;gt;).&lt;br /&gt;
* Java: [http://jgrapht.org JGraphT] (класс &amp;lt;code&amp;gt;[http://jgrapht.org/javadoc/org/jgrapht/alg/FloydWarshallShortestPaths.html FloydWarshallShortestPaths]&amp;lt;/code&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
== Литература ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;references /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Категория:Начатые статьи]]&lt;/div&gt;</summary>
		<author><name>EkaterinaShevchenko</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%A4%D0%BB%D0%BE%D0%B9%D0%B4%D0%B0-%D0%A3%D0%BE%D1%80%D1%88%D0%B5%D0%BB%D0%BB%D0%B0&amp;diff=24686</id>
		<title>Алгоритм Флойда-Уоршелла</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%A4%D0%BB%D0%BE%D0%B9%D0%B4%D0%B0-%D0%A3%D0%BE%D1%80%D1%88%D0%B5%D0%BB%D0%BB%D0%B0&amp;diff=24686"/>
		<updated>2017-11-30T18:08:00Z</updated>

		<summary type="html">&lt;p&gt;EkaterinaShevchenko: /* Вычислительное ядро алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Свойства и структура алгоритма ==&lt;br /&gt;
=== Общее описание алгоритма ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Алгоритм Флойда-Уоршелла&#039;&#039;&#039;&amp;lt;ref&amp;gt;Roy, Bernard. “Transitivité Et Connexité.” Comptes Rendus De l&#039;Académie Des Sciences 249 (1959): 216–218.&amp;lt;/ref&amp;gt;&amp;lt;ref&amp;gt;Warshall, Stephen. “A Theorem on Boolean Matrices.” Journal of the ACM 9, no. 1 (January 1, 1962): 11–12. doi:10.1145/321105.321107.&amp;lt;/ref&amp;gt;&amp;lt;ref&amp;gt;Floyd, Robert W. “Algorithm 97: Shortest Path.” Communications of the ACM 5, no. 6 (June 1, 1962): 345. doi:10.1145/367766.368168.&amp;lt;/ref&amp;gt; предназначен для решения [[Поиск кратчайшего пути для всех пар вершин (APSP)|задачи поиска всех кратчайших путей на графе]]. Для заданного ориентированного взвешенного графа алгоритм находит кратчайшие расстояния между всеми парами вершин за время &amp;lt;math&amp;gt;O(n^3)&amp;lt;/math&amp;gt;. Алгоритм применим к графам с произвольными, в том числе с отрицательными, весами. Таким образом, он является более общим в сравнении с [[Алгоритм Дейкстры|алгоритмом Дейкстры]], который не работает с отрицательными весами ребер. Также алгоритм распознаёт наличие отрицательных циклов.&lt;br /&gt;
&lt;br /&gt;
=== Математическое описание алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Имеем граф &amp;lt;math&amp;gt;G=(V,E)&amp;lt;/math&amp;gt;, в котором каждая вершина пронумерована от &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt; до &amp;lt;math&amp;gt;|V|&amp;lt;/math&amp;gt;. Сформируем матрицу смежности &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt;. Эта матрица имеет размер &amp;lt;math&amp;gt;|V|*|V|&amp;lt;/math&amp;gt; и каждому ее элементу &amp;lt;math&amp;gt;D_{ij}&amp;lt;/math&amp;gt; присвоен вес ребра, соединяющего вершину &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; с вершиной &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt;. Заметим, что в силу ориентированности графа &amp;lt;math&amp;gt;G&amp;lt;/math&amp;gt; матрица &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt; может быть несимметрична. &lt;br /&gt;
&lt;br /&gt;
По мере выполнения алгоритма данная матрица будет перезаписываться: в каждую из ее ячеек внесется значение, определяющее оптимальную длину пути из вершины &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; в вершину &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Полагаем диагональные элементы &amp;lt;math&amp;gt;D_{ii}&amp;lt;/math&amp;gt; равными нулю, а недиагональные элементы, соответствующие не инцидентным вершинам (не имеющим общего ребра), положим равными бесконечности или числу, заведомо большему возможного расстояния между ребрами.&lt;br /&gt;
&lt;br /&gt;
Ключевая часть алгоритма состоит из трех циклов:&amp;lt;br&amp;gt;&lt;br /&gt;
Для k от 1 до |V| выполнять &amp;lt;br&amp;gt;&lt;br /&gt;
Для i от 1 до |V| выполнять &amp;lt;br&amp;gt;&lt;br /&gt;
Для j от 1 до |V| выполнять &amp;lt;br&amp;gt;&lt;br /&gt;
Если &amp;lt;math&amp;gt;{D_{ik}+D_{kj} &amp;lt; D_{ij}}&amp;lt;/math&amp;gt;, то &amp;lt;math&amp;gt;{D_{ij} := D_{ik}+D_{kj}}&amp;lt;/math&amp;gt;. &amp;lt;br&amp;gt;&lt;br /&gt;
=== Вычислительное ядро алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Основной операцией алгоритма является релаксация элементов матрицы смежности: если &amp;lt;math&amp;gt;{D_{ik}+D_{kj} &amp;lt; D_{ij}}&amp;lt;/math&amp;gt;, то производится присваивание &amp;lt;math&amp;gt;{D_{ij} := D_{ik}+D_{kj}}&amp;lt;/math&amp;gt;. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Макроструктура алгоритма ===&lt;br /&gt;
=== Схема реализации последовательного алгоритма ===&lt;br /&gt;
=== Последовательная сложность алгоритма ===&lt;br /&gt;
Время выполнения этой программы, очевидно, имеет порядок &amp;lt;math&amp;gt;O(n^3)&amp;lt;/math&amp;gt;, поскольку в ней практически нет ничего, кроме вложенных друг в друга трех циклов.&lt;br /&gt;
&lt;br /&gt;
=== Информационный граф ===&lt;br /&gt;
=== Ресурс параллелизма алгоритма ===&lt;br /&gt;
В последовательном алгоритме единственная операция это нахождение минимума, ее нет смысла распараллеливать. Вся сложность алгоритма $(О^3)$ заключается в полном переборе «матрицы смежности». Идея параллельных схем алгоритма Флойда-Уоршелла состоит в том, чтобы модифицировать матрицу смежности одновременно несколькими процессорами. Можно выделить два основных подхода.&lt;br /&gt;
&lt;br /&gt;
Первый подход. В распоряжении имеется такое количество процессоров, что можно отдать каждому ровно по одному элементу $D_ij$, чтобы он считал для этого элемента минимум.&lt;br /&gt;
&lt;br /&gt;
Второй подход. В распоряжении ограниченное количество процессов. В этом случае грамотным решением будет отдать каждому процессору(или процессу) по одной строке матрицы смежности. Пусть каждый процесс посчитает минимумы в своей строке матрицы и отдаст результаты корневому процессу, это прилично ускорит работу алгоритма.&lt;br /&gt;
&lt;br /&gt;
Для параллельного алгоритма на отдельной итерации каждый процессор выполняет обновление элементов матрицы $D$. Всего в подзадачах $n^2/p$ таких элементов, число итераций алгоритма равно $n$, таким образом, показатели ускорения и эффективности параллельного алгоритма Флойда имеют вид ($p$ – число процессоров): &amp;amp;Sp = n^3/(n^3/p) = p$, $Ep = n^3/(p(n^3⁄p)) = 1$.&lt;br /&gt;
&lt;br /&gt;
=== Входные и выходные данные алгоритма ===&lt;br /&gt;
Входные данные: Матрица смежности D. Перед работой алгоритма матрица D заполняется длинами рёбер графа (или запредельно большим числом M, если ребра нет). &amp;lt;br&amp;gt;&lt;br /&gt;
Выходные данные: Матрица кратчайших расстояний D.&lt;br /&gt;
&lt;br /&gt;
=== Свойства алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Алгоритм может распознавать наличие отрицательных циклов: такой цикл существует, если один из диагональных элементов матрицы расстояний становится меньше нуля.&lt;br /&gt;
&lt;br /&gt;
== Программная реализация алгоритма ==&lt;br /&gt;
=== Особенности реализации последовательного алгоритма ===&lt;br /&gt;
=== Локальность данных и вычислений ===&lt;br /&gt;
==== Локальность реализации алгоритма ====&lt;br /&gt;
===== Структура обращений в память и качественная оценка локальности =====&lt;br /&gt;
===== Количественная оценка локальности =====&lt;br /&gt;
=== Возможные способы и особенности параллельной реализации алгоритма ===&lt;br /&gt;
=== Масштабируемость алгоритма и его реализации ===&lt;br /&gt;
==== Масштабируемость алгоритма ====&lt;br /&gt;
==== Масштабируемость реализации алгоритма ====&lt;br /&gt;
=== Динамические характеристики и эффективность реализации алгоритма ===&lt;br /&gt;
=== Выводы для классов архитектур ===&lt;br /&gt;
=== Существующие реализации алгоритма ===&lt;br /&gt;
&lt;br /&gt;
* C++: [http://www.boost.org/libs/graph/doc/ Boost Graph Library] (функция &amp;lt;code&amp;gt;[http://www.boost.org/libs/graph/doc/floyd_warshall_shortest.html floyd_warshall_shortest]&amp;lt;/code&amp;gt;).&lt;br /&gt;
* Python: [https://networkx.github.io NetworkX] (функция &amp;lt;code&amp;gt;[http://networkx.github.io/documentation/networkx-1.9.1/reference/generated/networkx.algorithms.shortest_paths.dense.floyd_warshall.html floyd_warshall]&amp;lt;/code&amp;gt;).&lt;br /&gt;
* Java: [http://jgrapht.org JGraphT] (класс &amp;lt;code&amp;gt;[http://jgrapht.org/javadoc/org/jgrapht/alg/FloydWarshallShortestPaths.html FloydWarshallShortestPaths]&amp;lt;/code&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
== Литература ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;references /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Категория:Начатые статьи]]&lt;/div&gt;</summary>
		<author><name>EkaterinaShevchenko</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%A4%D0%BB%D0%BE%D0%B9%D0%B4%D0%B0-%D0%A3%D0%BE%D1%80%D1%88%D0%B5%D0%BB%D0%BB%D0%B0&amp;diff=24685</id>
		<title>Алгоритм Флойда-Уоршелла</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%A4%D0%BB%D0%BE%D0%B9%D0%B4%D0%B0-%D0%A3%D0%BE%D1%80%D1%88%D0%B5%D0%BB%D0%BB%D0%B0&amp;diff=24685"/>
		<updated>2017-11-30T18:07:42Z</updated>

		<summary type="html">&lt;p&gt;EkaterinaShevchenko: /* Ресурс параллелизма алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Свойства и структура алгоритма ==&lt;br /&gt;
=== Общее описание алгоритма ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Алгоритм Флойда-Уоршелла&#039;&#039;&#039;&amp;lt;ref&amp;gt;Roy, Bernard. “Transitivité Et Connexité.” Comptes Rendus De l&#039;Académie Des Sciences 249 (1959): 216–218.&amp;lt;/ref&amp;gt;&amp;lt;ref&amp;gt;Warshall, Stephen. “A Theorem on Boolean Matrices.” Journal of the ACM 9, no. 1 (January 1, 1962): 11–12. doi:10.1145/321105.321107.&amp;lt;/ref&amp;gt;&amp;lt;ref&amp;gt;Floyd, Robert W. “Algorithm 97: Shortest Path.” Communications of the ACM 5, no. 6 (June 1, 1962): 345. doi:10.1145/367766.368168.&amp;lt;/ref&amp;gt; предназначен для решения [[Поиск кратчайшего пути для всех пар вершин (APSP)|задачи поиска всех кратчайших путей на графе]]. Для заданного ориентированного взвешенного графа алгоритм находит кратчайшие расстояния между всеми парами вершин за время &amp;lt;math&amp;gt;O(n^3)&amp;lt;/math&amp;gt;. Алгоритм применим к графам с произвольными, в том числе с отрицательными, весами. Таким образом, он является более общим в сравнении с [[Алгоритм Дейкстры|алгоритмом Дейкстры]], который не работает с отрицательными весами ребер. Также алгоритм распознаёт наличие отрицательных циклов.&lt;br /&gt;
&lt;br /&gt;
=== Математическое описание алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Имеем граф &amp;lt;math&amp;gt;G=(V,E)&amp;lt;/math&amp;gt;, в котором каждая вершина пронумерована от &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt; до &amp;lt;math&amp;gt;|V|&amp;lt;/math&amp;gt;. Сформируем матрицу смежности &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt;. Эта матрица имеет размер &amp;lt;math&amp;gt;|V|*|V|&amp;lt;/math&amp;gt; и каждому ее элементу &amp;lt;math&amp;gt;D_{ij}&amp;lt;/math&amp;gt; присвоен вес ребра, соединяющего вершину &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; с вершиной &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt;. Заметим, что в силу ориентированности графа &amp;lt;math&amp;gt;G&amp;lt;/math&amp;gt; матрица &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt; может быть несимметрична. &lt;br /&gt;
&lt;br /&gt;
По мере выполнения алгоритма данная матрица будет перезаписываться: в каждую из ее ячеек внесется значение, определяющее оптимальную длину пути из вершины &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; в вершину &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Полагаем диагональные элементы &amp;lt;math&amp;gt;D_{ii}&amp;lt;/math&amp;gt; равными нулю, а недиагональные элементы, соответствующие не инцидентным вершинам (не имеющим общего ребра), положим равными бесконечности или числу, заведомо большему возможного расстояния между ребрами.&lt;br /&gt;
&lt;br /&gt;
Ключевая часть алгоритма состоит из трех циклов:&amp;lt;br&amp;gt;&lt;br /&gt;
Для k от 1 до |V| выполнять &amp;lt;br&amp;gt;&lt;br /&gt;
Для i от 1 до |V| выполнять &amp;lt;br&amp;gt;&lt;br /&gt;
Для j от 1 до |V| выполнять &amp;lt;br&amp;gt;&lt;br /&gt;
Если &amp;lt;math&amp;gt;{D_{ik}+D_{kj} &amp;lt; D_{ij}}&amp;lt;/math&amp;gt;, то &amp;lt;math&amp;gt;{D_{ij} := D_{ik}+D_{kj}}&amp;lt;/math&amp;gt;. &amp;lt;br&amp;gt;&lt;br /&gt;
=== Вычислительное ядро алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Основной операцией алгоритма является релаксация элементов матрицы смежности: если &amp;lt;math&amp;gt;{D_{ik}+D_{kj} &amp;lt; D_{ij}}&amp;lt;/math&amp;gt;, то производится присваивание &amp;lt;math&amp;gt;{D_{ij} := D_{ik}+D_{kj}}&amp;lt;/math&amp;gt;. &amp;lt;br&amp;gt;&lt;br /&gt;
=== Макроструктура алгоритма ===&lt;br /&gt;
=== Схема реализации последовательного алгоритма ===&lt;br /&gt;
=== Последовательная сложность алгоритма ===&lt;br /&gt;
Время выполнения этой программы, очевидно, имеет порядок &amp;lt;math&amp;gt;O(n^3)&amp;lt;/math&amp;gt;, поскольку в ней практически нет ничего, кроме вложенных друг в друга трех циклов.&lt;br /&gt;
&lt;br /&gt;
=== Информационный граф ===&lt;br /&gt;
=== Ресурс параллелизма алгоритма ===&lt;br /&gt;
В последовательном алгоритме единственная операция это нахождение минимума, ее нет смысла распараллеливать. Вся сложность алгоритма $(О^3)$ заключается в полном переборе «матрицы смежности». Идея параллельных схем алгоритма Флойда-Уоршелла состоит в том, чтобы модифицировать матрицу смежности одновременно несколькими процессорами. Можно выделить два основных подхода.&lt;br /&gt;
&lt;br /&gt;
Первый подход. В распоряжении имеется такое количество процессоров, что можно отдать каждому ровно по одному элементу $D_ij$, чтобы он считал для этого элемента минимум.&lt;br /&gt;
&lt;br /&gt;
Второй подход. В распоряжении ограниченное количество процессов. В этом случае грамотным решением будет отдать каждому процессору(или процессу) по одной строке матрицы смежности. Пусть каждый процесс посчитает минимумы в своей строке матрицы и отдаст результаты корневому процессу, это прилично ускорит работу алгоритма.&lt;br /&gt;
&lt;br /&gt;
Для параллельного алгоритма на отдельной итерации каждый процессор выполняет обновление элементов матрицы $D$. Всего в подзадачах $n^2/p$ таких элементов, число итераций алгоритма равно $n$, таким образом, показатели ускорения и эффективности параллельного алгоритма Флойда имеют вид ($p$ – число процессоров): &amp;amp;Sp = n^3/(n^3/p) = p$, $Ep = n^3/(p(n^3⁄p)) = 1$.&lt;br /&gt;
&lt;br /&gt;
=== Входные и выходные данные алгоритма ===&lt;br /&gt;
Входные данные: Матрица смежности D. Перед работой алгоритма матрица D заполняется длинами рёбер графа (или запредельно большим числом M, если ребра нет). &amp;lt;br&amp;gt;&lt;br /&gt;
Выходные данные: Матрица кратчайших расстояний D.&lt;br /&gt;
&lt;br /&gt;
=== Свойства алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Алгоритм может распознавать наличие отрицательных циклов: такой цикл существует, если один из диагональных элементов матрицы расстояний становится меньше нуля.&lt;br /&gt;
&lt;br /&gt;
== Программная реализация алгоритма ==&lt;br /&gt;
=== Особенности реализации последовательного алгоритма ===&lt;br /&gt;
=== Локальность данных и вычислений ===&lt;br /&gt;
==== Локальность реализации алгоритма ====&lt;br /&gt;
===== Структура обращений в память и качественная оценка локальности =====&lt;br /&gt;
===== Количественная оценка локальности =====&lt;br /&gt;
=== Возможные способы и особенности параллельной реализации алгоритма ===&lt;br /&gt;
=== Масштабируемость алгоритма и его реализации ===&lt;br /&gt;
==== Масштабируемость алгоритма ====&lt;br /&gt;
==== Масштабируемость реализации алгоритма ====&lt;br /&gt;
=== Динамические характеристики и эффективность реализации алгоритма ===&lt;br /&gt;
=== Выводы для классов архитектур ===&lt;br /&gt;
=== Существующие реализации алгоритма ===&lt;br /&gt;
&lt;br /&gt;
* C++: [http://www.boost.org/libs/graph/doc/ Boost Graph Library] (функция &amp;lt;code&amp;gt;[http://www.boost.org/libs/graph/doc/floyd_warshall_shortest.html floyd_warshall_shortest]&amp;lt;/code&amp;gt;).&lt;br /&gt;
* Python: [https://networkx.github.io NetworkX] (функция &amp;lt;code&amp;gt;[http://networkx.github.io/documentation/networkx-1.9.1/reference/generated/networkx.algorithms.shortest_paths.dense.floyd_warshall.html floyd_warshall]&amp;lt;/code&amp;gt;).&lt;br /&gt;
* Java: [http://jgrapht.org JGraphT] (класс &amp;lt;code&amp;gt;[http://jgrapht.org/javadoc/org/jgrapht/alg/FloydWarshallShortestPaths.html FloydWarshallShortestPaths]&amp;lt;/code&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
== Литература ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;references /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Категория:Начатые статьи]]&lt;/div&gt;</summary>
		<author><name>EkaterinaShevchenko</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%A4%D0%BB%D0%BE%D0%B9%D0%B4%D0%B0-%D0%A3%D0%BE%D1%80%D1%88%D0%B5%D0%BB%D0%BB%D0%B0&amp;diff=23323</id>
		<title>Алгоритм Флойда-Уоршелла</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%A4%D0%BB%D0%BE%D0%B9%D0%B4%D0%B0-%D0%A3%D0%BE%D1%80%D1%88%D0%B5%D0%BB%D0%BB%D0%B0&amp;diff=23323"/>
		<updated>2017-10-22T18:53:42Z</updated>

		<summary type="html">&lt;p&gt;EkaterinaShevchenko: /* Свойства и структура алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Свойства и структура алгоритма ==&lt;br /&gt;
=== Общее описание алгоритма ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Алгоритм Флойда-Уоршелла&#039;&#039;&#039;&amp;lt;ref&amp;gt;Roy, Bernard. “Transitivité Et Connexité.” Comptes Rendus De l&#039;Académie Des Sciences 249 (1959): 216–218.&amp;lt;/ref&amp;gt;&amp;lt;ref&amp;gt;Warshall, Stephen. “A Theorem on Boolean Matrices.” Journal of the ACM 9, no. 1 (January 1, 1962): 11–12. doi:10.1145/321105.321107.&amp;lt;/ref&amp;gt;&amp;lt;ref&amp;gt;Floyd, Robert W. “Algorithm 97: Shortest Path.” Communications of the ACM 5, no. 6 (June 1, 1962): 345. doi:10.1145/367766.368168.&amp;lt;/ref&amp;gt; предназначен для решения [[Поиск кратчайшего пути для всех пар вершин (APSP)|задачи поиска всех кратчайших путей на графе]]. Для заданного ориентированного взвешенного графа алгоритм находит кратчайшие расстояния между всеми парами вершин за время &amp;lt;math&amp;gt;O(n^3)&amp;lt;/math&amp;gt;. Алгоритм применим к графам с произвольными, в том числе с отрицательными, весами. Таким образом, он является более общим в сравнении с [[Алгоритм Дейкстры|алгоритмом Дейкстры]], который не работает с отрицательными весами ребер. Также алгоритм распознаёт наличие отрицательных циклов.&lt;br /&gt;
&lt;br /&gt;
=== Математическое описание алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Имеем граф &amp;lt;math&amp;gt;G=(V,E)&amp;lt;/math&amp;gt;, в котором каждая вершина пронумерована от &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt; до &amp;lt;math&amp;gt;|V|&amp;lt;/math&amp;gt;. Сформируем матрицу смежности &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt;. Эта матрица имеет размер &amp;lt;math&amp;gt;|V|*|V|&amp;lt;/math&amp;gt; и каждому ее элементу &amp;lt;math&amp;gt;D_{ij}&amp;lt;/math&amp;gt; присвоен вес ребра, соединяющего вершину &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; с вершиной &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt;. Заметим, что в силу ориентированности графа &amp;lt;math&amp;gt;G&amp;lt;/math&amp;gt; матрица &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt; может быть несимметрична. &lt;br /&gt;
&lt;br /&gt;
По мере выполнения алгоритма данная матрица будет перезаписываться: в каждую из ее ячеек внесется значение, определяющее оптимальную длину пути из вершины &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; в вершину &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Полагаем диагональные элементы &amp;lt;math&amp;gt;D_{ii}&amp;lt;/math&amp;gt; равными нулю, а недиагональные элементы, соответствующие не инцидентным вершинам (не имеющим общего ребра), положим равными бесконечности или числу, заведомо большему возможного расстояния между ребрами.&lt;br /&gt;
&lt;br /&gt;
Ключевая часть алгоритма состоит из трех циклов:&amp;lt;br&amp;gt;&lt;br /&gt;
Для k от 1 до |V| выполнять &amp;lt;br&amp;gt;&lt;br /&gt;
Для i от 1 до |V| выполнять &amp;lt;br&amp;gt;&lt;br /&gt;
Для j от 1 до |V| выполнять &amp;lt;br&amp;gt;&lt;br /&gt;
Если &amp;lt;math&amp;gt;{D_{ik}+D_{kj} &amp;lt; D_{ij}}&amp;lt;/math&amp;gt;, то &amp;lt;math&amp;gt;{D_{ij} := D_{ik}+D_{kj}}&amp;lt;/math&amp;gt;. &amp;lt;br&amp;gt;&lt;br /&gt;
=== Вычислительное ядро алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Основной операцией алгоритма является релаксация элементов матрицы смежности: если &amp;lt;math&amp;gt;{D_{ik}+D_{kj} &amp;lt; D_{ij}}&amp;lt;/math&amp;gt;, то производится присваивание &amp;lt;math&amp;gt;{D_{ij} := D_{ik}+D_{kj}}&amp;lt;/math&amp;gt;. &amp;lt;br&amp;gt;&lt;br /&gt;
=== Макроструктура алгоритма ===&lt;br /&gt;
=== Схема реализации последовательного алгоритма ===&lt;br /&gt;
=== Последовательная сложность алгоритма ===&lt;br /&gt;
Время выполнения этой программы, очевидно, имеет порядок &amp;lt;math&amp;gt;O(n^3)&amp;lt;/math&amp;gt;, поскольку в ней практически нет ничего, кроме вложенных друг в друга трех циклов.&lt;br /&gt;
&lt;br /&gt;
=== Информационный граф ===&lt;br /&gt;
=== Ресурс параллелизма алгоритма ===&lt;br /&gt;
=== Входные и выходные данные алгоритма ===&lt;br /&gt;
Входные данные: Матрица смежности D. Перед работой алгоритма матрица D заполняется длинами рёбер графа (или запредельно большим числом M, если ребра нет). &amp;lt;br&amp;gt;&lt;br /&gt;
Выходные данные: Матрица кратчайших расстояний D.&lt;br /&gt;
&lt;br /&gt;
=== Свойства алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Алгоритм может распознавать наличие отрицательных циклов: такой цикл существует, если один из диагональных элементов матрицы расстояний становится меньше нуля.&lt;br /&gt;
&lt;br /&gt;
== Программная реализация алгоритма ==&lt;br /&gt;
=== Особенности реализации последовательного алгоритма ===&lt;br /&gt;
=== Локальность данных и вычислений ===&lt;br /&gt;
==== Локальность реализации алгоритма ====&lt;br /&gt;
===== Структура обращений в память и качественная оценка локальности =====&lt;br /&gt;
===== Количественная оценка локальности =====&lt;br /&gt;
=== Возможные способы и особенности параллельной реализации алгоритма ===&lt;br /&gt;
=== Масштабируемость алгоритма и его реализации ===&lt;br /&gt;
==== Масштабируемость алгоритма ====&lt;br /&gt;
==== Масштабируемость реализации алгоритма ====&lt;br /&gt;
=== Динамические характеристики и эффективность реализации алгоритма ===&lt;br /&gt;
=== Выводы для классов архитектур ===&lt;br /&gt;
=== Существующие реализации алгоритма ===&lt;br /&gt;
&lt;br /&gt;
* C++: [http://www.boost.org/libs/graph/doc/ Boost Graph Library] (функция &amp;lt;code&amp;gt;[http://www.boost.org/libs/graph/doc/floyd_warshall_shortest.html floyd_warshall_shortest]&amp;lt;/code&amp;gt;).&lt;br /&gt;
* Python: [https://networkx.github.io NetworkX] (функция &amp;lt;code&amp;gt;[http://networkx.github.io/documentation/networkx-1.9.1/reference/generated/networkx.algorithms.shortest_paths.dense.floyd_warshall.html floyd_warshall]&amp;lt;/code&amp;gt;).&lt;br /&gt;
* Java: [http://jgrapht.org JGraphT] (класс &amp;lt;code&amp;gt;[http://jgrapht.org/javadoc/org/jgrapht/alg/FloydWarshallShortestPaths.html FloydWarshallShortestPaths]&amp;lt;/code&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
== Литература ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;references /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Категория:Начатые статьи]]&lt;/div&gt;</summary>
		<author><name>EkaterinaShevchenko</name></author>
	</entry>
</feed>