<?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=AleksLevin</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=AleksLevin"/>
	<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/AleksLevin"/>
	<updated>2026-10-22T15:52:32Z</updated>
	<subtitle>Вклад</subtitle>
	<generator>MediaWiki 1.43.5</generator>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%9E%D0%B1%D1%81%D1%83%D0%B6%D0%B4%D0%B5%D0%BD%D0%B8%D0%B5_%D1%83%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA%D0%B0:AleksLevin&amp;diff=21491</id>
		<title>Обсуждение участника:AleksLevin</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%9E%D0%B1%D1%81%D1%83%D0%B6%D0%B4%D0%B5%D0%BD%D0%B8%D0%B5_%D1%83%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA%D0%B0:AleksLevin&amp;diff=21491"/>
		<updated>2016-12-23T13:12:54Z</updated>

		<summary type="html">&lt;p&gt;AleksLevin: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Статья [[Участник:AleksLevin/Алгоритм Ланцоша вычисления собственных значений симметричной матрицы для точной арифметики (без переортогонализации)]] ==&lt;br /&gt;
&lt;br /&gt;
=== Отсутствующие части ===&lt;br /&gt;
* Не заполнен раздел 2.4 описания. [[Участник:ASA|Александр Сергеевич Антонов]] ([[Обсуждение участника:ASA|обсуждение]]) 15:12, 16 ноября 2016 (MSK)&lt;br /&gt;
&lt;br /&gt;
=== Замечания ===&lt;br /&gt;
* убрать подробности (&amp;quot;студент, ...&amp;quot;) со страницы алгоритма, но оставить на самой странице автора&lt;br /&gt;
* убрать &amp;quot;все описанные разделы самостоятельно&amp;quot;&lt;br /&gt;
* во врезке про высоту ЯПФ убрать слова, оставив множитель &amp;quot;k&amp;quot; (все слова переместить в основной текст)&lt;br /&gt;
* 1.2 &amp;quot;Для лучшего понимания описания, данного в этом пункте статьи, рекомендуется ознакомиться с параграфом ...&amp;quot; представьте, что Вы пишете научную статью для профессоров другого университета для которых [2] не является достаточным авторитетом. Пишите более нейтрально и отстраненно.&lt;br /&gt;
* 1.3 чуть подробнее&lt;br /&gt;
* 1.4 &amp;quot;Вторая часть алгоритма&amp;quot; - здесь же или ниже рассказать об этой операции, не ограничиваясь отсылкой к ее нетривиальности.&lt;br /&gt;
* 1.5 не стоит выделять текст жирным &amp;quot;\mathbf{1.2}&amp;quot; (то же самое во свех остальных местах)&lt;br /&gt;
* 1.5 просьба заменить &amp;quot;j=\overline {1,k}&amp;quot; на более употребительное &amp;quot;j=1,...,k&amp;quot;&lt;br /&gt;
* 1.7 Рис. лучше пронумеровать, оставив короткую подпись, а теперешнюю подпись поместить в основной текст&lt;br /&gt;
* 1.8 хорошо написан этот важный пункт&lt;br /&gt;
* 2.1-2.6 отсутствуют...&lt;br /&gt;
* особенно хотелось бы узнать ваше мнение по п.2.6, это действительно, нетривиально и неоднозначно&lt;br /&gt;
* 3. не стоит разделять и противопоставлять [1]-[5] и 1.-13. Лучше все ссылки дать во втором стиле.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Сделал множество правок и учёл все вышеупомянутые замечания и пожелания! С уважением, Левин Александр.&#039;&#039;&#039;&lt;br /&gt;
&#039;&#039;По заданию, во второй части требовалось описать только разделы 2.4 и 2.7, прошу не спрашивать с меня все разделы 2.1-2.6. Надеюсь на понимание, мне физически не хватает времени на это задание + 2 других в течение семестра, стараюсь и делаю всё, что в моих силах :)&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* Справедливо. Зачтено. Успехов!&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;UPDATE (19.12.16)&#039;&#039; Спасибо большое вам!&lt;br /&gt;
Сегодня вдруг заметил, что в пункте 1.4 показывает у меня на ПК в браузерах Opera и Google Chrome какую-то ошибку : &amp;quot;Невозможно разобрать выражение (MathML с переходом в SVG или PNG (рекомендуется для современных браузеров и инструментов повышения доступности): Недопустимый ответ («Во время обработки HTTP-запроса обнаружена проблема: 502 Bad Gateway») от сервера «http://mathoid.testme.wmflabs.org»: &amp;quot;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Хотя я с того момента, как задание было зачтено, уже две недели вообще ничего не трогал и не менял, и это математическое выражение всегда отображалось хорошо и без проблем. Надеюсь, что просто возникла ошибка на каком-то сервере и скоро будет исправлена. Интересно, что в режиме предварительного просмотра этого же пункта (без каких-либо правок) всё отображается правильно и без каких-либо ошибок.&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;UPDATE 2 (23.12.16)&#039;&#039; Всё стало снова хорошо, никаких изменений не делал. Видимо, действительно, была проблема с каким-то удалённым сервером.&lt;br /&gt;
&#039;&#039;&#039;Левин Александр&#039;&#039;&#039;&lt;/div&gt;</summary>
		<author><name>AleksLevin</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%9E%D0%B1%D1%81%D1%83%D0%B6%D0%B4%D0%B5%D0%BD%D0%B8%D0%B5_%D1%83%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA%D0%B0:AleksLevin&amp;diff=21490</id>
		<title>Обсуждение участника:AleksLevin</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%9E%D0%B1%D1%81%D1%83%D0%B6%D0%B4%D0%B5%D0%BD%D0%B8%D0%B5_%D1%83%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA%D0%B0:AleksLevin&amp;diff=21490"/>
		<updated>2016-12-23T13:12:28Z</updated>

		<summary type="html">&lt;p&gt;AleksLevin: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Статья [[Участник:AleksLevin/Алгоритм Ланцоша вычисления собственных значений симметричной матрицы для точной арифметики (без переортогонализации)]] ==&lt;br /&gt;
&lt;br /&gt;
=== Отсутствующие части ===&lt;br /&gt;
* Не заполнен раздел 2.4 описания. [[Участник:ASA|Александр Сергеевич Антонов]] ([[Обсуждение участника:ASA|обсуждение]]) 15:12, 16 ноября 2016 (MSK)&lt;br /&gt;
&lt;br /&gt;
=== Замечания ===&lt;br /&gt;
* убрать подробности (&amp;quot;студент, ...&amp;quot;) со страницы алгоритма, но оставить на самой странице автора&lt;br /&gt;
* убрать &amp;quot;все описанные разделы самостоятельно&amp;quot;&lt;br /&gt;
* во врезке про высоту ЯПФ убрать слова, оставив множитель &amp;quot;k&amp;quot; (все слова переместить в основной текст)&lt;br /&gt;
* 1.2 &amp;quot;Для лучшего понимания описания, данного в этом пункте статьи, рекомендуется ознакомиться с параграфом ...&amp;quot; представьте, что Вы пишете научную статью для профессоров другого университета для которых [2] не является достаточным авторитетом. Пишите более нейтрально и отстраненно.&lt;br /&gt;
* 1.3 чуть подробнее&lt;br /&gt;
* 1.4 &amp;quot;Вторая часть алгоритма&amp;quot; - здесь же или ниже рассказать об этой операции, не ограничиваясь отсылкой к ее нетривиальности.&lt;br /&gt;
* 1.5 не стоит выделять текст жирным &amp;quot;\mathbf{1.2}&amp;quot; (то же самое во свех остальных местах)&lt;br /&gt;
* 1.5 просьба заменить &amp;quot;j=\overline {1,k}&amp;quot; на более употребительное &amp;quot;j=1,...,k&amp;quot;&lt;br /&gt;
* 1.7 Рис. лучше пронумеровать, оставив короткую подпись, а теперешнюю подпись поместить в основной текст&lt;br /&gt;
* 1.8 хорошо написан этот важный пункт&lt;br /&gt;
* 2.1-2.6 отсутствуют...&lt;br /&gt;
* особенно хотелось бы узнать ваше мнение по п.2.6, это действительно, нетривиально и неоднозначно&lt;br /&gt;
* 3. не стоит разделять и противопоставлять [1]-[5] и 1.-13. Лучше все ссылки дать во втором стиле.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Сделал множество правок и учёл все вышеупомянутые замечания и пожелания! С уважением, Левин Александр.&#039;&#039;&#039;&lt;br /&gt;
&#039;&#039;По заданию, во второй части требовалось описать только разделы 2.4 и 2.7, прошу не спрашивать с меня все разделы 2.1-2.6. Надеюсь на понимание, мне физически не хватает времени на это задание + 2 других в течение семестра, стараюсь и делаю всё, что в моих силах :)&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* Справедливо. Зачтено. Успехов!&lt;br /&gt;
&lt;br /&gt;
UPDATE (19.12.16) Спасибо большое вам!&lt;br /&gt;
Сегодня вдруг заметил, что в пункте 1.4 показывает у меня на ПК в браузерах Opera и Google Chrome какую-то ошибку : &amp;quot;Невозможно разобрать выражение (MathML с переходом в SVG или PNG (рекомендуется для современных браузеров и инструментов повышения доступности): Недопустимый ответ («Во время обработки HTTP-запроса обнаружена проблема: 502 Bad Gateway») от сервера «http://mathoid.testme.wmflabs.org»: &amp;quot;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Хотя я с того момента, как задание было зачтено, уже две недели вообще ничего не трогал и не менял, и это математическое выражение всегда отображалось хорошо и без проблем. Надеюсь, что просто возникла ошибка на каком-то сервере и скоро будет исправлена. Интересно, что в режиме предварительного просмотра этого же пункта (без каких-либо правок) всё отображается правильно и без каких-либо ошибок.&lt;br /&gt;
UPDATE 2 (23.12.16) Всё стало снова хорошо, никаких изменений не делал. Видимо, действительно, была проблема с каким-то удалённым сервером.&lt;br /&gt;
&#039;&#039;&#039;Левин Александр&#039;&#039;&#039;&lt;/div&gt;</summary>
		<author><name>AleksLevin</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%9E%D0%B1%D1%81%D1%83%D0%B6%D0%B4%D0%B5%D0%BD%D0%B8%D0%B5_%D1%83%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA%D0%B0:AleksLevin&amp;diff=21351</id>
		<title>Обсуждение участника:AleksLevin</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%9E%D0%B1%D1%81%D1%83%D0%B6%D0%B4%D0%B5%D0%BD%D0%B8%D0%B5_%D1%83%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA%D0%B0:AleksLevin&amp;diff=21351"/>
		<updated>2016-12-19T10:08:24Z</updated>

		<summary type="html">&lt;p&gt;AleksLevin: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Статья [[Участник:AleksLevin/Алгоритм Ланцоша вычисления собственных значений симметричной матрицы для точной арифметики (без переортогонализации)]] ==&lt;br /&gt;
&lt;br /&gt;
=== Отсутствующие части ===&lt;br /&gt;
* Не заполнен раздел 2.4 описания. [[Участник:ASA|Александр Сергеевич Антонов]] ([[Обсуждение участника:ASA|обсуждение]]) 15:12, 16 ноября 2016 (MSK)&lt;br /&gt;
&lt;br /&gt;
=== Замечания ===&lt;br /&gt;
* убрать подробности (&amp;quot;студент, ...&amp;quot;) со страницы алгоритма, но оставить на самой странице автора&lt;br /&gt;
* убрать &amp;quot;все описанные разделы самостоятельно&amp;quot;&lt;br /&gt;
* во врезке про высоту ЯПФ убрать слова, оставив множитель &amp;quot;k&amp;quot; (все слова переместить в основной текст)&lt;br /&gt;
* 1.2 &amp;quot;Для лучшего понимания описания, данного в этом пункте статьи, рекомендуется ознакомиться с параграфом ...&amp;quot; представьте, что Вы пишете научную статью для профессоров другого университета для которых [2] не является достаточным авторитетом. Пишите более нейтрально и отстраненно.&lt;br /&gt;
* 1.3 чуть подробнее&lt;br /&gt;
* 1.4 &amp;quot;Вторая часть алгоритма&amp;quot; - здесь же или ниже рассказать об этой операции, не ограничиваясь отсылкой к ее нетривиальности.&lt;br /&gt;
* 1.5 не стоит выделять текст жирным &amp;quot;\mathbf{1.2}&amp;quot; (то же самое во свех остальных местах)&lt;br /&gt;
* 1.5 просьба заменить &amp;quot;j=\overline {1,k}&amp;quot; на более употребительное &amp;quot;j=1,...,k&amp;quot;&lt;br /&gt;
* 1.7 Рис. лучше пронумеровать, оставив короткую подпись, а теперешнюю подпись поместить в основной текст&lt;br /&gt;
* 1.8 хорошо написан этот важный пункт&lt;br /&gt;
* 2.1-2.6 отсутствуют...&lt;br /&gt;
* особенно хотелось бы узнать ваше мнение по п.2.6, это действительно, нетривиально и неоднозначно&lt;br /&gt;
* 3. не стоит разделять и противопоставлять [1]-[5] и 1.-13. Лучше все ссылки дать во втором стиле.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Сделал множество правок и учёл все вышеупомянутые замечания и пожелания! С уважением, Левин Александр.&#039;&#039;&#039;&lt;br /&gt;
&#039;&#039;По заданию, во второй части требовалось описать только разделы 2.4 и 2.7, прошу не спрашивать с меня все разделы 2.1-2.6. Надеюсь на понимание, мне физически не хватает времени на это задание + 2 других в течение семестра, стараюсь и делаю всё, что в моих силах :)&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* Справедливо. Зачтено. Успехов!&lt;br /&gt;
&lt;br /&gt;
UPDATE (19.12.16) Спасибо большое вам!&lt;br /&gt;
Сегодня вдруг заметил, что в пункте 1.4 показывает у меня на ПК в браузерах Opera и Google Chrome какую-то ошибку : &amp;quot;Невозможно разобрать выражение (MathML с переходом в SVG или PNG (рекомендуется для современных браузеров и инструментов повышения доступности): Недопустимый ответ («Во время обработки HTTP-запроса обнаружена проблема: 502 Bad Gateway») от сервера «http://mathoid.testme.wmflabs.org»:): |T_{m,m-1}^{(k)}| \leq \varepsilon\,|T_{m,m}^{(k)}| \quad\quad &amp;quot;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Хотя я с того момента, как задание было зачтено, уже две недели вообще ничего не трогал и не менял, и это математическое выражение всегда отображалось хорошо и без проблем. Надеюсь, что просто возникла ошибка на каком-то сервере и скоро будет исправлена. Интересно, что в режиме предварительного просмотра этого же пункта (без каких-либо правок) всё отображается правильно и без каких-либо ошибок.&lt;br /&gt;
&#039;&#039;&#039;Левин Александр&#039;&#039;&#039;&lt;/div&gt;</summary>
		<author><name>AleksLevin</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%9E%D0%B1%D1%81%D1%83%D0%B6%D0%B4%D0%B5%D0%BD%D0%B8%D0%B5_%D1%83%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA%D0%B0:AleksLevin&amp;diff=21350</id>
		<title>Обсуждение участника:AleksLevin</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%9E%D0%B1%D1%81%D1%83%D0%B6%D0%B4%D0%B5%D0%BD%D0%B8%D0%B5_%D1%83%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA%D0%B0:AleksLevin&amp;diff=21350"/>
		<updated>2016-12-19T10:05:44Z</updated>

		<summary type="html">&lt;p&gt;AleksLevin: /* Статья Участник:AleksLevin/Алгоритм Ланцоша вычисления собственных значений симметричной матрицы для точной арифметики (без переортогонал…&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Статья [[Участник:AleksLevin/Алгоритм Ланцоша вычисления собственных значений симметричной матрицы для точной арифметики (без переортогонализации)]] ==&lt;br /&gt;
&lt;br /&gt;
=== Отсутствующие части ===&lt;br /&gt;
* Не заполнен раздел 2.4 описания. [[Участник:ASA|Александр Сергеевич Антонов]] ([[Обсуждение участника:ASA|обсуждение]]) 15:12, 16 ноября 2016 (MSK)&lt;br /&gt;
&lt;br /&gt;
=== Замечания ===&lt;br /&gt;
* убрать подробности (&amp;quot;студент, ...&amp;quot;) со страницы алгоритма, но оставить на самой странице автора&lt;br /&gt;
* убрать &amp;quot;все описанные разделы самостоятельно&amp;quot;&lt;br /&gt;
* во врезке про высоту ЯПФ убрать слова, оставив множитель &amp;quot;k&amp;quot; (все слова переместить в основной текст)&lt;br /&gt;
* 1.2 &amp;quot;Для лучшего понимания описания, данного в этом пункте статьи, рекомендуется ознакомиться с параграфом ...&amp;quot; представьте, что Вы пишете научную статью для профессоров другого университета для которых [2] не является достаточным авторитетом. Пишите более нейтрально и отстраненно.&lt;br /&gt;
* 1.3 чуть подробнее&lt;br /&gt;
* 1.4 &amp;quot;Вторая часть алгоритма&amp;quot; - здесь же или ниже рассказать об этой операции, не ограничиваясь отсылкой к ее нетривиальности.&lt;br /&gt;
* 1.5 не стоит выделять текст жирным &amp;quot;\mathbf{1.2}&amp;quot; (то же самое во свех остальных местах)&lt;br /&gt;
* 1.5 просьба заменить &amp;quot;j=\overline {1,k}&amp;quot; на более употребительное &amp;quot;j=1,...,k&amp;quot;&lt;br /&gt;
* 1.7 Рис. лучше пронумеровать, оставив короткую подпись, а теперешнюю подпись поместить в основной текст&lt;br /&gt;
* 1.8 хорошо написан этот важный пункт&lt;br /&gt;
* 2.1-2.6 отсутствуют...&lt;br /&gt;
* особенно хотелось бы узнать ваше мнение по п.2.6, это действительно, нетривиально и неоднозначно&lt;br /&gt;
* 3. не стоит разделять и противопоставлять [1]-[5] и 1.-13. Лучше все ссылки дать во втором стиле.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Сделал множество правок и учёл все вышеупомянутые замечания и пожелания! С уважением, Левин Александр.&#039;&#039;&#039;&lt;br /&gt;
&#039;&#039;По заданию, во второй части требовалось описать только разделы 2.4 и 2.7, прошу не спрашивать с меня все разделы 2.1-2.6. Надеюсь на понимание, мне физически не хватает времени на это задание + 2 других в течение семестра, стараюсь и делаю всё, что в моих силах :)&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* Справедливо. Зачтено. Успехов!&lt;br /&gt;
&lt;br /&gt;
UPDATE (19.12.16) Спасибо большое вам!&lt;br /&gt;
Сегодня вдруг заметил, что в пункте 1.4 показывает у меня на ПК в браузерах Opera и Google Chrome какую-то ошибку : &amp;quot;Невозможно разобрать выражение (MathML с переходом в SVG или PNG (рекомендуется для современных браузеров и инструментов повышения доступности): Недопустимый ответ («Во время обработки HTTP-запроса обнаружена проблема: 502 Bad Gateway») от сервера «http://mathoid.testme.wmflabs.org»:): |T_{m,m-1}^{(k)}| \leq \varepsilon\,|T_{m,m}^{(k)}| \quad\quad &amp;quot;&lt;br /&gt;
Хотя я с момента, как задание было зачтено, уже две недели вообще ничего не трогал и не менял, и это математическое выражение отображалось хорошо и без проблем. Надеюсь, что ошибка на каком-то сервере и скоро будет исправлена. Интересно, что в режиме предварительного просмотра этого пункта всё отображается правильно и без каких-либо ошибок.&lt;br /&gt;
&#039;&#039;&#039;Левин Александр&#039;&#039;&#039;&lt;/div&gt;</summary>
		<author><name>AleksLevin</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:AleksLevin/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%9B%D0%B0%D0%BD%D1%86%D0%BE%D1%88%D0%B0_%D0%B2%D1%8B%D1%87%D0%B8%D1%81%D0%BB%D0%B5%D0%BD%D0%B8%D1%8F_%D1%81%D0%BE%D0%B1%D1%81%D1%82%D0%B2%D0%B5%D0%BD%D0%BD%D1%8B%D1%85_%D0%B7%D0%BD%D0%B0%D1%87%D0%B5%D0%BD%D0%B8%D0%B9_%D1%81%D0%B8%D0%BC%D0%BC%D0%B5%D1%82%D1%80%D0%B8%D1%87%D0%BD%D0%BE%D0%B9_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86%D1%8B_%D0%B4%D0%BB%D1%8F_%D1%82%D0%BE%D1%87%D0%BD%D0%BE%D0%B9_%D0%B0%D1%80%D0%B8%D1%84%D0%BC%D0%B5%D1%82%D0%B8%D0%BA%D0%B8_(%D0%B1%D0%B5%D0%B7_%D0%BF%D0%B5%D1%80%D0%B5%D0%BE%D1%80%D1%82%D0%BE%D0%B3%D0%BE%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D0%B8)&amp;diff=20297</id>
		<title>Участник:AleksLevin/Алгоритм Ланцоша вычисления собственных значений симметричной матрицы для точной арифметики (без переортогонализации)</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:AleksLevin/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%9B%D0%B0%D0%BD%D1%86%D0%BE%D1%88%D0%B0_%D0%B2%D1%8B%D1%87%D0%B8%D1%81%D0%BB%D0%B5%D0%BD%D0%B8%D1%8F_%D1%81%D0%BE%D0%B1%D1%81%D1%82%D0%B2%D0%B5%D0%BD%D0%BD%D1%8B%D1%85_%D0%B7%D0%BD%D0%B0%D1%87%D0%B5%D0%BD%D0%B8%D0%B9_%D1%81%D0%B8%D0%BC%D0%BC%D0%B5%D1%82%D1%80%D0%B8%D1%87%D0%BD%D0%BE%D0%B9_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86%D1%8B_%D0%B4%D0%BB%D1%8F_%D1%82%D0%BE%D1%87%D0%BD%D0%BE%D0%B9_%D0%B0%D1%80%D0%B8%D1%84%D0%BC%D0%B5%D1%82%D0%B8%D0%BA%D0%B8_(%D0%B1%D0%B5%D0%B7_%D0%BF%D0%B5%D1%80%D0%B5%D0%BE%D1%80%D1%82%D0%BE%D0%B3%D0%BE%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D0%B8)&amp;diff=20297"/>
		<updated>2016-12-07T20:26:47Z</updated>

		<summary type="html">&lt;p&gt;AleksLevin: /* Масштабируемость алгоритма и его реализации */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Assignment}}&lt;br /&gt;
Основные авторы описания: Левин А.Д.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{algorithm&lt;br /&gt;
| name              = Алгоритм Ланцоша для точной арифметики (без переортогонализации)&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(k\,n^2)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(k\log_2 n)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;\frac{n^2+3n}{2} + 1&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;k\;(n + 1)&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритмов =&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Данный алгоритм появился в 1950 г. и носит имя венгерского физика и математика Корнелия Ланцоша (венг. Lánczos Kornél). Алгоритм Ланцоша относится к итерационным методам вычисления собственных значений для матриц столь больших порядков &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt; n&amp;lt;/math&amp;gt;, что к ним нельзя применить прямые методы из-за ограничений по времени и памяти.&lt;br /&gt;
&lt;br /&gt;
Сам Ланцош указывал, что его метод предназначен для отыскания нескольких собственных векторов симметричных матриц, хотя к методу сразу было обращено внимание, как к способу приведения всей матрицы к трёхдиагональному виду. Двадцатью годами позже канадский математик Крис Пэж показал, что, несмотря на чувствительность к округлениям, алгоритм Ланцоша - эффективное средство вычисления некоторых &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; собственных чисел и соответствующих им собственных векторов. &amp;lt;ref&amp;gt;Парлетт Б. - Симметричная проблема собственных значений. Численные методы //М.: Мир. - 1983. (c. 276)&amp;lt;/ref&amp;gt;&lt;br /&gt;
Обычно число &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; берут в два раза больше, чем количество собственных значений матрицы, которые поставлена цель найти, и оно имеет порядок не более &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;10^2&amp;lt;/math&amp;gt;.&amp;lt;ref&amp;gt;Susan W. Bostic - Lanczos Eigensolution Method for High-Perfomance Computers, page 7&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Алгоритм Ланцоша для вычисления собственных значений симметричной матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; соединяет в себе метод Ланцоша для построения последовательности подпространств Крылова и ортонормированных векторов Ланцоша и процедуру Рэлея-Ритца получения оптимальных приближений собственных значений и соответствующих собственных векторов исходной матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt;.&amp;lt;ref&amp;gt;James W. Demmel - Вычислительная линейная алгебра. Теория и приложения //Мир. - 2001 (c. 381)&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
В данной статье рассматривается вариант алгоритма Ланцоша, в котором опущено влияние ошибок округления на вычислительный процесс, хотя на практике этому посвящается отдельное внимание и существуют различные методы решения данной проблемы, такие как частичная или полная переортогонализация. Этим модифицированным методам посвящены отдельные статьи на данном ресурсе.&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
Обозначения и формулы, используемые в данном разделе, взяты из литературы, указанной по ссылке.&amp;lt;ref&amp;gt;James W. Demmel - Вычислительная линейная алгебра. Теория и приложения //Мир. - 2001 (c. 313, &#039;&#039;&amp;lt;math&amp;gt; \S &amp;lt;/math&amp;gt; 6.6 Методы Крыловского подпространства&#039;&#039;)&amp;lt;/ref&amp;gt; &lt;br /&gt;
&lt;br /&gt;
Алгоритм Ланцоша для вычисления &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; собственных значений и собственных векторов вещественной симметричной матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A=A^T&amp;lt;/math&amp;gt; в точной арифметике: &amp;lt;ref&amp;gt;James W. Demmel - Вычислительная линейная алгебра. Теория и приложения //Мир. - 2001 (c. 381)&amp;lt;/ref&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{align}&lt;br /&gt;
q_1 = &amp;amp; \,\frac{b}{\|b\|_2},\; \beta_0 = 0,\; q_0 = 0\\&lt;br /&gt;
\mathbf{for} \; &amp;amp; j = 1 \; to \; k \,\; \mathbf{do} \\&lt;br /&gt;
&amp;amp; z = A\,q_j\\&lt;br /&gt;
&amp;amp; \alpha_j = q^T_j z\\&lt;br /&gt;
&amp;amp; z = z - \alpha_j q_j - \beta_{j-1}q_{j-1}\\&lt;br /&gt;
&amp;amp; \beta_j = \|z\|_2\\&lt;br /&gt;
&amp;amp; \mathbf{If} \; (\beta_j == 0) \; \mathbf{then}\; stop\; the\; algorithm \\ &lt;br /&gt;
&amp;amp; \;  q_{j+1} = \frac{z}{\beta_j} \\&lt;br /&gt;
&amp;amp; compute\; eigenvalues\; and \;eigenvectors\;of \;matrix \;\;T_j= Q^T_j A Q\;\;and\;estimate \;the\; errors\\&lt;br /&gt;
\mathbf{end} \; &amp;amp; \mathbf{for}&lt;br /&gt;
\end{align}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
В продемонстрированном выше алгоритме &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;b&amp;lt;/math&amp;gt; - заданный вещественный вектор. Также полагается известным алгоритм вычисления произведения матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; на вектор &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;x&amp;lt;/math&amp;gt;. &lt;br /&gt;
Введём матрицу Крылова, определяемую следующим соотношением: &amp;lt;math&amp;gt;K_j = [b,Ab,A^2b,...,A^{j-1}b]&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Далее, на практике, матрица &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;K&amp;lt;/math&amp;gt; заменяется матрицей &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;Q&amp;lt;/math&amp;gt;, такой, что при любом числе &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; линейные оболочки первых &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; столбцов в &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;K&amp;lt;/math&amp;gt; и &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;Q&amp;lt;/math&amp;gt; являются одним и тем же подпространством.&amp;lt;ref&amp;gt;James W. Demmel - Вычислительная линейная алгебра. Теория и приложения //Мир. - 2001 (c. 315)&amp;lt;/ref&amp;gt; &lt;br /&gt;
Тогда матрица &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;Q&amp;lt;/math&amp;gt;, в отличие от матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;K&amp;lt;/math&amp;gt;, хорошо обусловлена и легко обратима. В результате получаем матрицу &amp;lt;math&amp;gt;Q_j = [q_1, q_2, \dots, q_j]&amp;lt;/math&amp;gt; размерности &amp;lt;math&amp;gt;n\times j&amp;lt;/math&amp;gt;, столбцы которой ортогональны, являются базисом подпространства Крылова и называются векторами Ланцоша.&lt;br /&gt;
&lt;br /&gt;
В алгоритме Ланцоша вычислению подлежит столько первых столбцов в матрице &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;Q_j&amp;lt;/math&amp;gt;, сколько необходимо для получения требуемого приближения к решению &amp;lt;math&amp;gt;A\,x\,=b\,\,(A\,x=\lambda \, x)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Получение нулевого &amp;lt;math&amp;gt;\beta_j&amp;lt;/math&amp;gt; в итерационном процессе - событие, желательное в том смысле, что оно свидетельствует о том, что найдено некоторое подпространство, являющееся в точности инвариантным, а все собственные значения матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;T_j&amp;lt;/math&amp;gt; являются собственными значениями матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt;. На практике же нулевое и близкие к нулю значения получаются редко.&amp;lt;ref&amp;gt;Голуб Дж., Ван Лоун Ч. - Матричные вычисления//М.: Мир. - 1999 (c. 429)&amp;lt;/ref&amp;gt; &lt;br /&gt;
&lt;br /&gt;
Затем на каждом шаге цикла формируется симметричная трёхдиагональная матрица &amp;lt;math&amp;gt;T_j = Q^T_j A Q&amp;lt;/math&amp;gt;, к которой применяется процесс Рэлея-Ритца для поиска её собственных значений (на практике для поиска этих собственных значений можно использовать любой из специальных методов в параграфе книги по ссылке).&amp;lt;ref&amp;gt;Голуб Дж., Ван Лоун Ч. - Матричные вычисления//М.: Мир. - 1999 (&amp;lt;math&amp;gt;\S&amp;lt;/math&amp;gt; 8.4)&amp;lt;/ref&amp;gt;  &lt;br /&gt;
Эти собственные значения, они же числа Ритца, и полагаются приближёнными собственными значениями исходной матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt;.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Существует множество методов для отыскания собственных значений вещественной симметричной трехдиагональной матрицы. Большинство из них требует &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt; операций &amp;lt;ref&amp;gt;Парлетт Б. Симметричная проблема собственных значений. Численные методы.,: Мир, 1983. с. 179-182&amp;lt;/ref&amp;gt;, но существуют и быстрые алгоритмы, требующие лишь &amp;lt;math&amp;gt;O(n\ln n)&amp;lt;/math&amp;gt; операций.&amp;lt;ref&amp;gt;https://en.wikipedia.org/wiki/Tridiagonal_matrix#Eigenvalues  Раздел eigenvalues&amp;lt;/ref&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Одним из возможных способов отыскать собственные значения симметричной трехдиагональной матрицы - прямое вычисление корней характеристического полинома &amp;lt;math&amp;gt;p_n(\lambda)&amp;lt;/math&amp;gt; через метод деления пополам, где формируется последовательность Штурма и локализуются собственные числа, являющиеся корнями характеристического полинома. Нахождение всех &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; собственных значений матрицы этим способом требует &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;2n^2t&amp;lt;/math&amp;gt; умножений и вычитаний, где &amp;lt;math&amp;gt;t&amp;lt;/math&amp;gt; - число сделанных шагов с применением метода деления пополам.&amp;lt;ref&amp;gt;Уилкинсон Дж. X. Алгебраическая проблема собственныx значений. Изд-во &amp;quot;Наука&amp;quot;, 1970. - глава 5, с. 272-278&amp;lt;/ref&amp;gt; Соответствующие собственные вектора могут быть найдены посредством обратных итераций за &amp;lt;math&amp;gt; O(n) &amp;lt;/math&amp;gt; флопов. &amp;lt;ref&amp;gt;Голуб Дж., Ван Лоун Ч. - Матричные вычисления//М.: Мир. - 1999 (c. 394-395)&amp;lt;/ref&amp;gt; &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;На практике, если требуется только небольшая часть от всей совокупности собственных векторов и значений, и матрица имеет Хессенбергову или трёхдиагональную форму, очень эффективными будут методы факторизации, как, например, QR-алгоритм или QL-алгоритм со сдвигами (c целью ускорить алгоритм и сделать порядок сходимости квадратичным) или же без них.&amp;lt;ref&amp;gt;http://algorithm.narod.ru/ln/eigen/ETridiag.html&amp;lt;/ref&amp;gt; &amp;lt;br&amp;gt;&lt;br /&gt;
Весьма молодые и не менее актуальные конкуренты QR и QL алгоритмов, применяющиеся для поиска собственных значений:&lt;br /&gt;
*Методы divide-and-conquer (разделяй и властвуй), появившиеся в 1980-ых годах &amp;lt;ref&amp;gt;https://goo.gl/dapvbn ссылку пришлось сократить с помощью Google url shortener, так как символы подчеркивания портили её и не давали перейти по 1 клику&amp;lt;/ref&amp;gt;&lt;br /&gt;
*Relatively robust representation методы, появившиеся в 1990-ых и позволяющие найти собственные числа симметричной матрицы порядка &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;n&amp;lt;/math&amp;gt; за &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt; операций&lt;br /&gt;
&lt;br /&gt;
Если требуется вычислить собственные векторы, то необходимо хранить вычисляемые векторы Ланцоша. Если работа при этом производится только с оперативной памятью, то при большом порядке исходной матрицы (а именно для таких матриц и предназначен метод Ланцоша) число шагов  &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;j&amp;lt;/math&amp;gt;, которые могут быть выполнены до того момента, как оперативная память будет исчерпана, будет очень незначительно, а следовательно, искомые собственные пары могут не успеть сойтись с требуемой точностью. В этом случае метод Ланцоша можно использовать итерационным образом: после выполнения заданного числа шагов процесс прерывается и, если еще не все требуемые пары Ритца сошлись с требуемой точностью, то формируется новый начальный вектор &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;q_1&amp;lt;/math&amp;gt;, являющийся линейной комбинацией векторов Ритца, еще не сошедшихся с заданной точностью, и процесс начинается заново.&amp;lt;ref&amp;gt;http://num-anal.srcc.msu.ru/lib_na/int_ae/int_ae6.htm (пункт 6.5)&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
Вычислительное ядро рассматриваемого алгоритма (наиболее ресурсно-затратная часть алгоритма) -  формирование на каждом шаге цикла промежуточного вектора &amp;lt;math&amp;gt;z&amp;lt;/math&amp;gt;, вычисляемого по формуле: &amp;lt;math&amp;gt;z = A\,q_j&amp;lt;/math&amp;gt;. Данная операция, по сравнению с другими операциями алгоритма, затратна и требовательна, как с точки зрения количества производимых операций, так и с точки зрения объема оперируемых данных. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Например, умножение матрицы размера &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;n\times n&amp;lt;/math&amp;gt; на вектор длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; требует: &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;n^2+(n-1)n = 2n^2-n&amp;lt;/math&amp;gt; операций умножения и сложения. В свою очередь аналогичная операция умножения матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;(n+1)\times (n+1)&amp;lt;/math&amp;gt; на вектор длины &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;(n+1)&amp;lt;/math&amp;gt; требует: &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;2n^2+3n+1&amp;lt;/math&amp;gt;  операций умножения и сложения. То есть повышение размерности задачи всего на 1 увеличивает число необходимых действий в этом шаге алгоритма на: &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;4n+1&amp;lt;/math&amp;gt;. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Так же, стоит помнить, что, согласно разделу 1.2, данную операцию умножения матрицы на вектор необходимо выполнить &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;k&amp;lt;/math&amp;gt; раз. Нетрудно понять, насколько возрастает и колоссален масштаб операций, если в задачах, где критична точность, размерности &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; могут иметь порядок &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;10^5&amp;lt;/math&amp;gt; или даже более.&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
Как уже было упомянуто в данной статье в описании алгоритма, рассматриваемый алгоритм состоит из двух последовательно выполненных алгоритмов: метод Ланцоша для построения последовательности подпространств Крылова и ортонормированных векторов Ланцоша и процедура Рэлея-Ритца получения оптимальных приближений собственных значений и соответствующих собственных векторов исходной матрицы.&lt;br /&gt;
&lt;br /&gt;
В первой части алгоритма, где итерационно строятся Крыловское подпространство и трёхдиагональная матрица &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&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 style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; разреженная. Именно она подлежит оптимизации с использованием техник распараллеливания, поскольку она является вычислительным ядром алгоритма, а весь упомянутый процесс построения матрицы &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&amp;lt;/math&amp;gt; выполняется последовательно.&lt;br /&gt;
&lt;br /&gt;
Рассмотрим вторую часть алгоритма - поиск собственных значений сформированной матрицы &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&amp;lt;/math&amp;gt;.&amp;lt;br&amp;gt;&lt;br /&gt;
Далее, наглядно, в виде псевдокода, представлен, упомянутый в разделе 1.2, QR-алгоритм (аналогично можно рассмотреть и QL-алгоритм) со сдвигами Релэя, который весьма популярен на практике.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{align}&lt;br /&gt;
\mathbf{Input}: \;&amp;amp;tridiagonal\;\;matrix \;T\;with\;\;n\times n\;\;size\\&lt;br /&gt;
T^{(0)}&amp;amp;:=T\\&lt;br /&gt;
\mathbf{for}&amp;amp; \;\;m=n,...,2 \;\; \mathbf{do}\\&lt;br /&gt;
&amp;amp;k=0\\&lt;br /&gt;
&amp;amp; \mathbf{repeat}\\&lt;br /&gt;
&amp;amp; \quad \;\; k=k+1\\&lt;br /&gt;
&amp;amp; \quad \;\; \mu^{(k)}=T_{m,m}^{(k-1)}\\&lt;br /&gt;
&amp;amp; \quad \;\; Q^{(k)}R^{(k)}=T^{(k-1)}-\mu^{(k)}I\;\;using\;\;QR\;decomposition\\&lt;br /&gt;
&amp;amp; \quad \;\; T^{(k)}=R^{(k)}Q^{(k)}+\mu^{(k)}I\\&lt;br /&gt;
&amp;amp; \mathbf{until} \;\;\; |T_{m,m-1}^{(k)}| \;is\;\;small\;\;enough\\&lt;br /&gt;
&amp;amp; Save  \;\;T_{m,m}^{(k)} \;\;as\;\; converged\;\;eigenvalue\;of\;T\\ &lt;br /&gt;
&amp;amp; Remove \;\boldsymbol{n}\,th\;row\;and\;\boldsymbol{n}\,th\;column\;\;from \;T \\&lt;br /&gt;
&amp;amp; and\;take\;this\;new\;cropped\;matrix\;as\;new\;T^{(0)}\;with\;\;(n-1)\times (n-1)\;\;size\\&lt;br /&gt;
 \mathbf{end}&amp;amp;\; \mathbf{for}&lt;br /&gt;
\end{align}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Малость наддиагональных и поддиагональных элементов матрицы (фраза &#039;&#039;&amp;quot;small enough&amp;quot;&#039;&#039; в псевдокоде) подразумевает:&lt;br /&gt;
&amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt; |T_{m,m-1}^{(k)}| \leq \varepsilon\,|T_{m,m}^{(k)}| \quad\quad &amp;lt;/math&amp;gt; , где &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt; \varepsilon &amp;lt;/math&amp;gt; - заданная точность&amp;lt;br&amp;gt;&lt;br /&gt;
Также вместо сдвига Релэя, обозначенного в алгоритме через &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;\mu^{(k)}&amp;lt;/math&amp;gt;, часто на практике используется сдвиг по Уилкинсону, который даёт гарантированную сходимость внедиагональных элементов матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt; T^{(k)} &amp;lt;/math&amp;gt;, формируемой на каждом шаге, к нулю, при этом жертвуя монотонностью их убывания.&amp;lt;ref&amp;gt;Голуб Дж., Ван Лоун Ч. - Матричные вычисления//М.: Мир. - 1999 (c. 378, вторая половина страницы)&amp;lt;/ref&amp;gt;&amp;lt;ref&amp;gt;Парлетт Б. Симметричная проблема собственных значений. Численные методы.,: Мир, 1983. с. 169&amp;lt;/ref&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Подробнее с различными сдвигами и соответствующими оценками скоростей и количествами операций можно ознакомиться по указанной ссылке:&amp;lt;ref&amp;gt;Парлетт Б. Симметричная проблема собственных значений. Численные методы.,: Мир, 1983. с. 179-182&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;Для совершения QR-декомпозиции на каждом шаге может использоваться любой из алгоритмов по ссылке.&amp;lt;ref&amp;gt;https://en.wikipedia.org/wiki/QR_decomposition&amp;lt;/ref&amp;gt; Подробные описания этих алгоритмов также доступны на данном ресурсе algowiki-project.&amp;lt;br&amp;gt;&lt;br /&gt;
Так как мы оперируем не обычной матрицей и даже не Хессенберговой, а симметричной и трёхдиагональной, то скорость таких алгоритмов значительно возрастёт. Например, согласно данному ресурсу &amp;lt;ref&amp;gt;http://algorithm.narod.ru/ln/eigen/ETridiag.html&amp;lt;/ref&amp;gt;, для QL-алгоритма с неявными сдвигами:&amp;lt;br&amp;gt;&lt;br /&gt;
Для трёхдиагональной матрицы объем арифметических действий составляет &amp;lt;math&amp;gt; O(n)&amp;lt;/math&amp;gt; на одну итерацию вместо &amp;lt;math&amp;gt; O(n^3)&amp;lt;/math&amp;gt; для матрицы общего вида, а число итераций для нахождения первых собственных значений примерно равно 4 - 5. Но на этих итерациях также уменьшаются внедиагональные элементы правого нижнего угла. И, таким образом, дальнейшие собственные значения ищутся значительно быстрее. Среднее число итераций на каждое собственное значение обычно составляет 1.3 - 1.6.&amp;lt;br&amp;gt; &lt;br /&gt;
Аналогично QL, QR-разложение трёхдиагольной матрицы также требует &amp;lt;math&amp;gt; O(n)&amp;lt;/math&amp;gt; флопов&amp;lt;ref&amp;gt;Голуб Дж., Ван Лоун Ч. - Матричные вычисления//М.: Мир. - 1999 (c. 378, начало раздела 8.2.2)&amp;lt;/ref&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Подводя итог, во второй части алгоритма Ланцоша можно выделить следующие макрооперации:&lt;br /&gt;
* умножение матрицы на вещественное число;&lt;br /&gt;
* перемножение матриц;&lt;br /&gt;
* умножение и сравнение вещественных чисел;&lt;br /&gt;
* + набор других макроопераций в зависимости от выбора метода, с помощью которого будет совершаться сама QR или QL-декомпозиция (выше продемонстрированы, уже, как минимум, 3 разных способа).&lt;br /&gt;
Так же, важно заметить, что набор макропераций может быть несколько другим, если выбрать какой-либо иной современный метод поиска собственных чисел трёхдиагональной матрицы, не использующий QR и QL разложения(факторизацию). Два таких метода были упомянуты в пункте 1.2.&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
С целью полностью не дублировать раздел 1.2 данной статьи, где представлен наглядный и доступный для понимания псевдокод алгоритма, постараемся лишь коротко просуммировать и обобщить весь перечень последовательных действий в рассматриваемом алгоритме.&lt;br /&gt;
&lt;br /&gt;
В качестве входных данных имеем: вещественная симметричная матрица &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; размера &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;n\times n&amp;lt;/math&amp;gt;, известный вещественный вектор &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;b&amp;lt;/math&amp;gt; длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; и число &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;n&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Далее:&lt;br /&gt;
* Инициализируем вещественную константу &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;\beta_0&amp;lt;/math&amp;gt; и векторы &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;q_0&amp;lt;/math&amp;gt; и &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;q_1&amp;lt;/math&amp;gt;&lt;br /&gt;
* Итерационно для всех &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j=1,...,k&amp;lt;/math&amp;gt;:&lt;br /&gt;
** Вычисляем вспомогательный вектор &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt;, используя умножение матрицы на вектор&lt;br /&gt;
** Вычисляем, используя скалярное произведение векторов, значение &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;\alpha_j&amp;lt;/math&amp;gt; - элемент на главной диагонали трёхдиагональной матрицы &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&amp;lt;/math&amp;gt;&lt;br /&gt;
** Вычисляем по формуле новое значение и перезаписываем вектор &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt;&lt;br /&gt;
** Вычисляем значение &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;\beta_j&amp;lt;/math&amp;gt; - элементы непосредственно над и под главной диагональю той же матрицы &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&amp;lt;/math&amp;gt;&lt;br /&gt;
** Вычисляем, зная вектор &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt;,  очередной столбец матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;Q&amp;lt;/math&amp;gt;, он же вектор Ланцоша : &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;\,\,q_{j+1}&amp;lt;/math&amp;gt;&lt;br /&gt;
** Теперь, когда матрица &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&amp;lt;/math&amp;gt; сформирована на очередном шаге, находим её собственные значения и вектора любым доступным способом, о чём было подробно сказано в пункте 1.2&lt;br /&gt;
** Переходим на следующую итерацию: &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j&amp;lt;/math&amp;gt;++&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
Оценим количество операций и сложность последовательного алгоритма, изложенного в предыдущем разделе.&lt;br /&gt;
*Для вычисления вектора &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt; умножается матрица размера &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;n\times n&amp;lt;/math&amp;gt; на вектор длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt;, и потребуется &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n^2&amp;lt;/math&amp;gt; операций умножения и &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n^2&amp;lt;/math&amp;gt; операций сложения.&lt;br /&gt;
*Умножение векторов &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;q^T_j&amp;lt;/math&amp;gt; и &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt; длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; потребует &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; операций умножения и &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; операций сложения.&lt;br /&gt;
*При вычислении нового значения вектора &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt; поэлементное сложение двух векторов длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; требует &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; операций сложения.&lt;br /&gt;
*Умножение вектора длины &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; на вещественное число требует &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; операций умножения.&lt;br /&gt;
*Нахождение квадратичной нормы вектора &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt;  длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; требует &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; умножений и &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; сложений и ещё 1 операцию извлечения квадратного корня.&lt;br /&gt;
*Заключительное нахождение собственных значений и собственных векторов трёхдиагональной матрицы &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;T_j&amp;lt;/math&amp;gt; размера &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j\times j&amp;lt;/math&amp;gt; с помощью QR-алгоритма потребует в худшем случае &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(j^3)&amp;lt;/math&amp;gt; операций.&amp;lt;ref&amp;gt;http://num-anal.srcc.msu.ru/lib_na/int_ae/int_ae6.htm (пункт 6.2, &amp;quot;Скорость сходимости при этом всегда не хуже квадратичной и почти всегда лучше кубической.&amp;quot;)&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Посчитаем теперь суммарное количество простейших операций на одной итерации алгоритма (без учёта записей в память):&lt;br /&gt;
*&amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n^2+5\,n&amp;lt;/math&amp;gt; операций умножения/деления&lt;br /&gt;
*&amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n^2+4\,n&amp;lt;/math&amp;gt; операций сложения/вычитания&lt;br /&gt;
*1 операция извлечения квадратного корня&amp;lt;br&amp;gt;&lt;br /&gt;
Отдельно после всех итераций при &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j=k&amp;lt;/math&amp;gt; :&lt;br /&gt;
*&amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(k^3)&amp;lt;/math&amp;gt; операций для поиска собственных значений и собственных векторов трёхдиагональной матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_k&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Итого можно утверждать следующее:&lt;br /&gt;
&lt;br /&gt;
Последовательная сложность одной итерации рассматриваемого алгоритма:  &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(n ^ 2) &amp;lt;/math&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Суммарная сложность алгоритма (&amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;/math&amp;gt; итераций): &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(k\,n ^ 2) + O(k ^ 3)&amp;lt;/math&amp;gt; &amp;lt;ref&amp;gt;Здесь мы полагаем, что мы не вычисляем собственные значения и векторы матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_j&amp;lt;/math&amp;gt; на каждом промежуточном шаге, а лишь единожды затрачиваем &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;O(k ^ 3)&amp;lt;/math&amp;gt; действий в конце для нахождения &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;/math&amp;gt; собственных значений и векторов матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_k&amp;lt;/math&amp;gt;&amp;lt;/ref&amp;gt; &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
На практике же обычно рассматривается число &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;&amp;lt;n&amp;lt;/math&amp;gt;, поэтому второе слагаемое можно опустить.&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
На рис. 1 продемонстрирован граф одной итерации (при каком-либо произвольном значении итератора &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j&amp;lt;/math&amp;gt;) описанного алгоритма без отображения входных и выходных данных. Наглядно продемонстрированы связи между всеми действиями, и с помощью деления на &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; потоков показано, какие операции возможно выполнять параллельно на каждом шаге с целью оптимизации и экономии машинного времени. В результате, после параллельно выполненных операций &#039;&#039;&#039;Division&#039;&#039;&#039; на заключительном ярусе, на выходе имеем значение следующего вектора Ланцоша &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;q_{j+1}&amp;lt;/math&amp;gt;, после чего следует переход на следующую итерацию, и процесс повторяется.&lt;br /&gt;
&lt;br /&gt;
[[Файл:Levin_graph.png|600px|thumb|center|Рис. 1  Структура одной итерации алгоритма]] &amp;lt;br&amp;gt;&lt;br /&gt;
Обозначения на рисунке: &amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Simp&#039;&#039;&#039; (от англ. simple) - операции сложения и умножения вещественных чисел при вычислении произведения матрицы на вектор;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Vec mult&#039;&#039;&#039; (от англ. vectors multiplication) - операция скалярного умножения двух векторов;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Vec subtr&#039;&#039;&#039; (от англ. vectors subtraction, из-за использованных в операции вычитаний векторов) - операция умножения вектора на число (выполняется дважды) и формирование нового значения &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;z_{new}&amp;lt;/math&amp;gt; по формуле: &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;z_{new} = z - \alpha_j q_j - \beta_{j-1}q_{j-1} \;&amp;lt;/math&amp;gt;;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;||\cdot||&amp;lt;/math&amp;gt; - операция вычисления нормы вектора;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Division&#039;&#039;&#039; - операция деления вектора на вещественное число  &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;\beta_j&amp;lt;/math&amp;gt; &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Важно отметить, что упомянутые выше операции также легко поддаются оптимизации. Например, попарные умножения вещественных координат векторов при вычислении скалярного произведения также легко выполняются параллельно на &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; потоках, а затем можно применить суммирование методом сдваивания, о котором сказано в следующем разделе. Умножение или деление вектора на вещественное число являющееся, по определению, умножением или делением всех его координат на это число тоже может быть выполнено эффективнее, если мы используем &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; потоков, а не выполняем эти действия последовательно.&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
Параллельные операции возможны только внутри итераций, так как рассматриваемый алгоритм является итерационным, и сами итерации строго последовательны.&amp;lt;br&amp;gt;&lt;br /&gt;
Рассмотрим в этом разделе подробнее, какой выигрыш мы можем получить при распараллеливании операций внутри одной итерации согласно графу из предыдущего раздела.&lt;br /&gt;
&lt;br /&gt;
Умножение вещественной симметричной матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; размера &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;n\times n&amp;lt;/math&amp;gt; на вектор &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;b&amp;lt;/math&amp;gt; длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; требует последовательного выполнения &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; ярусов умножений и сложений. Сложение элементов вектора длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; на каждом шаге перемножения можно оптимизировать и выполнить за &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;\log_2 n&amp;lt;/math&amp;gt; действий, если применять метод сдваивания.&lt;br /&gt;
&lt;br /&gt;
Дальнейшие операции выполняются последовательно, а вычисление значений векторов происходит за один ярус операций сложения или умножения.&lt;br /&gt;
&lt;br /&gt;
Ресурс параллелизма алгоритма вычисления собственных значений построенной трёхдиагональной матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_k&amp;lt;/math&amp;gt; размера &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k\times k&amp;lt;/math&amp;gt; зависит от выбранного алгоритма (об этих алгоритмах подробнее было сказано в разделах 1.2 и 1.4). Будет очень затратно с точки зрения объёма материала пытаться рассмотреть пусть даже часть этих методов в этой статье, а так же тонкости их распараллеливания. Предлагаем читателям при желании самим ознакомиться с этими алгоритмами на данном ресурсе или прибегнув к иным источникам.&lt;br /&gt;
&lt;br /&gt;
При классификации по высоте ЯПФ, таким образом, алгоритм Ланцоша без переортогонализации относится к алгоритмам с &#039;&#039;логарифмической сложностью&#039;&#039;, и его сложность равна &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(\log_2 n)&amp;lt;/math&amp;gt; с важным замечанием, что это сложность только одной итерации, а максимум в алгоритме может быть выполнено последовательно &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;/math&amp;gt; таких однотипных итераций, если не будет осуществлён ранний выход из цикла. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Несмотря на то, что на графе в предыдущем разделе для лучшей визуализации и понимания было изображено &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; потоков (никаких допущений мы не делали и нарушений с точки зрения логики и математики нет, можно изобразить большее число потоков, просто часть времени некоторые из них могут бездействовать и не использоваться), на самом деле правильным и разумным будет реализовать начальное параллельное выполнение &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n^2&amp;lt;/math&amp;gt; операций умножения всех вещественных элементов матрицы &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;A&amp;lt;/math&amp;gt; на соответствующие элементы вектора &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;q_j&amp;lt;/math&amp;gt;, после чего применять тот же самый упомянутый метод сдваивания. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Поэтому при классификации по ширине ЯПФ его сложность будет &#039;&#039;квадратичной&#039;&#039; и равна &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(n^2)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
&#039;&#039;&#039;Входные данные алгоритма:&#039;&#039;&#039; вещественная симметричная &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; размера &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;n\times n&amp;lt;/math&amp;gt;, вещественный вектор &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;b&amp;lt;/math&amp;gt; длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt;, и одно целое число &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;k&amp;lt;/math&amp;gt;, означающее количество итераций.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём входных данных:&#039;&#039;&#039; &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;n^2 +n + 1 &amp;lt;/math&amp;gt;. Если учесть, что матрица симметричная и достаточно для её однозначного определения задать элементы на главной диагонали и элементы над или под ней, то можно сократить объём входных данных с целью экономии памяти до: &amp;lt;math&amp;gt;\ \frac{n^2-n}{2}+n+n+1 =\frac{n^2+3n}{2} + 1&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные алгоритма:&#039;&#039;&#039; вектор собственных значений &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;\Theta^k&amp;lt;/math&amp;gt; длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;/math&amp;gt;, матрица &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;S^k&amp;lt;/math&amp;gt; из соответствующих собственных векторов размера &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n\times k&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём выходных данных:&#039;&#039;&#039; &amp;lt;math&amp;gt;k\;(n + 1)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
В данном разделе перечислены без какой-либо хронологии или связи друг с другом наиболее важные и разнообразные свойства алгоритма, на которые стоит и полезно обратить внимание, а также которые выгодно отличают его от схожих алгоритмов, решающих ту же задачу.&amp;lt;br&amp;gt;&lt;br /&gt;
1) Отношение последовательной сложности алгоритма к параллельной,с учётом &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;/math&amp;gt; итераций, равно &amp;lt;math&amp;gt;\;\;\frac{kn^2}{k \log_2{n}}=\frac{n^2}{\log_2{n}}&amp;lt;/math&amp;gt;;&amp;lt;br&amp;gt;&lt;br /&gt;
2) Вычислительная мощность алгоритма, как отношение числа операций к суммарному объему входных и выходных данных, равна &amp;lt;math style=&amp;quot;vertical-align:-70%&amp;gt;\;\;\frac{k\,n^2}{0.5\,n^2+1.5\,n+k\,n+k+1}&amp;lt;/math&amp;gt; и &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;\approx 2\,k&amp;lt;/math&amp;gt;, так как на практике верно отношение &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;&amp;lt;n&amp;lt;/math&amp;gt; ;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
3) Для собственных значений формируемых матриц &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_j&amp;lt;/math&amp;gt; верно отношение (следствие теоремы Коши о перемежаемости): &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;\lambda_i(T_{k+1})\geq \lambda_i(T_{k})\geq \lambda_{i+1}(T_{k+1})\geq \lambda_{i+1}(T_{k})&amp;lt;/math&amp;gt; ;&amp;lt;ref&amp;gt;James W. Demmel - Вычислительная линейная алгебра. Теория и приложения //Мир. - 2001 (c. 383)&amp;lt;/ref&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
4) Крайние (наибольшие и наименьшие) собственные значения матриц &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_j&amp;lt;/math&amp;gt; сходятся к крайним собственным значениям матрицы &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;A&amp;lt;/math&amp;gt; первыми (это часто происходит уже на ранних шагах при &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j\approx 2\,\sqrt{n}&amp;lt;/math&amp;gt;&amp;lt;ref&amp;gt;http://num-anal.srcc.msu.ru/lib_na/int_ae/int_ae6.htm (пункт 6.5)&amp;lt;/ref&amp;gt;), а собственные значения в середине спектра - последними;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
5) Из-за ограниченной точности постепенно теряется ортогональность вектора Ланцоша &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;q_j&amp;lt;/math&amp;gt; к предыдущим векторам Ланцоша, поэтому необходимо примерно каждые 10-15 итераций проводить дорогостоящую операцию реортогонализации, но это уже будет иной алгоритм с очень малым различием в одной операции и в программном коде, реализующем его, соответственно; &amp;lt;ref&amp;gt;Sam Handler - The Lanczos Algorithm For Large-Scale Eigenvalue Problems (08.01.07), slide №8&amp;lt;/ref&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
6) Эффективность и быстрота выполнения алгоритма очень сильно зависит от скорости памяти (диска). Согласно тесту только &#039;&#039;6%&#039;&#039; времени работы программы приходится на вычисления, остальное время затрачивается на ожидание отклика диска;&amp;lt;ref&amp;gt;Sam Handler - The Lanczos Algorithm For Large-Scale Eigenvalue Problems (08.01.07), slide №10&amp;lt;/ref&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
7) Метод Ланцоша удобен тем, что не требует хранения исходной матрицы полным массивом: метод использует исходную матрицу только в операциях умножения матрицы на вектор, что позволяет эффективно использовать разреженность матрицы или регулярность структуры матрицы. Поэтому метод Ланцоша может быть использован для матриц таких больших порядков, когда методы вращений и отражений не могут быть применены.&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;
Для исследования масштабируемости рассматриваемого алгоритма Ланцоша без переортогонализации автором была реализована программа на языке С++ с использованием технологии MPI. &amp;lt;ref&amp;gt;https://goo.gl/pNOFmW  или альтернативная ссылка с прикреплённым кодом: https://goo.gl/9AapM6 , по просьбе на почту я (автор статьи) готов предоставить желающим доступ к проекту с этим кодом на ресурсе Bitbucket&amp;lt;/ref&amp;gt; Дальнейшее исследование было проведено на суперкомпьютере &amp;quot;Ломоносов&amp;quot; Суперкомпьютерного комплекса МГУ.&amp;lt;ref&amp;gt;https://parallel.ru/cluster/lomonosov.html&amp;lt;/ref&amp;gt; &amp;lt;br&amp;gt; Важно отметить, что реализованная программа выполняет только первую часть алгоритма - формирование трёхдиагональной матрицы &amp;lt;math &amp;gt;T_j&amp;lt;/math&amp;gt;. Вторая часть алгоритма (задача поиска собственных значений матрицы &amp;lt;math &amp;gt;T_j&amp;lt;/math&amp;gt;) может быть решена несколькими методами, каждый из которых обладает своей эффективностью распараллеливания и характерными свойствами. Подробно этот вопрос уже обсуждался в статье ранее, поэтому не будем ещё раз заострять на этом внимание и останавливаться.&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Сборка осуществлялась со следующими параметрами:&lt;br /&gt;
* Компилятор intel/15.0.090 &lt;br /&gt;
* Openmpi/1.8.4-icc&lt;br /&gt;
В серии проведённых расчётов рассматривались следующие числовые значения параметров:&lt;br /&gt;
* Размер &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;n&amp;lt;/math&amp;gt; задачи и, соответственно, матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt;, задействованной в операции умножения на вектор: [2000 : 30000] с шагом 1000&lt;br /&gt;
* Число &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;p&amp;lt;/math&amp;gt; процессоров: 1, 2, 4, 16, 32, 48, 64, 96, 128, 192, 256&lt;br /&gt;
* Число итераций в алгоритме: &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k=350&amp;lt;/math&amp;gt;&lt;br /&gt;
Число &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; взято таким вопреки информации в начале статьи, где говорится, что значение &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; редко превышает &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;10^2&amp;lt;/math&amp;gt; (хоть мы и имеем право брать его любым по нашему усмотрению). Это сделано исключительно для лучшей визуализации пиков на графиках в данном разделе и наглядности получаемых результатов, так как при меньших на порядок значениях параметра &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; времена выполнения программ были слишком малы даже при минимальных числах процессоров и максимальных размерах &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;n&amp;lt;/math&amp;gt; задачи.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
На рис. 2 изображён график зависимости времени выполнения программы от числа процессоров и размера &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;n&amp;lt;/math&amp;gt; задачи. &amp;lt;br&amp;gt;&lt;br /&gt;
{|align=&amp;quot;center&amp;quot;&lt;br /&gt;
 |-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
 |[[file:Levin_task1_execTIME.png|620px|thumb|center|Рис. 2  График зависимости времени выполнения программы.]]&lt;br /&gt;
 |[[file:Levin604 task1 result EFFICIENCY.png|630px|thumb|center|Рис. 3  График зависимости эффективности распараллеливания программы.]]&lt;br /&gt;
|}&lt;br /&gt;
Многочисленные тесты показали при малых количествах ядер уменьшение времени выполнения программы почти в 2 раза при увеличении числа ядер в 2 раза на всём диапазоне размеров матриц, что и отражает сильный излом на первом графике. Изменение значений времени можно легко оценить по предоставленной цветовой шкале.&lt;br /&gt;
Был построен график эффективности распараллеливания (parallel efficiency)&amp;lt;ref&amp;gt;https://goo.gl/WCNEjR&amp;lt;/ref&amp;gt; в зависимости от числа процессоров и размера задачи, изображённый на рис. 3.&lt;br /&gt;
Получены следующие результаты численных экспериментов:&lt;br /&gt;
* Средняя эффективность распараллеливания программы составила: 42.5576% ;&lt;br /&gt;
* Минимальная эффективность реализации: 0.674% (число процессоров 256 и минимальный размер матрицы 2000);&lt;br /&gt;
* Максимальная эффективность реализации: 77.773% (число процессоров 2, размер матрицы 20000).&lt;br /&gt;
Нужно понимать, что это лишь экстремумы, соответствующие двум экспериментам, которые сами по себе не дают полной картины и не позволяют однозначно судить о параллельных качествах алгоритма и реализующей его программы при столь большом числе параметров и проводимых расчётов. &amp;lt;br&amp;gt;На основании рис. 3 можно отметить следующие значимые и важные факты:&lt;br /&gt;
*Имеется ярко выраженный спад эффективности при минимальном рассматриваемом размере матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;n=2000&amp;lt;/math&amp;gt; вдоль всей оси OY, отвечающей за число процессоров;&lt;br /&gt;
*Присутствуют два пика эффективности (жёлтого цвета на рис. 3): при числе &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;p&amp;lt;/math&amp;gt; процессоров 2 и 128. Затем при дальнейшем увеличении числа процессоров с 128 до 256 наблюдается постепенное уменьшение эффективности реализации. Это связано с увеличением накладных расходов и затрат времени на обмены сообщениями между процессами.&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;
Перечислим далее некоторые из них, указывая язык программирования, лежащий в их основе, и некоторые важные характеристики, которые обсуждались в статье ранее:&lt;br /&gt;
*&#039;&#039;Code on netlib.org by Jane Cullum and Ralph Willoughby&#039;&#039; (&#039;&#039;&#039;Fortran 77&#039;&#039;&#039;; без реортогонализации векторов; без реализации распараллеливания)&amp;lt;ref&amp;gt;http://www.netlib.org/lanczos/leval&amp;lt;/ref&amp;gt;&lt;br /&gt;
*&#039;&#039;Lanczos algorithm on freesourcecode.net&#039;&#039; (&#039;&#039;&#039;Matlab&#039;&#039;&#039;; присутствует реортогонализация векторов; без реализации распараллеливания)&amp;lt;ref&amp;gt;http://freesourcecode.net/matlabprojects/61741/lanczos-algorithm--in-matlab&amp;lt;/ref&amp;gt;&lt;br /&gt;
*&#039;&#039;Lanczos for eigenvalues in Numerical Linear Algebra, Spring 2007&#039;&#039; (&#039;&#039;&#039;Matlab&#039;&#039;&#039;; частичная или полная реортогонализация - доступны оба варианта; без реализации распараллеливания)&amp;lt;ref&amp;gt;Ссылки на файлы lanso.m и lanfu.m можно найти на https://www.nada.kth.se/~ruhe/2D5219/labs2007.html&amp;lt;/ref&amp;gt;&lt;br /&gt;
*&#039;&#039;Planso&#039;&#039; (название происходит от parallel Lanso.f) &#039;&#039;code by Kesheng Wu and Horst D. Simon&#039;&#039; (&#039;&#039;&#039;Fortran 77&#039;&#039;&#039;; частичная реортогонализация векторов; использование MPI для коммуникаций)&amp;lt;ref&amp;gt;https://github.com/jiahao/planso.jl/tree/master/external/PLAN/plan К сожалению, ссылка в описании пакета на github, ведущая на сайт National Energy Research Scientific Computing Center (NERSC), с более подробной информацией о данной программе больше не активна и выдаёт результат &#039;&#039;Page not found&#039;&#039;&amp;lt;/ref&amp;gt; &lt;br /&gt;
* &#039;&#039;Lanczos.cpp in the Vienna Computing Library&#039;&#039;  (&#039;&#039;&#039;C++&#039;&#039;&#039;, частичная реортогонализация, без реализации распараллеливания) &amp;lt;ref&amp;gt;http://viennacl.sourceforge.net/doc/lanczos_8cpp_source.html&amp;lt;/ref&amp;gt;&lt;br /&gt;
* &#039;&#039;Parallel Eigen Values code using C++ AMP on microsoft msdn blog&#039;&#039; (&#039;&#039;&#039;C++&#039;&#039;&#039;; ? ; распараллеливание есть и реализовано через C++ AMP) &amp;lt;ref&amp;gt;https://blogs.msdn.microsoft.com/nativeconcurrency/2013/12/20/eigen-values/ Подробнее о C++ Accelerated Massive Parallelism можно почитать здесь: https://msdn.microsoft.com/ru-ru/library/hh265137(v=vs.140).aspx или здесь: http://professorweb.ru/my/csharp/optimization/level4/4_6.php &amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;br /&gt;
[[en:Description of algorithm properties and structure]]&lt;/div&gt;</summary>
		<author><name>AleksLevin</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:AleksLevin/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%9B%D0%B0%D0%BD%D1%86%D0%BE%D1%88%D0%B0_%D0%B2%D1%8B%D1%87%D0%B8%D1%81%D0%BB%D0%B5%D0%BD%D0%B8%D1%8F_%D1%81%D0%BE%D0%B1%D1%81%D1%82%D0%B2%D0%B5%D0%BD%D0%BD%D1%8B%D1%85_%D0%B7%D0%BD%D0%B0%D1%87%D0%B5%D0%BD%D0%B8%D0%B9_%D1%81%D0%B8%D0%BC%D0%BC%D0%B5%D1%82%D1%80%D0%B8%D1%87%D0%BD%D0%BE%D0%B9_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86%D1%8B_%D0%B4%D0%BB%D1%8F_%D1%82%D0%BE%D1%87%D0%BD%D0%BE%D0%B9_%D0%B0%D1%80%D0%B8%D1%84%D0%BC%D0%B5%D1%82%D0%B8%D0%BA%D0%B8_(%D0%B1%D0%B5%D0%B7_%D0%BF%D0%B5%D1%80%D0%B5%D0%BE%D1%80%D1%82%D0%BE%D0%B3%D0%BE%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D0%B8)&amp;diff=20296</id>
		<title>Участник:AleksLevin/Алгоритм Ланцоша вычисления собственных значений симметричной матрицы для точной арифметики (без переортогонализации)</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:AleksLevin/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%9B%D0%B0%D0%BD%D1%86%D0%BE%D1%88%D0%B0_%D0%B2%D1%8B%D1%87%D0%B8%D1%81%D0%BB%D0%B5%D0%BD%D0%B8%D1%8F_%D1%81%D0%BE%D0%B1%D1%81%D1%82%D0%B2%D0%B5%D0%BD%D0%BD%D1%8B%D1%85_%D0%B7%D0%BD%D0%B0%D1%87%D0%B5%D0%BD%D0%B8%D0%B9_%D1%81%D0%B8%D0%BC%D0%BC%D0%B5%D1%82%D1%80%D0%B8%D1%87%D0%BD%D0%BE%D0%B9_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86%D1%8B_%D0%B4%D0%BB%D1%8F_%D1%82%D0%BE%D1%87%D0%BD%D0%BE%D0%B9_%D0%B0%D1%80%D0%B8%D1%84%D0%BC%D0%B5%D1%82%D0%B8%D0%BA%D0%B8_(%D0%B1%D0%B5%D0%B7_%D0%BF%D0%B5%D1%80%D0%B5%D0%BE%D1%80%D1%82%D0%BE%D0%B3%D0%BE%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D0%B8)&amp;diff=20296"/>
		<updated>2016-12-07T20:20:35Z</updated>

		<summary type="html">&lt;p&gt;AleksLevin: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Assignment}}&lt;br /&gt;
Основные авторы описания: Левин А.Д.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{algorithm&lt;br /&gt;
| name              = Алгоритм Ланцоша для точной арифметики (без переортогонализации)&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(k\,n^2)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(k\log_2 n)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;\frac{n^2+3n}{2} + 1&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;k\;(n + 1)&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритмов =&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Данный алгоритм появился в 1950 г. и носит имя венгерского физика и математика Корнелия Ланцоша (венг. Lánczos Kornél). Алгоритм Ланцоша относится к итерационным методам вычисления собственных значений для матриц столь больших порядков &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt; n&amp;lt;/math&amp;gt;, что к ним нельзя применить прямые методы из-за ограничений по времени и памяти.&lt;br /&gt;
&lt;br /&gt;
Сам Ланцош указывал, что его метод предназначен для отыскания нескольких собственных векторов симметричных матриц, хотя к методу сразу было обращено внимание, как к способу приведения всей матрицы к трёхдиагональному виду. Двадцатью годами позже канадский математик Крис Пэж показал, что, несмотря на чувствительность к округлениям, алгоритм Ланцоша - эффективное средство вычисления некоторых &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; собственных чисел и соответствующих им собственных векторов. &amp;lt;ref&amp;gt;Парлетт Б. - Симметричная проблема собственных значений. Численные методы //М.: Мир. - 1983. (c. 276)&amp;lt;/ref&amp;gt;&lt;br /&gt;
Обычно число &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; берут в два раза больше, чем количество собственных значений матрицы, которые поставлена цель найти, и оно имеет порядок не более &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;10^2&amp;lt;/math&amp;gt;.&amp;lt;ref&amp;gt;Susan W. Bostic - Lanczos Eigensolution Method for High-Perfomance Computers, page 7&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Алгоритм Ланцоша для вычисления собственных значений симметричной матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; соединяет в себе метод Ланцоша для построения последовательности подпространств Крылова и ортонормированных векторов Ланцоша и процедуру Рэлея-Ритца получения оптимальных приближений собственных значений и соответствующих собственных векторов исходной матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt;.&amp;lt;ref&amp;gt;James W. Demmel - Вычислительная линейная алгебра. Теория и приложения //Мир. - 2001 (c. 381)&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
В данной статье рассматривается вариант алгоритма Ланцоша, в котором опущено влияние ошибок округления на вычислительный процесс, хотя на практике этому посвящается отдельное внимание и существуют различные методы решения данной проблемы, такие как частичная или полная переортогонализация. Этим модифицированным методам посвящены отдельные статьи на данном ресурсе.&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
Обозначения и формулы, используемые в данном разделе, взяты из литературы, указанной по ссылке.&amp;lt;ref&amp;gt;James W. Demmel - Вычислительная линейная алгебра. Теория и приложения //Мир. - 2001 (c. 313, &#039;&#039;&amp;lt;math&amp;gt; \S &amp;lt;/math&amp;gt; 6.6 Методы Крыловского подпространства&#039;&#039;)&amp;lt;/ref&amp;gt; &lt;br /&gt;
&lt;br /&gt;
Алгоритм Ланцоша для вычисления &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; собственных значений и собственных векторов вещественной симметричной матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A=A^T&amp;lt;/math&amp;gt; в точной арифметике: &amp;lt;ref&amp;gt;James W. Demmel - Вычислительная линейная алгебра. Теория и приложения //Мир. - 2001 (c. 381)&amp;lt;/ref&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{align}&lt;br /&gt;
q_1 = &amp;amp; \,\frac{b}{\|b\|_2},\; \beta_0 = 0,\; q_0 = 0\\&lt;br /&gt;
\mathbf{for} \; &amp;amp; j = 1 \; to \; k \,\; \mathbf{do} \\&lt;br /&gt;
&amp;amp; z = A\,q_j\\&lt;br /&gt;
&amp;amp; \alpha_j = q^T_j z\\&lt;br /&gt;
&amp;amp; z = z - \alpha_j q_j - \beta_{j-1}q_{j-1}\\&lt;br /&gt;
&amp;amp; \beta_j = \|z\|_2\\&lt;br /&gt;
&amp;amp; \mathbf{If} \; (\beta_j == 0) \; \mathbf{then}\; stop\; the\; algorithm \\ &lt;br /&gt;
&amp;amp; \;  q_{j+1} = \frac{z}{\beta_j} \\&lt;br /&gt;
&amp;amp; compute\; eigenvalues\; and \;eigenvectors\;of \;matrix \;\;T_j= Q^T_j A Q\;\;and\;estimate \;the\; errors\\&lt;br /&gt;
\mathbf{end} \; &amp;amp; \mathbf{for}&lt;br /&gt;
\end{align}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
В продемонстрированном выше алгоритме &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;b&amp;lt;/math&amp;gt; - заданный вещественный вектор. Также полагается известным алгоритм вычисления произведения матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; на вектор &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;x&amp;lt;/math&amp;gt;. &lt;br /&gt;
Введём матрицу Крылова, определяемую следующим соотношением: &amp;lt;math&amp;gt;K_j = [b,Ab,A^2b,...,A^{j-1}b]&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Далее, на практике, матрица &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;K&amp;lt;/math&amp;gt; заменяется матрицей &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;Q&amp;lt;/math&amp;gt;, такой, что при любом числе &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; линейные оболочки первых &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; столбцов в &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;K&amp;lt;/math&amp;gt; и &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;Q&amp;lt;/math&amp;gt; являются одним и тем же подпространством.&amp;lt;ref&amp;gt;James W. Demmel - Вычислительная линейная алгебра. Теория и приложения //Мир. - 2001 (c. 315)&amp;lt;/ref&amp;gt; &lt;br /&gt;
Тогда матрица &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;Q&amp;lt;/math&amp;gt;, в отличие от матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;K&amp;lt;/math&amp;gt;, хорошо обусловлена и легко обратима. В результате получаем матрицу &amp;lt;math&amp;gt;Q_j = [q_1, q_2, \dots, q_j]&amp;lt;/math&amp;gt; размерности &amp;lt;math&amp;gt;n\times j&amp;lt;/math&amp;gt;, столбцы которой ортогональны, являются базисом подпространства Крылова и называются векторами Ланцоша.&lt;br /&gt;
&lt;br /&gt;
В алгоритме Ланцоша вычислению подлежит столько первых столбцов в матрице &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;Q_j&amp;lt;/math&amp;gt;, сколько необходимо для получения требуемого приближения к решению &amp;lt;math&amp;gt;A\,x\,=b\,\,(A\,x=\lambda \, x)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Получение нулевого &amp;lt;math&amp;gt;\beta_j&amp;lt;/math&amp;gt; в итерационном процессе - событие, желательное в том смысле, что оно свидетельствует о том, что найдено некоторое подпространство, являющееся в точности инвариантным, а все собственные значения матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;T_j&amp;lt;/math&amp;gt; являются собственными значениями матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt;. На практике же нулевое и близкие к нулю значения получаются редко.&amp;lt;ref&amp;gt;Голуб Дж., Ван Лоун Ч. - Матричные вычисления//М.: Мир. - 1999 (c. 429)&amp;lt;/ref&amp;gt; &lt;br /&gt;
&lt;br /&gt;
Затем на каждом шаге цикла формируется симметричная трёхдиагональная матрица &amp;lt;math&amp;gt;T_j = Q^T_j A Q&amp;lt;/math&amp;gt;, к которой применяется процесс Рэлея-Ритца для поиска её собственных значений (на практике для поиска этих собственных значений можно использовать любой из специальных методов в параграфе книги по ссылке).&amp;lt;ref&amp;gt;Голуб Дж., Ван Лоун Ч. - Матричные вычисления//М.: Мир. - 1999 (&amp;lt;math&amp;gt;\S&amp;lt;/math&amp;gt; 8.4)&amp;lt;/ref&amp;gt;  &lt;br /&gt;
Эти собственные значения, они же числа Ритца, и полагаются приближёнными собственными значениями исходной матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt;.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Существует множество методов для отыскания собственных значений вещественной симметричной трехдиагональной матрицы. Большинство из них требует &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt; операций &amp;lt;ref&amp;gt;Парлетт Б. Симметричная проблема собственных значений. Численные методы.,: Мир, 1983. с. 179-182&amp;lt;/ref&amp;gt;, но существуют и быстрые алгоритмы, требующие лишь &amp;lt;math&amp;gt;O(n\ln n)&amp;lt;/math&amp;gt; операций.&amp;lt;ref&amp;gt;https://en.wikipedia.org/wiki/Tridiagonal_matrix#Eigenvalues  Раздел eigenvalues&amp;lt;/ref&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Одним из возможных способов отыскать собственные значения симметричной трехдиагональной матрицы - прямое вычисление корней характеристического полинома &amp;lt;math&amp;gt;p_n(\lambda)&amp;lt;/math&amp;gt; через метод деления пополам, где формируется последовательность Штурма и локализуются собственные числа, являющиеся корнями характеристического полинома. Нахождение всех &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; собственных значений матрицы этим способом требует &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;2n^2t&amp;lt;/math&amp;gt; умножений и вычитаний, где &amp;lt;math&amp;gt;t&amp;lt;/math&amp;gt; - число сделанных шагов с применением метода деления пополам.&amp;lt;ref&amp;gt;Уилкинсон Дж. X. Алгебраическая проблема собственныx значений. Изд-во &amp;quot;Наука&amp;quot;, 1970. - глава 5, с. 272-278&amp;lt;/ref&amp;gt; Соответствующие собственные вектора могут быть найдены посредством обратных итераций за &amp;lt;math&amp;gt; O(n) &amp;lt;/math&amp;gt; флопов. &amp;lt;ref&amp;gt;Голуб Дж., Ван Лоун Ч. - Матричные вычисления//М.: Мир. - 1999 (c. 394-395)&amp;lt;/ref&amp;gt; &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;На практике, если требуется только небольшая часть от всей совокупности собственных векторов и значений, и матрица имеет Хессенбергову или трёхдиагональную форму, очень эффективными будут методы факторизации, как, например, QR-алгоритм или QL-алгоритм со сдвигами (c целью ускорить алгоритм и сделать порядок сходимости квадратичным) или же без них.&amp;lt;ref&amp;gt;http://algorithm.narod.ru/ln/eigen/ETridiag.html&amp;lt;/ref&amp;gt; &amp;lt;br&amp;gt;&lt;br /&gt;
Весьма молодые и не менее актуальные конкуренты QR и QL алгоритмов, применяющиеся для поиска собственных значений:&lt;br /&gt;
*Методы divide-and-conquer (разделяй и властвуй), появившиеся в 1980-ых годах &amp;lt;ref&amp;gt;https://goo.gl/dapvbn ссылку пришлось сократить с помощью Google url shortener, так как символы подчеркивания портили её и не давали перейти по 1 клику&amp;lt;/ref&amp;gt;&lt;br /&gt;
*Relatively robust representation методы, появившиеся в 1990-ых и позволяющие найти собственные числа симметричной матрицы порядка &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;n&amp;lt;/math&amp;gt; за &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt; операций&lt;br /&gt;
&lt;br /&gt;
Если требуется вычислить собственные векторы, то необходимо хранить вычисляемые векторы Ланцоша. Если работа при этом производится только с оперативной памятью, то при большом порядке исходной матрицы (а именно для таких матриц и предназначен метод Ланцоша) число шагов  &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;j&amp;lt;/math&amp;gt;, которые могут быть выполнены до того момента, как оперативная память будет исчерпана, будет очень незначительно, а следовательно, искомые собственные пары могут не успеть сойтись с требуемой точностью. В этом случае метод Ланцоша можно использовать итерационным образом: после выполнения заданного числа шагов процесс прерывается и, если еще не все требуемые пары Ритца сошлись с требуемой точностью, то формируется новый начальный вектор &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;q_1&amp;lt;/math&amp;gt;, являющийся линейной комбинацией векторов Ритца, еще не сошедшихся с заданной точностью, и процесс начинается заново.&amp;lt;ref&amp;gt;http://num-anal.srcc.msu.ru/lib_na/int_ae/int_ae6.htm (пункт 6.5)&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
Вычислительное ядро рассматриваемого алгоритма (наиболее ресурсно-затратная часть алгоритма) -  формирование на каждом шаге цикла промежуточного вектора &amp;lt;math&amp;gt;z&amp;lt;/math&amp;gt;, вычисляемого по формуле: &amp;lt;math&amp;gt;z = A\,q_j&amp;lt;/math&amp;gt;. Данная операция, по сравнению с другими операциями алгоритма, затратна и требовательна, как с точки зрения количества производимых операций, так и с точки зрения объема оперируемых данных. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Например, умножение матрицы размера &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;n\times n&amp;lt;/math&amp;gt; на вектор длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; требует: &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;n^2+(n-1)n = 2n^2-n&amp;lt;/math&amp;gt; операций умножения и сложения. В свою очередь аналогичная операция умножения матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;(n+1)\times (n+1)&amp;lt;/math&amp;gt; на вектор длины &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;(n+1)&amp;lt;/math&amp;gt; требует: &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;2n^2+3n+1&amp;lt;/math&amp;gt;  операций умножения и сложения. То есть повышение размерности задачи всего на 1 увеличивает число необходимых действий в этом шаге алгоритма на: &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;4n+1&amp;lt;/math&amp;gt;. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Так же, стоит помнить, что, согласно разделу 1.2, данную операцию умножения матрицы на вектор необходимо выполнить &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;k&amp;lt;/math&amp;gt; раз. Нетрудно понять, насколько возрастает и колоссален масштаб операций, если в задачах, где критична точность, размерности &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; могут иметь порядок &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;10^5&amp;lt;/math&amp;gt; или даже более.&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
Как уже было упомянуто в данной статье в описании алгоритма, рассматриваемый алгоритм состоит из двух последовательно выполненных алгоритмов: метод Ланцоша для построения последовательности подпространств Крылова и ортонормированных векторов Ланцоша и процедура Рэлея-Ритца получения оптимальных приближений собственных значений и соответствующих собственных векторов исходной матрицы.&lt;br /&gt;
&lt;br /&gt;
В первой части алгоритма, где итерационно строятся Крыловское подпространство и трёхдиагональная матрица &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&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 style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; разреженная. Именно она подлежит оптимизации с использованием техник распараллеливания, поскольку она является вычислительным ядром алгоритма, а весь упомянутый процесс построения матрицы &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&amp;lt;/math&amp;gt; выполняется последовательно.&lt;br /&gt;
&lt;br /&gt;
Рассмотрим вторую часть алгоритма - поиск собственных значений сформированной матрицы &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&amp;lt;/math&amp;gt;.&amp;lt;br&amp;gt;&lt;br /&gt;
Далее, наглядно, в виде псевдокода, представлен, упомянутый в разделе 1.2, QR-алгоритм (аналогично можно рассмотреть и QL-алгоритм) со сдвигами Релэя, который весьма популярен на практике.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{align}&lt;br /&gt;
\mathbf{Input}: \;&amp;amp;tridiagonal\;\;matrix \;T\;with\;\;n\times n\;\;size\\&lt;br /&gt;
T^{(0)}&amp;amp;:=T\\&lt;br /&gt;
\mathbf{for}&amp;amp; \;\;m=n,...,2 \;\; \mathbf{do}\\&lt;br /&gt;
&amp;amp;k=0\\&lt;br /&gt;
&amp;amp; \mathbf{repeat}\\&lt;br /&gt;
&amp;amp; \quad \;\; k=k+1\\&lt;br /&gt;
&amp;amp; \quad \;\; \mu^{(k)}=T_{m,m}^{(k-1)}\\&lt;br /&gt;
&amp;amp; \quad \;\; Q^{(k)}R^{(k)}=T^{(k-1)}-\mu^{(k)}I\;\;using\;\;QR\;decomposition\\&lt;br /&gt;
&amp;amp; \quad \;\; T^{(k)}=R^{(k)}Q^{(k)}+\mu^{(k)}I\\&lt;br /&gt;
&amp;amp; \mathbf{until} \;\;\; |T_{m,m-1}^{(k)}| \;is\;\;small\;\;enough\\&lt;br /&gt;
&amp;amp; Save  \;\;T_{m,m}^{(k)} \;\;as\;\; converged\;\;eigenvalue\;of\;T\\ &lt;br /&gt;
&amp;amp; Remove \;\boldsymbol{n}\,th\;row\;and\;\boldsymbol{n}\,th\;column\;\;from \;T \\&lt;br /&gt;
&amp;amp; and\;take\;this\;new\;cropped\;matrix\;as\;new\;T^{(0)}\;with\;\;(n-1)\times (n-1)\;\;size\\&lt;br /&gt;
 \mathbf{end}&amp;amp;\; \mathbf{for}&lt;br /&gt;
\end{align}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Малость наддиагональных и поддиагональных элементов матрицы (фраза &#039;&#039;&amp;quot;small enough&amp;quot;&#039;&#039; в псевдокоде) подразумевает:&lt;br /&gt;
&amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt; |T_{m,m-1}^{(k)}| \leq \varepsilon\,|T_{m,m}^{(k)}| \quad\quad &amp;lt;/math&amp;gt; , где &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt; \varepsilon &amp;lt;/math&amp;gt; - заданная точность&amp;lt;br&amp;gt;&lt;br /&gt;
Также вместо сдвига Релэя, обозначенного в алгоритме через &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;\mu^{(k)}&amp;lt;/math&amp;gt;, часто на практике используется сдвиг по Уилкинсону, который даёт гарантированную сходимость внедиагональных элементов матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt; T^{(k)} &amp;lt;/math&amp;gt;, формируемой на каждом шаге, к нулю, при этом жертвуя монотонностью их убывания.&amp;lt;ref&amp;gt;Голуб Дж., Ван Лоун Ч. - Матричные вычисления//М.: Мир. - 1999 (c. 378, вторая половина страницы)&amp;lt;/ref&amp;gt;&amp;lt;ref&amp;gt;Парлетт Б. Симметричная проблема собственных значений. Численные методы.,: Мир, 1983. с. 169&amp;lt;/ref&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Подробнее с различными сдвигами и соответствующими оценками скоростей и количествами операций можно ознакомиться по указанной ссылке:&amp;lt;ref&amp;gt;Парлетт Б. Симметричная проблема собственных значений. Численные методы.,: Мир, 1983. с. 179-182&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;Для совершения QR-декомпозиции на каждом шаге может использоваться любой из алгоритмов по ссылке.&amp;lt;ref&amp;gt;https://en.wikipedia.org/wiki/QR_decomposition&amp;lt;/ref&amp;gt; Подробные описания этих алгоритмов также доступны на данном ресурсе algowiki-project.&amp;lt;br&amp;gt;&lt;br /&gt;
Так как мы оперируем не обычной матрицей и даже не Хессенберговой, а симметричной и трёхдиагональной, то скорость таких алгоритмов значительно возрастёт. Например, согласно данному ресурсу &amp;lt;ref&amp;gt;http://algorithm.narod.ru/ln/eigen/ETridiag.html&amp;lt;/ref&amp;gt;, для QL-алгоритма с неявными сдвигами:&amp;lt;br&amp;gt;&lt;br /&gt;
Для трёхдиагональной матрицы объем арифметических действий составляет &amp;lt;math&amp;gt; O(n)&amp;lt;/math&amp;gt; на одну итерацию вместо &amp;lt;math&amp;gt; O(n^3)&amp;lt;/math&amp;gt; для матрицы общего вида, а число итераций для нахождения первых собственных значений примерно равно 4 - 5. Но на этих итерациях также уменьшаются внедиагональные элементы правого нижнего угла. И, таким образом, дальнейшие собственные значения ищутся значительно быстрее. Среднее число итераций на каждое собственное значение обычно составляет 1.3 - 1.6.&amp;lt;br&amp;gt; &lt;br /&gt;
Аналогично QL, QR-разложение трёхдиагольной матрицы также требует &amp;lt;math&amp;gt; O(n)&amp;lt;/math&amp;gt; флопов&amp;lt;ref&amp;gt;Голуб Дж., Ван Лоун Ч. - Матричные вычисления//М.: Мир. - 1999 (c. 378, начало раздела 8.2.2)&amp;lt;/ref&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Подводя итог, во второй части алгоритма Ланцоша можно выделить следующие макрооперации:&lt;br /&gt;
* умножение матрицы на вещественное число;&lt;br /&gt;
* перемножение матриц;&lt;br /&gt;
* умножение и сравнение вещественных чисел;&lt;br /&gt;
* + набор других макроопераций в зависимости от выбора метода, с помощью которого будет совершаться сама QR или QL-декомпозиция (выше продемонстрированы, уже, как минимум, 3 разных способа).&lt;br /&gt;
Так же, важно заметить, что набор макропераций может быть несколько другим, если выбрать какой-либо иной современный метод поиска собственных чисел трёхдиагональной матрицы, не использующий QR и QL разложения(факторизацию). Два таких метода были упомянуты в пункте 1.2.&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
С целью полностью не дублировать раздел 1.2 данной статьи, где представлен наглядный и доступный для понимания псевдокод алгоритма, постараемся лишь коротко просуммировать и обобщить весь перечень последовательных действий в рассматриваемом алгоритме.&lt;br /&gt;
&lt;br /&gt;
В качестве входных данных имеем: вещественная симметричная матрица &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; размера &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;n\times n&amp;lt;/math&amp;gt;, известный вещественный вектор &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;b&amp;lt;/math&amp;gt; длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; и число &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;n&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Далее:&lt;br /&gt;
* Инициализируем вещественную константу &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;\beta_0&amp;lt;/math&amp;gt; и векторы &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;q_0&amp;lt;/math&amp;gt; и &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;q_1&amp;lt;/math&amp;gt;&lt;br /&gt;
* Итерационно для всех &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j=1,...,k&amp;lt;/math&amp;gt;:&lt;br /&gt;
** Вычисляем вспомогательный вектор &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt;, используя умножение матрицы на вектор&lt;br /&gt;
** Вычисляем, используя скалярное произведение векторов, значение &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;\alpha_j&amp;lt;/math&amp;gt; - элемент на главной диагонали трёхдиагональной матрицы &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&amp;lt;/math&amp;gt;&lt;br /&gt;
** Вычисляем по формуле новое значение и перезаписываем вектор &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt;&lt;br /&gt;
** Вычисляем значение &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;\beta_j&amp;lt;/math&amp;gt; - элементы непосредственно над и под главной диагональю той же матрицы &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&amp;lt;/math&amp;gt;&lt;br /&gt;
** Вычисляем, зная вектор &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt;,  очередной столбец матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;Q&amp;lt;/math&amp;gt;, он же вектор Ланцоша : &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;\,\,q_{j+1}&amp;lt;/math&amp;gt;&lt;br /&gt;
** Теперь, когда матрица &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&amp;lt;/math&amp;gt; сформирована на очередном шаге, находим её собственные значения и вектора любым доступным способом, о чём было подробно сказано в пункте 1.2&lt;br /&gt;
** Переходим на следующую итерацию: &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j&amp;lt;/math&amp;gt;++&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
Оценим количество операций и сложность последовательного алгоритма, изложенного в предыдущем разделе.&lt;br /&gt;
*Для вычисления вектора &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt; умножается матрица размера &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;n\times n&amp;lt;/math&amp;gt; на вектор длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt;, и потребуется &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n^2&amp;lt;/math&amp;gt; операций умножения и &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n^2&amp;lt;/math&amp;gt; операций сложения.&lt;br /&gt;
*Умножение векторов &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;q^T_j&amp;lt;/math&amp;gt; и &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt; длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; потребует &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; операций умножения и &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; операций сложения.&lt;br /&gt;
*При вычислении нового значения вектора &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt; поэлементное сложение двух векторов длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; требует &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; операций сложения.&lt;br /&gt;
*Умножение вектора длины &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; на вещественное число требует &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; операций умножения.&lt;br /&gt;
*Нахождение квадратичной нормы вектора &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt;  длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; требует &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; умножений и &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; сложений и ещё 1 операцию извлечения квадратного корня.&lt;br /&gt;
*Заключительное нахождение собственных значений и собственных векторов трёхдиагональной матрицы &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;T_j&amp;lt;/math&amp;gt; размера &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j\times j&amp;lt;/math&amp;gt; с помощью QR-алгоритма потребует в худшем случае &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(j^3)&amp;lt;/math&amp;gt; операций.&amp;lt;ref&amp;gt;http://num-anal.srcc.msu.ru/lib_na/int_ae/int_ae6.htm (пункт 6.2, &amp;quot;Скорость сходимости при этом всегда не хуже квадратичной и почти всегда лучше кубической.&amp;quot;)&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Посчитаем теперь суммарное количество простейших операций на одной итерации алгоритма (без учёта записей в память):&lt;br /&gt;
*&amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n^2+5\,n&amp;lt;/math&amp;gt; операций умножения/деления&lt;br /&gt;
*&amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n^2+4\,n&amp;lt;/math&amp;gt; операций сложения/вычитания&lt;br /&gt;
*1 операция извлечения квадратного корня&amp;lt;br&amp;gt;&lt;br /&gt;
Отдельно после всех итераций при &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j=k&amp;lt;/math&amp;gt; :&lt;br /&gt;
*&amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(k^3)&amp;lt;/math&amp;gt; операций для поиска собственных значений и собственных векторов трёхдиагональной матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_k&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Итого можно утверждать следующее:&lt;br /&gt;
&lt;br /&gt;
Последовательная сложность одной итерации рассматриваемого алгоритма:  &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(n ^ 2) &amp;lt;/math&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Суммарная сложность алгоритма (&amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;/math&amp;gt; итераций): &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(k\,n ^ 2) + O(k ^ 3)&amp;lt;/math&amp;gt; &amp;lt;ref&amp;gt;Здесь мы полагаем, что мы не вычисляем собственные значения и векторы матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_j&amp;lt;/math&amp;gt; на каждом промежуточном шаге, а лишь единожды затрачиваем &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;O(k ^ 3)&amp;lt;/math&amp;gt; действий в конце для нахождения &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;/math&amp;gt; собственных значений и векторов матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_k&amp;lt;/math&amp;gt;&amp;lt;/ref&amp;gt; &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
На практике же обычно рассматривается число &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;&amp;lt;n&amp;lt;/math&amp;gt;, поэтому второе слагаемое можно опустить.&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
На рис. 1 продемонстрирован граф одной итерации (при каком-либо произвольном значении итератора &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j&amp;lt;/math&amp;gt;) описанного алгоритма без отображения входных и выходных данных. Наглядно продемонстрированы связи между всеми действиями, и с помощью деления на &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; потоков показано, какие операции возможно выполнять параллельно на каждом шаге с целью оптимизации и экономии машинного времени. В результате, после параллельно выполненных операций &#039;&#039;&#039;Division&#039;&#039;&#039; на заключительном ярусе, на выходе имеем значение следующего вектора Ланцоша &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;q_{j+1}&amp;lt;/math&amp;gt;, после чего следует переход на следующую итерацию, и процесс повторяется.&lt;br /&gt;
&lt;br /&gt;
[[Файл:Levin_graph.png|600px|thumb|center|Рис. 1  Структура одной итерации алгоритма]] &amp;lt;br&amp;gt;&lt;br /&gt;
Обозначения на рисунке: &amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Simp&#039;&#039;&#039; (от англ. simple) - операции сложения и умножения вещественных чисел при вычислении произведения матрицы на вектор;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Vec mult&#039;&#039;&#039; (от англ. vectors multiplication) - операция скалярного умножения двух векторов;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Vec subtr&#039;&#039;&#039; (от англ. vectors subtraction, из-за использованных в операции вычитаний векторов) - операция умножения вектора на число (выполняется дважды) и формирование нового значения &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;z_{new}&amp;lt;/math&amp;gt; по формуле: &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;z_{new} = z - \alpha_j q_j - \beta_{j-1}q_{j-1} \;&amp;lt;/math&amp;gt;;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;||\cdot||&amp;lt;/math&amp;gt; - операция вычисления нормы вектора;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Division&#039;&#039;&#039; - операция деления вектора на вещественное число  &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;\beta_j&amp;lt;/math&amp;gt; &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Важно отметить, что упомянутые выше операции также легко поддаются оптимизации. Например, попарные умножения вещественных координат векторов при вычислении скалярного произведения также легко выполняются параллельно на &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; потоках, а затем можно применить суммирование методом сдваивания, о котором сказано в следующем разделе. Умножение или деление вектора на вещественное число являющееся, по определению, умножением или делением всех его координат на это число тоже может быть выполнено эффективнее, если мы используем &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; потоков, а не выполняем эти действия последовательно.&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
Параллельные операции возможны только внутри итераций, так как рассматриваемый алгоритм является итерационным, и сами итерации строго последовательны.&amp;lt;br&amp;gt;&lt;br /&gt;
Рассмотрим в этом разделе подробнее, какой выигрыш мы можем получить при распараллеливании операций внутри одной итерации согласно графу из предыдущего раздела.&lt;br /&gt;
&lt;br /&gt;
Умножение вещественной симметричной матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; размера &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;n\times n&amp;lt;/math&amp;gt; на вектор &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;b&amp;lt;/math&amp;gt; длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; требует последовательного выполнения &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; ярусов умножений и сложений. Сложение элементов вектора длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; на каждом шаге перемножения можно оптимизировать и выполнить за &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;\log_2 n&amp;lt;/math&amp;gt; действий, если применять метод сдваивания.&lt;br /&gt;
&lt;br /&gt;
Дальнейшие операции выполняются последовательно, а вычисление значений векторов происходит за один ярус операций сложения или умножения.&lt;br /&gt;
&lt;br /&gt;
Ресурс параллелизма алгоритма вычисления собственных значений построенной трёхдиагональной матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_k&amp;lt;/math&amp;gt; размера &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k\times k&amp;lt;/math&amp;gt; зависит от выбранного алгоритма (об этих алгоритмах подробнее было сказано в разделах 1.2 и 1.4). Будет очень затратно с точки зрения объёма материала пытаться рассмотреть пусть даже часть этих методов в этой статье, а так же тонкости их распараллеливания. Предлагаем читателям при желании самим ознакомиться с этими алгоритмами на данном ресурсе или прибегнув к иным источникам.&lt;br /&gt;
&lt;br /&gt;
При классификации по высоте ЯПФ, таким образом, алгоритм Ланцоша без переортогонализации относится к алгоритмам с &#039;&#039;логарифмической сложностью&#039;&#039;, и его сложность равна &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(\log_2 n)&amp;lt;/math&amp;gt; с важным замечанием, что это сложность только одной итерации, а максимум в алгоритме может быть выполнено последовательно &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;/math&amp;gt; таких однотипных итераций, если не будет осуществлён ранний выход из цикла. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Несмотря на то, что на графе в предыдущем разделе для лучшей визуализации и понимания было изображено &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; потоков (никаких допущений мы не делали и нарушений с точки зрения логики и математики нет, можно изобразить большее число потоков, просто часть времени некоторые из них могут бездействовать и не использоваться), на самом деле правильным и разумным будет реализовать начальное параллельное выполнение &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n^2&amp;lt;/math&amp;gt; операций умножения всех вещественных элементов матрицы &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;A&amp;lt;/math&amp;gt; на соответствующие элементы вектора &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;q_j&amp;lt;/math&amp;gt;, после чего применять тот же самый упомянутый метод сдваивания. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Поэтому при классификации по ширине ЯПФ его сложность будет &#039;&#039;квадратичной&#039;&#039; и равна &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(n^2)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
&#039;&#039;&#039;Входные данные алгоритма:&#039;&#039;&#039; вещественная симметричная &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; размера &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;n\times n&amp;lt;/math&amp;gt;, вещественный вектор &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;b&amp;lt;/math&amp;gt; длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt;, и одно целое число &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;k&amp;lt;/math&amp;gt;, означающее количество итераций.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём входных данных:&#039;&#039;&#039; &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;n^2 +n + 1 &amp;lt;/math&amp;gt;. Если учесть, что матрица симметричная и достаточно для её однозначного определения задать элементы на главной диагонали и элементы над или под ней, то можно сократить объём входных данных с целью экономии памяти до: &amp;lt;math&amp;gt;\ \frac{n^2-n}{2}+n+n+1 =\frac{n^2+3n}{2} + 1&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные алгоритма:&#039;&#039;&#039; вектор собственных значений &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;\Theta^k&amp;lt;/math&amp;gt; длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;/math&amp;gt;, матрица &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;S^k&amp;lt;/math&amp;gt; из соответствующих собственных векторов размера &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n\times k&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём выходных данных:&#039;&#039;&#039; &amp;lt;math&amp;gt;k\;(n + 1)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
В данном разделе перечислены без какой-либо хронологии или связи друг с другом наиболее важные и разнообразные свойства алгоритма, на которые стоит и полезно обратить внимание, а также которые выгодно отличают его от схожих алгоритмов, решающих ту же задачу.&amp;lt;br&amp;gt;&lt;br /&gt;
1) Отношение последовательной сложности алгоритма к параллельной,с учётом &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;/math&amp;gt; итераций, равно &amp;lt;math&amp;gt;\;\;\frac{kn^2}{k \log_2{n}}=\frac{n^2}{\log_2{n}}&amp;lt;/math&amp;gt;;&amp;lt;br&amp;gt;&lt;br /&gt;
2) Вычислительная мощность алгоритма, как отношение числа операций к суммарному объему входных и выходных данных, равна &amp;lt;math style=&amp;quot;vertical-align:-70%&amp;gt;\;\;\frac{k\,n^2}{0.5\,n^2+1.5\,n+k\,n+k+1}&amp;lt;/math&amp;gt; и &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;\approx 2\,k&amp;lt;/math&amp;gt;, так как на практике верно отношение &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;&amp;lt;n&amp;lt;/math&amp;gt; ;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
3) Для собственных значений формируемых матриц &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_j&amp;lt;/math&amp;gt; верно отношение (следствие теоремы Коши о перемежаемости): &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;\lambda_i(T_{k+1})\geq \lambda_i(T_{k})\geq \lambda_{i+1}(T_{k+1})\geq \lambda_{i+1}(T_{k})&amp;lt;/math&amp;gt; ;&amp;lt;ref&amp;gt;James W. Demmel - Вычислительная линейная алгебра. Теория и приложения //Мир. - 2001 (c. 383)&amp;lt;/ref&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
4) Крайние (наибольшие и наименьшие) собственные значения матриц &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_j&amp;lt;/math&amp;gt; сходятся к крайним собственным значениям матрицы &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;A&amp;lt;/math&amp;gt; первыми (это часто происходит уже на ранних шагах при &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j\approx 2\,\sqrt{n}&amp;lt;/math&amp;gt;&amp;lt;ref&amp;gt;http://num-anal.srcc.msu.ru/lib_na/int_ae/int_ae6.htm (пункт 6.5)&amp;lt;/ref&amp;gt;), а собственные значения в середине спектра - последними;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
5) Из-за ограниченной точности постепенно теряется ортогональность вектора Ланцоша &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;q_j&amp;lt;/math&amp;gt; к предыдущим векторам Ланцоша, поэтому необходимо примерно каждые 10-15 итераций проводить дорогостоящую операцию реортогонализации, но это уже будет иной алгоритм с очень малым различием в одной операции и в программном коде, реализующем его, соответственно; &amp;lt;ref&amp;gt;Sam Handler - The Lanczos Algorithm For Large-Scale Eigenvalue Problems (08.01.07), slide №8&amp;lt;/ref&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
6) Эффективность и быстрота выполнения алгоритма очень сильно зависит от скорости памяти (диска). Согласно тесту только &#039;&#039;6%&#039;&#039; времени работы программы приходится на вычисления, остальное время затрачивается на ожидание отклика диска;&amp;lt;ref&amp;gt;Sam Handler - The Lanczos Algorithm For Large-Scale Eigenvalue Problems (08.01.07), slide №10&amp;lt;/ref&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
7) Метод Ланцоша удобен тем, что не требует хранения исходной матрицы полным массивом: метод использует исходную матрицу только в операциях умножения матрицы на вектор, что позволяет эффективно использовать разреженность матрицы или регулярность структуры матрицы. Поэтому метод Ланцоша может быть использован для матриц таких больших порядков, когда методы вращений и отражений не могут быть применены.&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;
Для исследования масштабируемости рассматриваемого алгоритма Ланцоша без переортогонализации автором была реализована программа на языке С++ с использованием технологии MPI. &amp;lt;ref&amp;gt;https://goo.gl/pNOFmW  или альтернативная ссылка с прикреплённым кодом: https://goo.gl/9AapM6 , по просьбе на почту я (автор статьи) готов предоставить желающим доступ к проекту с этим кодом на ресурсе Bitbucket&amp;lt;/ref&amp;gt; Дальнейшее исследование было проведено на суперкомпьютере &amp;quot;Ломоносов&amp;quot; Суперкомпьютерного комплекса МГУ.&amp;lt;ref&amp;gt;https://parallel.ru/cluster/lomonosov.html&amp;lt;/ref&amp;gt; &amp;lt;br&amp;gt; Важно отметить, что реализованная программа выполняет только первую часть алгоритма - формирование трёхдиагональной матрицы &amp;lt;math &amp;gt;T_j&amp;lt;/math&amp;gt;. Вторая часть алгоритма (задача поиска собственных значений матрицы &amp;lt;math &amp;gt;T_j&amp;lt;/math&amp;gt;) может быть решена несколькими методами, каждый из которых обладает своей эффективностью распараллеливания и характерными свойствами. Подробно этот вопрос уже обсуждался в статье ранее, поэтому не будем ещё раз заострять на этом внимание и останавливаться.&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Сборка осуществлялась со следующими параметрами:&lt;br /&gt;
* Компилятор intel/15.0.090 &lt;br /&gt;
* Openmpi/1.8.4-icc&lt;br /&gt;
В серии проведённых расчётов рассматривались следующие числовые значения параметров:&lt;br /&gt;
* Размер &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;n&amp;lt;/math&amp;gt; задачи и, соответственно, матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt;, задействованной в операции умножения на вектор: [2000 : 30000] с шагом 1000&lt;br /&gt;
* Число &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;p&amp;lt;/math&amp;gt; процессоров: 1, 2, 4, 16, 32, 48, 64, 96, 128, 192, 256&lt;br /&gt;
* Число итераций в алгоритме: &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k=350&amp;lt;/math&amp;gt;&lt;br /&gt;
Число &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; взято таким вопреки информации в начале статьи, где говорится, что значение &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; редко превышает &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;10^2&amp;lt;/math&amp;gt; (хоть мы и имеем право брать его любым по нашему усмотрению). Это сделано исключительно для лучшей визуализации пиков на графиках в данном разделе и наглядности получаемых результатов, так как при меньших на порядок значениях параметра &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; времена выполнения программ были слишком малы даже при минимальных числах процессоров и максимальных размерах &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;n&amp;lt;/math&amp;gt; задачи.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
На рис. 2 изображён график зависимости времени выполнения программы от числа процессоров и размера &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;n&amp;lt;/math&amp;gt; задачи. &amp;lt;br&amp;gt;&lt;br /&gt;
{|align=&amp;quot;center&amp;quot;&lt;br /&gt;
 |-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
 |[[file:Levin_task1_execTIME.png|620px|thumb|center|Рис. 2  График зависимости времени выполнения программы.]]&lt;br /&gt;
 |[[file:Levin604 task1 result EFFICIENCY.png|630px|thumb|center|Рис. 3  График зависимости эффективности распараллеливания программы.]]&lt;br /&gt;
|}&lt;br /&gt;
Многочисленные тесты показали при малых количествах ядер уменьшение времени выполнения программы почти в 2 раза при увеличении числа ядер в 2 раза на всём диапазоне размеров матриц, что и отражает сильный излом на первом графике. Изменение значений времени можно легко оценить по предоставленной цветовой шкале.&lt;br /&gt;
Был построен график эффективности распараллеливания (parallel efficiency) в зависимости от числа процессоров и размера задачи, изображённый на рис. 3.&lt;br /&gt;
Получены следующие результаты численных экспериментов:&lt;br /&gt;
* Средняя эффективность распараллеливания программы составила: 42.5576% ;&lt;br /&gt;
* Минимальная эффективность реализации: 0.674% (число процессоров 256 и минимальный размер матрицы 2000);&lt;br /&gt;
* Максимальная эффективность реализации: 77.773% (число процессоров 2, размер матрицы 20000).&lt;br /&gt;
Нужно понимать, что это лишь экстремумы, соответствующие двум экспериментам, которые сами по себе не дают полной картины и не позволяют однозначно судить о параллельных качествах алгоритма и реализующей его программы при столь большом числе параметров и проводимых расчётов. &amp;lt;br&amp;gt;На основании рис. 3 можно отметить следующие значимые и важные факты:&lt;br /&gt;
*Имеется ярко выраженный спад эффективности при минимальном рассматриваемом размере матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;n=2000&amp;lt;/math&amp;gt; вдоль всей оси OY, отвечающей за число процессоров;&lt;br /&gt;
*Присутствуют два пика эффективности (жёлтого цвета на рис. 3): при числе &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;p&amp;lt;/math&amp;gt; процессоров 2 и 128. Затем при дальнейшем увеличении числа процессоров с 128 до 256 наблюдается постепенное уменьшение эффективности реализации. Это связано с увеличением накладных расходов и затрат времени на обмены сообщениями между процессами.&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;
Перечислим далее некоторые из них, указывая язык программирования, лежащий в их основе, и некоторые важные характеристики, которые обсуждались в статье ранее:&lt;br /&gt;
*&#039;&#039;Code on netlib.org by Jane Cullum and Ralph Willoughby&#039;&#039; (&#039;&#039;&#039;Fortran 77&#039;&#039;&#039;; без реортогонализации векторов; без реализации распараллеливания)&amp;lt;ref&amp;gt;http://www.netlib.org/lanczos/leval&amp;lt;/ref&amp;gt;&lt;br /&gt;
*&#039;&#039;Lanczos algorithm on freesourcecode.net&#039;&#039; (&#039;&#039;&#039;Matlab&#039;&#039;&#039;; присутствует реортогонализация векторов; без реализации распараллеливания)&amp;lt;ref&amp;gt;http://freesourcecode.net/matlabprojects/61741/lanczos-algorithm--in-matlab&amp;lt;/ref&amp;gt;&lt;br /&gt;
*&#039;&#039;Lanczos for eigenvalues in Numerical Linear Algebra, Spring 2007&#039;&#039; (&#039;&#039;&#039;Matlab&#039;&#039;&#039;; частичная или полная реортогонализация - доступны оба варианта; без реализации распараллеливания)&amp;lt;ref&amp;gt;Ссылки на файлы lanso.m и lanfu.m можно найти на https://www.nada.kth.se/~ruhe/2D5219/labs2007.html&amp;lt;/ref&amp;gt;&lt;br /&gt;
*&#039;&#039;Planso&#039;&#039; (название происходит от parallel Lanso.f) &#039;&#039;code by Kesheng Wu and Horst D. Simon&#039;&#039; (&#039;&#039;&#039;Fortran 77&#039;&#039;&#039;; частичная реортогонализация векторов; использование MPI для коммуникаций)&amp;lt;ref&amp;gt;https://github.com/jiahao/planso.jl/tree/master/external/PLAN/plan К сожалению, ссылка в описании пакета на github, ведущая на сайт National Energy Research Scientific Computing Center (NERSC), с более подробной информацией о данной программе больше не активна и выдаёт результат &#039;&#039;Page not found&#039;&#039;&amp;lt;/ref&amp;gt; &lt;br /&gt;
* &#039;&#039;Lanczos.cpp in the Vienna Computing Library&#039;&#039;  (&#039;&#039;&#039;C++&#039;&#039;&#039;, частичная реортогонализация, без реализации распараллеливания) &amp;lt;ref&amp;gt;http://viennacl.sourceforge.net/doc/lanczos_8cpp_source.html&amp;lt;/ref&amp;gt;&lt;br /&gt;
* &#039;&#039;Parallel Eigen Values code using C++ AMP on microsoft msdn blog&#039;&#039; (&#039;&#039;&#039;C++&#039;&#039;&#039;; ? ; распараллеливание есть и реализовано через C++ AMP) &amp;lt;ref&amp;gt;https://blogs.msdn.microsoft.com/nativeconcurrency/2013/12/20/eigen-values/ Подробнее о C++ Accelerated Massive Parallelism можно почитать здесь: https://msdn.microsoft.com/ru-ru/library/hh265137(v=vs.140).aspx или здесь: http://professorweb.ru/my/csharp/optimization/level4/4_6.php &amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;br /&gt;
[[en:Description of algorithm properties and structure]]&lt;/div&gt;</summary>
		<author><name>AleksLevin</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:AleksLevin/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%9B%D0%B0%D0%BD%D1%86%D0%BE%D1%88%D0%B0_%D0%B2%D1%8B%D1%87%D0%B8%D1%81%D0%BB%D0%B5%D0%BD%D0%B8%D1%8F_%D1%81%D0%BE%D0%B1%D1%81%D1%82%D0%B2%D0%B5%D0%BD%D0%BD%D1%8B%D1%85_%D0%B7%D0%BD%D0%B0%D1%87%D0%B5%D0%BD%D0%B8%D0%B9_%D1%81%D0%B8%D0%BC%D0%BC%D0%B5%D1%82%D1%80%D0%B8%D1%87%D0%BD%D0%BE%D0%B9_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86%D1%8B_%D0%B4%D0%BB%D1%8F_%D1%82%D0%BE%D1%87%D0%BD%D0%BE%D0%B9_%D0%B0%D1%80%D0%B8%D1%84%D0%BC%D0%B5%D1%82%D0%B8%D0%BA%D0%B8_(%D0%B1%D0%B5%D0%B7_%D0%BF%D0%B5%D1%80%D0%B5%D0%BE%D1%80%D1%82%D0%BE%D0%B3%D0%BE%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D0%B8)&amp;diff=20295</id>
		<title>Участник:AleksLevin/Алгоритм Ланцоша вычисления собственных значений симметричной матрицы для точной арифметики (без переортогонализации)</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:AleksLevin/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%9B%D0%B0%D0%BD%D1%86%D0%BE%D1%88%D0%B0_%D0%B2%D1%8B%D1%87%D0%B8%D1%81%D0%BB%D0%B5%D0%BD%D0%B8%D1%8F_%D1%81%D0%BE%D0%B1%D1%81%D1%82%D0%B2%D0%B5%D0%BD%D0%BD%D1%8B%D1%85_%D0%B7%D0%BD%D0%B0%D1%87%D0%B5%D0%BD%D0%B8%D0%B9_%D1%81%D0%B8%D0%BC%D0%BC%D0%B5%D1%82%D1%80%D0%B8%D1%87%D0%BD%D0%BE%D0%B9_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86%D1%8B_%D0%B4%D0%BB%D1%8F_%D1%82%D0%BE%D1%87%D0%BD%D0%BE%D0%B9_%D0%B0%D1%80%D0%B8%D1%84%D0%BC%D0%B5%D1%82%D0%B8%D0%BA%D0%B8_(%D0%B1%D0%B5%D0%B7_%D0%BF%D0%B5%D1%80%D0%B5%D0%BE%D1%80%D1%82%D0%BE%D0%B3%D0%BE%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D0%B8)&amp;diff=20295"/>
		<updated>2016-12-07T20:16:41Z</updated>

		<summary type="html">&lt;p&gt;AleksLevin: /* Масштабируемость алгоритма и его реализации */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Основные авторы описания: Левин А.Д.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{algorithm&lt;br /&gt;
| name              = Алгоритм Ланцоша для точной арифметики (без переортогонализации)&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(k\,n^2)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(k\log_2 n)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;\frac{n^2+3n}{2} + 1&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;k\;(n + 1)&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритмов =&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Данный алгоритм появился в 1950 г. и носит имя венгерского физика и математика Корнелия Ланцоша (венг. Lánczos Kornél). Алгоритм Ланцоша относится к итерационным методам вычисления собственных значений для матриц столь больших порядков &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt; n&amp;lt;/math&amp;gt;, что к ним нельзя применить прямые методы из-за ограничений по времени и памяти.&lt;br /&gt;
&lt;br /&gt;
Сам Ланцош указывал, что его метод предназначен для отыскания нескольких собственных векторов симметричных матриц, хотя к методу сразу было обращено внимание, как к способу приведения всей матрицы к трёхдиагональному виду. Двадцатью годами позже канадский математик Крис Пэж показал, что, несмотря на чувствительность к округлениям, алгоритм Ланцоша - эффективное средство вычисления некоторых &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; собственных чисел и соответствующих им собственных векторов. &amp;lt;ref&amp;gt;Парлетт Б. - Симметричная проблема собственных значений. Численные методы //М.: Мир. - 1983. (c. 276)&amp;lt;/ref&amp;gt;&lt;br /&gt;
Обычно число &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; берут в два раза больше, чем количество собственных значений матрицы, которые поставлена цель найти, и оно имеет порядок не более &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;10^2&amp;lt;/math&amp;gt;.&amp;lt;ref&amp;gt;Susan W. Bostic - Lanczos Eigensolution Method for High-Perfomance Computers, page 7&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Алгоритм Ланцоша для вычисления собственных значений симметричной матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; соединяет в себе метод Ланцоша для построения последовательности подпространств Крылова и ортонормированных векторов Ланцоша и процедуру Рэлея-Ритца получения оптимальных приближений собственных значений и соответствующих собственных векторов исходной матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt;.&amp;lt;ref&amp;gt;James W. Demmel - Вычислительная линейная алгебра. Теория и приложения //Мир. - 2001 (c. 381)&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
В данной статье рассматривается вариант алгоритма Ланцоша, в котором опущено влияние ошибок округления на вычислительный процесс, хотя на практике этому посвящается отдельное внимание и существуют различные методы решения данной проблемы, такие как частичная или полная переортогонализация. Этим модифицированным методам посвящены отдельные статьи на данном ресурсе.&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
Обозначения и формулы, используемые в данном разделе, взяты из литературы, указанной по ссылке.&amp;lt;ref&amp;gt;James W. Demmel - Вычислительная линейная алгебра. Теория и приложения //Мир. - 2001 (c. 313, &#039;&#039;&amp;lt;math&amp;gt; \S &amp;lt;/math&amp;gt; 6.6 Методы Крыловского подпространства&#039;&#039;)&amp;lt;/ref&amp;gt; &lt;br /&gt;
&lt;br /&gt;
Алгоритм Ланцоша для вычисления &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; собственных значений и собственных векторов вещественной симметричной матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A=A^T&amp;lt;/math&amp;gt; в точной арифметике: &amp;lt;ref&amp;gt;James W. Demmel - Вычислительная линейная алгебра. Теория и приложения //Мир. - 2001 (c. 381)&amp;lt;/ref&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{align}&lt;br /&gt;
q_1 = &amp;amp; \,\frac{b}{\|b\|_2},\; \beta_0 = 0,\; q_0 = 0\\&lt;br /&gt;
\mathbf{for} \; &amp;amp; j = 1 \; to \; k \,\; \mathbf{do} \\&lt;br /&gt;
&amp;amp; z = A\,q_j\\&lt;br /&gt;
&amp;amp; \alpha_j = q^T_j z\\&lt;br /&gt;
&amp;amp; z = z - \alpha_j q_j - \beta_{j-1}q_{j-1}\\&lt;br /&gt;
&amp;amp; \beta_j = \|z\|_2\\&lt;br /&gt;
&amp;amp; \mathbf{If} \; (\beta_j == 0) \; \mathbf{then}\; stop\; the\; algorithm \\ &lt;br /&gt;
&amp;amp; \;  q_{j+1} = \frac{z}{\beta_j} \\&lt;br /&gt;
&amp;amp; compute\; eigenvalues\; and \;eigenvectors\;of \;matrix \;\;T_j= Q^T_j A Q\;\;and\;estimate \;the\; errors\\&lt;br /&gt;
\mathbf{end} \; &amp;amp; \mathbf{for}&lt;br /&gt;
\end{align}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
В продемонстрированном выше алгоритме &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;b&amp;lt;/math&amp;gt; - заданный вещественный вектор. Также полагается известным алгоритм вычисления произведения матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; на вектор &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;x&amp;lt;/math&amp;gt;. &lt;br /&gt;
Введём матрицу Крылова, определяемую следующим соотношением: &amp;lt;math&amp;gt;K_j = [b,Ab,A^2b,...,A^{j-1}b]&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Далее, на практике, матрица &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;K&amp;lt;/math&amp;gt; заменяется матрицей &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;Q&amp;lt;/math&amp;gt;, такой, что при любом числе &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; линейные оболочки первых &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; столбцов в &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;K&amp;lt;/math&amp;gt; и &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;Q&amp;lt;/math&amp;gt; являются одним и тем же подпространством.&amp;lt;ref&amp;gt;James W. Demmel - Вычислительная линейная алгебра. Теория и приложения //Мир. - 2001 (c. 315)&amp;lt;/ref&amp;gt; &lt;br /&gt;
Тогда матрица &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;Q&amp;lt;/math&amp;gt;, в отличие от матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;K&amp;lt;/math&amp;gt;, хорошо обусловлена и легко обратима. В результате получаем матрицу &amp;lt;math&amp;gt;Q_j = [q_1, q_2, \dots, q_j]&amp;lt;/math&amp;gt; размерности &amp;lt;math&amp;gt;n\times j&amp;lt;/math&amp;gt;, столбцы которой ортогональны, являются базисом подпространства Крылова и называются векторами Ланцоша.&lt;br /&gt;
&lt;br /&gt;
В алгоритме Ланцоша вычислению подлежит столько первых столбцов в матрице &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;Q_j&amp;lt;/math&amp;gt;, сколько необходимо для получения требуемого приближения к решению &amp;lt;math&amp;gt;A\,x\,=b\,\,(A\,x=\lambda \, x)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Получение нулевого &amp;lt;math&amp;gt;\beta_j&amp;lt;/math&amp;gt; в итерационном процессе - событие, желательное в том смысле, что оно свидетельствует о том, что найдено некоторое подпространство, являющееся в точности инвариантным, а все собственные значения матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;T_j&amp;lt;/math&amp;gt; являются собственными значениями матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt;. На практике же нулевое и близкие к нулю значения получаются редко.&amp;lt;ref&amp;gt;Голуб Дж., Ван Лоун Ч. - Матричные вычисления//М.: Мир. - 1999 (c. 429)&amp;lt;/ref&amp;gt; &lt;br /&gt;
&lt;br /&gt;
Затем на каждом шаге цикла формируется симметричная трёхдиагональная матрица &amp;lt;math&amp;gt;T_j = Q^T_j A Q&amp;lt;/math&amp;gt;, к которой применяется процесс Рэлея-Ритца для поиска её собственных значений (на практике для поиска этих собственных значений можно использовать любой из специальных методов в параграфе книги по ссылке).&amp;lt;ref&amp;gt;Голуб Дж., Ван Лоун Ч. - Матричные вычисления//М.: Мир. - 1999 (&amp;lt;math&amp;gt;\S&amp;lt;/math&amp;gt; 8.4)&amp;lt;/ref&amp;gt;  &lt;br /&gt;
Эти собственные значения, они же числа Ритца, и полагаются приближёнными собственными значениями исходной матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt;.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Существует множество методов для отыскания собственных значений вещественной симметричной трехдиагональной матрицы. Большинство из них требует &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt; операций &amp;lt;ref&amp;gt;Парлетт Б. Симметричная проблема собственных значений. Численные методы.,: Мир, 1983. с. 179-182&amp;lt;/ref&amp;gt;, но существуют и быстрые алгоритмы, требующие лишь &amp;lt;math&amp;gt;O(n\ln n)&amp;lt;/math&amp;gt; операций.&amp;lt;ref&amp;gt;https://en.wikipedia.org/wiki/Tridiagonal_matrix#Eigenvalues  Раздел eigenvalues&amp;lt;/ref&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Одним из возможных способов отыскать собственные значения симметричной трехдиагональной матрицы - прямое вычисление корней характеристического полинома &amp;lt;math&amp;gt;p_n(\lambda)&amp;lt;/math&amp;gt; через метод деления пополам, где формируется последовательность Штурма и локализуются собственные числа, являющиеся корнями характеристического полинома. Нахождение всех &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; собственных значений матрицы этим способом требует &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;2n^2t&amp;lt;/math&amp;gt; умножений и вычитаний, где &amp;lt;math&amp;gt;t&amp;lt;/math&amp;gt; - число сделанных шагов с применением метода деления пополам.&amp;lt;ref&amp;gt;Уилкинсон Дж. X. Алгебраическая проблема собственныx значений. Изд-во &amp;quot;Наука&amp;quot;, 1970. - глава 5, с. 272-278&amp;lt;/ref&amp;gt; Соответствующие собственные вектора могут быть найдены посредством обратных итераций за &amp;lt;math&amp;gt; O(n) &amp;lt;/math&amp;gt; флопов. &amp;lt;ref&amp;gt;Голуб Дж., Ван Лоун Ч. - Матричные вычисления//М.: Мир. - 1999 (c. 394-395)&amp;lt;/ref&amp;gt; &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;На практике, если требуется только небольшая часть от всей совокупности собственных векторов и значений, и матрица имеет Хессенбергову или трёхдиагональную форму, очень эффективными будут методы факторизации, как, например, QR-алгоритм или QL-алгоритм со сдвигами (c целью ускорить алгоритм и сделать порядок сходимости квадратичным) или же без них.&amp;lt;ref&amp;gt;http://algorithm.narod.ru/ln/eigen/ETridiag.html&amp;lt;/ref&amp;gt; &amp;lt;br&amp;gt;&lt;br /&gt;
Весьма молодые и не менее актуальные конкуренты QR и QL алгоритмов, применяющиеся для поиска собственных значений:&lt;br /&gt;
*Методы divide-and-conquer (разделяй и властвуй), появившиеся в 1980-ых годах &amp;lt;ref&amp;gt;https://goo.gl/dapvbn ссылку пришлось сократить с помощью Google url shortener, так как символы подчеркивания портили её и не давали перейти по 1 клику&amp;lt;/ref&amp;gt;&lt;br /&gt;
*Relatively robust representation методы, появившиеся в 1990-ых и позволяющие найти собственные числа симметричной матрицы порядка &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;n&amp;lt;/math&amp;gt; за &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt; операций&lt;br /&gt;
&lt;br /&gt;
Если требуется вычислить собственные векторы, то необходимо хранить вычисляемые векторы Ланцоша. Если работа при этом производится только с оперативной памятью, то при большом порядке исходной матрицы (а именно для таких матриц и предназначен метод Ланцоша) число шагов  &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;j&amp;lt;/math&amp;gt;, которые могут быть выполнены до того момента, как оперативная память будет исчерпана, будет очень незначительно, а следовательно, искомые собственные пары могут не успеть сойтись с требуемой точностью. В этом случае метод Ланцоша можно использовать итерационным образом: после выполнения заданного числа шагов процесс прерывается и, если еще не все требуемые пары Ритца сошлись с требуемой точностью, то формируется новый начальный вектор &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;q_1&amp;lt;/math&amp;gt;, являющийся линейной комбинацией векторов Ритца, еще не сошедшихся с заданной точностью, и процесс начинается заново.&amp;lt;ref&amp;gt;http://num-anal.srcc.msu.ru/lib_na/int_ae/int_ae6.htm (пункт 6.5)&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
Вычислительное ядро рассматриваемого алгоритма (наиболее ресурсно-затратная часть алгоритма) -  формирование на каждом шаге цикла промежуточного вектора &amp;lt;math&amp;gt;z&amp;lt;/math&amp;gt;, вычисляемого по формуле: &amp;lt;math&amp;gt;z = A\,q_j&amp;lt;/math&amp;gt;. Данная операция, по сравнению с другими операциями алгоритма, затратна и требовательна, как с точки зрения количества производимых операций, так и с точки зрения объема оперируемых данных. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Например, умножение матрицы размера &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;n\times n&amp;lt;/math&amp;gt; на вектор длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; требует: &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;n^2+(n-1)n = 2n^2-n&amp;lt;/math&amp;gt; операций умножения и сложения. В свою очередь аналогичная операция умножения матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;(n+1)\times (n+1)&amp;lt;/math&amp;gt; на вектор длины &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;(n+1)&amp;lt;/math&amp;gt; требует: &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;2n^2+3n+1&amp;lt;/math&amp;gt;  операций умножения и сложения. То есть повышение размерности задачи всего на 1 увеличивает число необходимых действий в этом шаге алгоритма на: &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;4n+1&amp;lt;/math&amp;gt;. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Так же, стоит помнить, что, согласно разделу 1.2, данную операцию умножения матрицы на вектор необходимо выполнить &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;k&amp;lt;/math&amp;gt; раз. Нетрудно понять, насколько возрастает и колоссален масштаб операций, если в задачах, где критична точность, размерности &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; могут иметь порядок &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;10^5&amp;lt;/math&amp;gt; или даже более.&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
Как уже было упомянуто в данной статье в описании алгоритма, рассматриваемый алгоритм состоит из двух последовательно выполненных алгоритмов: метод Ланцоша для построения последовательности подпространств Крылова и ортонормированных векторов Ланцоша и процедура Рэлея-Ритца получения оптимальных приближений собственных значений и соответствующих собственных векторов исходной матрицы.&lt;br /&gt;
&lt;br /&gt;
В первой части алгоритма, где итерационно строятся Крыловское подпространство и трёхдиагональная матрица &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&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 style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; разреженная. Именно она подлежит оптимизации с использованием техник распараллеливания, поскольку она является вычислительным ядром алгоритма, а весь упомянутый процесс построения матрицы &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&amp;lt;/math&amp;gt; выполняется последовательно.&lt;br /&gt;
&lt;br /&gt;
Рассмотрим вторую часть алгоритма - поиск собственных значений сформированной матрицы &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&amp;lt;/math&amp;gt;.&amp;lt;br&amp;gt;&lt;br /&gt;
Далее, наглядно, в виде псевдокода, представлен, упомянутый в разделе 1.2, QR-алгоритм (аналогично можно рассмотреть и QL-алгоритм) со сдвигами Релэя, который весьма популярен на практике.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{align}&lt;br /&gt;
\mathbf{Input}: \;&amp;amp;tridiagonal\;\;matrix \;T\;with\;\;n\times n\;\;size\\&lt;br /&gt;
T^{(0)}&amp;amp;:=T\\&lt;br /&gt;
\mathbf{for}&amp;amp; \;\;m=n,...,2 \;\; \mathbf{do}\\&lt;br /&gt;
&amp;amp;k=0\\&lt;br /&gt;
&amp;amp; \mathbf{repeat}\\&lt;br /&gt;
&amp;amp; \quad \;\; k=k+1\\&lt;br /&gt;
&amp;amp; \quad \;\; \mu^{(k)}=T_{m,m}^{(k-1)}\\&lt;br /&gt;
&amp;amp; \quad \;\; Q^{(k)}R^{(k)}=T^{(k-1)}-\mu^{(k)}I\;\;using\;\;QR\;decomposition\\&lt;br /&gt;
&amp;amp; \quad \;\; T^{(k)}=R^{(k)}Q^{(k)}+\mu^{(k)}I\\&lt;br /&gt;
&amp;amp; \mathbf{until} \;\;\; |T_{m,m-1}^{(k)}| \;is\;\;small\;\;enough\\&lt;br /&gt;
&amp;amp; Save  \;\;T_{m,m}^{(k)} \;\;as\;\; converged\;\;eigenvalue\;of\;T\\ &lt;br /&gt;
&amp;amp; Remove \;\boldsymbol{n}\,th\;row\;and\;\boldsymbol{n}\,th\;column\;\;from \;T \\&lt;br /&gt;
&amp;amp; and\;take\;this\;new\;cropped\;matrix\;as\;new\;T^{(0)}\;with\;\;(n-1)\times (n-1)\;\;size\\&lt;br /&gt;
 \mathbf{end}&amp;amp;\; \mathbf{for}&lt;br /&gt;
\end{align}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Малость наддиагональных и поддиагональных элементов матрицы (фраза &#039;&#039;&amp;quot;small enough&amp;quot;&#039;&#039; в псевдокоде) подразумевает:&lt;br /&gt;
&amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt; |T_{m,m-1}^{(k)}| \leq \varepsilon\,|T_{m,m}^{(k)}| \quad\quad &amp;lt;/math&amp;gt; , где &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt; \varepsilon &amp;lt;/math&amp;gt; - заданная точность&amp;lt;br&amp;gt;&lt;br /&gt;
Также вместо сдвига Релэя, обозначенного в алгоритме через &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;\mu^{(k)}&amp;lt;/math&amp;gt;, часто на практике используется сдвиг по Уилкинсону, который даёт гарантированную сходимость внедиагональных элементов матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt; T^{(k)} &amp;lt;/math&amp;gt;, формируемой на каждом шаге, к нулю, при этом жертвуя монотонностью их убывания.&amp;lt;ref&amp;gt;Голуб Дж., Ван Лоун Ч. - Матричные вычисления//М.: Мир. - 1999 (c. 378, вторая половина страницы)&amp;lt;/ref&amp;gt;&amp;lt;ref&amp;gt;Парлетт Б. Симметричная проблема собственных значений. Численные методы.,: Мир, 1983. с. 169&amp;lt;/ref&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Подробнее с различными сдвигами и соответствующими оценками скоростей и количествами операций можно ознакомиться по указанной ссылке:&amp;lt;ref&amp;gt;Парлетт Б. Симметричная проблема собственных значений. Численные методы.,: Мир, 1983. с. 179-182&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;Для совершения QR-декомпозиции на каждом шаге может использоваться любой из алгоритмов по ссылке.&amp;lt;ref&amp;gt;https://en.wikipedia.org/wiki/QR_decomposition&amp;lt;/ref&amp;gt; Подробные описания этих алгоритмов также доступны на данном ресурсе algowiki-project.&amp;lt;br&amp;gt;&lt;br /&gt;
Так как мы оперируем не обычной матрицей и даже не Хессенберговой, а симметричной и трёхдиагональной, то скорость таких алгоритмов значительно возрастёт. Например, согласно данному ресурсу &amp;lt;ref&amp;gt;http://algorithm.narod.ru/ln/eigen/ETridiag.html&amp;lt;/ref&amp;gt;, для QL-алгоритма с неявными сдвигами:&amp;lt;br&amp;gt;&lt;br /&gt;
Для трёхдиагональной матрицы объем арифметических действий составляет &amp;lt;math&amp;gt; O(n)&amp;lt;/math&amp;gt; на одну итерацию вместо &amp;lt;math&amp;gt; O(n^3)&amp;lt;/math&amp;gt; для матрицы общего вида, а число итераций для нахождения первых собственных значений примерно равно 4 - 5. Но на этих итерациях также уменьшаются внедиагональные элементы правого нижнего угла. И, таким образом, дальнейшие собственные значения ищутся значительно быстрее. Среднее число итераций на каждое собственное значение обычно составляет 1.3 - 1.6.&amp;lt;br&amp;gt; &lt;br /&gt;
Аналогично QL, QR-разложение трёхдиагольной матрицы также требует &amp;lt;math&amp;gt; O(n)&amp;lt;/math&amp;gt; флопов&amp;lt;ref&amp;gt;Голуб Дж., Ван Лоун Ч. - Матричные вычисления//М.: Мир. - 1999 (c. 378, начало раздела 8.2.2)&amp;lt;/ref&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Подводя итог, во второй части алгоритма Ланцоша можно выделить следующие макрооперации:&lt;br /&gt;
* умножение матрицы на вещественное число;&lt;br /&gt;
* перемножение матриц;&lt;br /&gt;
* умножение и сравнение вещественных чисел;&lt;br /&gt;
* + набор других макроопераций в зависимости от выбора метода, с помощью которого будет совершаться сама QR или QL-декомпозиция (выше продемонстрированы, уже, как минимум, 3 разных способа).&lt;br /&gt;
Так же, важно заметить, что набор макропераций может быть несколько другим, если выбрать какой-либо иной современный метод поиска собственных чисел трёхдиагональной матрицы, не использующий QR и QL разложения(факторизацию). Два таких метода были упомянуты в пункте 1.2.&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
С целью полностью не дублировать раздел 1.2 данной статьи, где представлен наглядный и доступный для понимания псевдокод алгоритма, постараемся лишь коротко просуммировать и обобщить весь перечень последовательных действий в рассматриваемом алгоритме.&lt;br /&gt;
&lt;br /&gt;
В качестве входных данных имеем: вещественная симметричная матрица &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; размера &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;n\times n&amp;lt;/math&amp;gt;, известный вещественный вектор &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;b&amp;lt;/math&amp;gt; длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; и число &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;n&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Далее:&lt;br /&gt;
* Инициализируем вещественную константу &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;\beta_0&amp;lt;/math&amp;gt; и векторы &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;q_0&amp;lt;/math&amp;gt; и &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;q_1&amp;lt;/math&amp;gt;&lt;br /&gt;
* Итерационно для всех &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j=1,...,k&amp;lt;/math&amp;gt;:&lt;br /&gt;
** Вычисляем вспомогательный вектор &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt;, используя умножение матрицы на вектор&lt;br /&gt;
** Вычисляем, используя скалярное произведение векторов, значение &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;\alpha_j&amp;lt;/math&amp;gt; - элемент на главной диагонали трёхдиагональной матрицы &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&amp;lt;/math&amp;gt;&lt;br /&gt;
** Вычисляем по формуле новое значение и перезаписываем вектор &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt;&lt;br /&gt;
** Вычисляем значение &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;\beta_j&amp;lt;/math&amp;gt; - элементы непосредственно над и под главной диагональю той же матрицы &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&amp;lt;/math&amp;gt;&lt;br /&gt;
** Вычисляем, зная вектор &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt;,  очередной столбец матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;Q&amp;lt;/math&amp;gt;, он же вектор Ланцоша : &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;\,\,q_{j+1}&amp;lt;/math&amp;gt;&lt;br /&gt;
** Теперь, когда матрица &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&amp;lt;/math&amp;gt; сформирована на очередном шаге, находим её собственные значения и вектора любым доступным способом, о чём было подробно сказано в пункте 1.2&lt;br /&gt;
** Переходим на следующую итерацию: &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j&amp;lt;/math&amp;gt;++&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
Оценим количество операций и сложность последовательного алгоритма, изложенного в предыдущем разделе.&lt;br /&gt;
*Для вычисления вектора &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt; умножается матрица размера &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;n\times n&amp;lt;/math&amp;gt; на вектор длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt;, и потребуется &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n^2&amp;lt;/math&amp;gt; операций умножения и &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n^2&amp;lt;/math&amp;gt; операций сложения.&lt;br /&gt;
*Умножение векторов &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;q^T_j&amp;lt;/math&amp;gt; и &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt; длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; потребует &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; операций умножения и &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; операций сложения.&lt;br /&gt;
*При вычислении нового значения вектора &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt; поэлементное сложение двух векторов длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; требует &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; операций сложения.&lt;br /&gt;
*Умножение вектора длины &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; на вещественное число требует &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; операций умножения.&lt;br /&gt;
*Нахождение квадратичной нормы вектора &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt;  длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; требует &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; умножений и &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; сложений и ещё 1 операцию извлечения квадратного корня.&lt;br /&gt;
*Заключительное нахождение собственных значений и собственных векторов трёхдиагональной матрицы &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;T_j&amp;lt;/math&amp;gt; размера &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j\times j&amp;lt;/math&amp;gt; с помощью QR-алгоритма потребует в худшем случае &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(j^3)&amp;lt;/math&amp;gt; операций.&amp;lt;ref&amp;gt;http://num-anal.srcc.msu.ru/lib_na/int_ae/int_ae6.htm (пункт 6.2, &amp;quot;Скорость сходимости при этом всегда не хуже квадратичной и почти всегда лучше кубической.&amp;quot;)&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Посчитаем теперь суммарное количество простейших операций на одной итерации алгоритма (без учёта записей в память):&lt;br /&gt;
*&amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n^2+5\,n&amp;lt;/math&amp;gt; операций умножения/деления&lt;br /&gt;
*&amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n^2+4\,n&amp;lt;/math&amp;gt; операций сложения/вычитания&lt;br /&gt;
*1 операция извлечения квадратного корня&amp;lt;br&amp;gt;&lt;br /&gt;
Отдельно после всех итераций при &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j=k&amp;lt;/math&amp;gt; :&lt;br /&gt;
*&amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(k^3)&amp;lt;/math&amp;gt; операций для поиска собственных значений и собственных векторов трёхдиагональной матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_k&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Итого можно утверждать следующее:&lt;br /&gt;
&lt;br /&gt;
Последовательная сложность одной итерации рассматриваемого алгоритма:  &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(n ^ 2) &amp;lt;/math&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Суммарная сложность алгоритма (&amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;/math&amp;gt; итераций): &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(k\,n ^ 2) + O(k ^ 3)&amp;lt;/math&amp;gt; &amp;lt;ref&amp;gt;Здесь мы полагаем, что мы не вычисляем собственные значения и векторы матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_j&amp;lt;/math&amp;gt; на каждом промежуточном шаге, а лишь единожды затрачиваем &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;O(k ^ 3)&amp;lt;/math&amp;gt; действий в конце для нахождения &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;/math&amp;gt; собственных значений и векторов матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_k&amp;lt;/math&amp;gt;&amp;lt;/ref&amp;gt; &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
На практике же обычно рассматривается число &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;&amp;lt;n&amp;lt;/math&amp;gt;, поэтому второе слагаемое можно опустить.&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
На рис. 1 продемонстрирован граф одной итерации (при каком-либо произвольном значении итератора &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j&amp;lt;/math&amp;gt;) описанного алгоритма без отображения входных и выходных данных. Наглядно продемонстрированы связи между всеми действиями, и с помощью деления на &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; потоков показано, какие операции возможно выполнять параллельно на каждом шаге с целью оптимизации и экономии машинного времени. В результате, после параллельно выполненных операций &#039;&#039;&#039;Division&#039;&#039;&#039; на заключительном ярусе, на выходе имеем значение следующего вектора Ланцоша &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;q_{j+1}&amp;lt;/math&amp;gt;, после чего следует переход на следующую итерацию, и процесс повторяется.&lt;br /&gt;
&lt;br /&gt;
[[Файл:Levin_graph.png|600px|thumb|center|Рис. 1  Структура одной итерации алгоритма]] &amp;lt;br&amp;gt;&lt;br /&gt;
Обозначения на рисунке: &amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Simp&#039;&#039;&#039; (от англ. simple) - операции сложения и умножения вещественных чисел при вычислении произведения матрицы на вектор;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Vec mult&#039;&#039;&#039; (от англ. vectors multiplication) - операция скалярного умножения двух векторов;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Vec subtr&#039;&#039;&#039; (от англ. vectors subtraction, из-за использованных в операции вычитаний векторов) - операция умножения вектора на число (выполняется дважды) и формирование нового значения &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;z_{new}&amp;lt;/math&amp;gt; по формуле: &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;z_{new} = z - \alpha_j q_j - \beta_{j-1}q_{j-1} \;&amp;lt;/math&amp;gt;;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;||\cdot||&amp;lt;/math&amp;gt; - операция вычисления нормы вектора;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Division&#039;&#039;&#039; - операция деления вектора на вещественное число  &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;\beta_j&amp;lt;/math&amp;gt; &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Важно отметить, что упомянутые выше операции также легко поддаются оптимизации. Например, попарные умножения вещественных координат векторов при вычислении скалярного произведения также легко выполняются параллельно на &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; потоках, а затем можно применить суммирование методом сдваивания, о котором сказано в следующем разделе. Умножение или деление вектора на вещественное число являющееся, по определению, умножением или делением всех его координат на это число тоже может быть выполнено эффективнее, если мы используем &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; потоков, а не выполняем эти действия последовательно.&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
Параллельные операции возможны только внутри итераций, так как рассматриваемый алгоритм является итерационным, и сами итерации строго последовательны.&amp;lt;br&amp;gt;&lt;br /&gt;
Рассмотрим в этом разделе подробнее, какой выигрыш мы можем получить при распараллеливании операций внутри одной итерации согласно графу из предыдущего раздела.&lt;br /&gt;
&lt;br /&gt;
Умножение вещественной симметричной матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; размера &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;n\times n&amp;lt;/math&amp;gt; на вектор &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;b&amp;lt;/math&amp;gt; длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; требует последовательного выполнения &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; ярусов умножений и сложений. Сложение элементов вектора длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; на каждом шаге перемножения можно оптимизировать и выполнить за &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;\log_2 n&amp;lt;/math&amp;gt; действий, если применять метод сдваивания.&lt;br /&gt;
&lt;br /&gt;
Дальнейшие операции выполняются последовательно, а вычисление значений векторов происходит за один ярус операций сложения или умножения.&lt;br /&gt;
&lt;br /&gt;
Ресурс параллелизма алгоритма вычисления собственных значений построенной трёхдиагональной матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_k&amp;lt;/math&amp;gt; размера &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k\times k&amp;lt;/math&amp;gt; зависит от выбранного алгоритма (об этих алгоритмах подробнее было сказано в разделах 1.2 и 1.4). Будет очень затратно с точки зрения объёма материала пытаться рассмотреть пусть даже часть этих методов в этой статье, а так же тонкости их распараллеливания. Предлагаем читателям при желании самим ознакомиться с этими алгоритмами на данном ресурсе или прибегнув к иным источникам.&lt;br /&gt;
&lt;br /&gt;
При классификации по высоте ЯПФ, таким образом, алгоритм Ланцоша без переортогонализации относится к алгоритмам с &#039;&#039;логарифмической сложностью&#039;&#039;, и его сложность равна &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(\log_2 n)&amp;lt;/math&amp;gt; с важным замечанием, что это сложность только одной итерации, а максимум в алгоритме может быть выполнено последовательно &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;/math&amp;gt; таких однотипных итераций, если не будет осуществлён ранний выход из цикла. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Несмотря на то, что на графе в предыдущем разделе для лучшей визуализации и понимания было изображено &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; потоков (никаких допущений мы не делали и нарушений с точки зрения логики и математики нет, можно изобразить большее число потоков, просто часть времени некоторые из них могут бездействовать и не использоваться), на самом деле правильным и разумным будет реализовать начальное параллельное выполнение &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n^2&amp;lt;/math&amp;gt; операций умножения всех вещественных элементов матрицы &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;A&amp;lt;/math&amp;gt; на соответствующие элементы вектора &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;q_j&amp;lt;/math&amp;gt;, после чего применять тот же самый упомянутый метод сдваивания. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Поэтому при классификации по ширине ЯПФ его сложность будет &#039;&#039;квадратичной&#039;&#039; и равна &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(n^2)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
&#039;&#039;&#039;Входные данные алгоритма:&#039;&#039;&#039; вещественная симметричная &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; размера &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;n\times n&amp;lt;/math&amp;gt;, вещественный вектор &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;b&amp;lt;/math&amp;gt; длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt;, и одно целое число &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;k&amp;lt;/math&amp;gt;, означающее количество итераций.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём входных данных:&#039;&#039;&#039; &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;n^2 +n + 1 &amp;lt;/math&amp;gt;. Если учесть, что матрица симметричная и достаточно для её однозначного определения задать элементы на главной диагонали и элементы над или под ней, то можно сократить объём входных данных с целью экономии памяти до: &amp;lt;math&amp;gt;\ \frac{n^2-n}{2}+n+n+1 =\frac{n^2+3n}{2} + 1&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные алгоритма:&#039;&#039;&#039; вектор собственных значений &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;\Theta^k&amp;lt;/math&amp;gt; длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;/math&amp;gt;, матрица &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;S^k&amp;lt;/math&amp;gt; из соответствующих собственных векторов размера &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n\times k&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём выходных данных:&#039;&#039;&#039; &amp;lt;math&amp;gt;k\;(n + 1)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
В данном разделе перечислены без какой-либо хронологии или связи друг с другом наиболее важные и разнообразные свойства алгоритма, на которые стоит и полезно обратить внимание, а также которые выгодно отличают его от схожих алгоритмов, решающих ту же задачу.&amp;lt;br&amp;gt;&lt;br /&gt;
1) Отношение последовательной сложности алгоритма к параллельной,с учётом &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;/math&amp;gt; итераций, равно &amp;lt;math&amp;gt;\;\;\frac{kn^2}{k \log_2{n}}=\frac{n^2}{\log_2{n}}&amp;lt;/math&amp;gt;;&amp;lt;br&amp;gt;&lt;br /&gt;
2) Вычислительная мощность алгоритма, как отношение числа операций к суммарному объему входных и выходных данных, равна &amp;lt;math style=&amp;quot;vertical-align:-70%&amp;gt;\;\;\frac{k\,n^2}{0.5\,n^2+1.5\,n+k\,n+k+1}&amp;lt;/math&amp;gt; и &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;\approx 2\,k&amp;lt;/math&amp;gt;, так как на практике верно отношение &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;&amp;lt;n&amp;lt;/math&amp;gt; ;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
3) Для собственных значений формируемых матриц &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_j&amp;lt;/math&amp;gt; верно отношение (следствие теоремы Коши о перемежаемости): &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;\lambda_i(T_{k+1})\geq \lambda_i(T_{k})\geq \lambda_{i+1}(T_{k+1})\geq \lambda_{i+1}(T_{k})&amp;lt;/math&amp;gt; ;&amp;lt;ref&amp;gt;James W. Demmel - Вычислительная линейная алгебра. Теория и приложения //Мир. - 2001 (c. 383)&amp;lt;/ref&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
4) Крайние (наибольшие и наименьшие) собственные значения матриц &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_j&amp;lt;/math&amp;gt; сходятся к крайним собственным значениям матрицы &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;A&amp;lt;/math&amp;gt; первыми (это часто происходит уже на ранних шагах при &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j\approx 2\,\sqrt{n}&amp;lt;/math&amp;gt;&amp;lt;ref&amp;gt;http://num-anal.srcc.msu.ru/lib_na/int_ae/int_ae6.htm (пункт 6.5)&amp;lt;/ref&amp;gt;), а собственные значения в середине спектра - последними;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
5) Из-за ограниченной точности постепенно теряется ортогональность вектора Ланцоша &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;q_j&amp;lt;/math&amp;gt; к предыдущим векторам Ланцоша, поэтому необходимо примерно каждые 10-15 итераций проводить дорогостоящую операцию реортогонализации, но это уже будет иной алгоритм с очень малым различием в одной операции и в программном коде, реализующем его, соответственно; &amp;lt;ref&amp;gt;Sam Handler - The Lanczos Algorithm For Large-Scale Eigenvalue Problems (08.01.07), slide №8&amp;lt;/ref&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
6) Эффективность и быстрота выполнения алгоритма очень сильно зависит от скорости памяти (диска). Согласно тесту только &#039;&#039;6%&#039;&#039; времени работы программы приходится на вычисления, остальное время затрачивается на ожидание отклика диска;&amp;lt;ref&amp;gt;Sam Handler - The Lanczos Algorithm For Large-Scale Eigenvalue Problems (08.01.07), slide №10&amp;lt;/ref&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
7) Метод Ланцоша удобен тем, что не требует хранения исходной матрицы полным массивом: метод использует исходную матрицу только в операциях умножения матрицы на вектор, что позволяет эффективно использовать разреженность матрицы или регулярность структуры матрицы. Поэтому метод Ланцоша может быть использован для матриц таких больших порядков, когда методы вращений и отражений не могут быть применены.&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;
Для исследования масштабируемости рассматриваемого алгоритма Ланцоша без переортогонализации автором была реализована программа на языке С++ с использованием технологии MPI. &amp;lt;ref&amp;gt;https://goo.gl/pNOFmW  или альтернативная ссылка с прикреплённым кодом: https://goo.gl/9AapM6 , по просьбе на почту я (автор статьи) готов предоставить желающим доступ к проекту с этим кодом на ресурсе Bitbucket&amp;lt;/ref&amp;gt; Дальнейшее исследование было проведено на суперкомпьютере &amp;quot;Ломоносов&amp;quot; Суперкомпьютерного комплекса МГУ.&amp;lt;ref&amp;gt;https://parallel.ru/cluster/lomonosov.html&amp;lt;/ref&amp;gt; &amp;lt;br&amp;gt; Важно отметить, что реализованная программа выполняет только первую часть алгоритма - формирование трёхдиагональной матрицы &amp;lt;math &amp;gt;T_j&amp;lt;/math&amp;gt;. Вторая часть алгоритма (задача поиска собственных значений матрицы &amp;lt;math &amp;gt;T_j&amp;lt;/math&amp;gt;) может быть решена несколькими методами, каждый из которых обладает своей эффективностью распараллеливания и характерными свойствами. Подробно этот вопрос уже обсуждался в статье ранее, поэтому не будем ещё раз заострять на этом внимание и останавливаться.&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Сборка осуществлялась со следующими параметрами:&lt;br /&gt;
* Компилятор intel/15.0.090 &lt;br /&gt;
* Openmpi/1.8.4-icc&lt;br /&gt;
В серии проведённых расчётов рассматривались следующие числовые значения параметров:&lt;br /&gt;
* Размер &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;n&amp;lt;/math&amp;gt; задачи и, соответственно, матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt;, задействованной в операции умножения на вектор: [2000 : 30000] с шагом 1000&lt;br /&gt;
* Число &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;p&amp;lt;/math&amp;gt; процессоров: 1, 2, 4, 16, 32, 48, 64, 96, 128, 192, 256&lt;br /&gt;
* Число итераций в алгоритме: &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k=350&amp;lt;/math&amp;gt;&lt;br /&gt;
Число &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; взято таким вопреки информации в начале статьи, где говорится, что значение &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; редко превышает &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;10^2&amp;lt;/math&amp;gt; (хоть мы и имеем право брать его любым по нашему усмотрению). Это сделано исключительно для лучшей визуализации пиков на графиках в данном разделе и наглядности получаемых результатов, так как при меньших на порядок значениях параметра &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; времена выполнения программ были слишком малы даже при минимальных числах процессоров и максимальных размерах &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;n&amp;lt;/math&amp;gt; задачи.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
На рис. 2 изображён график зависимости времени выполнения программы от числа процессоров и размера &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;n&amp;lt;/math&amp;gt; задачи. &amp;lt;br&amp;gt;&lt;br /&gt;
{|align=&amp;quot;center&amp;quot;&lt;br /&gt;
 |-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
 |[[file:Levin_task1_execTIME.png|620px|thumb|center|Рис. 2  График зависимости времени выполнения программы.]]&lt;br /&gt;
 |[[file:Levin604 task1 result EFFICIENCY.png|630px|thumb|center|Рис. 3  График зависимости эффективности распараллеливания программы.]]&lt;br /&gt;
|}&lt;br /&gt;
Многочисленные тесты показали при малых количествах ядер уменьшение времени выполнения программы почти в 2 раза при увеличении числа ядер в 2 раза на всём диапазоне размеров матриц, что и отражает сильный излом на первом графике. Изменение значений времени можно легко оценить по предоставленной цветовой шкале.&lt;br /&gt;
Был построен график эффективности распараллеливания (parallel efficiency) в зависимости от числа процессоров и размера задачи, изображённый на рис. 3.&lt;br /&gt;
Получены следующие результаты численных экспериментов:&lt;br /&gt;
* Средняя эффективность распараллеливания программы составила: 42.5576% ;&lt;br /&gt;
* Минимальная эффективность реализации: 0.674% (число процессоров 256 и минимальный размер матрицы 2000);&lt;br /&gt;
* Максимальная эффективность реализации: 77.773% (число процессоров 2, размер матрицы 20000).&lt;br /&gt;
Нужно понимать, что это лишь экстремумы, соответствующие двум экспериментам, которые сами по себе не дают полной картины и не позволяют однозначно судить о параллельных качествах алгоритма и реализующей его программы при столь большом числе параметров и проводимых расчётов. &amp;lt;br&amp;gt;На основании рис. 3 можно отметить следующие значимые и важные факты:&lt;br /&gt;
*Имеется ярко выраженный спад эффективности при минимальном рассматриваемом размере матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;n=2000&amp;lt;/math&amp;gt; вдоль всей оси OY, отвечающей за число процессоров;&lt;br /&gt;
*Присутствуют два пика эффективности (жёлтого цвета на рис. 3): при числе &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;p&amp;lt;/math&amp;gt; процессоров 2 и 128. Затем при дальнейшем увеличении числа процессоров с 128 до 256 наблюдается постепенное уменьшение эффективности реализации. Это связано с увеличением накладных расходов и затрат времени на обмены сообщениями между процессами.&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;
Перечислим далее некоторые из них, указывая язык программирования, лежащий в их основе, и некоторые важные характеристики, которые обсуждались в статье ранее:&lt;br /&gt;
*&#039;&#039;Code on netlib.org by Jane Cullum and Ralph Willoughby&#039;&#039; (&#039;&#039;&#039;Fortran 77&#039;&#039;&#039;; без реортогонализации векторов; без реализации распараллеливания)&amp;lt;ref&amp;gt;http://www.netlib.org/lanczos/leval&amp;lt;/ref&amp;gt;&lt;br /&gt;
*&#039;&#039;Lanczos algorithm on freesourcecode.net&#039;&#039; (&#039;&#039;&#039;Matlab&#039;&#039;&#039;; присутствует реортогонализация векторов; без реализации распараллеливания)&amp;lt;ref&amp;gt;http://freesourcecode.net/matlabprojects/61741/lanczos-algorithm--in-matlab&amp;lt;/ref&amp;gt;&lt;br /&gt;
*&#039;&#039;Lanczos for eigenvalues in Numerical Linear Algebra, Spring 2007&#039;&#039; (&#039;&#039;&#039;Matlab&#039;&#039;&#039;; частичная или полная реортогонализация - доступны оба варианта; без реализации распараллеливания)&amp;lt;ref&amp;gt;Ссылки на файлы lanso.m и lanfu.m можно найти на https://www.nada.kth.se/~ruhe/2D5219/labs2007.html&amp;lt;/ref&amp;gt;&lt;br /&gt;
*&#039;&#039;Planso&#039;&#039; (название происходит от parallel Lanso.f) &#039;&#039;code by Kesheng Wu and Horst D. Simon&#039;&#039; (&#039;&#039;&#039;Fortran 77&#039;&#039;&#039;; частичная реортогонализация векторов; использование MPI для коммуникаций)&amp;lt;ref&amp;gt;https://github.com/jiahao/planso.jl/tree/master/external/PLAN/plan К сожалению, ссылка в описании пакета на github, ведущая на сайт National Energy Research Scientific Computing Center (NERSC), с более подробной информацией о данной программе больше не активна и выдаёт результат &#039;&#039;Page not found&#039;&#039;&amp;lt;/ref&amp;gt; &lt;br /&gt;
* &#039;&#039;Lanczos.cpp in the Vienna Computing Library&#039;&#039;  (&#039;&#039;&#039;C++&#039;&#039;&#039;, частичная реортогонализация, без реализации распараллеливания) &amp;lt;ref&amp;gt;http://viennacl.sourceforge.net/doc/lanczos_8cpp_source.html&amp;lt;/ref&amp;gt;&lt;br /&gt;
* &#039;&#039;Parallel Eigen Values code using C++ AMP on microsoft msdn blog&#039;&#039; (&#039;&#039;&#039;C++&#039;&#039;&#039;; ? ; распараллеливание есть и реализовано через C++ AMP) &amp;lt;ref&amp;gt;https://blogs.msdn.microsoft.com/nativeconcurrency/2013/12/20/eigen-values/ Подробнее о C++ Accelerated Massive Parallelism можно почитать здесь: https://msdn.microsoft.com/ru-ru/library/hh265137(v=vs.140).aspx или здесь: http://professorweb.ru/my/csharp/optimization/level4/4_6.php &amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;br /&gt;
[[en:Description of algorithm properties and structure]]&lt;/div&gt;</summary>
		<author><name>AleksLevin</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:AleksLevin/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%9B%D0%B0%D0%BD%D1%86%D0%BE%D1%88%D0%B0_%D0%B2%D1%8B%D1%87%D0%B8%D1%81%D0%BB%D0%B5%D0%BD%D0%B8%D1%8F_%D1%81%D0%BE%D0%B1%D1%81%D1%82%D0%B2%D0%B5%D0%BD%D0%BD%D1%8B%D1%85_%D0%B7%D0%BD%D0%B0%D1%87%D0%B5%D0%BD%D0%B8%D0%B9_%D1%81%D0%B8%D0%BC%D0%BC%D0%B5%D1%82%D1%80%D0%B8%D1%87%D0%BD%D0%BE%D0%B9_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86%D1%8B_%D0%B4%D0%BB%D1%8F_%D1%82%D0%BE%D1%87%D0%BD%D0%BE%D0%B9_%D0%B0%D1%80%D0%B8%D1%84%D0%BC%D0%B5%D1%82%D0%B8%D0%BA%D0%B8_(%D0%B1%D0%B5%D0%B7_%D0%BF%D0%B5%D1%80%D0%B5%D0%BE%D1%80%D1%82%D0%BE%D0%B3%D0%BE%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D0%B8)&amp;diff=20290</id>
		<title>Участник:AleksLevin/Алгоритм Ланцоша вычисления собственных значений симметричной матрицы для точной арифметики (без переортогонализации)</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:AleksLevin/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%9B%D0%B0%D0%BD%D1%86%D0%BE%D1%88%D0%B0_%D0%B2%D1%8B%D1%87%D0%B8%D1%81%D0%BB%D0%B5%D0%BD%D0%B8%D1%8F_%D1%81%D0%BE%D0%B1%D1%81%D1%82%D0%B2%D0%B5%D0%BD%D0%BD%D1%8B%D1%85_%D0%B7%D0%BD%D0%B0%D1%87%D0%B5%D0%BD%D0%B8%D0%B9_%D1%81%D0%B8%D0%BC%D0%BC%D0%B5%D1%82%D1%80%D0%B8%D1%87%D0%BD%D0%BE%D0%B9_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86%D1%8B_%D0%B4%D0%BB%D1%8F_%D1%82%D0%BE%D1%87%D0%BD%D0%BE%D0%B9_%D0%B0%D1%80%D0%B8%D1%84%D0%BC%D0%B5%D1%82%D0%B8%D0%BA%D0%B8_(%D0%B1%D0%B5%D0%B7_%D0%BF%D0%B5%D1%80%D0%B5%D0%BE%D1%80%D1%82%D0%BE%D0%B3%D0%BE%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D0%B8)&amp;diff=20290"/>
		<updated>2016-12-07T20:10:43Z</updated>

		<summary type="html">&lt;p&gt;AleksLevin: /* Масштабируемость алгоритма и его реализации */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Основные авторы описания: Левин А.Д.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{algorithm&lt;br /&gt;
| name              = Алгоритм Ланцоша для точной арифметики (без переортогонализации)&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(k\,n^2)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(k\log_2 n)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;\frac{n^2+3n}{2} + 1&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;k\;(n + 1)&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритмов =&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Данный алгоритм появился в 1950 г. и носит имя венгерского физика и математика Корнелия Ланцоша (венг. Lánczos Kornél). Алгоритм Ланцоша относится к итерационным методам вычисления собственных значений для матриц столь больших порядков &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt; n&amp;lt;/math&amp;gt;, что к ним нельзя применить прямые методы из-за ограничений по времени и памяти.&lt;br /&gt;
&lt;br /&gt;
Сам Ланцош указывал, что его метод предназначен для отыскания нескольких собственных векторов симметричных матриц, хотя к методу сразу было обращено внимание, как к способу приведения всей матрицы к трёхдиагональному виду. Двадцатью годами позже канадский математик Крис Пэж показал, что, несмотря на чувствительность к округлениям, алгоритм Ланцоша - эффективное средство вычисления некоторых &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; собственных чисел и соответствующих им собственных векторов. &amp;lt;ref&amp;gt;Парлетт Б. - Симметричная проблема собственных значений. Численные методы //М.: Мир. - 1983. (c. 276)&amp;lt;/ref&amp;gt;&lt;br /&gt;
Обычно число &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; берут в два раза больше, чем количество собственных значений матрицы, которые поставлена цель найти, и оно имеет порядок не более &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;10^2&amp;lt;/math&amp;gt;.&amp;lt;ref&amp;gt;Susan W. Bostic - Lanczos Eigensolution Method for High-Perfomance Computers, page 7&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Алгоритм Ланцоша для вычисления собственных значений симметричной матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; соединяет в себе метод Ланцоша для построения последовательности подпространств Крылова и ортонормированных векторов Ланцоша и процедуру Рэлея-Ритца получения оптимальных приближений собственных значений и соответствующих собственных векторов исходной матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt;.&amp;lt;ref&amp;gt;James W. Demmel - Вычислительная линейная алгебра. Теория и приложения //Мир. - 2001 (c. 381)&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
В данной статье рассматривается вариант алгоритма Ланцоша, в котором опущено влияние ошибок округления на вычислительный процесс, хотя на практике этому посвящается отдельное внимание и существуют различные методы решения данной проблемы, такие как частичная или полная переортогонализация. Этим модифицированным методам посвящены отдельные статьи на данном ресурсе.&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
Обозначения и формулы, используемые в данном разделе, взяты из литературы, указанной по ссылке.&amp;lt;ref&amp;gt;James W. Demmel - Вычислительная линейная алгебра. Теория и приложения //Мир. - 2001 (c. 313, &#039;&#039;&amp;lt;math&amp;gt; \S &amp;lt;/math&amp;gt; 6.6 Методы Крыловского подпространства&#039;&#039;)&amp;lt;/ref&amp;gt; &lt;br /&gt;
&lt;br /&gt;
Алгоритм Ланцоша для вычисления &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; собственных значений и собственных векторов вещественной симметричной матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A=A^T&amp;lt;/math&amp;gt; в точной арифметике: &amp;lt;ref&amp;gt;James W. Demmel - Вычислительная линейная алгебра. Теория и приложения //Мир. - 2001 (c. 381)&amp;lt;/ref&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{align}&lt;br /&gt;
q_1 = &amp;amp; \,\frac{b}{\|b\|_2},\; \beta_0 = 0,\; q_0 = 0\\&lt;br /&gt;
\mathbf{for} \; &amp;amp; j = 1 \; to \; k \,\; \mathbf{do} \\&lt;br /&gt;
&amp;amp; z = A\,q_j\\&lt;br /&gt;
&amp;amp; \alpha_j = q^T_j z\\&lt;br /&gt;
&amp;amp; z = z - \alpha_j q_j - \beta_{j-1}q_{j-1}\\&lt;br /&gt;
&amp;amp; \beta_j = \|z\|_2\\&lt;br /&gt;
&amp;amp; \mathbf{If} \; (\beta_j == 0) \; \mathbf{then}\; stop\; the\; algorithm \\ &lt;br /&gt;
&amp;amp; \;  q_{j+1} = \frac{z}{\beta_j} \\&lt;br /&gt;
&amp;amp; compute\; eigenvalues\; and \;eigenvectors\;of \;matrix \;\;T_j= Q^T_j A Q\;\;and\;estimate \;the\; errors\\&lt;br /&gt;
\mathbf{end} \; &amp;amp; \mathbf{for}&lt;br /&gt;
\end{align}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
В продемонстрированном выше алгоритме &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;b&amp;lt;/math&amp;gt; - заданный вещественный вектор. Также полагается известным алгоритм вычисления произведения матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; на вектор &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;x&amp;lt;/math&amp;gt;. &lt;br /&gt;
Введём матрицу Крылова, определяемую следующим соотношением: &amp;lt;math&amp;gt;K_j = [b,Ab,A^2b,...,A^{j-1}b]&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Далее, на практике, матрица &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;K&amp;lt;/math&amp;gt; заменяется матрицей &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;Q&amp;lt;/math&amp;gt;, такой, что при любом числе &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; линейные оболочки первых &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; столбцов в &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;K&amp;lt;/math&amp;gt; и &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;Q&amp;lt;/math&amp;gt; являются одним и тем же подпространством.&amp;lt;ref&amp;gt;James W. Demmel - Вычислительная линейная алгебра. Теория и приложения //Мир. - 2001 (c. 315)&amp;lt;/ref&amp;gt; &lt;br /&gt;
Тогда матрица &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;Q&amp;lt;/math&amp;gt;, в отличие от матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;K&amp;lt;/math&amp;gt;, хорошо обусловлена и легко обратима. В результате получаем матрицу &amp;lt;math&amp;gt;Q_j = [q_1, q_2, \dots, q_j]&amp;lt;/math&amp;gt; размерности &amp;lt;math&amp;gt;n\times j&amp;lt;/math&amp;gt;, столбцы которой ортогональны, являются базисом подпространства Крылова и называются векторами Ланцоша.&lt;br /&gt;
&lt;br /&gt;
В алгоритме Ланцоша вычислению подлежит столько первых столбцов в матрице &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;Q_j&amp;lt;/math&amp;gt;, сколько необходимо для получения требуемого приближения к решению &amp;lt;math&amp;gt;A\,x\,=b\,\,(A\,x=\lambda \, x)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Получение нулевого &amp;lt;math&amp;gt;\beta_j&amp;lt;/math&amp;gt; в итерационном процессе - событие, желательное в том смысле, что оно свидетельствует о том, что найдено некоторое подпространство, являющееся в точности инвариантным, а все собственные значения матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;T_j&amp;lt;/math&amp;gt; являются собственными значениями матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt;. На практике же нулевое и близкие к нулю значения получаются редко.&amp;lt;ref&amp;gt;Голуб Дж., Ван Лоун Ч. - Матричные вычисления//М.: Мир. - 1999 (c. 429)&amp;lt;/ref&amp;gt; &lt;br /&gt;
&lt;br /&gt;
Затем на каждом шаге цикла формируется симметричная трёхдиагональная матрица &amp;lt;math&amp;gt;T_j = Q^T_j A Q&amp;lt;/math&amp;gt;, к которой применяется процесс Рэлея-Ритца для поиска её собственных значений (на практике для поиска этих собственных значений можно использовать любой из специальных методов в параграфе книги по ссылке).&amp;lt;ref&amp;gt;Голуб Дж., Ван Лоун Ч. - Матричные вычисления//М.: Мир. - 1999 (&amp;lt;math&amp;gt;\S&amp;lt;/math&amp;gt; 8.4)&amp;lt;/ref&amp;gt;  &lt;br /&gt;
Эти собственные значения, они же числа Ритца, и полагаются приближёнными собственными значениями исходной матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt;.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Существует множество методов для отыскания собственных значений вещественной симметричной трехдиагональной матрицы. Большинство из них требует &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt; операций &amp;lt;ref&amp;gt;Парлетт Б. Симметричная проблема собственных значений. Численные методы.,: Мир, 1983. с. 179-182&amp;lt;/ref&amp;gt;, но существуют и быстрые алгоритмы, требующие лишь &amp;lt;math&amp;gt;O(n\ln n)&amp;lt;/math&amp;gt; операций.&amp;lt;ref&amp;gt;https://en.wikipedia.org/wiki/Tridiagonal_matrix#Eigenvalues  Раздел eigenvalues&amp;lt;/ref&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Одним из возможных способов отыскать собственные значения симметричной трехдиагональной матрицы - прямое вычисление корней характеристического полинома &amp;lt;math&amp;gt;p_n(\lambda)&amp;lt;/math&amp;gt; через метод деления пополам, где формируется последовательность Штурма и локализуются собственные числа, являющиеся корнями характеристического полинома. Нахождение всех &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; собственных значений матрицы этим способом требует &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;2n^2t&amp;lt;/math&amp;gt; умножений и вычитаний, где &amp;lt;math&amp;gt;t&amp;lt;/math&amp;gt; - число сделанных шагов с применением метода деления пополам.&amp;lt;ref&amp;gt;Уилкинсон Дж. X. Алгебраическая проблема собственныx значений. Изд-во &amp;quot;Наука&amp;quot;, 1970. - глава 5, с. 272-278&amp;lt;/ref&amp;gt; Соответствующие собственные вектора могут быть найдены посредством обратных итераций за &amp;lt;math&amp;gt; O(n) &amp;lt;/math&amp;gt; флопов. &amp;lt;ref&amp;gt;Голуб Дж., Ван Лоун Ч. - Матричные вычисления//М.: Мир. - 1999 (c. 394-395)&amp;lt;/ref&amp;gt; &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;На практике, если требуется только небольшая часть от всей совокупности собственных векторов и значений, и матрица имеет Хессенбергову или трёхдиагональную форму, очень эффективными будут методы факторизации, как, например, QR-алгоритм или QL-алгоритм со сдвигами (c целью ускорить алгоритм и сделать порядок сходимости квадратичным) или же без них.&amp;lt;ref&amp;gt;http://algorithm.narod.ru/ln/eigen/ETridiag.html&amp;lt;/ref&amp;gt; &amp;lt;br&amp;gt;&lt;br /&gt;
Весьма молодые и не менее актуальные конкуренты QR и QL алгоритмов, применяющиеся для поиска собственных значений:&lt;br /&gt;
*Методы divide-and-conquer (разделяй и властвуй), появившиеся в 1980-ых годах &amp;lt;ref&amp;gt;https://goo.gl/dapvbn ссылку пришлось сократить с помощью Google url shortener, так как символы подчеркивания портили её и не давали перейти по 1 клику&amp;lt;/ref&amp;gt;&lt;br /&gt;
*Relatively robust representation методы, появившиеся в 1990-ых и позволяющие найти собственные числа симметричной матрицы порядка &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;n&amp;lt;/math&amp;gt; за &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt; операций&lt;br /&gt;
&lt;br /&gt;
Если требуется вычислить собственные векторы, то необходимо хранить вычисляемые векторы Ланцоша. Если работа при этом производится только с оперативной памятью, то при большом порядке исходной матрицы (а именно для таких матриц и предназначен метод Ланцоша) число шагов  &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;j&amp;lt;/math&amp;gt;, которые могут быть выполнены до того момента, как оперативная память будет исчерпана, будет очень незначительно, а следовательно, искомые собственные пары могут не успеть сойтись с требуемой точностью. В этом случае метод Ланцоша можно использовать итерационным образом: после выполнения заданного числа шагов процесс прерывается и, если еще не все требуемые пары Ритца сошлись с требуемой точностью, то формируется новый начальный вектор &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;q_1&amp;lt;/math&amp;gt;, являющийся линейной комбинацией векторов Ритца, еще не сошедшихся с заданной точностью, и процесс начинается заново.&amp;lt;ref&amp;gt;http://num-anal.srcc.msu.ru/lib_na/int_ae/int_ae6.htm (пункт 6.5)&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
Вычислительное ядро рассматриваемого алгоритма (наиболее ресурсно-затратная часть алгоритма) -  формирование на каждом шаге цикла промежуточного вектора &amp;lt;math&amp;gt;z&amp;lt;/math&amp;gt;, вычисляемого по формуле: &amp;lt;math&amp;gt;z = A\,q_j&amp;lt;/math&amp;gt;. Данная операция, по сравнению с другими операциями алгоритма, затратна и требовательна, как с точки зрения количества производимых операций, так и с точки зрения объема оперируемых данных. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Например, умножение матрицы размера &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;n\times n&amp;lt;/math&amp;gt; на вектор длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; требует: &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;n^2+(n-1)n = 2n^2-n&amp;lt;/math&amp;gt; операций умножения и сложения. В свою очередь аналогичная операция умножения матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;(n+1)\times (n+1)&amp;lt;/math&amp;gt; на вектор длины &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;(n+1)&amp;lt;/math&amp;gt; требует: &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;2n^2+3n+1&amp;lt;/math&amp;gt;  операций умножения и сложения. То есть повышение размерности задачи всего на 1 увеличивает число необходимых действий в этом шаге алгоритма на: &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;4n+1&amp;lt;/math&amp;gt;. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Так же, стоит помнить, что, согласно разделу 1.2, данную операцию умножения матрицы на вектор необходимо выполнить &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;k&amp;lt;/math&amp;gt; раз. Нетрудно понять, насколько возрастает и колоссален масштаб операций, если в задачах, где критична точность, размерности &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; могут иметь порядок &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;10^5&amp;lt;/math&amp;gt; или даже более.&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
Как уже было упомянуто в данной статье в описании алгоритма, рассматриваемый алгоритм состоит из двух последовательно выполненных алгоритмов: метод Ланцоша для построения последовательности подпространств Крылова и ортонормированных векторов Ланцоша и процедура Рэлея-Ритца получения оптимальных приближений собственных значений и соответствующих собственных векторов исходной матрицы.&lt;br /&gt;
&lt;br /&gt;
В первой части алгоритма, где итерационно строятся Крыловское подпространство и трёхдиагональная матрица &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&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 style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; разреженная. Именно она подлежит оптимизации с использованием техник распараллеливания, поскольку она является вычислительным ядром алгоритма, а весь упомянутый процесс построения матрицы &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&amp;lt;/math&amp;gt; выполняется последовательно.&lt;br /&gt;
&lt;br /&gt;
Рассмотрим вторую часть алгоритма - поиск собственных значений сформированной матрицы &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&amp;lt;/math&amp;gt;.&amp;lt;br&amp;gt;&lt;br /&gt;
Далее, наглядно, в виде псевдокода, представлен, упомянутый в разделе 1.2, QR-алгоритм (аналогично можно рассмотреть и QL-алгоритм) со сдвигами Релэя, который весьма популярен на практике.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{align}&lt;br /&gt;
\mathbf{Input}: \;&amp;amp;tridiagonal\;\;matrix \;T\;with\;\;n\times n\;\;size\\&lt;br /&gt;
T^{(0)}&amp;amp;:=T\\&lt;br /&gt;
\mathbf{for}&amp;amp; \;\;m=n,...,2 \;\; \mathbf{do}\\&lt;br /&gt;
&amp;amp;k=0\\&lt;br /&gt;
&amp;amp; \mathbf{repeat}\\&lt;br /&gt;
&amp;amp; \quad \;\; k=k+1\\&lt;br /&gt;
&amp;amp; \quad \;\; \mu^{(k)}=T_{m,m}^{(k-1)}\\&lt;br /&gt;
&amp;amp; \quad \;\; Q^{(k)}R^{(k)}=T^{(k-1)}-\mu^{(k)}I\;\;using\;\;QR\;decomposition\\&lt;br /&gt;
&amp;amp; \quad \;\; T^{(k)}=R^{(k)}Q^{(k)}+\mu^{(k)}I\\&lt;br /&gt;
&amp;amp; \mathbf{until} \;\;\; |T_{m,m-1}^{(k)}| \;is\;\;small\;\;enough\\&lt;br /&gt;
&amp;amp; Save  \;\;T_{m,m}^{(k)} \;\;as\;\; converged\;\;eigenvalue\;of\;T\\ &lt;br /&gt;
&amp;amp; Remove \;\boldsymbol{n}\,th\;row\;and\;\boldsymbol{n}\,th\;column\;\;from \;T \\&lt;br /&gt;
&amp;amp; and\;take\;this\;new\;cropped\;matrix\;as\;new\;T^{(0)}\;with\;\;(n-1)\times (n-1)\;\;size\\&lt;br /&gt;
 \mathbf{end}&amp;amp;\; \mathbf{for}&lt;br /&gt;
\end{align}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Малость наддиагональных и поддиагональных элементов матрицы (фраза &#039;&#039;&amp;quot;small enough&amp;quot;&#039;&#039; в псевдокоде) подразумевает:&lt;br /&gt;
&amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt; |T_{m,m-1}^{(k)}| \leq \varepsilon\,|T_{m,m}^{(k)}| \quad\quad &amp;lt;/math&amp;gt; , где &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt; \varepsilon &amp;lt;/math&amp;gt; - заданная точность&amp;lt;br&amp;gt;&lt;br /&gt;
Также вместо сдвига Релэя, обозначенного в алгоритме через &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;\mu^{(k)}&amp;lt;/math&amp;gt;, часто на практике используется сдвиг по Уилкинсону, который даёт гарантированную сходимость внедиагональных элементов матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt; T^{(k)} &amp;lt;/math&amp;gt;, формируемой на каждом шаге, к нулю, при этом жертвуя монотонностью их убывания.&amp;lt;ref&amp;gt;Голуб Дж., Ван Лоун Ч. - Матричные вычисления//М.: Мир. - 1999 (c. 378, вторая половина страницы)&amp;lt;/ref&amp;gt;&amp;lt;ref&amp;gt;Парлетт Б. Симметричная проблема собственных значений. Численные методы.,: Мир, 1983. с. 169&amp;lt;/ref&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Подробнее с различными сдвигами и соответствующими оценками скоростей и количествами операций можно ознакомиться по указанной ссылке:&amp;lt;ref&amp;gt;Парлетт Б. Симметричная проблема собственных значений. Численные методы.,: Мир, 1983. с. 179-182&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;Для совершения QR-декомпозиции на каждом шаге может использоваться любой из алгоритмов по ссылке.&amp;lt;ref&amp;gt;https://en.wikipedia.org/wiki/QR_decomposition&amp;lt;/ref&amp;gt; Подробные описания этих алгоритмов также доступны на данном ресурсе algowiki-project.&amp;lt;br&amp;gt;&lt;br /&gt;
Так как мы оперируем не обычной матрицей и даже не Хессенберговой, а симметричной и трёхдиагональной, то скорость таких алгоритмов значительно возрастёт. Например, согласно данному ресурсу &amp;lt;ref&amp;gt;http://algorithm.narod.ru/ln/eigen/ETridiag.html&amp;lt;/ref&amp;gt;, для QL-алгоритма с неявными сдвигами:&amp;lt;br&amp;gt;&lt;br /&gt;
Для трёхдиагональной матрицы объем арифметических действий составляет &amp;lt;math&amp;gt; O(n)&amp;lt;/math&amp;gt; на одну итерацию вместо &amp;lt;math&amp;gt; O(n^3)&amp;lt;/math&amp;gt; для матрицы общего вида, а число итераций для нахождения первых собственных значений примерно равно 4 - 5. Но на этих итерациях также уменьшаются внедиагональные элементы правого нижнего угла. И, таким образом, дальнейшие собственные значения ищутся значительно быстрее. Среднее число итераций на каждое собственное значение обычно составляет 1.3 - 1.6.&amp;lt;br&amp;gt; &lt;br /&gt;
Аналогично QL, QR-разложение трёхдиагольной матрицы также требует &amp;lt;math&amp;gt; O(n)&amp;lt;/math&amp;gt; флопов&amp;lt;ref&amp;gt;Голуб Дж., Ван Лоун Ч. - Матричные вычисления//М.: Мир. - 1999 (c. 378, начало раздела 8.2.2)&amp;lt;/ref&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Подводя итог, во второй части алгоритма Ланцоша можно выделить следующие макрооперации:&lt;br /&gt;
* умножение матрицы на вещественное число;&lt;br /&gt;
* перемножение матриц;&lt;br /&gt;
* умножение и сравнение вещественных чисел;&lt;br /&gt;
* + набор других макроопераций в зависимости от выбора метода, с помощью которого будет совершаться сама QR или QL-декомпозиция (выше продемонстрированы, уже, как минимум, 3 разных способа).&lt;br /&gt;
Так же, важно заметить, что набор макропераций может быть несколько другим, если выбрать какой-либо иной современный метод поиска собственных чисел трёхдиагональной матрицы, не использующий QR и QL разложения(факторизацию). Два таких метода были упомянуты в пункте 1.2.&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
С целью полностью не дублировать раздел 1.2 данной статьи, где представлен наглядный и доступный для понимания псевдокод алгоритма, постараемся лишь коротко просуммировать и обобщить весь перечень последовательных действий в рассматриваемом алгоритме.&lt;br /&gt;
&lt;br /&gt;
В качестве входных данных имеем: вещественная симметричная матрица &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; размера &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;n\times n&amp;lt;/math&amp;gt;, известный вещественный вектор &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;b&amp;lt;/math&amp;gt; длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; и число &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;n&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Далее:&lt;br /&gt;
* Инициализируем вещественную константу &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;\beta_0&amp;lt;/math&amp;gt; и векторы &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;q_0&amp;lt;/math&amp;gt; и &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;q_1&amp;lt;/math&amp;gt;&lt;br /&gt;
* Итерационно для всех &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j=1,...,k&amp;lt;/math&amp;gt;:&lt;br /&gt;
** Вычисляем вспомогательный вектор &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt;, используя умножение матрицы на вектор&lt;br /&gt;
** Вычисляем, используя скалярное произведение векторов, значение &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;\alpha_j&amp;lt;/math&amp;gt; - элемент на главной диагонали трёхдиагональной матрицы &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&amp;lt;/math&amp;gt;&lt;br /&gt;
** Вычисляем по формуле новое значение и перезаписываем вектор &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt;&lt;br /&gt;
** Вычисляем значение &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;\beta_j&amp;lt;/math&amp;gt; - элементы непосредственно над и под главной диагональю той же матрицы &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&amp;lt;/math&amp;gt;&lt;br /&gt;
** Вычисляем, зная вектор &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt;,  очередной столбец матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;Q&amp;lt;/math&amp;gt;, он же вектор Ланцоша : &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;\,\,q_{j+1}&amp;lt;/math&amp;gt;&lt;br /&gt;
** Теперь, когда матрица &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&amp;lt;/math&amp;gt; сформирована на очередном шаге, находим её собственные значения и вектора любым доступным способом, о чём было подробно сказано в пункте 1.2&lt;br /&gt;
** Переходим на следующую итерацию: &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j&amp;lt;/math&amp;gt;++&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
Оценим количество операций и сложность последовательного алгоритма, изложенного в предыдущем разделе.&lt;br /&gt;
*Для вычисления вектора &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt; умножается матрица размера &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;n\times n&amp;lt;/math&amp;gt; на вектор длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt;, и потребуется &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n^2&amp;lt;/math&amp;gt; операций умножения и &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n^2&amp;lt;/math&amp;gt; операций сложения.&lt;br /&gt;
*Умножение векторов &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;q^T_j&amp;lt;/math&amp;gt; и &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt; длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; потребует &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; операций умножения и &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; операций сложения.&lt;br /&gt;
*При вычислении нового значения вектора &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt; поэлементное сложение двух векторов длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; требует &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; операций сложения.&lt;br /&gt;
*Умножение вектора длины &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; на вещественное число требует &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; операций умножения.&lt;br /&gt;
*Нахождение квадратичной нормы вектора &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt;  длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; требует &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; умножений и &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; сложений и ещё 1 операцию извлечения квадратного корня.&lt;br /&gt;
*Заключительное нахождение собственных значений и собственных векторов трёхдиагональной матрицы &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;T_j&amp;lt;/math&amp;gt; размера &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j\times j&amp;lt;/math&amp;gt; с помощью QR-алгоритма потребует в худшем случае &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(j^3)&amp;lt;/math&amp;gt; операций.&amp;lt;ref&amp;gt;http://num-anal.srcc.msu.ru/lib_na/int_ae/int_ae6.htm (пункт 6.2, &amp;quot;Скорость сходимости при этом всегда не хуже квадратичной и почти всегда лучше кубической.&amp;quot;)&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Посчитаем теперь суммарное количество простейших операций на одной итерации алгоритма (без учёта записей в память):&lt;br /&gt;
*&amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n^2+5\,n&amp;lt;/math&amp;gt; операций умножения/деления&lt;br /&gt;
*&amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n^2+4\,n&amp;lt;/math&amp;gt; операций сложения/вычитания&lt;br /&gt;
*1 операция извлечения квадратного корня&amp;lt;br&amp;gt;&lt;br /&gt;
Отдельно после всех итераций при &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j=k&amp;lt;/math&amp;gt; :&lt;br /&gt;
*&amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(k^3)&amp;lt;/math&amp;gt; операций для поиска собственных значений и собственных векторов трёхдиагональной матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_k&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Итого можно утверждать следующее:&lt;br /&gt;
&lt;br /&gt;
Последовательная сложность одной итерации рассматриваемого алгоритма:  &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(n ^ 2) &amp;lt;/math&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Суммарная сложность алгоритма (&amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;/math&amp;gt; итераций): &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(k\,n ^ 2) + O(k ^ 3)&amp;lt;/math&amp;gt; &amp;lt;ref&amp;gt;Здесь мы полагаем, что мы не вычисляем собственные значения и векторы матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_j&amp;lt;/math&amp;gt; на каждом промежуточном шаге, а лишь единожды затрачиваем &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;O(k ^ 3)&amp;lt;/math&amp;gt; действий в конце для нахождения &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;/math&amp;gt; собственных значений и векторов матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_k&amp;lt;/math&amp;gt;&amp;lt;/ref&amp;gt; &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
На практике же обычно рассматривается число &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;&amp;lt;n&amp;lt;/math&amp;gt;, поэтому второе слагаемое можно опустить.&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
На рис. 1 продемонстрирован граф одной итерации (при каком-либо произвольном значении итератора &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j&amp;lt;/math&amp;gt;) описанного алгоритма без отображения входных и выходных данных. Наглядно продемонстрированы связи между всеми действиями, и с помощью деления на &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; потоков показано, какие операции возможно выполнять параллельно на каждом шаге с целью оптимизации и экономии машинного времени. В результате, после параллельно выполненных операций &#039;&#039;&#039;Division&#039;&#039;&#039; на заключительном ярусе, на выходе имеем значение следующего вектора Ланцоша &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;q_{j+1}&amp;lt;/math&amp;gt;, после чего следует переход на следующую итерацию, и процесс повторяется.&lt;br /&gt;
&lt;br /&gt;
[[Файл:Levin_graph.png|600px|thumb|center|Рис. 1  Структура одной итерации алгоритма]] &amp;lt;br&amp;gt;&lt;br /&gt;
Обозначения на рисунке: &amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Simp&#039;&#039;&#039; (от англ. simple) - операции сложения и умножения вещественных чисел при вычислении произведения матрицы на вектор;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Vec mult&#039;&#039;&#039; (от англ. vectors multiplication) - операция скалярного умножения двух векторов;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Vec subtr&#039;&#039;&#039; (от англ. vectors subtraction, из-за использованных в операции вычитаний векторов) - операция умножения вектора на число (выполняется дважды) и формирование нового значения &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;z_{new}&amp;lt;/math&amp;gt; по формуле: &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;z_{new} = z - \alpha_j q_j - \beta_{j-1}q_{j-1} \;&amp;lt;/math&amp;gt;;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;||\cdot||&amp;lt;/math&amp;gt; - операция вычисления нормы вектора;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Division&#039;&#039;&#039; - операция деления вектора на вещественное число  &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;\beta_j&amp;lt;/math&amp;gt; &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Важно отметить, что упомянутые выше операции также легко поддаются оптимизации. Например, попарные умножения вещественных координат векторов при вычислении скалярного произведения также легко выполняются параллельно на &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; потоках, а затем можно применить суммирование методом сдваивания, о котором сказано в следующем разделе. Умножение или деление вектора на вещественное число являющееся, по определению, умножением или делением всех его координат на это число тоже может быть выполнено эффективнее, если мы используем &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; потоков, а не выполняем эти действия последовательно.&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
Параллельные операции возможны только внутри итераций, так как рассматриваемый алгоритм является итерационным, и сами итерации строго последовательны.&amp;lt;br&amp;gt;&lt;br /&gt;
Рассмотрим в этом разделе подробнее, какой выигрыш мы можем получить при распараллеливании операций внутри одной итерации согласно графу из предыдущего раздела.&lt;br /&gt;
&lt;br /&gt;
Умножение вещественной симметричной матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; размера &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;n\times n&amp;lt;/math&amp;gt; на вектор &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;b&amp;lt;/math&amp;gt; длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; требует последовательного выполнения &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; ярусов умножений и сложений. Сложение элементов вектора длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; на каждом шаге перемножения можно оптимизировать и выполнить за &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;\log_2 n&amp;lt;/math&amp;gt; действий, если применять метод сдваивания.&lt;br /&gt;
&lt;br /&gt;
Дальнейшие операции выполняются последовательно, а вычисление значений векторов происходит за один ярус операций сложения или умножения.&lt;br /&gt;
&lt;br /&gt;
Ресурс параллелизма алгоритма вычисления собственных значений построенной трёхдиагональной матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_k&amp;lt;/math&amp;gt; размера &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k\times k&amp;lt;/math&amp;gt; зависит от выбранного алгоритма (об этих алгоритмах подробнее было сказано в разделах 1.2 и 1.4). Будет очень затратно с точки зрения объёма материала пытаться рассмотреть пусть даже часть этих методов в этой статье, а так же тонкости их распараллеливания. Предлагаем читателям при желании самим ознакомиться с этими алгоритмами на данном ресурсе или прибегнув к иным источникам.&lt;br /&gt;
&lt;br /&gt;
При классификации по высоте ЯПФ, таким образом, алгоритм Ланцоша без переортогонализации относится к алгоритмам с &#039;&#039;логарифмической сложностью&#039;&#039;, и его сложность равна &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(\log_2 n)&amp;lt;/math&amp;gt; с важным замечанием, что это сложность только одной итерации, а максимум в алгоритме может быть выполнено последовательно &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;/math&amp;gt; таких однотипных итераций, если не будет осуществлён ранний выход из цикла. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Несмотря на то, что на графе в предыдущем разделе для лучшей визуализации и понимания было изображено &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; потоков (никаких допущений мы не делали и нарушений с точки зрения логики и математики нет, можно изобразить большее число потоков, просто часть времени некоторые из них могут бездействовать и не использоваться), на самом деле правильным и разумным будет реализовать начальное параллельное выполнение &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n^2&amp;lt;/math&amp;gt; операций умножения всех вещественных элементов матрицы &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;A&amp;lt;/math&amp;gt; на соответствующие элементы вектора &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;q_j&amp;lt;/math&amp;gt;, после чего применять тот же самый упомянутый метод сдваивания. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Поэтому при классификации по ширине ЯПФ его сложность будет &#039;&#039;квадратичной&#039;&#039; и равна &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(n^2)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
&#039;&#039;&#039;Входные данные алгоритма:&#039;&#039;&#039; вещественная симметричная &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; размера &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;n\times n&amp;lt;/math&amp;gt;, вещественный вектор &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;b&amp;lt;/math&amp;gt; длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt;, и одно целое число &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;k&amp;lt;/math&amp;gt;, означающее количество итераций.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём входных данных:&#039;&#039;&#039; &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;n^2 +n + 1 &amp;lt;/math&amp;gt;. Если учесть, что матрица симметричная и достаточно для её однозначного определения задать элементы на главной диагонали и элементы над или под ней, то можно сократить объём входных данных с целью экономии памяти до: &amp;lt;math&amp;gt;\ \frac{n^2-n}{2}+n+n+1 =\frac{n^2+3n}{2} + 1&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные алгоритма:&#039;&#039;&#039; вектор собственных значений &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;\Theta^k&amp;lt;/math&amp;gt; длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;/math&amp;gt;, матрица &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;S^k&amp;lt;/math&amp;gt; из соответствующих собственных векторов размера &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n\times k&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём выходных данных:&#039;&#039;&#039; &amp;lt;math&amp;gt;k\;(n + 1)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
В данном разделе перечислены без какой-либо хронологии или связи друг с другом наиболее важные и разнообразные свойства алгоритма, на которые стоит и полезно обратить внимание, а также которые выгодно отличают его от схожих алгоритмов, решающих ту же задачу.&amp;lt;br&amp;gt;&lt;br /&gt;
1) Отношение последовательной сложности алгоритма к параллельной,с учётом &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;/math&amp;gt; итераций, равно &amp;lt;math&amp;gt;\;\;\frac{kn^2}{k \log_2{n}}=\frac{n^2}{\log_2{n}}&amp;lt;/math&amp;gt;;&amp;lt;br&amp;gt;&lt;br /&gt;
2) Вычислительная мощность алгоритма, как отношение числа операций к суммарному объему входных и выходных данных, равна &amp;lt;math style=&amp;quot;vertical-align:-70%&amp;gt;\;\;\frac{k\,n^2}{0.5\,n^2+1.5\,n+k\,n+k+1}&amp;lt;/math&amp;gt; и &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;\approx 2\,k&amp;lt;/math&amp;gt;, так как на практике верно отношение &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;&amp;lt;n&amp;lt;/math&amp;gt; ;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
3) Для собственных значений формируемых матриц &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_j&amp;lt;/math&amp;gt; верно отношение (следствие теоремы Коши о перемежаемости): &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;\lambda_i(T_{k+1})\geq \lambda_i(T_{k})\geq \lambda_{i+1}(T_{k+1})\geq \lambda_{i+1}(T_{k})&amp;lt;/math&amp;gt; ;&amp;lt;ref&amp;gt;James W. Demmel - Вычислительная линейная алгебра. Теория и приложения //Мир. - 2001 (c. 383)&amp;lt;/ref&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
4) Крайние (наибольшие и наименьшие) собственные значения матриц &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_j&amp;lt;/math&amp;gt; сходятся к крайним собственным значениям матрицы &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;A&amp;lt;/math&amp;gt; первыми (это часто происходит уже на ранних шагах при &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j\approx 2\,\sqrt{n}&amp;lt;/math&amp;gt;&amp;lt;ref&amp;gt;http://num-anal.srcc.msu.ru/lib_na/int_ae/int_ae6.htm (пункт 6.5)&amp;lt;/ref&amp;gt;), а собственные значения в середине спектра - последними;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
5) Из-за ограниченной точности постепенно теряется ортогональность вектора Ланцоша &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;q_j&amp;lt;/math&amp;gt; к предыдущим векторам Ланцоша, поэтому необходимо примерно каждые 10-15 итераций проводить дорогостоящую операцию реортогонализации, но это уже будет иной алгоритм с очень малым различием в одной операции и в программном коде, реализующем его, соответственно; &amp;lt;ref&amp;gt;Sam Handler - The Lanczos Algorithm For Large-Scale Eigenvalue Problems (08.01.07), slide №8&amp;lt;/ref&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
6) Эффективность и быстрота выполнения алгоритма очень сильно зависит от скорости памяти (диска). Согласно тесту только &#039;&#039;6%&#039;&#039; времени работы программы приходится на вычисления, остальное время затрачивается на ожидание отклика диска;&amp;lt;ref&amp;gt;Sam Handler - The Lanczos Algorithm For Large-Scale Eigenvalue Problems (08.01.07), slide №10&amp;lt;/ref&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
7) Метод Ланцоша удобен тем, что не требует хранения исходной матрицы полным массивом: метод использует исходную матрицу только в операциях умножения матрицы на вектор, что позволяет эффективно использовать разреженность матрицы или регулярность структуры матрицы. Поэтому метод Ланцоша может быть использован для матриц таких больших порядков, когда методы вращений и отражений не могут быть применены.&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;
Для исследования масштабируемости рассматриваемого алгоритма Ланцоша без переортогонализации автором была реализована программа на языке С++ с использованием технологии MPI. &amp;lt;ref&amp;gt;https://goo.gl/pNOFmW  или альтернативная ссылка с прикреплённым кодом: https://goo.gl/9AapM6 , по просьбе на почту я (автор статьи) готов предоставить желающим доступ к проекту с этим кодом на ресурсе Bitbucket&amp;lt;/ref&amp;gt; Дальнейшее исследование было проведено на суперкомпьютере &amp;quot;Ломоносов&amp;quot; Суперкомпьютерного комплекса МГУ.&amp;lt;ref&amp;gt;https://parallel.ru/cluster/lomonosov.html&amp;lt;/ref&amp;gt; &amp;lt;br&amp;gt; Важно отметить, что реализованная программа выполняет только первую часть алгоритма - формирование трёхдиагональной матрицы &amp;lt;math &amp;gt;T_j&amp;lt;/math&amp;gt;. Вторая часть алгоритма (задача поиска собственных значений матрицы &amp;lt;math &amp;gt;T_j&amp;lt;/math&amp;gt;) может быть решена несколькими методами, каждый из которых обладает своей эффективностью распараллеливания и характерными свойствами. Подробно этот вопрос уже обсуждался в статье ранее, поэтому не будем ещё раз заострять на этом внимание и останавливаться.&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Сборка осуществлялась со следующими параметрами:&lt;br /&gt;
* Компилятор intel/15.0.090 &lt;br /&gt;
* Openmpi/1.8.4-icc&lt;br /&gt;
В серии проведённых расчётов рассматривались следующие числовые значения параметров:&lt;br /&gt;
* Размер &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;n&amp;lt;/math&amp;gt; задачи и, соответственно, матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt;, задействованной в операции умножения на вектор: [2000 : 30000] с шагом 1000&lt;br /&gt;
* Число &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;p&amp;lt;/math&amp;gt; процессоров: 1, 2, 4, 16, 32, 48, 64, 96, 128, 192, 256&lt;br /&gt;
* Число итераций в алгоритме: &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k=350&amp;lt;/math&amp;gt;&lt;br /&gt;
Число &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; взято таким вопреки информации в начале статьи, где говорится, что значение &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; редко превышает &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;10^2&amp;lt;/math&amp;gt; (хоть мы и имеем право брать его любым по нашему усмотрению). Это сделано исключительно для лучшей визуализации пиков на графиках в данном разделе и наглядности получаемых результатов, так как при меньших на порядок значениях параметра &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; времена выполнения программ были слишком малы даже при минимальных числах процессоров и максимальных размерах &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;n&amp;lt;/math&amp;gt; задачи.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
На рис. 2 изображён график зависимости времени выполнения программы от числа процессоров и размера &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;n&amp;lt;/math&amp;gt; задачи. &amp;lt;br&amp;gt;&lt;br /&gt;
{|align=&amp;quot;center&amp;quot;&lt;br /&gt;
 |-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
 |[[file:Levin_task1_execTIME.png|620px|thumb|center|Рис. 2  График зависимости времени выполнения программы.]]&lt;br /&gt;
 |[[file:Levin604 task1 result EFFICIENCY.png|630px|thumb|center|Рис. 3  График зависимости эффективности распараллеливания программы.]]&lt;br /&gt;
|}&lt;br /&gt;
Многочисленные тесты показали при малых количествах ядер уменьшение времени выполнения программы почти в 2 раза при увеличении числа ядер в 2 раза на всём диапазоне размеров матриц, что и отражает сильный излом на первом графике. Изменение значений времени можно легко оценить по предоставленной цветовой шкале.&lt;br /&gt;
Был построен график эффективности распараллеливания (parallel efficiency) в зависимости от числа процессоров и размера задачи, изображённый на рис. 3.&lt;br /&gt;
Получены следующие результаты численных экспериментов:&lt;br /&gt;
* Средняя эффективность распараллеливания программы составила: 42.5576% ;&lt;br /&gt;
* Минимальная эффективность реализации: 0.674% (число процессоров 256 и минимальный размер матрицы 2000);&lt;br /&gt;
* Максимальная эффективность реализации: 77.773% (число процессоров 2, размер матрицы 20000).&lt;br /&gt;
Нужно понимать, что это лишь экстремумы, соответствующие двум экспериментам, которые сами по себе не дают полной картины и не позволяют однозначно судить о параллельных качествах алгоритма и реализующей его программы при столь большом числе параметров и проводимых расчётов. &amp;lt;br&amp;gt;На основании рис. 3 можно отметить следующие значимые и важные факты:&lt;br /&gt;
*Имеется ярко выраженный спад эффективности при минимальном рассматриваемом размере матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;n=2000&amp;lt;/math&amp;gt; вдоль всей оси OY, отвечающей за число процессоров;&lt;br /&gt;
*Присутствуют два пика эффективности (жёлтого цвета на рис. 3): при числе &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;p&amp;lt;/math&amp;gt; процессоров 2 и 128. Затем при дальнейшем увеличении числа процессоров с 128 до 256 наблюдается постепенное уменьшение эффективности реализации. Это связано с увеличением накладных расходов и затрат времени на обмен сообщениями между процессами.&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;
Перечислим далее некоторые из них, указывая язык программирования, лежащий в их основе, и некоторые важные характеристики, которые обсуждались в статье ранее:&lt;br /&gt;
*&#039;&#039;Code on netlib.org by Jane Cullum and Ralph Willoughby&#039;&#039; (&#039;&#039;&#039;Fortran 77&#039;&#039;&#039;; без реортогонализации векторов; без реализации распараллеливания)&amp;lt;ref&amp;gt;http://www.netlib.org/lanczos/leval&amp;lt;/ref&amp;gt;&lt;br /&gt;
*&#039;&#039;Lanczos algorithm on freesourcecode.net&#039;&#039; (&#039;&#039;&#039;Matlab&#039;&#039;&#039;; присутствует реортогонализация векторов; без реализации распараллеливания)&amp;lt;ref&amp;gt;http://freesourcecode.net/matlabprojects/61741/lanczos-algorithm--in-matlab&amp;lt;/ref&amp;gt;&lt;br /&gt;
*&#039;&#039;Lanczos for eigenvalues in Numerical Linear Algebra, Spring 2007&#039;&#039; (&#039;&#039;&#039;Matlab&#039;&#039;&#039;; частичная или полная реортогонализация - доступны оба варианта; без реализации распараллеливания)&amp;lt;ref&amp;gt;Ссылки на файлы lanso.m и lanfu.m можно найти на https://www.nada.kth.se/~ruhe/2D5219/labs2007.html&amp;lt;/ref&amp;gt;&lt;br /&gt;
*&#039;&#039;Planso&#039;&#039; (название происходит от parallel Lanso.f) &#039;&#039;code by Kesheng Wu and Horst D. Simon&#039;&#039; (&#039;&#039;&#039;Fortran 77&#039;&#039;&#039;; частичная реортогонализация векторов; использование MPI для коммуникаций)&amp;lt;ref&amp;gt;https://github.com/jiahao/planso.jl/tree/master/external/PLAN/plan К сожалению, ссылка в описании пакета на github, ведущая на сайт National Energy Research Scientific Computing Center (NERSC), с более подробной информацией о данной программе больше не активна и выдаёт результат &#039;&#039;Page not found&#039;&#039;&amp;lt;/ref&amp;gt; &lt;br /&gt;
* &#039;&#039;Lanczos.cpp in the Vienna Computing Library&#039;&#039;  (&#039;&#039;&#039;C++&#039;&#039;&#039;, частичная реортогонализация, без реализации распараллеливания) &amp;lt;ref&amp;gt;http://viennacl.sourceforge.net/doc/lanczos_8cpp_source.html&amp;lt;/ref&amp;gt;&lt;br /&gt;
* &#039;&#039;Parallel Eigen Values code using C++ AMP on microsoft msdn blog&#039;&#039; (&#039;&#039;&#039;C++&#039;&#039;&#039;; ? ; распараллеливание есть и реализовано через C++ AMP) &amp;lt;ref&amp;gt;https://blogs.msdn.microsoft.com/nativeconcurrency/2013/12/20/eigen-values/ Подробнее о C++ Accelerated Massive Parallelism можно почитать здесь: https://msdn.microsoft.com/ru-ru/library/hh265137(v=vs.140).aspx или здесь: http://professorweb.ru/my/csharp/optimization/level4/4_6.php &amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;br /&gt;
[[en:Description of algorithm properties and structure]]&lt;/div&gt;</summary>
		<author><name>AleksLevin</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:AleksLevin/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%9B%D0%B0%D0%BD%D1%86%D0%BE%D1%88%D0%B0_%D0%B2%D1%8B%D1%87%D0%B8%D1%81%D0%BB%D0%B5%D0%BD%D0%B8%D1%8F_%D1%81%D0%BE%D0%B1%D1%81%D1%82%D0%B2%D0%B5%D0%BD%D0%BD%D1%8B%D1%85_%D0%B7%D0%BD%D0%B0%D1%87%D0%B5%D0%BD%D0%B8%D0%B9_%D1%81%D0%B8%D0%BC%D0%BC%D0%B5%D1%82%D1%80%D0%B8%D1%87%D0%BD%D0%BE%D0%B9_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86%D1%8B_%D0%B4%D0%BB%D1%8F_%D1%82%D0%BE%D1%87%D0%BD%D0%BE%D0%B9_%D0%B0%D1%80%D0%B8%D1%84%D0%BC%D0%B5%D1%82%D0%B8%D0%BA%D0%B8_(%D0%B1%D0%B5%D0%B7_%D0%BF%D0%B5%D1%80%D0%B5%D0%BE%D1%80%D1%82%D0%BE%D0%B3%D0%BE%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D0%B8)&amp;diff=20288</id>
		<title>Участник:AleksLevin/Алгоритм Ланцоша вычисления собственных значений симметричной матрицы для точной арифметики (без переортогонализации)</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:AleksLevin/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%9B%D0%B0%D0%BD%D1%86%D0%BE%D1%88%D0%B0_%D0%B2%D1%8B%D1%87%D0%B8%D1%81%D0%BB%D0%B5%D0%BD%D0%B8%D1%8F_%D1%81%D0%BE%D0%B1%D1%81%D1%82%D0%B2%D0%B5%D0%BD%D0%BD%D1%8B%D1%85_%D0%B7%D0%BD%D0%B0%D1%87%D0%B5%D0%BD%D0%B8%D0%B9_%D1%81%D0%B8%D0%BC%D0%BC%D0%B5%D1%82%D1%80%D0%B8%D1%87%D0%BD%D0%BE%D0%B9_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86%D1%8B_%D0%B4%D0%BB%D1%8F_%D1%82%D0%BE%D1%87%D0%BD%D0%BE%D0%B9_%D0%B0%D1%80%D0%B8%D1%84%D0%BC%D0%B5%D1%82%D0%B8%D0%BA%D0%B8_(%D0%B1%D0%B5%D0%B7_%D0%BF%D0%B5%D1%80%D0%B5%D0%BE%D1%80%D1%82%D0%BE%D0%B3%D0%BE%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D0%B8)&amp;diff=20288"/>
		<updated>2016-12-07T20:08:09Z</updated>

		<summary type="html">&lt;p&gt;AleksLevin: /* Масштабируемость алгоритма и его реализации */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Основные авторы описания: Левин А.Д.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{algorithm&lt;br /&gt;
| name              = Алгоритм Ланцоша для точной арифметики (без переортогонализации)&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(k\,n^2)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(k\log_2 n)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;\frac{n^2+3n}{2} + 1&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;k\;(n + 1)&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритмов =&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Данный алгоритм появился в 1950 г. и носит имя венгерского физика и математика Корнелия Ланцоша (венг. Lánczos Kornél). Алгоритм Ланцоша относится к итерационным методам вычисления собственных значений для матриц столь больших порядков &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt; n&amp;lt;/math&amp;gt;, что к ним нельзя применить прямые методы из-за ограничений по времени и памяти.&lt;br /&gt;
&lt;br /&gt;
Сам Ланцош указывал, что его метод предназначен для отыскания нескольких собственных векторов симметричных матриц, хотя к методу сразу было обращено внимание, как к способу приведения всей матрицы к трёхдиагональному виду. Двадцатью годами позже канадский математик Крис Пэж показал, что, несмотря на чувствительность к округлениям, алгоритм Ланцоша - эффективное средство вычисления некоторых &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; собственных чисел и соответствующих им собственных векторов. &amp;lt;ref&amp;gt;Парлетт Б. - Симметричная проблема собственных значений. Численные методы //М.: Мир. - 1983. (c. 276)&amp;lt;/ref&amp;gt;&lt;br /&gt;
Обычно число &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; берут в два раза больше, чем количество собственных значений матрицы, которые поставлена цель найти, и оно имеет порядок не более &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;10^2&amp;lt;/math&amp;gt;.&amp;lt;ref&amp;gt;Susan W. Bostic - Lanczos Eigensolution Method for High-Perfomance Computers, page 7&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Алгоритм Ланцоша для вычисления собственных значений симметричной матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; соединяет в себе метод Ланцоша для построения последовательности подпространств Крылова и ортонормированных векторов Ланцоша и процедуру Рэлея-Ритца получения оптимальных приближений собственных значений и соответствующих собственных векторов исходной матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt;.&amp;lt;ref&amp;gt;James W. Demmel - Вычислительная линейная алгебра. Теория и приложения //Мир. - 2001 (c. 381)&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
В данной статье рассматривается вариант алгоритма Ланцоша, в котором опущено влияние ошибок округления на вычислительный процесс, хотя на практике этому посвящается отдельное внимание и существуют различные методы решения данной проблемы, такие как частичная или полная переортогонализация. Этим модифицированным методам посвящены отдельные статьи на данном ресурсе.&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
Обозначения и формулы, используемые в данном разделе, взяты из литературы, указанной по ссылке.&amp;lt;ref&amp;gt;James W. Demmel - Вычислительная линейная алгебра. Теория и приложения //Мир. - 2001 (c. 313, &#039;&#039;&amp;lt;math&amp;gt; \S &amp;lt;/math&amp;gt; 6.6 Методы Крыловского подпространства&#039;&#039;)&amp;lt;/ref&amp;gt; &lt;br /&gt;
&lt;br /&gt;
Алгоритм Ланцоша для вычисления &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; собственных значений и собственных векторов вещественной симметричной матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A=A^T&amp;lt;/math&amp;gt; в точной арифметике: &amp;lt;ref&amp;gt;James W. Demmel - Вычислительная линейная алгебра. Теория и приложения //Мир. - 2001 (c. 381)&amp;lt;/ref&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{align}&lt;br /&gt;
q_1 = &amp;amp; \,\frac{b}{\|b\|_2},\; \beta_0 = 0,\; q_0 = 0\\&lt;br /&gt;
\mathbf{for} \; &amp;amp; j = 1 \; to \; k \,\; \mathbf{do} \\&lt;br /&gt;
&amp;amp; z = A\,q_j\\&lt;br /&gt;
&amp;amp; \alpha_j = q^T_j z\\&lt;br /&gt;
&amp;amp; z = z - \alpha_j q_j - \beta_{j-1}q_{j-1}\\&lt;br /&gt;
&amp;amp; \beta_j = \|z\|_2\\&lt;br /&gt;
&amp;amp; \mathbf{If} \; (\beta_j == 0) \; \mathbf{then}\; stop\; the\; algorithm \\ &lt;br /&gt;
&amp;amp; \;  q_{j+1} = \frac{z}{\beta_j} \\&lt;br /&gt;
&amp;amp; compute\; eigenvalues\; and \;eigenvectors\;of \;matrix \;\;T_j= Q^T_j A Q\;\;and\;estimate \;the\; errors\\&lt;br /&gt;
\mathbf{end} \; &amp;amp; \mathbf{for}&lt;br /&gt;
\end{align}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
В продемонстрированном выше алгоритме &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;b&amp;lt;/math&amp;gt; - заданный вещественный вектор. Также полагается известным алгоритм вычисления произведения матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; на вектор &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;x&amp;lt;/math&amp;gt;. &lt;br /&gt;
Введём матрицу Крылова, определяемую следующим соотношением: &amp;lt;math&amp;gt;K_j = [b,Ab,A^2b,...,A^{j-1}b]&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Далее, на практике, матрица &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;K&amp;lt;/math&amp;gt; заменяется матрицей &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;Q&amp;lt;/math&amp;gt;, такой, что при любом числе &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; линейные оболочки первых &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; столбцов в &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;K&amp;lt;/math&amp;gt; и &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;Q&amp;lt;/math&amp;gt; являются одним и тем же подпространством.&amp;lt;ref&amp;gt;James W. Demmel - Вычислительная линейная алгебра. Теория и приложения //Мир. - 2001 (c. 315)&amp;lt;/ref&amp;gt; &lt;br /&gt;
Тогда матрица &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;Q&amp;lt;/math&amp;gt;, в отличие от матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;K&amp;lt;/math&amp;gt;, хорошо обусловлена и легко обратима. В результате получаем матрицу &amp;lt;math&amp;gt;Q_j = [q_1, q_2, \dots, q_j]&amp;lt;/math&amp;gt; размерности &amp;lt;math&amp;gt;n\times j&amp;lt;/math&amp;gt;, столбцы которой ортогональны, являются базисом подпространства Крылова и называются векторами Ланцоша.&lt;br /&gt;
&lt;br /&gt;
В алгоритме Ланцоша вычислению подлежит столько первых столбцов в матрице &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;Q_j&amp;lt;/math&amp;gt;, сколько необходимо для получения требуемого приближения к решению &amp;lt;math&amp;gt;A\,x\,=b\,\,(A\,x=\lambda \, x)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Получение нулевого &amp;lt;math&amp;gt;\beta_j&amp;lt;/math&amp;gt; в итерационном процессе - событие, желательное в том смысле, что оно свидетельствует о том, что найдено некоторое подпространство, являющееся в точности инвариантным, а все собственные значения матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;T_j&amp;lt;/math&amp;gt; являются собственными значениями матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt;. На практике же нулевое и близкие к нулю значения получаются редко.&amp;lt;ref&amp;gt;Голуб Дж., Ван Лоун Ч. - Матричные вычисления//М.: Мир. - 1999 (c. 429)&amp;lt;/ref&amp;gt; &lt;br /&gt;
&lt;br /&gt;
Затем на каждом шаге цикла формируется симметричная трёхдиагональная матрица &amp;lt;math&amp;gt;T_j = Q^T_j A Q&amp;lt;/math&amp;gt;, к которой применяется процесс Рэлея-Ритца для поиска её собственных значений (на практике для поиска этих собственных значений можно использовать любой из специальных методов в параграфе книги по ссылке).&amp;lt;ref&amp;gt;Голуб Дж., Ван Лоун Ч. - Матричные вычисления//М.: Мир. - 1999 (&amp;lt;math&amp;gt;\S&amp;lt;/math&amp;gt; 8.4)&amp;lt;/ref&amp;gt;  &lt;br /&gt;
Эти собственные значения, они же числа Ритца, и полагаются приближёнными собственными значениями исходной матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt;.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Существует множество методов для отыскания собственных значений вещественной симметричной трехдиагональной матрицы. Большинство из них требует &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt; операций &amp;lt;ref&amp;gt;Парлетт Б. Симметричная проблема собственных значений. Численные методы.,: Мир, 1983. с. 179-182&amp;lt;/ref&amp;gt;, но существуют и быстрые алгоритмы, требующие лишь &amp;lt;math&amp;gt;O(n\ln n)&amp;lt;/math&amp;gt; операций.&amp;lt;ref&amp;gt;https://en.wikipedia.org/wiki/Tridiagonal_matrix#Eigenvalues  Раздел eigenvalues&amp;lt;/ref&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Одним из возможных способов отыскать собственные значения симметричной трехдиагональной матрицы - прямое вычисление корней характеристического полинома &amp;lt;math&amp;gt;p_n(\lambda)&amp;lt;/math&amp;gt; через метод деления пополам, где формируется последовательность Штурма и локализуются собственные числа, являющиеся корнями характеристического полинома. Нахождение всех &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; собственных значений матрицы этим способом требует &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;2n^2t&amp;lt;/math&amp;gt; умножений и вычитаний, где &amp;lt;math&amp;gt;t&amp;lt;/math&amp;gt; - число сделанных шагов с применением метода деления пополам.&amp;lt;ref&amp;gt;Уилкинсон Дж. X. Алгебраическая проблема собственныx значений. Изд-во &amp;quot;Наука&amp;quot;, 1970. - глава 5, с. 272-278&amp;lt;/ref&amp;gt; Соответствующие собственные вектора могут быть найдены посредством обратных итераций за &amp;lt;math&amp;gt; O(n) &amp;lt;/math&amp;gt; флопов. &amp;lt;ref&amp;gt;Голуб Дж., Ван Лоун Ч. - Матричные вычисления//М.: Мир. - 1999 (c. 394-395)&amp;lt;/ref&amp;gt; &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;На практике, если требуется только небольшая часть от всей совокупности собственных векторов и значений, и матрица имеет Хессенбергову или трёхдиагональную форму, очень эффективными будут методы факторизации, как, например, QR-алгоритм или QL-алгоритм со сдвигами (c целью ускорить алгоритм и сделать порядок сходимости квадратичным) или же без них.&amp;lt;ref&amp;gt;http://algorithm.narod.ru/ln/eigen/ETridiag.html&amp;lt;/ref&amp;gt; &amp;lt;br&amp;gt;&lt;br /&gt;
Весьма молодые и не менее актуальные конкуренты QR и QL алгоритмов, применяющиеся для поиска собственных значений:&lt;br /&gt;
*Методы divide-and-conquer (разделяй и властвуй), появившиеся в 1980-ых годах &amp;lt;ref&amp;gt;https://goo.gl/dapvbn ссылку пришлось сократить с помощью Google url shortener, так как символы подчеркивания портили её и не давали перейти по 1 клику&amp;lt;/ref&amp;gt;&lt;br /&gt;
*Relatively robust representation методы, появившиеся в 1990-ых и позволяющие найти собственные числа симметричной матрицы порядка &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;n&amp;lt;/math&amp;gt; за &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt; операций&lt;br /&gt;
&lt;br /&gt;
Если требуется вычислить собственные векторы, то необходимо хранить вычисляемые векторы Ланцоша. Если работа при этом производится только с оперативной памятью, то при большом порядке исходной матрицы (а именно для таких матриц и предназначен метод Ланцоша) число шагов  &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;j&amp;lt;/math&amp;gt;, которые могут быть выполнены до того момента, как оперативная память будет исчерпана, будет очень незначительно, а следовательно, искомые собственные пары могут не успеть сойтись с требуемой точностью. В этом случае метод Ланцоша можно использовать итерационным образом: после выполнения заданного числа шагов процесс прерывается и, если еще не все требуемые пары Ритца сошлись с требуемой точностью, то формируется новый начальный вектор &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;q_1&amp;lt;/math&amp;gt;, являющийся линейной комбинацией векторов Ритца, еще не сошедшихся с заданной точностью, и процесс начинается заново.&amp;lt;ref&amp;gt;http://num-anal.srcc.msu.ru/lib_na/int_ae/int_ae6.htm (пункт 6.5)&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
Вычислительное ядро рассматриваемого алгоритма (наиболее ресурсно-затратная часть алгоритма) -  формирование на каждом шаге цикла промежуточного вектора &amp;lt;math&amp;gt;z&amp;lt;/math&amp;gt;, вычисляемого по формуле: &amp;lt;math&amp;gt;z = A\,q_j&amp;lt;/math&amp;gt;. Данная операция, по сравнению с другими операциями алгоритма, затратна и требовательна, как с точки зрения количества производимых операций, так и с точки зрения объема оперируемых данных. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Например, умножение матрицы размера &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;n\times n&amp;lt;/math&amp;gt; на вектор длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; требует: &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;n^2+(n-1)n = 2n^2-n&amp;lt;/math&amp;gt; операций умножения и сложения. В свою очередь аналогичная операция умножения матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;(n+1)\times (n+1)&amp;lt;/math&amp;gt; на вектор длины &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;(n+1)&amp;lt;/math&amp;gt; требует: &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;2n^2+3n+1&amp;lt;/math&amp;gt;  операций умножения и сложения. То есть повышение размерности задачи всего на 1 увеличивает число необходимых действий в этом шаге алгоритма на: &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;4n+1&amp;lt;/math&amp;gt;. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Так же, стоит помнить, что, согласно разделу 1.2, данную операцию умножения матрицы на вектор необходимо выполнить &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;k&amp;lt;/math&amp;gt; раз. Нетрудно понять, насколько возрастает и колоссален масштаб операций, если в задачах, где критична точность, размерности &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; могут иметь порядок &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;10^5&amp;lt;/math&amp;gt; или даже более.&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
Как уже было упомянуто в данной статье в описании алгоритма, рассматриваемый алгоритм состоит из двух последовательно выполненных алгоритмов: метод Ланцоша для построения последовательности подпространств Крылова и ортонормированных векторов Ланцоша и процедура Рэлея-Ритца получения оптимальных приближений собственных значений и соответствующих собственных векторов исходной матрицы.&lt;br /&gt;
&lt;br /&gt;
В первой части алгоритма, где итерационно строятся Крыловское подпространство и трёхдиагональная матрица &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&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 style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; разреженная. Именно она подлежит оптимизации с использованием техник распараллеливания, поскольку она является вычислительным ядром алгоритма, а весь упомянутый процесс построения матрицы &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&amp;lt;/math&amp;gt; выполняется последовательно.&lt;br /&gt;
&lt;br /&gt;
Рассмотрим вторую часть алгоритма - поиск собственных значений сформированной матрицы &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&amp;lt;/math&amp;gt;.&amp;lt;br&amp;gt;&lt;br /&gt;
Далее, наглядно, в виде псевдокода, представлен, упомянутый в разделе 1.2, QR-алгоритм (аналогично можно рассмотреть и QL-алгоритм) со сдвигами Релэя, который весьма популярен на практике.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{align}&lt;br /&gt;
\mathbf{Input}: \;&amp;amp;tridiagonal\;\;matrix \;T\;with\;\;n\times n\;\;size\\&lt;br /&gt;
T^{(0)}&amp;amp;:=T\\&lt;br /&gt;
\mathbf{for}&amp;amp; \;\;m=n,...,2 \;\; \mathbf{do}\\&lt;br /&gt;
&amp;amp;k=0\\&lt;br /&gt;
&amp;amp; \mathbf{repeat}\\&lt;br /&gt;
&amp;amp; \quad \;\; k=k+1\\&lt;br /&gt;
&amp;amp; \quad \;\; \mu^{(k)}=T_{m,m}^{(k-1)}\\&lt;br /&gt;
&amp;amp; \quad \;\; Q^{(k)}R^{(k)}=T^{(k-1)}-\mu^{(k)}I\;\;using\;\;QR\;decomposition\\&lt;br /&gt;
&amp;amp; \quad \;\; T^{(k)}=R^{(k)}Q^{(k)}+\mu^{(k)}I\\&lt;br /&gt;
&amp;amp; \mathbf{until} \;\;\; |T_{m,m-1}^{(k)}| \;is\;\;small\;\;enough\\&lt;br /&gt;
&amp;amp; Save  \;\;T_{m,m}^{(k)} \;\;as\;\; converged\;\;eigenvalue\;of\;T\\ &lt;br /&gt;
&amp;amp; Remove \;\boldsymbol{n}\,th\;row\;and\;\boldsymbol{n}\,th\;column\;\;from \;T \\&lt;br /&gt;
&amp;amp; and\;take\;this\;new\;cropped\;matrix\;as\;new\;T^{(0)}\;with\;\;(n-1)\times (n-1)\;\;size\\&lt;br /&gt;
 \mathbf{end}&amp;amp;\; \mathbf{for}&lt;br /&gt;
\end{align}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Малость наддиагональных и поддиагональных элементов матрицы (фраза &#039;&#039;&amp;quot;small enough&amp;quot;&#039;&#039; в псевдокоде) подразумевает:&lt;br /&gt;
&amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt; |T_{m,m-1}^{(k)}| \leq \varepsilon\,|T_{m,m}^{(k)}| \quad\quad &amp;lt;/math&amp;gt; , где &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt; \varepsilon &amp;lt;/math&amp;gt; - заданная точность&amp;lt;br&amp;gt;&lt;br /&gt;
Также вместо сдвига Релэя, обозначенного в алгоритме через &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;\mu^{(k)}&amp;lt;/math&amp;gt;, часто на практике используется сдвиг по Уилкинсону, который даёт гарантированную сходимость внедиагональных элементов матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt; T^{(k)} &amp;lt;/math&amp;gt;, формируемой на каждом шаге, к нулю, при этом жертвуя монотонностью их убывания.&amp;lt;ref&amp;gt;Голуб Дж., Ван Лоун Ч. - Матричные вычисления//М.: Мир. - 1999 (c. 378, вторая половина страницы)&amp;lt;/ref&amp;gt;&amp;lt;ref&amp;gt;Парлетт Б. Симметричная проблема собственных значений. Численные методы.,: Мир, 1983. с. 169&amp;lt;/ref&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Подробнее с различными сдвигами и соответствующими оценками скоростей и количествами операций можно ознакомиться по указанной ссылке:&amp;lt;ref&amp;gt;Парлетт Б. Симметричная проблема собственных значений. Численные методы.,: Мир, 1983. с. 179-182&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;Для совершения QR-декомпозиции на каждом шаге может использоваться любой из алгоритмов по ссылке.&amp;lt;ref&amp;gt;https://en.wikipedia.org/wiki/QR_decomposition&amp;lt;/ref&amp;gt; Подробные описания этих алгоритмов также доступны на данном ресурсе algowiki-project.&amp;lt;br&amp;gt;&lt;br /&gt;
Так как мы оперируем не обычной матрицей и даже не Хессенберговой, а симметричной и трёхдиагональной, то скорость таких алгоритмов значительно возрастёт. Например, согласно данному ресурсу &amp;lt;ref&amp;gt;http://algorithm.narod.ru/ln/eigen/ETridiag.html&amp;lt;/ref&amp;gt;, для QL-алгоритма с неявными сдвигами:&amp;lt;br&amp;gt;&lt;br /&gt;
Для трёхдиагональной матрицы объем арифметических действий составляет &amp;lt;math&amp;gt; O(n)&amp;lt;/math&amp;gt; на одну итерацию вместо &amp;lt;math&amp;gt; O(n^3)&amp;lt;/math&amp;gt; для матрицы общего вида, а число итераций для нахождения первых собственных значений примерно равно 4 - 5. Но на этих итерациях также уменьшаются внедиагональные элементы правого нижнего угла. И, таким образом, дальнейшие собственные значения ищутся значительно быстрее. Среднее число итераций на каждое собственное значение обычно составляет 1.3 - 1.6.&amp;lt;br&amp;gt; &lt;br /&gt;
Аналогично QL, QR-разложение трёхдиагольной матрицы также требует &amp;lt;math&amp;gt; O(n)&amp;lt;/math&amp;gt; флопов&amp;lt;ref&amp;gt;Голуб Дж., Ван Лоун Ч. - Матричные вычисления//М.: Мир. - 1999 (c. 378, начало раздела 8.2.2)&amp;lt;/ref&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Подводя итог, во второй части алгоритма Ланцоша можно выделить следующие макрооперации:&lt;br /&gt;
* умножение матрицы на вещественное число;&lt;br /&gt;
* перемножение матриц;&lt;br /&gt;
* умножение и сравнение вещественных чисел;&lt;br /&gt;
* + набор других макроопераций в зависимости от выбора метода, с помощью которого будет совершаться сама QR или QL-декомпозиция (выше продемонстрированы, уже, как минимум, 3 разных способа).&lt;br /&gt;
Так же, важно заметить, что набор макропераций может быть несколько другим, если выбрать какой-либо иной современный метод поиска собственных чисел трёхдиагональной матрицы, не использующий QR и QL разложения(факторизацию). Два таких метода были упомянуты в пункте 1.2.&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
С целью полностью не дублировать раздел 1.2 данной статьи, где представлен наглядный и доступный для понимания псевдокод алгоритма, постараемся лишь коротко просуммировать и обобщить весь перечень последовательных действий в рассматриваемом алгоритме.&lt;br /&gt;
&lt;br /&gt;
В качестве входных данных имеем: вещественная симметричная матрица &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; размера &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;n\times n&amp;lt;/math&amp;gt;, известный вещественный вектор &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;b&amp;lt;/math&amp;gt; длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; и число &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;n&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Далее:&lt;br /&gt;
* Инициализируем вещественную константу &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;\beta_0&amp;lt;/math&amp;gt; и векторы &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;q_0&amp;lt;/math&amp;gt; и &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;q_1&amp;lt;/math&amp;gt;&lt;br /&gt;
* Итерационно для всех &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j=1,...,k&amp;lt;/math&amp;gt;:&lt;br /&gt;
** Вычисляем вспомогательный вектор &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt;, используя умножение матрицы на вектор&lt;br /&gt;
** Вычисляем, используя скалярное произведение векторов, значение &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;\alpha_j&amp;lt;/math&amp;gt; - элемент на главной диагонали трёхдиагональной матрицы &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&amp;lt;/math&amp;gt;&lt;br /&gt;
** Вычисляем по формуле новое значение и перезаписываем вектор &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt;&lt;br /&gt;
** Вычисляем значение &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;\beta_j&amp;lt;/math&amp;gt; - элементы непосредственно над и под главной диагональю той же матрицы &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&amp;lt;/math&amp;gt;&lt;br /&gt;
** Вычисляем, зная вектор &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt;,  очередной столбец матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;Q&amp;lt;/math&amp;gt;, он же вектор Ланцоша : &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;\,\,q_{j+1}&amp;lt;/math&amp;gt;&lt;br /&gt;
** Теперь, когда матрица &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&amp;lt;/math&amp;gt; сформирована на очередном шаге, находим её собственные значения и вектора любым доступным способом, о чём было подробно сказано в пункте 1.2&lt;br /&gt;
** Переходим на следующую итерацию: &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j&amp;lt;/math&amp;gt;++&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
Оценим количество операций и сложность последовательного алгоритма, изложенного в предыдущем разделе.&lt;br /&gt;
*Для вычисления вектора &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt; умножается матрица размера &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;n\times n&amp;lt;/math&amp;gt; на вектор длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt;, и потребуется &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n^2&amp;lt;/math&amp;gt; операций умножения и &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n^2&amp;lt;/math&amp;gt; операций сложения.&lt;br /&gt;
*Умножение векторов &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;q^T_j&amp;lt;/math&amp;gt; и &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt; длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; потребует &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; операций умножения и &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; операций сложения.&lt;br /&gt;
*При вычислении нового значения вектора &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt; поэлементное сложение двух векторов длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; требует &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; операций сложения.&lt;br /&gt;
*Умножение вектора длины &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; на вещественное число требует &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; операций умножения.&lt;br /&gt;
*Нахождение квадратичной нормы вектора &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt;  длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; требует &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; умножений и &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; сложений и ещё 1 операцию извлечения квадратного корня.&lt;br /&gt;
*Заключительное нахождение собственных значений и собственных векторов трёхдиагональной матрицы &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;T_j&amp;lt;/math&amp;gt; размера &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j\times j&amp;lt;/math&amp;gt; с помощью QR-алгоритма потребует в худшем случае &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(j^3)&amp;lt;/math&amp;gt; операций.&amp;lt;ref&amp;gt;http://num-anal.srcc.msu.ru/lib_na/int_ae/int_ae6.htm (пункт 6.2, &amp;quot;Скорость сходимости при этом всегда не хуже квадратичной и почти всегда лучше кубической.&amp;quot;)&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Посчитаем теперь суммарное количество простейших операций на одной итерации алгоритма (без учёта записей в память):&lt;br /&gt;
*&amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n^2+5\,n&amp;lt;/math&amp;gt; операций умножения/деления&lt;br /&gt;
*&amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n^2+4\,n&amp;lt;/math&amp;gt; операций сложения/вычитания&lt;br /&gt;
*1 операция извлечения квадратного корня&amp;lt;br&amp;gt;&lt;br /&gt;
Отдельно после всех итераций при &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j=k&amp;lt;/math&amp;gt; :&lt;br /&gt;
*&amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(k^3)&amp;lt;/math&amp;gt; операций для поиска собственных значений и собственных векторов трёхдиагональной матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_k&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Итого можно утверждать следующее:&lt;br /&gt;
&lt;br /&gt;
Последовательная сложность одной итерации рассматриваемого алгоритма:  &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(n ^ 2) &amp;lt;/math&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Суммарная сложность алгоритма (&amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;/math&amp;gt; итераций): &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(k\,n ^ 2) + O(k ^ 3)&amp;lt;/math&amp;gt; &amp;lt;ref&amp;gt;Здесь мы полагаем, что мы не вычисляем собственные значения и векторы матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_j&amp;lt;/math&amp;gt; на каждом промежуточном шаге, а лишь единожды затрачиваем &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;O(k ^ 3)&amp;lt;/math&amp;gt; действий в конце для нахождения &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;/math&amp;gt; собственных значений и векторов матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_k&amp;lt;/math&amp;gt;&amp;lt;/ref&amp;gt; &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
На практике же обычно рассматривается число &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;&amp;lt;n&amp;lt;/math&amp;gt;, поэтому второе слагаемое можно опустить.&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
На рис. 1 продемонстрирован граф одной итерации (при каком-либо произвольном значении итератора &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j&amp;lt;/math&amp;gt;) описанного алгоритма без отображения входных и выходных данных. Наглядно продемонстрированы связи между всеми действиями, и с помощью деления на &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; потоков показано, какие операции возможно выполнять параллельно на каждом шаге с целью оптимизации и экономии машинного времени. В результате, после параллельно выполненных операций &#039;&#039;&#039;Division&#039;&#039;&#039; на заключительном ярусе, на выходе имеем значение следующего вектора Ланцоша &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;q_{j+1}&amp;lt;/math&amp;gt;, после чего следует переход на следующую итерацию, и процесс повторяется.&lt;br /&gt;
&lt;br /&gt;
[[Файл:Levin_graph.png|600px|thumb|center|Рис. 1  Структура одной итерации алгоритма]] &amp;lt;br&amp;gt;&lt;br /&gt;
Обозначения на рисунке: &amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Simp&#039;&#039;&#039; (от англ. simple) - операции сложения и умножения вещественных чисел при вычислении произведения матрицы на вектор;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Vec mult&#039;&#039;&#039; (от англ. vectors multiplication) - операция скалярного умножения двух векторов;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Vec subtr&#039;&#039;&#039; (от англ. vectors subtraction, из-за использованных в операции вычитаний векторов) - операция умножения вектора на число (выполняется дважды) и формирование нового значения &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;z_{new}&amp;lt;/math&amp;gt; по формуле: &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;z_{new} = z - \alpha_j q_j - \beta_{j-1}q_{j-1} \;&amp;lt;/math&amp;gt;;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;||\cdot||&amp;lt;/math&amp;gt; - операция вычисления нормы вектора;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Division&#039;&#039;&#039; - операция деления вектора на вещественное число  &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;\beta_j&amp;lt;/math&amp;gt; &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Важно отметить, что упомянутые выше операции также легко поддаются оптимизации. Например, попарные умножения вещественных координат векторов при вычислении скалярного произведения также легко выполняются параллельно на &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; потоках, а затем можно применить суммирование методом сдваивания, о котором сказано в следующем разделе. Умножение или деление вектора на вещественное число являющееся, по определению, умножением или делением всех его координат на это число тоже может быть выполнено эффективнее, если мы используем &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; потоков, а не выполняем эти действия последовательно.&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
Параллельные операции возможны только внутри итераций, так как рассматриваемый алгоритм является итерационным, и сами итерации строго последовательны.&amp;lt;br&amp;gt;&lt;br /&gt;
Рассмотрим в этом разделе подробнее, какой выигрыш мы можем получить при распараллеливании операций внутри одной итерации согласно графу из предыдущего раздела.&lt;br /&gt;
&lt;br /&gt;
Умножение вещественной симметричной матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; размера &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;n\times n&amp;lt;/math&amp;gt; на вектор &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;b&amp;lt;/math&amp;gt; длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; требует последовательного выполнения &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; ярусов умножений и сложений. Сложение элементов вектора длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; на каждом шаге перемножения можно оптимизировать и выполнить за &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;\log_2 n&amp;lt;/math&amp;gt; действий, если применять метод сдваивания.&lt;br /&gt;
&lt;br /&gt;
Дальнейшие операции выполняются последовательно, а вычисление значений векторов происходит за один ярус операций сложения или умножения.&lt;br /&gt;
&lt;br /&gt;
Ресурс параллелизма алгоритма вычисления собственных значений построенной трёхдиагональной матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_k&amp;lt;/math&amp;gt; размера &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k\times k&amp;lt;/math&amp;gt; зависит от выбранного алгоритма (об этих алгоритмах подробнее было сказано в разделах 1.2 и 1.4). Будет очень затратно с точки зрения объёма материала пытаться рассмотреть пусть даже часть этих методов в этой статье, а так же тонкости их распараллеливания. Предлагаем читателям при желании самим ознакомиться с этими алгоритмами на данном ресурсе или прибегнув к иным источникам.&lt;br /&gt;
&lt;br /&gt;
При классификации по высоте ЯПФ, таким образом, алгоритм Ланцоша без переортогонализации относится к алгоритмам с &#039;&#039;логарифмической сложностью&#039;&#039;, и его сложность равна &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(\log_2 n)&amp;lt;/math&amp;gt; с важным замечанием, что это сложность только одной итерации, а максимум в алгоритме может быть выполнено последовательно &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;/math&amp;gt; таких однотипных итераций, если не будет осуществлён ранний выход из цикла. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Несмотря на то, что на графе в предыдущем разделе для лучшей визуализации и понимания было изображено &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; потоков (никаких допущений мы не делали и нарушений с точки зрения логики и математики нет, можно изобразить большее число потоков, просто часть времени некоторые из них могут бездействовать и не использоваться), на самом деле правильным и разумным будет реализовать начальное параллельное выполнение &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n^2&amp;lt;/math&amp;gt; операций умножения всех вещественных элементов матрицы &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;A&amp;lt;/math&amp;gt; на соответствующие элементы вектора &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;q_j&amp;lt;/math&amp;gt;, после чего применять тот же самый упомянутый метод сдваивания. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Поэтому при классификации по ширине ЯПФ его сложность будет &#039;&#039;квадратичной&#039;&#039; и равна &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(n^2)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
&#039;&#039;&#039;Входные данные алгоритма:&#039;&#039;&#039; вещественная симметричная &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; размера &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;n\times n&amp;lt;/math&amp;gt;, вещественный вектор &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;b&amp;lt;/math&amp;gt; длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt;, и одно целое число &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;k&amp;lt;/math&amp;gt;, означающее количество итераций.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём входных данных:&#039;&#039;&#039; &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;n^2 +n + 1 &amp;lt;/math&amp;gt;. Если учесть, что матрица симметричная и достаточно для её однозначного определения задать элементы на главной диагонали и элементы над или под ней, то можно сократить объём входных данных с целью экономии памяти до: &amp;lt;math&amp;gt;\ \frac{n^2-n}{2}+n+n+1 =\frac{n^2+3n}{2} + 1&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные алгоритма:&#039;&#039;&#039; вектор собственных значений &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;\Theta^k&amp;lt;/math&amp;gt; длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;/math&amp;gt;, матрица &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;S^k&amp;lt;/math&amp;gt; из соответствующих собственных векторов размера &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n\times k&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём выходных данных:&#039;&#039;&#039; &amp;lt;math&amp;gt;k\;(n + 1)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
В данном разделе перечислены без какой-либо хронологии или связи друг с другом наиболее важные и разнообразные свойства алгоритма, на которые стоит и полезно обратить внимание, а также которые выгодно отличают его от схожих алгоритмов, решающих ту же задачу.&amp;lt;br&amp;gt;&lt;br /&gt;
1) Отношение последовательной сложности алгоритма к параллельной,с учётом &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;/math&amp;gt; итераций, равно &amp;lt;math&amp;gt;\;\;\frac{kn^2}{k \log_2{n}}=\frac{n^2}{\log_2{n}}&amp;lt;/math&amp;gt;;&amp;lt;br&amp;gt;&lt;br /&gt;
2) Вычислительная мощность алгоритма, как отношение числа операций к суммарному объему входных и выходных данных, равна &amp;lt;math style=&amp;quot;vertical-align:-70%&amp;gt;\;\;\frac{k\,n^2}{0.5\,n^2+1.5\,n+k\,n+k+1}&amp;lt;/math&amp;gt; и &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;\approx 2\,k&amp;lt;/math&amp;gt;, так как на практике верно отношение &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;&amp;lt;n&amp;lt;/math&amp;gt; ;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
3) Для собственных значений формируемых матриц &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_j&amp;lt;/math&amp;gt; верно отношение (следствие теоремы Коши о перемежаемости): &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;\lambda_i(T_{k+1})\geq \lambda_i(T_{k})\geq \lambda_{i+1}(T_{k+1})\geq \lambda_{i+1}(T_{k})&amp;lt;/math&amp;gt; ;&amp;lt;ref&amp;gt;James W. Demmel - Вычислительная линейная алгебра. Теория и приложения //Мир. - 2001 (c. 383)&amp;lt;/ref&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
4) Крайние (наибольшие и наименьшие) собственные значения матриц &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_j&amp;lt;/math&amp;gt; сходятся к крайним собственным значениям матрицы &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;A&amp;lt;/math&amp;gt; первыми (это часто происходит уже на ранних шагах при &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j\approx 2\,\sqrt{n}&amp;lt;/math&amp;gt;&amp;lt;ref&amp;gt;http://num-anal.srcc.msu.ru/lib_na/int_ae/int_ae6.htm (пункт 6.5)&amp;lt;/ref&amp;gt;), а собственные значения в середине спектра - последними;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
5) Из-за ограниченной точности постепенно теряется ортогональность вектора Ланцоша &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;q_j&amp;lt;/math&amp;gt; к предыдущим векторам Ланцоша, поэтому необходимо примерно каждые 10-15 итераций проводить дорогостоящую операцию реортогонализации, но это уже будет иной алгоритм с очень малым различием в одной операции и в программном коде, реализующем его, соответственно; &amp;lt;ref&amp;gt;Sam Handler - The Lanczos Algorithm For Large-Scale Eigenvalue Problems (08.01.07), slide №8&amp;lt;/ref&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
6) Эффективность и быстрота выполнения алгоритма очень сильно зависит от скорости памяти (диска). Согласно тесту только &#039;&#039;6%&#039;&#039; времени работы программы приходится на вычисления, остальное время затрачивается на ожидание отклика диска;&amp;lt;ref&amp;gt;Sam Handler - The Lanczos Algorithm For Large-Scale Eigenvalue Problems (08.01.07), slide №10&amp;lt;/ref&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
7) Метод Ланцоша удобен тем, что не требует хранения исходной матрицы полным массивом: метод использует исходную матрицу только в операциях умножения матрицы на вектор, что позволяет эффективно использовать разреженность матрицы или регулярность структуры матрицы. Поэтому метод Ланцоша может быть использован для матриц таких больших порядков, когда методы вращений и отражений не могут быть применены.&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;
Для исследования масштабируемости рассматриваемого алгоритма Ланцоша без переортогонализации автором была реализована программа на языке С++ с использованием технологии MPI. &amp;lt;ref&amp;gt;https://goo.gl/pNOFmW  или альтернативная ссылка с прикреплённым кодом: https://goo.gl/9AapM6 , по просьбе на почту я (автор статьи) готов предоставить желающим доступ к проекту с этим кодом на ресурсе Bitbucket&amp;lt;/ref&amp;gt; Дальнейшее исследование было проведено на суперкомпьютере &amp;quot;Ломоносов&amp;quot; Суперкомпьютерного комплекса МГУ.&amp;lt;ref&amp;gt;https://parallel.ru/cluster/lomonosov.html&amp;lt;/ref&amp;gt; &amp;lt;br&amp;gt; Важно отметить, что реализованная программа выполняет только первую часть алгоритма - формирование трёхдиагональной матрицы &amp;lt;math &amp;gt;T_j&amp;lt;/math&amp;gt;. Вторая часть алгоритма (задача поиска собственных значений матрицы &amp;lt;math &amp;gt;T_j&amp;lt;/math&amp;gt;) может быть решена несколькими методами, каждый из которых обладает своей эффективностью распараллеливания и характерными свойствами. Подробно этот вопрос уже обсуждался в статье ранее, поэтому не будем ещё раз заострять на этом внимание и останавливаться.&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Сборка осуществлялась со следующими параметрами:&lt;br /&gt;
* Компилятор intel/15.0.090 &lt;br /&gt;
* Openmpi/1.8.4-icc&lt;br /&gt;
В серии проведённых расчётов рассматривались следующие числовые значения параметров:&lt;br /&gt;
* Размер &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;n&amp;lt;/math&amp;gt; задачи и, соответственно, матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt;, задействованной в операции умножения на вектор: [2000 : 30000] с шагом 1000&lt;br /&gt;
* Число &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;p&amp;lt;/math&amp;gt; процессоров: 1, 2, 4, 16, 32, 48, 64, 96, 128, 192, 256&lt;br /&gt;
* Число итераций в алгоритме: &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k=350&amp;lt;/math&amp;gt;&lt;br /&gt;
Число &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; взято таким вопреки информации в начале статьи, где говорится, что значение &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; редко превышает &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;10^2&amp;lt;/math&amp;gt; (хоть мы и имеем право брать его любым по нашему усмотрению). Это сделано исключительно для лучшей визуализации пиков на графиках в данном разделе и наглядности получаемых результатов, так как при меньших на порядок значениях параметра &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; времена выполнения программ были слишком малы даже при минимальных числах процессоров и максимальных размерах &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;n&amp;lt;/math&amp;gt; задачи.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
На рис. 2 изображён график зависимости времени выполнения программы от числа процессоров и размера &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;n&amp;lt;/math&amp;gt; задачи. &amp;lt;br&amp;gt;&lt;br /&gt;
{|align=&amp;quot;center&amp;quot;&lt;br /&gt;
 |-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
 |[[file:Levin_task1_execTIME.png|620px|thumb|center|Рис. 2  График зависимости времени выполнения программы.]]&lt;br /&gt;
 |[[file:Levin604 task1 result EFFICIENCY.png|630px|thumb|center|Рис. 3  График зависимости эффективности распараллеливания программы.]]&lt;br /&gt;
|}&lt;br /&gt;
Многочисленные тесты показали при малых количествах ядер уменьшение времени выполнения программы почти в 2 раза при увеличении числа ядер в 2 раза на всём диапазоне размеров матриц, что и отражает сильный излом на первом графике. Изменение значений времени можно легко оценить по предоставленной цветовой шкале.&lt;br /&gt;
Был построен график эффективности распараллеливания (parallel efficiency) в зависимости от числа процессоров и размера задачи, изображённый на рис. 3.&lt;br /&gt;
Получены следующие результаты численных экспериментов:&lt;br /&gt;
* Средняя эффективность распараллеливания программы составила: 42.5576% ;&lt;br /&gt;
* Минимальная эффективность реализации: 0.674% (число процессоров 256 и минимальный размер матрицы 2000);&lt;br /&gt;
* Максимальная эффективность реализации: 77.773% (число процессоров 2, размер матрицы 20000).&lt;br /&gt;
Нужно понимать, что это лишь экстремумы, соответствующие двум экспериментам, которые сами по себе не дают полной картины и не позволяют однозначно судить о параллельных качествах алгоритма и реализующей его программы при столь большом числе параметров и проводимых расчётов. &amp;lt;br&amp;gt;На основании рис. 3 можно отметить следующие значимые и важные факты:&lt;br /&gt;
*Имеется ярко выраженный спад эффективности при минимальном рассматриваемом размере матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;n=2000&amp;lt;/math&amp;gt; вдоль всей оси OY, на которой отложено число процессоров;&lt;br /&gt;
*Присутствуют два пика эффективности (жёлтого цвета на рис. 3): при числе &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;p&amp;lt;/math&amp;gt; процессоров 2 и 128. Затем при дальнейшем увеличении числа процессоров с 128 до 256 наблюдается постепенное уменьшение эффективности реализации. Это связано с увеличением накладных расходов и затрат времени на обмен сообщениями между процессами.&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;
Перечислим далее некоторые из них, указывая язык программирования, лежащий в их основе, и некоторые важные характеристики, которые обсуждались в статье ранее:&lt;br /&gt;
*&#039;&#039;Code on netlib.org by Jane Cullum and Ralph Willoughby&#039;&#039; (&#039;&#039;&#039;Fortran 77&#039;&#039;&#039;; без реортогонализации векторов; без реализации распараллеливания)&amp;lt;ref&amp;gt;http://www.netlib.org/lanczos/leval&amp;lt;/ref&amp;gt;&lt;br /&gt;
*&#039;&#039;Lanczos algorithm on freesourcecode.net&#039;&#039; (&#039;&#039;&#039;Matlab&#039;&#039;&#039;; присутствует реортогонализация векторов; без реализации распараллеливания)&amp;lt;ref&amp;gt;http://freesourcecode.net/matlabprojects/61741/lanczos-algorithm--in-matlab&amp;lt;/ref&amp;gt;&lt;br /&gt;
*&#039;&#039;Lanczos for eigenvalues in Numerical Linear Algebra, Spring 2007&#039;&#039; (&#039;&#039;&#039;Matlab&#039;&#039;&#039;; частичная или полная реортогонализация - доступны оба варианта; без реализации распараллеливания)&amp;lt;ref&amp;gt;Ссылки на файлы lanso.m и lanfu.m можно найти на https://www.nada.kth.se/~ruhe/2D5219/labs2007.html&amp;lt;/ref&amp;gt;&lt;br /&gt;
*&#039;&#039;Planso&#039;&#039; (название происходит от parallel Lanso.f) &#039;&#039;code by Kesheng Wu and Horst D. Simon&#039;&#039; (&#039;&#039;&#039;Fortran 77&#039;&#039;&#039;; частичная реортогонализация векторов; использование MPI для коммуникаций)&amp;lt;ref&amp;gt;https://github.com/jiahao/planso.jl/tree/master/external/PLAN/plan К сожалению, ссылка в описании пакета на github, ведущая на сайт National Energy Research Scientific Computing Center (NERSC), с более подробной информацией о данной программе больше не активна и выдаёт результат &#039;&#039;Page not found&#039;&#039;&amp;lt;/ref&amp;gt; &lt;br /&gt;
* &#039;&#039;Lanczos.cpp in the Vienna Computing Library&#039;&#039;  (&#039;&#039;&#039;C++&#039;&#039;&#039;, частичная реортогонализация, без реализации распараллеливания) &amp;lt;ref&amp;gt;http://viennacl.sourceforge.net/doc/lanczos_8cpp_source.html&amp;lt;/ref&amp;gt;&lt;br /&gt;
* &#039;&#039;Parallel Eigen Values code using C++ AMP on microsoft msdn blog&#039;&#039; (&#039;&#039;&#039;C++&#039;&#039;&#039;; ? ; распараллеливание есть и реализовано через C++ AMP) &amp;lt;ref&amp;gt;https://blogs.msdn.microsoft.com/nativeconcurrency/2013/12/20/eigen-values/ Подробнее о C++ Accelerated Massive Parallelism можно почитать здесь: https://msdn.microsoft.com/ru-ru/library/hh265137(v=vs.140).aspx или здесь: http://professorweb.ru/my/csharp/optimization/level4/4_6.php &amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;br /&gt;
[[en:Description of algorithm properties and structure]]&lt;/div&gt;</summary>
		<author><name>AleksLevin</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:AleksLevin/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%9B%D0%B0%D0%BD%D1%86%D0%BE%D1%88%D0%B0_%D0%B2%D1%8B%D1%87%D0%B8%D1%81%D0%BB%D0%B5%D0%BD%D0%B8%D1%8F_%D1%81%D0%BE%D0%B1%D1%81%D1%82%D0%B2%D0%B5%D0%BD%D0%BD%D1%8B%D1%85_%D0%B7%D0%BD%D0%B0%D1%87%D0%B5%D0%BD%D0%B8%D0%B9_%D1%81%D0%B8%D0%BC%D0%BC%D0%B5%D1%82%D1%80%D0%B8%D1%87%D0%BD%D0%BE%D0%B9_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86%D1%8B_%D0%B4%D0%BB%D1%8F_%D1%82%D0%BE%D1%87%D0%BD%D0%BE%D0%B9_%D0%B0%D1%80%D0%B8%D1%84%D0%BC%D0%B5%D1%82%D0%B8%D0%BA%D0%B8_(%D0%B1%D0%B5%D0%B7_%D0%BF%D0%B5%D1%80%D0%B5%D0%BE%D1%80%D1%82%D0%BE%D0%B3%D0%BE%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D0%B8)&amp;diff=20274</id>
		<title>Участник:AleksLevin/Алгоритм Ланцоша вычисления собственных значений симметричной матрицы для точной арифметики (без переортогонализации)</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:AleksLevin/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%9B%D0%B0%D0%BD%D1%86%D0%BE%D1%88%D0%B0_%D0%B2%D1%8B%D1%87%D0%B8%D1%81%D0%BB%D0%B5%D0%BD%D0%B8%D1%8F_%D1%81%D0%BE%D0%B1%D1%81%D1%82%D0%B2%D0%B5%D0%BD%D0%BD%D1%8B%D1%85_%D0%B7%D0%BD%D0%B0%D1%87%D0%B5%D0%BD%D0%B8%D0%B9_%D1%81%D0%B8%D0%BC%D0%BC%D0%B5%D1%82%D1%80%D0%B8%D1%87%D0%BD%D0%BE%D0%B9_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86%D1%8B_%D0%B4%D0%BB%D1%8F_%D1%82%D0%BE%D1%87%D0%BD%D0%BE%D0%B9_%D0%B0%D1%80%D0%B8%D1%84%D0%BC%D0%B5%D1%82%D0%B8%D0%BA%D0%B8_(%D0%B1%D0%B5%D0%B7_%D0%BF%D0%B5%D1%80%D0%B5%D0%BE%D1%80%D1%82%D0%BE%D0%B3%D0%BE%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D0%B8)&amp;diff=20274"/>
		<updated>2016-12-07T19:13:02Z</updated>

		<summary type="html">&lt;p&gt;AleksLevin: /* Масштабируемость алгоритма и его реализации */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Основные авторы описания: Левин А.Д.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{algorithm&lt;br /&gt;
| name              = Алгоритм Ланцоша для точной арифметики (без переортогонализации)&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(k\,n^2)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(k\log_2 n)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;\frac{n^2+3n}{2} + 1&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;k\;(n + 1)&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритмов =&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Данный алгоритм появился в 1950 г. и носит имя венгерского физика и математика Корнелия Ланцоша (венг. Lánczos Kornél). Алгоритм Ланцоша относится к итерационным методам вычисления собственных значений для матриц столь больших порядков &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt; n&amp;lt;/math&amp;gt;, что к ним нельзя применить прямые методы из-за ограничений по времени и памяти.&lt;br /&gt;
&lt;br /&gt;
Сам Ланцош указывал, что его метод предназначен для отыскания нескольких собственных векторов симметричных матриц, хотя к методу сразу было обращено внимание, как к способу приведения всей матрицы к трёхдиагональному виду. Двадцатью годами позже канадский математик Крис Пэж показал, что, несмотря на чувствительность к округлениям, алгоритм Ланцоша - эффективное средство вычисления некоторых &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; собственных чисел и соответствующих им собственных векторов. &amp;lt;ref&amp;gt;Парлетт Б. - Симметричная проблема собственных значений. Численные методы //М.: Мир. - 1983. (c. 276)&amp;lt;/ref&amp;gt;&lt;br /&gt;
Обычно число &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; берут в два раза больше, чем количество собственных значений матрицы, которые поставлена цель найти, и оно имеет порядок не более &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;10^2&amp;lt;/math&amp;gt;.&amp;lt;ref&amp;gt;Susan W. Bostic - Lanczos Eigensolution Method for High-Perfomance Computers, page 7&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Алгоритм Ланцоша для вычисления собственных значений симметричной матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; соединяет в себе метод Ланцоша для построения последовательности подпространств Крылова и ортонормированных векторов Ланцоша и процедуру Рэлея-Ритца получения оптимальных приближений собственных значений и соответствующих собственных векторов исходной матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt;.&amp;lt;ref&amp;gt;James W. Demmel - Вычислительная линейная алгебра. Теория и приложения //Мир. - 2001 (c. 381)&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
В данной статье рассматривается вариант алгоритма Ланцоша, в котором опущено влияние ошибок округления на вычислительный процесс, хотя на практике этому посвящается отдельное внимание и существуют различные методы решения данной проблемы, такие как частичная или полная переортогонализация. Этим модифицированным методам посвящены отдельные статьи на данном ресурсе.&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
Обозначения и формулы, используемые в данном разделе, взяты из литературы, указанной по ссылке.&amp;lt;ref&amp;gt;James W. Demmel - Вычислительная линейная алгебра. Теория и приложения //Мир. - 2001 (c. 313, &#039;&#039;&amp;lt;math&amp;gt; \S &amp;lt;/math&amp;gt; 6.6 Методы Крыловского подпространства&#039;&#039;)&amp;lt;/ref&amp;gt; &lt;br /&gt;
&lt;br /&gt;
Алгоритм Ланцоша для вычисления &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; собственных значений и собственных векторов вещественной симметричной матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A=A^T&amp;lt;/math&amp;gt; в точной арифметике: &amp;lt;ref&amp;gt;James W. Demmel - Вычислительная линейная алгебра. Теория и приложения //Мир. - 2001 (c. 381)&amp;lt;/ref&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{align}&lt;br /&gt;
q_1 = &amp;amp; \,\frac{b}{\|b\|_2},\; \beta_0 = 0,\; q_0 = 0\\&lt;br /&gt;
\mathbf{for} \; &amp;amp; j = 1 \; to \; k \,\; \mathbf{do} \\&lt;br /&gt;
&amp;amp; z = A\,q_j\\&lt;br /&gt;
&amp;amp; \alpha_j = q^T_j z\\&lt;br /&gt;
&amp;amp; z = z - \alpha_j q_j - \beta_{j-1}q_{j-1}\\&lt;br /&gt;
&amp;amp; \beta_j = \|z\|_2\\&lt;br /&gt;
&amp;amp; \mathbf{If} \; (\beta_j == 0) \; \mathbf{then}\; stop\; the\; algorithm \\ &lt;br /&gt;
&amp;amp; \;  q_{j+1} = \frac{z}{\beta_j} \\&lt;br /&gt;
&amp;amp; compute\; eigenvalues\; and \;eigenvectors\;of \;matrix \;\;T_j= Q^T_j A Q\;\;and\;estimate \;the\; errors\\&lt;br /&gt;
\mathbf{end} \; &amp;amp; \mathbf{for}&lt;br /&gt;
\end{align}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
В продемонстрированном выше алгоритме &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;b&amp;lt;/math&amp;gt; - заданный вещественный вектор. Также полагается известным алгоритм вычисления произведения матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; на вектор &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;x&amp;lt;/math&amp;gt;. &lt;br /&gt;
Введём матрицу Крылова, определяемую следующим соотношением: &amp;lt;math&amp;gt;K_j = [b,Ab,A^2b,...,A^{j-1}b]&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Далее, на практике, матрица &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;K&amp;lt;/math&amp;gt; заменяется матрицей &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;Q&amp;lt;/math&amp;gt;, такой, что при любом числе &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; линейные оболочки первых &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; столбцов в &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;K&amp;lt;/math&amp;gt; и &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;Q&amp;lt;/math&amp;gt; являются одним и тем же подпространством.&amp;lt;ref&amp;gt;James W. Demmel - Вычислительная линейная алгебра. Теория и приложения //Мир. - 2001 (c. 315)&amp;lt;/ref&amp;gt; &lt;br /&gt;
Тогда матрица &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;Q&amp;lt;/math&amp;gt;, в отличие от матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;K&amp;lt;/math&amp;gt;, хорошо обусловлена и легко обратима. В результате получаем матрицу &amp;lt;math&amp;gt;Q_j = [q_1, q_2, \dots, q_j]&amp;lt;/math&amp;gt; размерности &amp;lt;math&amp;gt;n\times j&amp;lt;/math&amp;gt;, столбцы которой ортогональны, являются базисом подпространства Крылова и называются векторами Ланцоша.&lt;br /&gt;
&lt;br /&gt;
В алгоритме Ланцоша вычислению подлежит столько первых столбцов в матрице &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;Q_j&amp;lt;/math&amp;gt;, сколько необходимо для получения требуемого приближения к решению &amp;lt;math&amp;gt;A\,x\,=b\,\,(A\,x=\lambda \, x)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Получение нулевого &amp;lt;math&amp;gt;\beta_j&amp;lt;/math&amp;gt; в итерационном процессе - событие, желательное в том смысле, что оно свидетельствует о том, что найдено некоторое подпространство, являющееся в точности инвариантным, а все собственные значения матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;T_j&amp;lt;/math&amp;gt; являются собственными значениями матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt;. На практике же нулевое и близкие к нулю значения получаются редко.&amp;lt;ref&amp;gt;Голуб Дж., Ван Лоун Ч. - Матричные вычисления//М.: Мир. - 1999 (c. 429)&amp;lt;/ref&amp;gt; &lt;br /&gt;
&lt;br /&gt;
Затем на каждом шаге цикла формируется симметричная трёхдиагональная матрица &amp;lt;math&amp;gt;T_j = Q^T_j A Q&amp;lt;/math&amp;gt;, к которой применяется процесс Рэлея-Ритца для поиска её собственных значений (на практике для поиска этих собственных значений можно использовать любой из специальных методов в параграфе книги по ссылке).&amp;lt;ref&amp;gt;Голуб Дж., Ван Лоун Ч. - Матричные вычисления//М.: Мир. - 1999 (&amp;lt;math&amp;gt;\S&amp;lt;/math&amp;gt; 8.4)&amp;lt;/ref&amp;gt;  &lt;br /&gt;
Эти собственные значения, они же числа Ритца, и полагаются приближёнными собственными значениями исходной матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt;.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Существует множество методов для отыскания собственных значений вещественной симметричной трехдиагональной матрицы. Большинство из них требует &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt; операций &amp;lt;ref&amp;gt;Парлетт Б. Симметричная проблема собственных значений. Численные методы.,: Мир, 1983. с. 179-182&amp;lt;/ref&amp;gt;, но существуют и быстрые алгоритмы, требующие лишь &amp;lt;math&amp;gt;O(n\ln n)&amp;lt;/math&amp;gt; операций.&amp;lt;ref&amp;gt;https://en.wikipedia.org/wiki/Tridiagonal_matrix#Eigenvalues  Раздел eigenvalues&amp;lt;/ref&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Одним из возможных способов отыскать собственные значения симметричной трехдиагональной матрицы - прямое вычисление корней характеристического полинома &amp;lt;math&amp;gt;p_n(\lambda)&amp;lt;/math&amp;gt; через метод деления пополам, где формируется последовательность Штурма и локализуются собственные числа, являющиеся корнями характеристического полинома. Нахождение всех &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; собственных значений матрицы этим способом требует &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;2n^2t&amp;lt;/math&amp;gt; умножений и вычитаний, где &amp;lt;math&amp;gt;t&amp;lt;/math&amp;gt; - число сделанных шагов с применением метода деления пополам.&amp;lt;ref&amp;gt;Уилкинсон Дж. X. Алгебраическая проблема собственныx значений. Изд-во &amp;quot;Наука&amp;quot;, 1970. - глава 5, с. 272-278&amp;lt;/ref&amp;gt; Соответствующие собственные вектора могут быть найдены посредством обратных итераций за &amp;lt;math&amp;gt; O(n) &amp;lt;/math&amp;gt; флопов. &amp;lt;ref&amp;gt;Голуб Дж., Ван Лоун Ч. - Матричные вычисления//М.: Мир. - 1999 (c. 394-395)&amp;lt;/ref&amp;gt; &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;На практике, если требуется только небольшая часть от всей совокупности собственных векторов и значений, и матрица имеет Хессенбергову или трёхдиагональную форму, очень эффективными будут методы факторизации, как, например, QR-алгоритм или QL-алгоритм со сдвигами (c целью ускорить алгоритм и сделать порядок сходимости квадратичным) или же без них.&amp;lt;ref&amp;gt;http://algorithm.narod.ru/ln/eigen/ETridiag.html&amp;lt;/ref&amp;gt; &amp;lt;br&amp;gt;&lt;br /&gt;
Весьма молодые и не менее актуальные конкуренты QR и QL алгоритмов, применяющиеся для поиска собственных значений:&lt;br /&gt;
*Методы divide-and-conquer (разделяй и властвуй), появившиеся в 1980-ых годах &amp;lt;ref&amp;gt;https://goo.gl/dapvbn ссылку пришлось сократить с помощью Google url shortener, так как символы подчеркивания портили её и не давали перейти по 1 клику&amp;lt;/ref&amp;gt;&lt;br /&gt;
*Relatively robust representation методы, появившиеся в 1990-ых и позволяющие найти собственные числа симметричной матрицы порядка &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;n&amp;lt;/math&amp;gt; за &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt; операций&lt;br /&gt;
&lt;br /&gt;
Если требуется вычислить собственные векторы, то необходимо хранить вычисляемые векторы Ланцоша. Если работа при этом производится только с оперативной памятью, то при большом порядке исходной матрицы (а именно для таких матриц и предназначен метод Ланцоша) число шагов  &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;j&amp;lt;/math&amp;gt;, которые могут быть выполнены до того момента, как оперативная память будет исчерпана, будет очень незначительно, а следовательно, искомые собственные пары могут не успеть сойтись с требуемой точностью. В этом случае метод Ланцоша можно использовать итерационным образом: после выполнения заданного числа шагов процесс прерывается и, если еще не все требуемые пары Ритца сошлись с требуемой точностью, то формируется новый начальный вектор &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;q_1&amp;lt;/math&amp;gt;, являющийся линейной комбинацией векторов Ритца, еще не сошедшихся с заданной точностью, и процесс начинается заново.&amp;lt;ref&amp;gt;http://num-anal.srcc.msu.ru/lib_na/int_ae/int_ae6.htm (пункт 6.5)&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
Вычислительное ядро рассматриваемого алгоритма (наиболее ресурсно-затратная часть алгоритма) -  формирование на каждом шаге цикла промежуточного вектора &amp;lt;math&amp;gt;z&amp;lt;/math&amp;gt;, вычисляемого по формуле: &amp;lt;math&amp;gt;z = A\,q_j&amp;lt;/math&amp;gt;. Данная операция, по сравнению с другими операциями алгоритма, затратна и требовательна, как с точки зрения количества производимых операций, так и с точки зрения объема оперируемых данных. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Например, умножение матрицы размера &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;n\times n&amp;lt;/math&amp;gt; на вектор длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; требует: &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;n^2+(n-1)n = 2n^2-n&amp;lt;/math&amp;gt; операций умножения и сложения. В свою очередь аналогичная операция умножения матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;(n+1)\times (n+1)&amp;lt;/math&amp;gt; на вектор длины &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;(n+1)&amp;lt;/math&amp;gt; требует: &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;2n^2+3n+1&amp;lt;/math&amp;gt;  операций умножения и сложения. То есть повышение размерности задачи всего на 1 увеличивает число необходимых действий в этом шаге алгоритма на: &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;4n+1&amp;lt;/math&amp;gt;. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Так же, стоит помнить, что, согласно разделу 1.2, данную операцию умножения матрицы на вектор необходимо выполнить &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;k&amp;lt;/math&amp;gt; раз. Нетрудно понять, насколько возрастает и колоссален масштаб операций, если в задачах, где критична точность, размерности &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; могут иметь порядок &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;10^5&amp;lt;/math&amp;gt; или даже более.&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
Как уже было упомянуто в данной статье в описании алгоритма, рассматриваемый алгоритм состоит из двух последовательно выполненных алгоритмов: метод Ланцоша для построения последовательности подпространств Крылова и ортонормированных векторов Ланцоша и процедура Рэлея-Ритца получения оптимальных приближений собственных значений и соответствующих собственных векторов исходной матрицы.&lt;br /&gt;
&lt;br /&gt;
В первой части алгоритма, где итерационно строятся Крыловское подпространство и трёхдиагональная матрица &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&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 style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; разреженная. Именно она подлежит оптимизации с использованием техник распараллеливания, поскольку она является вычислительным ядром алгоритма, а весь упомянутый процесс построения матрицы &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&amp;lt;/math&amp;gt; выполняется последовательно.&lt;br /&gt;
&lt;br /&gt;
Рассмотрим вторую часть алгоритма - поиск собственных значений сформированной матрицы &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&amp;lt;/math&amp;gt;.&amp;lt;br&amp;gt;&lt;br /&gt;
Далее, наглядно, в виде псевдокода, представлен, упомянутый в разделе 1.2, QR-алгоритм (аналогично можно рассмотреть и QL-алгоритм) со сдвигами Релэя, который весьма популярен на практике.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{align}&lt;br /&gt;
\mathbf{Input}: \;&amp;amp;tridiagonal\;\;matrix \;T\;with\;\;n\times n\;\;size\\&lt;br /&gt;
T^{(0)}&amp;amp;:=T\\&lt;br /&gt;
\mathbf{for}&amp;amp; \;\;m=n,...,2 \;\; \mathbf{do}\\&lt;br /&gt;
&amp;amp;k=0\\&lt;br /&gt;
&amp;amp; \mathbf{repeat}\\&lt;br /&gt;
&amp;amp; \quad \;\; k=k+1\\&lt;br /&gt;
&amp;amp; \quad \;\; \mu^{(k)}=T_{m,m}^{(k-1)}\\&lt;br /&gt;
&amp;amp; \quad \;\; Q^{(k)}R^{(k)}=T^{(k-1)}-\mu^{(k)}I\;\;using\;\;QR\;decomposition\\&lt;br /&gt;
&amp;amp; \quad \;\; T^{(k)}=R^{(k)}Q^{(k)}+\mu^{(k)}I\\&lt;br /&gt;
&amp;amp; \mathbf{until} \;\;\; |T_{m,m-1}^{(k)}| \;is\;\;small\;\;enough\\&lt;br /&gt;
&amp;amp; Save  \;\;T_{m,m}^{(k)} \;\;as\;\; converged\;\;eigenvalue\;of\;T\\ &lt;br /&gt;
&amp;amp; Remove \;\boldsymbol{n}\,th\;row\;and\;\boldsymbol{n}\,th\;column\;\;from \;T \\&lt;br /&gt;
&amp;amp; and\;take\;this\;new\;cropped\;matrix\;as\;new\;T^{(0)}\;with\;\;(n-1)\times (n-1)\;\;size\\&lt;br /&gt;
 \mathbf{end}&amp;amp;\; \mathbf{for}&lt;br /&gt;
\end{align}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Малость наддиагональных и поддиагональных элементов матрицы (фраза &#039;&#039;&amp;quot;small enough&amp;quot;&#039;&#039; в псевдокоде) подразумевает:&lt;br /&gt;
&amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt; |T_{m,m-1}^{(k)}| \leq \varepsilon\,|T_{m,m}^{(k)}| \quad\quad &amp;lt;/math&amp;gt; , где &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt; \varepsilon &amp;lt;/math&amp;gt; - заданная точность&amp;lt;br&amp;gt;&lt;br /&gt;
Также вместо сдвига Релэя, обозначенного в алгоритме через &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;\mu^{(k)}&amp;lt;/math&amp;gt;, часто на практике используется сдвиг по Уилкинсону, который даёт гарантированную сходимость внедиагональных элементов матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt; T^{(k)} &amp;lt;/math&amp;gt;, формируемой на каждом шаге, к нулю, при этом жертвуя монотонностью их убывания.&amp;lt;ref&amp;gt;Голуб Дж., Ван Лоун Ч. - Матричные вычисления//М.: Мир. - 1999 (c. 378, вторая половина страницы)&amp;lt;/ref&amp;gt;&amp;lt;ref&amp;gt;Парлетт Б. Симметричная проблема собственных значений. Численные методы.,: Мир, 1983. с. 169&amp;lt;/ref&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Подробнее с различными сдвигами и соответствующими оценками скоростей и количествами операций можно ознакомиться по указанной ссылке:&amp;lt;ref&amp;gt;Парлетт Б. Симметричная проблема собственных значений. Численные методы.,: Мир, 1983. с. 179-182&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;Для совершения QR-декомпозиции на каждом шаге может использоваться любой из алгоритмов по ссылке.&amp;lt;ref&amp;gt;https://en.wikipedia.org/wiki/QR_decomposition&amp;lt;/ref&amp;gt; Подробные описания этих алгоритмов также доступны на данном ресурсе algowiki-project.&amp;lt;br&amp;gt;&lt;br /&gt;
Так как мы оперируем не обычной матрицей и даже не Хессенберговой, а симметричной и трёхдиагональной, то скорость таких алгоритмов значительно возрастёт. Например, согласно данному ресурсу &amp;lt;ref&amp;gt;http://algorithm.narod.ru/ln/eigen/ETridiag.html&amp;lt;/ref&amp;gt;, для QL-алгоритма с неявными сдвигами:&amp;lt;br&amp;gt;&lt;br /&gt;
Для трёхдиагональной матрицы объем арифметических действий составляет &amp;lt;math&amp;gt; O(n)&amp;lt;/math&amp;gt; на одну итерацию вместо &amp;lt;math&amp;gt; O(n^3)&amp;lt;/math&amp;gt; для матрицы общего вида, а число итераций для нахождения первых собственных значений примерно равно 4 - 5. Но на этих итерациях также уменьшаются внедиагональные элементы правого нижнего угла. И, таким образом, дальнейшие собственные значения ищутся значительно быстрее. Среднее число итераций на каждое собственное значение обычно составляет 1.3 - 1.6.&amp;lt;br&amp;gt; &lt;br /&gt;
Аналогично QL, QR-разложение трёхдиагольной матрицы также требует &amp;lt;math&amp;gt; O(n)&amp;lt;/math&amp;gt; флопов&amp;lt;ref&amp;gt;Голуб Дж., Ван Лоун Ч. - Матричные вычисления//М.: Мир. - 1999 (c. 378, начало раздела 8.2.2)&amp;lt;/ref&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Подводя итог, во второй части алгоритма Ланцоша можно выделить следующие макрооперации:&lt;br /&gt;
* умножение матрицы на вещественное число;&lt;br /&gt;
* перемножение матриц;&lt;br /&gt;
* умножение и сравнение вещественных чисел;&lt;br /&gt;
* + набор других макроопераций в зависимости от выбора метода, с помощью которого будет совершаться сама QR или QL-декомпозиция (выше продемонстрированы, уже, как минимум, 3 разных способа).&lt;br /&gt;
Так же, важно заметить, что набор макропераций может быть несколько другим, если выбрать какой-либо иной современный метод поиска собственных чисел трёхдиагональной матрицы, не использующий QR и QL разложения(факторизацию). Два таких метода были упомянуты в пункте 1.2.&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
С целью полностью не дублировать раздел 1.2 данной статьи, где представлен наглядный и доступный для понимания псевдокод алгоритма, постараемся лишь коротко просуммировать и обобщить весь перечень последовательных действий в рассматриваемом алгоритме.&lt;br /&gt;
&lt;br /&gt;
В качестве входных данных имеем: вещественная симметричная матрица &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; размера &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;n\times n&amp;lt;/math&amp;gt;, известный вещественный вектор &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;b&amp;lt;/math&amp;gt; длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; и число &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;n&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Далее:&lt;br /&gt;
* Инициализируем вещественную константу &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;\beta_0&amp;lt;/math&amp;gt; и векторы &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;q_0&amp;lt;/math&amp;gt; и &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;q_1&amp;lt;/math&amp;gt;&lt;br /&gt;
* Итерационно для всех &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j=1,...,k&amp;lt;/math&amp;gt;:&lt;br /&gt;
** Вычисляем вспомогательный вектор &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt;, используя умножение матрицы на вектор&lt;br /&gt;
** Вычисляем, используя скалярное произведение векторов, значение &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;\alpha_j&amp;lt;/math&amp;gt; - элемент на главной диагонали трёхдиагональной матрицы &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&amp;lt;/math&amp;gt;&lt;br /&gt;
** Вычисляем по формуле новое значение и перезаписываем вектор &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt;&lt;br /&gt;
** Вычисляем значение &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;\beta_j&amp;lt;/math&amp;gt; - элементы непосредственно над и под главной диагональю той же матрицы &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&amp;lt;/math&amp;gt;&lt;br /&gt;
** Вычисляем, зная вектор &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt;,  очередной столбец матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;Q&amp;lt;/math&amp;gt;, он же вектор Ланцоша : &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;\,\,q_{j+1}&amp;lt;/math&amp;gt;&lt;br /&gt;
** Теперь, когда матрица &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&amp;lt;/math&amp;gt; сформирована на очередном шаге, находим её собственные значения и вектора любым доступным способом, о чём было подробно сказано в пункте 1.2&lt;br /&gt;
** Переходим на следующую итерацию: &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j&amp;lt;/math&amp;gt;++&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
Оценим количество операций и сложность последовательного алгоритма, изложенного в предыдущем разделе.&lt;br /&gt;
*Для вычисления вектора &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt; умножается матрица размера &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;n\times n&amp;lt;/math&amp;gt; на вектор длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt;, и потребуется &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n^2&amp;lt;/math&amp;gt; операций умножения и &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n^2&amp;lt;/math&amp;gt; операций сложения.&lt;br /&gt;
*Умножение векторов &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;q^T_j&amp;lt;/math&amp;gt; и &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt; длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; потребует &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; операций умножения и &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; операций сложения.&lt;br /&gt;
*При вычислении нового значения вектора &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt; поэлементное сложение двух векторов длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; требует &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; операций сложения.&lt;br /&gt;
*Умножение вектора длины &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; на вещественное число требует &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; операций умножения.&lt;br /&gt;
*Нахождение квадратичной нормы вектора &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt;  длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; требует &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; умножений и &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; сложений и ещё 1 операцию извлечения квадратного корня.&lt;br /&gt;
*Заключительное нахождение собственных значений и собственных векторов трёхдиагональной матрицы &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;T_j&amp;lt;/math&amp;gt; размера &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j\times j&amp;lt;/math&amp;gt; с помощью QR-алгоритма потребует в худшем случае &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(j^3)&amp;lt;/math&amp;gt; операций.&amp;lt;ref&amp;gt;http://num-anal.srcc.msu.ru/lib_na/int_ae/int_ae6.htm (пункт 6.2, &amp;quot;Скорость сходимости при этом всегда не хуже квадратичной и почти всегда лучше кубической.&amp;quot;)&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Посчитаем теперь суммарное количество простейших операций на одной итерации алгоритма (без учёта записей в память):&lt;br /&gt;
*&amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n^2+5\,n&amp;lt;/math&amp;gt; операций умножения/деления&lt;br /&gt;
*&amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n^2+4\,n&amp;lt;/math&amp;gt; операций сложения/вычитания&lt;br /&gt;
*1 операция извлечения квадратного корня&amp;lt;br&amp;gt;&lt;br /&gt;
Отдельно после всех итераций при &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j=k&amp;lt;/math&amp;gt; :&lt;br /&gt;
*&amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(k^3)&amp;lt;/math&amp;gt; операций для поиска собственных значений и собственных векторов трёхдиагональной матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_k&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Итого можно утверждать следующее:&lt;br /&gt;
&lt;br /&gt;
Последовательная сложность одной итерации рассматриваемого алгоритма:  &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(n ^ 2) &amp;lt;/math&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Суммарная сложность алгоритма (&amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;/math&amp;gt; итераций): &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(k\,n ^ 2) + O(k ^ 3)&amp;lt;/math&amp;gt; &amp;lt;ref&amp;gt;Здесь мы полагаем, что мы не вычисляем собственные значения и векторы матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_j&amp;lt;/math&amp;gt; на каждом промежуточном шаге, а лишь единожды затрачиваем &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;O(k ^ 3)&amp;lt;/math&amp;gt; действий в конце для нахождения &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;/math&amp;gt; собственных значений и векторов матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_k&amp;lt;/math&amp;gt;&amp;lt;/ref&amp;gt; &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
На практике же обычно рассматривается число &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;&amp;lt;n&amp;lt;/math&amp;gt;, поэтому второе слагаемое можно опустить.&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
На рис. 1 продемонстрирован граф одной итерации (при каком-либо произвольном значении итератора &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j&amp;lt;/math&amp;gt;) описанного алгоритма без отображения входных и выходных данных. Наглядно продемонстрированы связи между всеми действиями, и с помощью деления на &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; потоков показано, какие операции возможно выполнять параллельно на каждом шаге с целью оптимизации и экономии машинного времени. В результате, после параллельно выполненных операций &#039;&#039;&#039;Division&#039;&#039;&#039; на заключительном ярусе, на выходе имеем значение следующего вектора Ланцоша &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;q_{j+1}&amp;lt;/math&amp;gt;, после чего следует переход на следующую итерацию, и процесс повторяется.&lt;br /&gt;
&lt;br /&gt;
[[Файл:Levin_graph.png|600px|thumb|center|Рис. 1  Структура одной итерации алгоритма]] &amp;lt;br&amp;gt;&lt;br /&gt;
Обозначения на рисунке: &amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Simp&#039;&#039;&#039; (от англ. simple) - операции сложения и умножения вещественных чисел при вычислении произведения матрицы на вектор;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Vec mult&#039;&#039;&#039; (от англ. vectors multiplication) - операция скалярного умножения двух векторов;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Vec subtr&#039;&#039;&#039; (от англ. vectors subtraction, из-за использованных в операции вычитаний векторов) - операция умножения вектора на число (выполняется дважды) и формирование нового значения &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;z_{new}&amp;lt;/math&amp;gt; по формуле: &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;z_{new} = z - \alpha_j q_j - \beta_{j-1}q_{j-1} \;&amp;lt;/math&amp;gt;;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;||\cdot||&amp;lt;/math&amp;gt; - операция вычисления нормы вектора;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Division&#039;&#039;&#039; - операция деления вектора на вещественное число  &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;\beta_j&amp;lt;/math&amp;gt; &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Важно отметить, что упомянутые выше операции также легко поддаются оптимизации. Например, попарные умножения вещественных координат векторов при вычислении скалярного произведения также легко выполняются параллельно на &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; потоках, а затем можно применить суммирование методом сдваивания, о котором сказано в следующем разделе. Умножение или деление вектора на вещественное число являющееся, по определению, умножением или делением всех его координат на это число тоже может быть выполнено эффективнее, если мы используем &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; потоков, а не выполняем эти действия последовательно.&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
Параллельные операции возможны только внутри итераций, так как рассматриваемый алгоритм является итерационным, и сами итерации строго последовательны.&amp;lt;br&amp;gt;&lt;br /&gt;
Рассмотрим в этом разделе подробнее, какой выигрыш мы можем получить при распараллеливании операций внутри одной итерации согласно графу из предыдущего раздела.&lt;br /&gt;
&lt;br /&gt;
Умножение вещественной симметричной матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; размера &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;n\times n&amp;lt;/math&amp;gt; на вектор &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;b&amp;lt;/math&amp;gt; длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; требует последовательного выполнения &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; ярусов умножений и сложений. Сложение элементов вектора длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; на каждом шаге перемножения можно оптимизировать и выполнить за &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;\log_2 n&amp;lt;/math&amp;gt; действий, если применять метод сдваивания.&lt;br /&gt;
&lt;br /&gt;
Дальнейшие операции выполняются последовательно, а вычисление значений векторов происходит за один ярус операций сложения или умножения.&lt;br /&gt;
&lt;br /&gt;
Ресурс параллелизма алгоритма вычисления собственных значений построенной трёхдиагональной матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_k&amp;lt;/math&amp;gt; размера &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k\times k&amp;lt;/math&amp;gt; зависит от выбранного алгоритма (об этих алгоритмах подробнее было сказано в разделах 1.2 и 1.4). Будет очень затратно с точки зрения объёма материала пытаться рассмотреть пусть даже часть этих методов в этой статье, а так же тонкости их распараллеливания. Предлагаем читателям при желании самим ознакомиться с этими алгоритмами на данном ресурсе или прибегнув к иным источникам.&lt;br /&gt;
&lt;br /&gt;
При классификации по высоте ЯПФ, таким образом, алгоритм Ланцоша без переортогонализации относится к алгоритмам с &#039;&#039;логарифмической сложностью&#039;&#039;, и его сложность равна &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(\log_2 n)&amp;lt;/math&amp;gt; с важным замечанием, что это сложность только одной итерации, а максимум в алгоритме может быть выполнено последовательно &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;/math&amp;gt; таких однотипных итераций, если не будет осуществлён ранний выход из цикла. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Несмотря на то, что на графе в предыдущем разделе для лучшей визуализации и понимания было изображено &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; потоков (никаких допущений мы не делали и нарушений с точки зрения логики и математики нет, можно изобразить большее число потоков, просто часть времени некоторые из них могут бездействовать и не использоваться), на самом деле правильным и разумным будет реализовать начальное параллельное выполнение &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n^2&amp;lt;/math&amp;gt; операций умножения всех вещественных элементов матрицы &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;A&amp;lt;/math&amp;gt; на соответствующие элементы вектора &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;q_j&amp;lt;/math&amp;gt;, после чего применять тот же самый упомянутый метод сдваивания. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Поэтому при классификации по ширине ЯПФ его сложность будет &#039;&#039;квадратичной&#039;&#039; и равна &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(n^2)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
&#039;&#039;&#039;Входные данные алгоритма:&#039;&#039;&#039; вещественная симметричная &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; размера &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;n\times n&amp;lt;/math&amp;gt;, вещественный вектор &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;b&amp;lt;/math&amp;gt; длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt;, и одно целое число &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;k&amp;lt;/math&amp;gt;, означающее количество итераций.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём входных данных:&#039;&#039;&#039; &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;n^2 +n + 1 &amp;lt;/math&amp;gt;. Если учесть, что матрица симметричная и достаточно для её однозначного определения задать элементы на главной диагонали и элементы над или под ней, то можно сократить объём входных данных с целью экономии памяти до: &amp;lt;math&amp;gt;\ \frac{n^2-n}{2}+n+n+1 =\frac{n^2+3n}{2} + 1&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные алгоритма:&#039;&#039;&#039; вектор собственных значений &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;\Theta^k&amp;lt;/math&amp;gt; длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;/math&amp;gt;, матрица &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;S^k&amp;lt;/math&amp;gt; из соответствующих собственных векторов размера &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n\times k&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём выходных данных:&#039;&#039;&#039; &amp;lt;math&amp;gt;k\;(n + 1)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
В данном разделе перечислены без какой-либо хронологии или связи друг с другом наиболее важные и разнообразные свойства алгоритма, на которые стоит и полезно обратить внимание, а также которые выгодно отличают его от схожих алгоритмов, решающих ту же задачу.&amp;lt;br&amp;gt;&lt;br /&gt;
1) Отношение последовательной сложности алгоритма к параллельной,с учётом &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;/math&amp;gt; итераций, равно &amp;lt;math&amp;gt;\;\;\frac{kn^2}{k \log_2{n}}=\frac{n^2}{\log_2{n}}&amp;lt;/math&amp;gt;;&amp;lt;br&amp;gt;&lt;br /&gt;
2) Вычислительная мощность алгоритма, как отношение числа операций к суммарному объему входных и выходных данных, равна &amp;lt;math style=&amp;quot;vertical-align:-70%&amp;gt;\;\;\frac{k\,n^2}{0.5\,n^2+1.5\,n+k\,n+k+1}&amp;lt;/math&amp;gt; и &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;\approx 2\,k&amp;lt;/math&amp;gt;, так как на практике верно отношение &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;&amp;lt;n&amp;lt;/math&amp;gt; ;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
3) Для собственных значений формируемых матриц &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_j&amp;lt;/math&amp;gt; верно отношение (следствие теоремы Коши о перемежаемости): &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;\lambda_i(T_{k+1})\geq \lambda_i(T_{k})\geq \lambda_{i+1}(T_{k+1})\geq \lambda_{i+1}(T_{k})&amp;lt;/math&amp;gt; ;&amp;lt;ref&amp;gt;James W. Demmel - Вычислительная линейная алгебра. Теория и приложения //Мир. - 2001 (c. 383)&amp;lt;/ref&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
4) Крайние (наибольшие и наименьшие) собственные значения матриц &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_j&amp;lt;/math&amp;gt; сходятся к крайним собственным значениям матрицы &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;A&amp;lt;/math&amp;gt; первыми (это часто происходит уже на ранних шагах при &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j\approx 2\,\sqrt{n}&amp;lt;/math&amp;gt;&amp;lt;ref&amp;gt;http://num-anal.srcc.msu.ru/lib_na/int_ae/int_ae6.htm (пункт 6.5)&amp;lt;/ref&amp;gt;), а собственные значения в середине спектра - последними;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
5) Из-за ограниченной точности постепенно теряется ортогональность вектора Ланцоша &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;q_j&amp;lt;/math&amp;gt; к предыдущим векторам Ланцоша, поэтому необходимо примерно каждые 10-15 итераций проводить дорогостоящую операцию реортогонализации, но это уже будет иной алгоритм с очень малым различием в одной операции и в программном коде, реализующем его, соответственно; &amp;lt;ref&amp;gt;Sam Handler - The Lanczos Algorithm For Large-Scale Eigenvalue Problems (08.01.07), slide №8&amp;lt;/ref&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
6) Эффективность и быстрота выполнения алгоритма очень сильно зависит от скорости памяти (диска). Согласно тесту только &#039;&#039;6%&#039;&#039; времени работы программы приходится на вычисления, остальное время затрачивается на ожидание отклика диска;&amp;lt;ref&amp;gt;Sam Handler - The Lanczos Algorithm For Large-Scale Eigenvalue Problems (08.01.07), slide №10&amp;lt;/ref&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
7) Метод Ланцоша удобен тем, что не требует хранения исходной матрицы полным массивом: метод использует исходную матрицу только в операциях умножения матрицы на вектор, что позволяет эффективно использовать разреженность матрицы или регулярность структуры матрицы. Поэтому метод Ланцоша может быть использован для матриц таких больших порядков, когда методы вращений и отражений не могут быть применены.&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;
Для исследования масштабируемости рассматриваемого алгоритма Ланцоша без переортогонализации автором была реализована программа на языке С++ с использованием технологии MPI. &amp;lt;ref&amp;gt;https://goo.gl/pNOFmW  или альтернативная ссылка с прикреплённым кодом: https://goo.gl/9AapM6 , по просьбе на почту я (автор статьи) готов предоставить желающим доступ к проекту с этим кодом на ресурсе Bitbucket&amp;lt;/ref&amp;gt; Дальнейшее исследование было проведено на суперкомпьютере &amp;quot;Ломоносов&amp;quot; Суперкомпьютерного комплекса МГУ.&amp;lt;ref&amp;gt;https://parallel.ru/cluster/lomonosov.html&amp;lt;/ref&amp;gt; &amp;lt;br&amp;gt; Важно отметить, что реализованная программа выполняет только первую часть алгоритма - формирование матрицы &amp;lt;math &amp;gt;T_j&amp;lt;/math&amp;gt;. Вторая часть алгоритма (задача поиска собственных значений матрицы &amp;lt;math &amp;gt;T_j&amp;lt;/math&amp;gt;) может быть решена несколькими методами, каждый из которых обладает своей эффективностью распараллеливания и характерными свойствами. Подробно этот вопрос уже обсуждался в статье раннее, поэтому не будем ещё раз заострять на этом внимание и останавливаться.&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Сборка осуществлялась со следующими параметрами:&lt;br /&gt;
* Компилятор intel/15.0.090 &lt;br /&gt;
* Openmpi/1.8.4-icc&lt;br /&gt;
В серии проведённых расчётов рассматривались следующие числовые значения параметров:&lt;br /&gt;
* Размер &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;n&amp;lt;/math&amp;gt; задачи и, соответственно, матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt;, задействованной в операции умножения на вектор: [2000 : 30000] с шагом 1000&lt;br /&gt;
* Число процессоров: 1, 2, 4, 16, 32, 48, 64, 96, 128, 192, 256&lt;br /&gt;
* Число итераций в алгоритме: &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k=350&amp;lt;/math&amp;gt;&lt;br /&gt;
Число &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; взято таким вопреки информации в начале статьи, где говорится, что значение &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; редко превышает &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;10^2&amp;lt;/math&amp;gt; (хоть мы и имеем право брать его любым по нашему усмотрению). Это сделано исключительно для лучшей визуализации пиков на графиках в данном разделе и наглядности получаемых результатов, так как при меньших на порядок значениях параметра &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; времена выполнения программ были слишком малы даже при минимальных числах процессоров и максимальных размерах &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;n&amp;lt;/math&amp;gt; задачи.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
На рис. 2 изображён график зависимости времени выполнения программы от числа процессоров и размера &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;n&amp;lt;/math&amp;gt; задачи. &amp;lt;br&amp;gt;&lt;br /&gt;
[[Файл:Levin_task1_execTIME.png|580px|thumb|center|Рис. 2  График зависимости времени выполнения программы]] &amp;lt;br&amp;gt;&lt;br /&gt;
Многочисленные тесты показали при малых количествах ядер уменьшение времени выполнения программы почти в 2 раза при увеличении числа ядер в 2 раза на всём диапазоне размеров матриц, что и отражает сильный излом на предоставленом графике. Изменение значения времени можно легко оценить по предоставленной цветовой шкале.&lt;br /&gt;
Также был построен график эффективности распараллеливания (parallel efficiency) в зависимости от числа процессоров и размера &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;n&amp;lt;/math&amp;gt; задачи, изображённый на рис. 3.&lt;br /&gt;
[[Файл:Levin604 task1 result EFFICIENCY.png|680px|thumb|center|Рис. 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;
Несмотря на то, что алгоритм является далеко не самым популярным, алгоритмом, про который нельзя сказать, что он всегда «на слуху», на сегодняшний день существует множество реализаций на различных популярных языках.&amp;lt;br&amp;gt;&lt;br /&gt;
Перечислим далее некоторые из них, указывая язык программирования, лежащий в их основе, и некоторые важные характеристики, которые обсуждались в статье ранее:&lt;br /&gt;
*&#039;&#039;Code on netlib.org by Jane Cullum and Ralph Willoughby&#039;&#039; (&#039;&#039;&#039;Fortran 77&#039;&#039;&#039;; без реортогонализации векторов; без реализации распараллеливания)&amp;lt;ref&amp;gt;http://www.netlib.org/lanczos/leval&amp;lt;/ref&amp;gt;&lt;br /&gt;
*&#039;&#039;Lanczos algorithm on freesourcecode.net&#039;&#039; (&#039;&#039;&#039;Matlab&#039;&#039;&#039;; присутствует реортогонализация векторов; без реализации распараллеливания)&amp;lt;ref&amp;gt;http://freesourcecode.net/matlabprojects/61741/lanczos-algorithm--in-matlab&amp;lt;/ref&amp;gt;&lt;br /&gt;
*&#039;&#039;Lanczos for eigenvalues in Numerical Linear Algebra, Spring 2007&#039;&#039; (&#039;&#039;&#039;Matlab&#039;&#039;&#039;; частичная или полная реортогонализация - доступны оба варианта; без реализации распараллеливания)&amp;lt;ref&amp;gt;Ссылки на файлы lanso.m и lanfu.m можно найти на https://www.nada.kth.se/~ruhe/2D5219/labs2007.html&amp;lt;/ref&amp;gt;&lt;br /&gt;
*&#039;&#039;Planso&#039;&#039; (название происходит от parallel Lanso.f) &#039;&#039;code by Kesheng Wu and Horst D. Simon&#039;&#039; (&#039;&#039;&#039;Fortran 77&#039;&#039;&#039;; частичная реортогонализация векторов; использование MPI для коммуникаций)&amp;lt;ref&amp;gt;https://github.com/jiahao/planso.jl/tree/master/external/PLAN/plan К сожалению, ссылка в описании пакета на github, ведущая на сайт National Energy Research Scientific Computing Center (NERSC), с более подробной информацией о данной программе больше не активна и выдаёт результат &#039;&#039;Page not found&#039;&#039;&amp;lt;/ref&amp;gt; &lt;br /&gt;
* &#039;&#039;Lanczos.cpp in the Vienna Computing Library&#039;&#039;  (&#039;&#039;&#039;C++&#039;&#039;&#039;, частичная реортогонализация, без реализации распараллеливания) &amp;lt;ref&amp;gt;http://viennacl.sourceforge.net/doc/lanczos_8cpp_source.html&amp;lt;/ref&amp;gt;&lt;br /&gt;
* &#039;&#039;Parallel Eigen Values code using C++ AMP on microsoft msdn blog&#039;&#039; (&#039;&#039;&#039;C++&#039;&#039;&#039;; ? ; распараллеливание есть и реализовано через C++ AMP) &amp;lt;ref&amp;gt;https://blogs.msdn.microsoft.com/nativeconcurrency/2013/12/20/eigen-values/ Подробнее о C++ Accelerated Massive Parallelism можно почитать здесь: https://msdn.microsoft.com/ru-ru/library/hh265137(v=vs.140).aspx или здесь: http://professorweb.ru/my/csharp/optimization/level4/4_6.php &amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;br /&gt;
[[en:Description of algorithm properties and structure]]&lt;/div&gt;</summary>
		<author><name>AleksLevin</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:AleksLevin/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%9B%D0%B0%D0%BD%D1%86%D0%BE%D1%88%D0%B0_%D0%B2%D1%8B%D1%87%D0%B8%D1%81%D0%BB%D0%B5%D0%BD%D0%B8%D1%8F_%D1%81%D0%BE%D0%B1%D1%81%D1%82%D0%B2%D0%B5%D0%BD%D0%BD%D1%8B%D1%85_%D0%B7%D0%BD%D0%B0%D1%87%D0%B5%D0%BD%D0%B8%D0%B9_%D1%81%D0%B8%D0%BC%D0%BC%D0%B5%D1%82%D1%80%D0%B8%D1%87%D0%BD%D0%BE%D0%B9_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86%D1%8B_%D0%B4%D0%BB%D1%8F_%D1%82%D0%BE%D1%87%D0%BD%D0%BE%D0%B9_%D0%B0%D1%80%D0%B8%D1%84%D0%BC%D0%B5%D1%82%D0%B8%D0%BA%D0%B8_(%D0%B1%D0%B5%D0%B7_%D0%BF%D0%B5%D1%80%D0%B5%D0%BE%D1%80%D1%82%D0%BE%D0%B3%D0%BE%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D0%B8)&amp;diff=20273</id>
		<title>Участник:AleksLevin/Алгоритм Ланцоша вычисления собственных значений симметричной матрицы для точной арифметики (без переортогонализации)</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:AleksLevin/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%9B%D0%B0%D0%BD%D1%86%D0%BE%D1%88%D0%B0_%D0%B2%D1%8B%D1%87%D0%B8%D1%81%D0%BB%D0%B5%D0%BD%D0%B8%D1%8F_%D1%81%D0%BE%D0%B1%D1%81%D1%82%D0%B2%D0%B5%D0%BD%D0%BD%D1%8B%D1%85_%D0%B7%D0%BD%D0%B0%D1%87%D0%B5%D0%BD%D0%B8%D0%B9_%D1%81%D0%B8%D0%BC%D0%BC%D0%B5%D1%82%D1%80%D0%B8%D1%87%D0%BD%D0%BE%D0%B9_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86%D1%8B_%D0%B4%D0%BB%D1%8F_%D1%82%D0%BE%D1%87%D0%BD%D0%BE%D0%B9_%D0%B0%D1%80%D0%B8%D1%84%D0%BC%D0%B5%D1%82%D0%B8%D0%BA%D0%B8_(%D0%B1%D0%B5%D0%B7_%D0%BF%D0%B5%D1%80%D0%B5%D0%BE%D1%80%D1%82%D0%BE%D0%B3%D0%BE%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D0%B8)&amp;diff=20273"/>
		<updated>2016-12-07T19:10:07Z</updated>

		<summary type="html">&lt;p&gt;AleksLevin: /* Масштабируемость алгоритма и его реализации */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Основные авторы описания: Левин А.Д.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{algorithm&lt;br /&gt;
| name              = Алгоритм Ланцоша для точной арифметики (без переортогонализации)&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(k\,n^2)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(k\log_2 n)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;\frac{n^2+3n}{2} + 1&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;k\;(n + 1)&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритмов =&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Данный алгоритм появился в 1950 г. и носит имя венгерского физика и математика Корнелия Ланцоша (венг. Lánczos Kornél). Алгоритм Ланцоша относится к итерационным методам вычисления собственных значений для матриц столь больших порядков &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt; n&amp;lt;/math&amp;gt;, что к ним нельзя применить прямые методы из-за ограничений по времени и памяти.&lt;br /&gt;
&lt;br /&gt;
Сам Ланцош указывал, что его метод предназначен для отыскания нескольких собственных векторов симметричных матриц, хотя к методу сразу было обращено внимание, как к способу приведения всей матрицы к трёхдиагональному виду. Двадцатью годами позже канадский математик Крис Пэж показал, что, несмотря на чувствительность к округлениям, алгоритм Ланцоша - эффективное средство вычисления некоторых &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; собственных чисел и соответствующих им собственных векторов. &amp;lt;ref&amp;gt;Парлетт Б. - Симметричная проблема собственных значений. Численные методы //М.: Мир. - 1983. (c. 276)&amp;lt;/ref&amp;gt;&lt;br /&gt;
Обычно число &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; берут в два раза больше, чем количество собственных значений матрицы, которые поставлена цель найти, и оно имеет порядок не более &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;10^2&amp;lt;/math&amp;gt;.&amp;lt;ref&amp;gt;Susan W. Bostic - Lanczos Eigensolution Method for High-Perfomance Computers, page 7&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Алгоритм Ланцоша для вычисления собственных значений симметричной матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; соединяет в себе метод Ланцоша для построения последовательности подпространств Крылова и ортонормированных векторов Ланцоша и процедуру Рэлея-Ритца получения оптимальных приближений собственных значений и соответствующих собственных векторов исходной матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt;.&amp;lt;ref&amp;gt;James W. Demmel - Вычислительная линейная алгебра. Теория и приложения //Мир. - 2001 (c. 381)&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
В данной статье рассматривается вариант алгоритма Ланцоша, в котором опущено влияние ошибок округления на вычислительный процесс, хотя на практике этому посвящается отдельное внимание и существуют различные методы решения данной проблемы, такие как частичная или полная переортогонализация. Этим модифицированным методам посвящены отдельные статьи на данном ресурсе.&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
Обозначения и формулы, используемые в данном разделе, взяты из литературы, указанной по ссылке.&amp;lt;ref&amp;gt;James W. Demmel - Вычислительная линейная алгебра. Теория и приложения //Мир. - 2001 (c. 313, &#039;&#039;&amp;lt;math&amp;gt; \S &amp;lt;/math&amp;gt; 6.6 Методы Крыловского подпространства&#039;&#039;)&amp;lt;/ref&amp;gt; &lt;br /&gt;
&lt;br /&gt;
Алгоритм Ланцоша для вычисления &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; собственных значений и собственных векторов вещественной симметричной матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A=A^T&amp;lt;/math&amp;gt; в точной арифметике: &amp;lt;ref&amp;gt;James W. Demmel - Вычислительная линейная алгебра. Теория и приложения //Мир. - 2001 (c. 381)&amp;lt;/ref&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{align}&lt;br /&gt;
q_1 = &amp;amp; \,\frac{b}{\|b\|_2},\; \beta_0 = 0,\; q_0 = 0\\&lt;br /&gt;
\mathbf{for} \; &amp;amp; j = 1 \; to \; k \,\; \mathbf{do} \\&lt;br /&gt;
&amp;amp; z = A\,q_j\\&lt;br /&gt;
&amp;amp; \alpha_j = q^T_j z\\&lt;br /&gt;
&amp;amp; z = z - \alpha_j q_j - \beta_{j-1}q_{j-1}\\&lt;br /&gt;
&amp;amp; \beta_j = \|z\|_2\\&lt;br /&gt;
&amp;amp; \mathbf{If} \; (\beta_j == 0) \; \mathbf{then}\; stop\; the\; algorithm \\ &lt;br /&gt;
&amp;amp; \;  q_{j+1} = \frac{z}{\beta_j} \\&lt;br /&gt;
&amp;amp; compute\; eigenvalues\; and \;eigenvectors\;of \;matrix \;\;T_j= Q^T_j A Q\;\;and\;estimate \;the\; errors\\&lt;br /&gt;
\mathbf{end} \; &amp;amp; \mathbf{for}&lt;br /&gt;
\end{align}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
В продемонстрированном выше алгоритме &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;b&amp;lt;/math&amp;gt; - заданный вещественный вектор. Также полагается известным алгоритм вычисления произведения матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; на вектор &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;x&amp;lt;/math&amp;gt;. &lt;br /&gt;
Введём матрицу Крылова, определяемую следующим соотношением: &amp;lt;math&amp;gt;K_j = [b,Ab,A^2b,...,A^{j-1}b]&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Далее, на практике, матрица &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;K&amp;lt;/math&amp;gt; заменяется матрицей &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;Q&amp;lt;/math&amp;gt;, такой, что при любом числе &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; линейные оболочки первых &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; столбцов в &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;K&amp;lt;/math&amp;gt; и &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;Q&amp;lt;/math&amp;gt; являются одним и тем же подпространством.&amp;lt;ref&amp;gt;James W. Demmel - Вычислительная линейная алгебра. Теория и приложения //Мир. - 2001 (c. 315)&amp;lt;/ref&amp;gt; &lt;br /&gt;
Тогда матрица &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;Q&amp;lt;/math&amp;gt;, в отличие от матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;K&amp;lt;/math&amp;gt;, хорошо обусловлена и легко обратима. В результате получаем матрицу &amp;lt;math&amp;gt;Q_j = [q_1, q_2, \dots, q_j]&amp;lt;/math&amp;gt; размерности &amp;lt;math&amp;gt;n\times j&amp;lt;/math&amp;gt;, столбцы которой ортогональны, являются базисом подпространства Крылова и называются векторами Ланцоша.&lt;br /&gt;
&lt;br /&gt;
В алгоритме Ланцоша вычислению подлежит столько первых столбцов в матрице &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;Q_j&amp;lt;/math&amp;gt;, сколько необходимо для получения требуемого приближения к решению &amp;lt;math&amp;gt;A\,x\,=b\,\,(A\,x=\lambda \, x)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Получение нулевого &amp;lt;math&amp;gt;\beta_j&amp;lt;/math&amp;gt; в итерационном процессе - событие, желательное в том смысле, что оно свидетельствует о том, что найдено некоторое подпространство, являющееся в точности инвариантным, а все собственные значения матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;T_j&amp;lt;/math&amp;gt; являются собственными значениями матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt;. На практике же нулевое и близкие к нулю значения получаются редко.&amp;lt;ref&amp;gt;Голуб Дж., Ван Лоун Ч. - Матричные вычисления//М.: Мир. - 1999 (c. 429)&amp;lt;/ref&amp;gt; &lt;br /&gt;
&lt;br /&gt;
Затем на каждом шаге цикла формируется симметричная трёхдиагональная матрица &amp;lt;math&amp;gt;T_j = Q^T_j A Q&amp;lt;/math&amp;gt;, к которой применяется процесс Рэлея-Ритца для поиска её собственных значений (на практике для поиска этих собственных значений можно использовать любой из специальных методов в параграфе книги по ссылке).&amp;lt;ref&amp;gt;Голуб Дж., Ван Лоун Ч. - Матричные вычисления//М.: Мир. - 1999 (&amp;lt;math&amp;gt;\S&amp;lt;/math&amp;gt; 8.4)&amp;lt;/ref&amp;gt;  &lt;br /&gt;
Эти собственные значения, они же числа Ритца, и полагаются приближёнными собственными значениями исходной матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt;.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Существует множество методов для отыскания собственных значений вещественной симметричной трехдиагональной матрицы. Большинство из них требует &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt; операций &amp;lt;ref&amp;gt;Парлетт Б. Симметричная проблема собственных значений. Численные методы.,: Мир, 1983. с. 179-182&amp;lt;/ref&amp;gt;, но существуют и быстрые алгоритмы, требующие лишь &amp;lt;math&amp;gt;O(n\ln n)&amp;lt;/math&amp;gt; операций.&amp;lt;ref&amp;gt;https://en.wikipedia.org/wiki/Tridiagonal_matrix#Eigenvalues  Раздел eigenvalues&amp;lt;/ref&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Одним из возможных способов отыскать собственные значения симметричной трехдиагональной матрицы - прямое вычисление корней характеристического полинома &amp;lt;math&amp;gt;p_n(\lambda)&amp;lt;/math&amp;gt; через метод деления пополам, где формируется последовательность Штурма и локализуются собственные числа, являющиеся корнями характеристического полинома. Нахождение всех &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; собственных значений матрицы этим способом требует &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;2n^2t&amp;lt;/math&amp;gt; умножений и вычитаний, где &amp;lt;math&amp;gt;t&amp;lt;/math&amp;gt; - число сделанных шагов с применением метода деления пополам.&amp;lt;ref&amp;gt;Уилкинсон Дж. X. Алгебраическая проблема собственныx значений. Изд-во &amp;quot;Наука&amp;quot;, 1970. - глава 5, с. 272-278&amp;lt;/ref&amp;gt; Соответствующие собственные вектора могут быть найдены посредством обратных итераций за &amp;lt;math&amp;gt; O(n) &amp;lt;/math&amp;gt; флопов. &amp;lt;ref&amp;gt;Голуб Дж., Ван Лоун Ч. - Матричные вычисления//М.: Мир. - 1999 (c. 394-395)&amp;lt;/ref&amp;gt; &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;На практике, если требуется только небольшая часть от всей совокупности собственных векторов и значений, и матрица имеет Хессенбергову или трёхдиагональную форму, очень эффективными будут методы факторизации, как, например, QR-алгоритм или QL-алгоритм со сдвигами (c целью ускорить алгоритм и сделать порядок сходимости квадратичным) или же без них.&amp;lt;ref&amp;gt;http://algorithm.narod.ru/ln/eigen/ETridiag.html&amp;lt;/ref&amp;gt; &amp;lt;br&amp;gt;&lt;br /&gt;
Весьма молодые и не менее актуальные конкуренты QR и QL алгоритмов, применяющиеся для поиска собственных значений:&lt;br /&gt;
*Методы divide-and-conquer (разделяй и властвуй), появившиеся в 1980-ых годах &amp;lt;ref&amp;gt;https://goo.gl/dapvbn ссылку пришлось сократить с помощью Google url shortener, так как символы подчеркивания портили её и не давали перейти по 1 клику&amp;lt;/ref&amp;gt;&lt;br /&gt;
*Relatively robust representation методы, появившиеся в 1990-ых и позволяющие найти собственные числа симметричной матрицы порядка &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;n&amp;lt;/math&amp;gt; за &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt; операций&lt;br /&gt;
&lt;br /&gt;
Если требуется вычислить собственные векторы, то необходимо хранить вычисляемые векторы Ланцоша. Если работа при этом производится только с оперативной памятью, то при большом порядке исходной матрицы (а именно для таких матриц и предназначен метод Ланцоша) число шагов  &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;j&amp;lt;/math&amp;gt;, которые могут быть выполнены до того момента, как оперативная память будет исчерпана, будет очень незначительно, а следовательно, искомые собственные пары могут не успеть сойтись с требуемой точностью. В этом случае метод Ланцоша можно использовать итерационным образом: после выполнения заданного числа шагов процесс прерывается и, если еще не все требуемые пары Ритца сошлись с требуемой точностью, то формируется новый начальный вектор &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;q_1&amp;lt;/math&amp;gt;, являющийся линейной комбинацией векторов Ритца, еще не сошедшихся с заданной точностью, и процесс начинается заново.&amp;lt;ref&amp;gt;http://num-anal.srcc.msu.ru/lib_na/int_ae/int_ae6.htm (пункт 6.5)&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
Вычислительное ядро рассматриваемого алгоритма (наиболее ресурсно-затратная часть алгоритма) -  формирование на каждом шаге цикла промежуточного вектора &amp;lt;math&amp;gt;z&amp;lt;/math&amp;gt;, вычисляемого по формуле: &amp;lt;math&amp;gt;z = A\,q_j&amp;lt;/math&amp;gt;. Данная операция, по сравнению с другими операциями алгоритма, затратна и требовательна, как с точки зрения количества производимых операций, так и с точки зрения объема оперируемых данных. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Например, умножение матрицы размера &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;n\times n&amp;lt;/math&amp;gt; на вектор длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; требует: &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;n^2+(n-1)n = 2n^2-n&amp;lt;/math&amp;gt; операций умножения и сложения. В свою очередь аналогичная операция умножения матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;(n+1)\times (n+1)&amp;lt;/math&amp;gt; на вектор длины &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;(n+1)&amp;lt;/math&amp;gt; требует: &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;2n^2+3n+1&amp;lt;/math&amp;gt;  операций умножения и сложения. То есть повышение размерности задачи всего на 1 увеличивает число необходимых действий в этом шаге алгоритма на: &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;4n+1&amp;lt;/math&amp;gt;. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Так же, стоит помнить, что, согласно разделу 1.2, данную операцию умножения матрицы на вектор необходимо выполнить &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;k&amp;lt;/math&amp;gt; раз. Нетрудно понять, насколько возрастает и колоссален масштаб операций, если в задачах, где критична точность, размерности &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; могут иметь порядок &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;10^5&amp;lt;/math&amp;gt; или даже более.&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
Как уже было упомянуто в данной статье в описании алгоритма, рассматриваемый алгоритм состоит из двух последовательно выполненных алгоритмов: метод Ланцоша для построения последовательности подпространств Крылова и ортонормированных векторов Ланцоша и процедура Рэлея-Ритца получения оптимальных приближений собственных значений и соответствующих собственных векторов исходной матрицы.&lt;br /&gt;
&lt;br /&gt;
В первой части алгоритма, где итерационно строятся Крыловское подпространство и трёхдиагональная матрица &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&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 style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; разреженная. Именно она подлежит оптимизации с использованием техник распараллеливания, поскольку она является вычислительным ядром алгоритма, а весь упомянутый процесс построения матрицы &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&amp;lt;/math&amp;gt; выполняется последовательно.&lt;br /&gt;
&lt;br /&gt;
Рассмотрим вторую часть алгоритма - поиск собственных значений сформированной матрицы &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&amp;lt;/math&amp;gt;.&amp;lt;br&amp;gt;&lt;br /&gt;
Далее, наглядно, в виде псевдокода, представлен, упомянутый в разделе 1.2, QR-алгоритм (аналогично можно рассмотреть и QL-алгоритм) со сдвигами Релэя, который весьма популярен на практике.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{align}&lt;br /&gt;
\mathbf{Input}: \;&amp;amp;tridiagonal\;\;matrix \;T\;with\;\;n\times n\;\;size\\&lt;br /&gt;
T^{(0)}&amp;amp;:=T\\&lt;br /&gt;
\mathbf{for}&amp;amp; \;\;m=n,...,2 \;\; \mathbf{do}\\&lt;br /&gt;
&amp;amp;k=0\\&lt;br /&gt;
&amp;amp; \mathbf{repeat}\\&lt;br /&gt;
&amp;amp; \quad \;\; k=k+1\\&lt;br /&gt;
&amp;amp; \quad \;\; \mu^{(k)}=T_{m,m}^{(k-1)}\\&lt;br /&gt;
&amp;amp; \quad \;\; Q^{(k)}R^{(k)}=T^{(k-1)}-\mu^{(k)}I\;\;using\;\;QR\;decomposition\\&lt;br /&gt;
&amp;amp; \quad \;\; T^{(k)}=R^{(k)}Q^{(k)}+\mu^{(k)}I\\&lt;br /&gt;
&amp;amp; \mathbf{until} \;\;\; |T_{m,m-1}^{(k)}| \;is\;\;small\;\;enough\\&lt;br /&gt;
&amp;amp; Save  \;\;T_{m,m}^{(k)} \;\;as\;\; converged\;\;eigenvalue\;of\;T\\ &lt;br /&gt;
&amp;amp; Remove \;\boldsymbol{n}\,th\;row\;and\;\boldsymbol{n}\,th\;column\;\;from \;T \\&lt;br /&gt;
&amp;amp; and\;take\;this\;new\;cropped\;matrix\;as\;new\;T^{(0)}\;with\;\;(n-1)\times (n-1)\;\;size\\&lt;br /&gt;
 \mathbf{end}&amp;amp;\; \mathbf{for}&lt;br /&gt;
\end{align}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Малость наддиагональных и поддиагональных элементов матрицы (фраза &#039;&#039;&amp;quot;small enough&amp;quot;&#039;&#039; в псевдокоде) подразумевает:&lt;br /&gt;
&amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt; |T_{m,m-1}^{(k)}| \leq \varepsilon\,|T_{m,m}^{(k)}| \quad\quad &amp;lt;/math&amp;gt; , где &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt; \varepsilon &amp;lt;/math&amp;gt; - заданная точность&amp;lt;br&amp;gt;&lt;br /&gt;
Также вместо сдвига Релэя, обозначенного в алгоритме через &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;\mu^{(k)}&amp;lt;/math&amp;gt;, часто на практике используется сдвиг по Уилкинсону, который даёт гарантированную сходимость внедиагональных элементов матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt; T^{(k)} &amp;lt;/math&amp;gt;, формируемой на каждом шаге, к нулю, при этом жертвуя монотонностью их убывания.&amp;lt;ref&amp;gt;Голуб Дж., Ван Лоун Ч. - Матричные вычисления//М.: Мир. - 1999 (c. 378, вторая половина страницы)&amp;lt;/ref&amp;gt;&amp;lt;ref&amp;gt;Парлетт Б. Симметричная проблема собственных значений. Численные методы.,: Мир, 1983. с. 169&amp;lt;/ref&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Подробнее с различными сдвигами и соответствующими оценками скоростей и количествами операций можно ознакомиться по указанной ссылке:&amp;lt;ref&amp;gt;Парлетт Б. Симметричная проблема собственных значений. Численные методы.,: Мир, 1983. с. 179-182&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;Для совершения QR-декомпозиции на каждом шаге может использоваться любой из алгоритмов по ссылке.&amp;lt;ref&amp;gt;https://en.wikipedia.org/wiki/QR_decomposition&amp;lt;/ref&amp;gt; Подробные описания этих алгоритмов также доступны на данном ресурсе algowiki-project.&amp;lt;br&amp;gt;&lt;br /&gt;
Так как мы оперируем не обычной матрицей и даже не Хессенберговой, а симметричной и трёхдиагональной, то скорость таких алгоритмов значительно возрастёт. Например, согласно данному ресурсу &amp;lt;ref&amp;gt;http://algorithm.narod.ru/ln/eigen/ETridiag.html&amp;lt;/ref&amp;gt;, для QL-алгоритма с неявными сдвигами:&amp;lt;br&amp;gt;&lt;br /&gt;
Для трёхдиагональной матрицы объем арифметических действий составляет &amp;lt;math&amp;gt; O(n)&amp;lt;/math&amp;gt; на одну итерацию вместо &amp;lt;math&amp;gt; O(n^3)&amp;lt;/math&amp;gt; для матрицы общего вида, а число итераций для нахождения первых собственных значений примерно равно 4 - 5. Но на этих итерациях также уменьшаются внедиагональные элементы правого нижнего угла. И, таким образом, дальнейшие собственные значения ищутся значительно быстрее. Среднее число итераций на каждое собственное значение обычно составляет 1.3 - 1.6.&amp;lt;br&amp;gt; &lt;br /&gt;
Аналогично QL, QR-разложение трёхдиагольной матрицы также требует &amp;lt;math&amp;gt; O(n)&amp;lt;/math&amp;gt; флопов&amp;lt;ref&amp;gt;Голуб Дж., Ван Лоун Ч. - Матричные вычисления//М.: Мир. - 1999 (c. 378, начало раздела 8.2.2)&amp;lt;/ref&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Подводя итог, во второй части алгоритма Ланцоша можно выделить следующие макрооперации:&lt;br /&gt;
* умножение матрицы на вещественное число;&lt;br /&gt;
* перемножение матриц;&lt;br /&gt;
* умножение и сравнение вещественных чисел;&lt;br /&gt;
* + набор других макроопераций в зависимости от выбора метода, с помощью которого будет совершаться сама QR или QL-декомпозиция (выше продемонстрированы, уже, как минимум, 3 разных способа).&lt;br /&gt;
Так же, важно заметить, что набор макропераций может быть несколько другим, если выбрать какой-либо иной современный метод поиска собственных чисел трёхдиагональной матрицы, не использующий QR и QL разложения(факторизацию). Два таких метода были упомянуты в пункте 1.2.&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
С целью полностью не дублировать раздел 1.2 данной статьи, где представлен наглядный и доступный для понимания псевдокод алгоритма, постараемся лишь коротко просуммировать и обобщить весь перечень последовательных действий в рассматриваемом алгоритме.&lt;br /&gt;
&lt;br /&gt;
В качестве входных данных имеем: вещественная симметричная матрица &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; размера &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;n\times n&amp;lt;/math&amp;gt;, известный вещественный вектор &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;b&amp;lt;/math&amp;gt; длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; и число &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;n&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Далее:&lt;br /&gt;
* Инициализируем вещественную константу &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;\beta_0&amp;lt;/math&amp;gt; и векторы &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;q_0&amp;lt;/math&amp;gt; и &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;q_1&amp;lt;/math&amp;gt;&lt;br /&gt;
* Итерационно для всех &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j=1,...,k&amp;lt;/math&amp;gt;:&lt;br /&gt;
** Вычисляем вспомогательный вектор &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt;, используя умножение матрицы на вектор&lt;br /&gt;
** Вычисляем, используя скалярное произведение векторов, значение &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;\alpha_j&amp;lt;/math&amp;gt; - элемент на главной диагонали трёхдиагональной матрицы &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&amp;lt;/math&amp;gt;&lt;br /&gt;
** Вычисляем по формуле новое значение и перезаписываем вектор &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt;&lt;br /&gt;
** Вычисляем значение &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;\beta_j&amp;lt;/math&amp;gt; - элементы непосредственно над и под главной диагональю той же матрицы &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&amp;lt;/math&amp;gt;&lt;br /&gt;
** Вычисляем, зная вектор &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt;,  очередной столбец матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;Q&amp;lt;/math&amp;gt;, он же вектор Ланцоша : &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;\,\,q_{j+1}&amp;lt;/math&amp;gt;&lt;br /&gt;
** Теперь, когда матрица &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&amp;lt;/math&amp;gt; сформирована на очередном шаге, находим её собственные значения и вектора любым доступным способом, о чём было подробно сказано в пункте 1.2&lt;br /&gt;
** Переходим на следующую итерацию: &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j&amp;lt;/math&amp;gt;++&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
Оценим количество операций и сложность последовательного алгоритма, изложенного в предыдущем разделе.&lt;br /&gt;
*Для вычисления вектора &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt; умножается матрица размера &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;n\times n&amp;lt;/math&amp;gt; на вектор длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt;, и потребуется &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n^2&amp;lt;/math&amp;gt; операций умножения и &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n^2&amp;lt;/math&amp;gt; операций сложения.&lt;br /&gt;
*Умножение векторов &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;q^T_j&amp;lt;/math&amp;gt; и &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt; длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; потребует &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; операций умножения и &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; операций сложения.&lt;br /&gt;
*При вычислении нового значения вектора &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt; поэлементное сложение двух векторов длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; требует &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; операций сложения.&lt;br /&gt;
*Умножение вектора длины &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; на вещественное число требует &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; операций умножения.&lt;br /&gt;
*Нахождение квадратичной нормы вектора &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt;  длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; требует &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; умножений и &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; сложений и ещё 1 операцию извлечения квадратного корня.&lt;br /&gt;
*Заключительное нахождение собственных значений и собственных векторов трёхдиагональной матрицы &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;T_j&amp;lt;/math&amp;gt; размера &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j\times j&amp;lt;/math&amp;gt; с помощью QR-алгоритма потребует в худшем случае &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(j^3)&amp;lt;/math&amp;gt; операций.&amp;lt;ref&amp;gt;http://num-anal.srcc.msu.ru/lib_na/int_ae/int_ae6.htm (пункт 6.2, &amp;quot;Скорость сходимости при этом всегда не хуже квадратичной и почти всегда лучше кубической.&amp;quot;)&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Посчитаем теперь суммарное количество простейших операций на одной итерации алгоритма (без учёта записей в память):&lt;br /&gt;
*&amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n^2+5\,n&amp;lt;/math&amp;gt; операций умножения/деления&lt;br /&gt;
*&amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n^2+4\,n&amp;lt;/math&amp;gt; операций сложения/вычитания&lt;br /&gt;
*1 операция извлечения квадратного корня&amp;lt;br&amp;gt;&lt;br /&gt;
Отдельно после всех итераций при &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j=k&amp;lt;/math&amp;gt; :&lt;br /&gt;
*&amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(k^3)&amp;lt;/math&amp;gt; операций для поиска собственных значений и собственных векторов трёхдиагональной матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_k&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Итого можно утверждать следующее:&lt;br /&gt;
&lt;br /&gt;
Последовательная сложность одной итерации рассматриваемого алгоритма:  &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(n ^ 2) &amp;lt;/math&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Суммарная сложность алгоритма (&amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;/math&amp;gt; итераций): &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(k\,n ^ 2) + O(k ^ 3)&amp;lt;/math&amp;gt; &amp;lt;ref&amp;gt;Здесь мы полагаем, что мы не вычисляем собственные значения и векторы матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_j&amp;lt;/math&amp;gt; на каждом промежуточном шаге, а лишь единожды затрачиваем &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;O(k ^ 3)&amp;lt;/math&amp;gt; действий в конце для нахождения &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;/math&amp;gt; собственных значений и векторов матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_k&amp;lt;/math&amp;gt;&amp;lt;/ref&amp;gt; &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
На практике же обычно рассматривается число &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;&amp;lt;n&amp;lt;/math&amp;gt;, поэтому второе слагаемое можно опустить.&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
На рис. 1 продемонстрирован граф одной итерации (при каком-либо произвольном значении итератора &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j&amp;lt;/math&amp;gt;) описанного алгоритма без отображения входных и выходных данных. Наглядно продемонстрированы связи между всеми действиями, и с помощью деления на &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; потоков показано, какие операции возможно выполнять параллельно на каждом шаге с целью оптимизации и экономии машинного времени. В результате, после параллельно выполненных операций &#039;&#039;&#039;Division&#039;&#039;&#039; на заключительном ярусе, на выходе имеем значение следующего вектора Ланцоша &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;q_{j+1}&amp;lt;/math&amp;gt;, после чего следует переход на следующую итерацию, и процесс повторяется.&lt;br /&gt;
&lt;br /&gt;
[[Файл:Levin_graph.png|600px|thumb|center|Рис. 1  Структура одной итерации алгоритма]] &amp;lt;br&amp;gt;&lt;br /&gt;
Обозначения на рисунке: &amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Simp&#039;&#039;&#039; (от англ. simple) - операции сложения и умножения вещественных чисел при вычислении произведения матрицы на вектор;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Vec mult&#039;&#039;&#039; (от англ. vectors multiplication) - операция скалярного умножения двух векторов;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Vec subtr&#039;&#039;&#039; (от англ. vectors subtraction, из-за использованных в операции вычитаний векторов) - операция умножения вектора на число (выполняется дважды) и формирование нового значения &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;z_{new}&amp;lt;/math&amp;gt; по формуле: &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;z_{new} = z - \alpha_j q_j - \beta_{j-1}q_{j-1} \;&amp;lt;/math&amp;gt;;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;||\cdot||&amp;lt;/math&amp;gt; - операция вычисления нормы вектора;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Division&#039;&#039;&#039; - операция деления вектора на вещественное число  &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;\beta_j&amp;lt;/math&amp;gt; &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Важно отметить, что упомянутые выше операции также легко поддаются оптимизации. Например, попарные умножения вещественных координат векторов при вычислении скалярного произведения также легко выполняются параллельно на &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; потоках, а затем можно применить суммирование методом сдваивания, о котором сказано в следующем разделе. Умножение или деление вектора на вещественное число являющееся, по определению, умножением или делением всех его координат на это число тоже может быть выполнено эффективнее, если мы используем &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; потоков, а не выполняем эти действия последовательно.&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
Параллельные операции возможны только внутри итераций, так как рассматриваемый алгоритм является итерационным, и сами итерации строго последовательны.&amp;lt;br&amp;gt;&lt;br /&gt;
Рассмотрим в этом разделе подробнее, какой выигрыш мы можем получить при распараллеливании операций внутри одной итерации согласно графу из предыдущего раздела.&lt;br /&gt;
&lt;br /&gt;
Умножение вещественной симметричной матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; размера &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;n\times n&amp;lt;/math&amp;gt; на вектор &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;b&amp;lt;/math&amp;gt; длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; требует последовательного выполнения &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; ярусов умножений и сложений. Сложение элементов вектора длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; на каждом шаге перемножения можно оптимизировать и выполнить за &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;\log_2 n&amp;lt;/math&amp;gt; действий, если применять метод сдваивания.&lt;br /&gt;
&lt;br /&gt;
Дальнейшие операции выполняются последовательно, а вычисление значений векторов происходит за один ярус операций сложения или умножения.&lt;br /&gt;
&lt;br /&gt;
Ресурс параллелизма алгоритма вычисления собственных значений построенной трёхдиагональной матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_k&amp;lt;/math&amp;gt; размера &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k\times k&amp;lt;/math&amp;gt; зависит от выбранного алгоритма (об этих алгоритмах подробнее было сказано в разделах 1.2 и 1.4). Будет очень затратно с точки зрения объёма материала пытаться рассмотреть пусть даже часть этих методов в этой статье, а так же тонкости их распараллеливания. Предлагаем читателям при желании самим ознакомиться с этими алгоритмами на данном ресурсе или прибегнув к иным источникам.&lt;br /&gt;
&lt;br /&gt;
При классификации по высоте ЯПФ, таким образом, алгоритм Ланцоша без переортогонализации относится к алгоритмам с &#039;&#039;логарифмической сложностью&#039;&#039;, и его сложность равна &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(\log_2 n)&amp;lt;/math&amp;gt; с важным замечанием, что это сложность только одной итерации, а максимум в алгоритме может быть выполнено последовательно &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;/math&amp;gt; таких однотипных итераций, если не будет осуществлён ранний выход из цикла. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Несмотря на то, что на графе в предыдущем разделе для лучшей визуализации и понимания было изображено &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; потоков (никаких допущений мы не делали и нарушений с точки зрения логики и математики нет, можно изобразить большее число потоков, просто часть времени некоторые из них могут бездействовать и не использоваться), на самом деле правильным и разумным будет реализовать начальное параллельное выполнение &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n^2&amp;lt;/math&amp;gt; операций умножения всех вещественных элементов матрицы &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;A&amp;lt;/math&amp;gt; на соответствующие элементы вектора &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;q_j&amp;lt;/math&amp;gt;, после чего применять тот же самый упомянутый метод сдваивания. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Поэтому при классификации по ширине ЯПФ его сложность будет &#039;&#039;квадратичной&#039;&#039; и равна &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(n^2)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
&#039;&#039;&#039;Входные данные алгоритма:&#039;&#039;&#039; вещественная симметричная &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; размера &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;n\times n&amp;lt;/math&amp;gt;, вещественный вектор &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;b&amp;lt;/math&amp;gt; длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt;, и одно целое число &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;k&amp;lt;/math&amp;gt;, означающее количество итераций.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём входных данных:&#039;&#039;&#039; &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;n^2 +n + 1 &amp;lt;/math&amp;gt;. Если учесть, что матрица симметричная и достаточно для её однозначного определения задать элементы на главной диагонали и элементы над или под ней, то можно сократить объём входных данных с целью экономии памяти до: &amp;lt;math&amp;gt;\ \frac{n^2-n}{2}+n+n+1 =\frac{n^2+3n}{2} + 1&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные алгоритма:&#039;&#039;&#039; вектор собственных значений &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;\Theta^k&amp;lt;/math&amp;gt; длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;/math&amp;gt;, матрица &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;S^k&amp;lt;/math&amp;gt; из соответствующих собственных векторов размера &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n\times k&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём выходных данных:&#039;&#039;&#039; &amp;lt;math&amp;gt;k\;(n + 1)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
В данном разделе перечислены без какой-либо хронологии или связи друг с другом наиболее важные и разнообразные свойства алгоритма, на которые стоит и полезно обратить внимание, а также которые выгодно отличают его от схожих алгоритмов, решающих ту же задачу.&amp;lt;br&amp;gt;&lt;br /&gt;
1) Отношение последовательной сложности алгоритма к параллельной,с учётом &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;/math&amp;gt; итераций, равно &amp;lt;math&amp;gt;\;\;\frac{kn^2}{k \log_2{n}}=\frac{n^2}{\log_2{n}}&amp;lt;/math&amp;gt;;&amp;lt;br&amp;gt;&lt;br /&gt;
2) Вычислительная мощность алгоритма, как отношение числа операций к суммарному объему входных и выходных данных, равна &amp;lt;math style=&amp;quot;vertical-align:-70%&amp;gt;\;\;\frac{k\,n^2}{0.5\,n^2+1.5\,n+k\,n+k+1}&amp;lt;/math&amp;gt; и &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;\approx 2\,k&amp;lt;/math&amp;gt;, так как на практике верно отношение &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;&amp;lt;n&amp;lt;/math&amp;gt; ;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
3) Для собственных значений формируемых матриц &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_j&amp;lt;/math&amp;gt; верно отношение (следствие теоремы Коши о перемежаемости): &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;\lambda_i(T_{k+1})\geq \lambda_i(T_{k})\geq \lambda_{i+1}(T_{k+1})\geq \lambda_{i+1}(T_{k})&amp;lt;/math&amp;gt; ;&amp;lt;ref&amp;gt;James W. Demmel - Вычислительная линейная алгебра. Теория и приложения //Мир. - 2001 (c. 383)&amp;lt;/ref&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
4) Крайние (наибольшие и наименьшие) собственные значения матриц &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_j&amp;lt;/math&amp;gt; сходятся к крайним собственным значениям матрицы &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;A&amp;lt;/math&amp;gt; первыми (это часто происходит уже на ранних шагах при &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j\approx 2\,\sqrt{n}&amp;lt;/math&amp;gt;&amp;lt;ref&amp;gt;http://num-anal.srcc.msu.ru/lib_na/int_ae/int_ae6.htm (пункт 6.5)&amp;lt;/ref&amp;gt;), а собственные значения в середине спектра - последними;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
5) Из-за ограниченной точности постепенно теряется ортогональность вектора Ланцоша &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;q_j&amp;lt;/math&amp;gt; к предыдущим векторам Ланцоша, поэтому необходимо примерно каждые 10-15 итераций проводить дорогостоящую операцию реортогонализации, но это уже будет иной алгоритм с очень малым различием в одной операции и в программном коде, реализующем его, соответственно; &amp;lt;ref&amp;gt;Sam Handler - The Lanczos Algorithm For Large-Scale Eigenvalue Problems (08.01.07), slide №8&amp;lt;/ref&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
6) Эффективность и быстрота выполнения алгоритма очень сильно зависит от скорости памяти (диска). Согласно тесту только &#039;&#039;6%&#039;&#039; времени работы программы приходится на вычисления, остальное время затрачивается на ожидание отклика диска;&amp;lt;ref&amp;gt;Sam Handler - The Lanczos Algorithm For Large-Scale Eigenvalue Problems (08.01.07), slide №10&amp;lt;/ref&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
7) Метод Ланцоша удобен тем, что не требует хранения исходной матрицы полным массивом: метод использует исходную матрицу только в операциях умножения матрицы на вектор, что позволяет эффективно использовать разреженность матрицы или регулярность структуры матрицы. Поэтому метод Ланцоша может быть использован для матриц таких больших порядков, когда методы вращений и отражений не могут быть применены.&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;
Для исследования масштабируемости рассматриваемого алгоритма Ланцоша без переортогонализации автором была реализована программа на языке С++ с использованием технологии MPI. &amp;lt;ref&amp;gt;https://goo.gl/pNOFmW  или альтернативная ссылка с прикреплённым кодом: https://goo.gl/9AapM6 , по просьбе на почту я (автор статьи) готов предоставить желающим доступ к проекту с этим кодом на ресурсе Bitbucket&amp;lt;/ref&amp;gt; Дальнейшее исследование было проведено на суперкомпьютере &amp;quot;Ломоносов&amp;quot; Суперкомпьютерного комплекса МГУ. &amp;lt;br&amp;gt; Важно отметить, что реализованная программа выполняет только первую часть алгоритма - формирование матрицы &amp;lt;math &amp;gt;T_j&amp;lt;/math&amp;gt;. Вторая часть алгоритма (задача поиска собственных значений матрицы &amp;lt;math &amp;gt;T_j&amp;lt;/math&amp;gt;) может быть решена несколькими методами, каждый из которых обладает своей эффективностью распараллеливания и характерными свойствами. Подробно этот вопрос уже обсуждался в статье раннее, поэтому не будем ещё раз заострять на этом внимание и останавливаться.&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Сборка осуществлялась со следующими параметрами:&lt;br /&gt;
* Компилятор intel/15.0.090 &lt;br /&gt;
* Openmpi/1.8.4-icc&lt;br /&gt;
В серии проведённых расчётов рассматривались следующие числовые значения параметров:&lt;br /&gt;
* Размер &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;n&amp;lt;/math&amp;gt; задачи и, соответственно, матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt;, задействованной в операции умножения на вектор: [2000 : 30000] с шагом 1000&lt;br /&gt;
* Число процессоров: 1, 2, 4, 16, 32, 48, 64, 96, 128, 192, 256&lt;br /&gt;
* Число итераций в алгоритме: &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k=350&amp;lt;/math&amp;gt;&lt;br /&gt;
Число &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; взято таким вопреки информации в начале статьи, где говорится, что значение &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; редко превышает &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;10^2&amp;lt;/math&amp;gt; (хоть мы и имеем право брать его любым по нашему усмотрению). Это сделано исключительно для лучшей визуализации пиков на графиках в данном разделе и наглядности получаемых результатов, так как при меньших на порядок значениях параметра &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; времена выполнения программ были слишком малы даже при минимальных числах процессоров и максимальных размерах &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;n&amp;lt;/math&amp;gt; задачи.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
На рис. 2 изображён график зависимости времени выполнения программы от числа процессоров и размера &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;n&amp;lt;/math&amp;gt; задачи. &amp;lt;br&amp;gt;&lt;br /&gt;
[[Файл:Levin_task1_execTIME.png|580px|thumb|center|Рис. 2  График зависимости времени выполнения программы]] &amp;lt;br&amp;gt;&lt;br /&gt;
Многочисленные тесты показали при малых количествах ядер уменьшение времени выполнения программы почти в 2 раза при увеличении числа ядер в 2 раза на всём диапазоне размеров матриц, что и отражает сильный излом на предоставленом графике. Изменение значения времени можно легко оценить по предоставленной цветовой шкале.&lt;br /&gt;
Также был построен график эффективности распараллеливания (parallel efficiency) в зависимости от числа процессоров и размера &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;n&amp;lt;/math&amp;gt; задачи, изображённый на рис. 3.&lt;br /&gt;
[[Файл:Levin604_task1_result_EFFICIENCY.png|680px|thumb|center|Рис. 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;
Несмотря на то, что алгоритм является далеко не самым популярным, алгоритмом, про который нельзя сказать, что он всегда «на слуху», на сегодняшний день существует множество реализаций на различных популярных языках.&amp;lt;br&amp;gt;&lt;br /&gt;
Перечислим далее некоторые из них, указывая язык программирования, лежащий в их основе, и некоторые важные характеристики, которые обсуждались в статье ранее:&lt;br /&gt;
*&#039;&#039;Code on netlib.org by Jane Cullum and Ralph Willoughby&#039;&#039; (&#039;&#039;&#039;Fortran 77&#039;&#039;&#039;; без реортогонализации векторов; без реализации распараллеливания)&amp;lt;ref&amp;gt;http://www.netlib.org/lanczos/leval&amp;lt;/ref&amp;gt;&lt;br /&gt;
*&#039;&#039;Lanczos algorithm on freesourcecode.net&#039;&#039; (&#039;&#039;&#039;Matlab&#039;&#039;&#039;; присутствует реортогонализация векторов; без реализации распараллеливания)&amp;lt;ref&amp;gt;http://freesourcecode.net/matlabprojects/61741/lanczos-algorithm--in-matlab&amp;lt;/ref&amp;gt;&lt;br /&gt;
*&#039;&#039;Lanczos for eigenvalues in Numerical Linear Algebra, Spring 2007&#039;&#039; (&#039;&#039;&#039;Matlab&#039;&#039;&#039;; частичная или полная реортогонализация - доступны оба варианта; без реализации распараллеливания)&amp;lt;ref&amp;gt;Ссылки на файлы lanso.m и lanfu.m можно найти на https://www.nada.kth.se/~ruhe/2D5219/labs2007.html&amp;lt;/ref&amp;gt;&lt;br /&gt;
*&#039;&#039;Planso&#039;&#039; (название происходит от parallel Lanso.f) &#039;&#039;code by Kesheng Wu and Horst D. Simon&#039;&#039; (&#039;&#039;&#039;Fortran 77&#039;&#039;&#039;; частичная реортогонализация векторов; использование MPI для коммуникаций)&amp;lt;ref&amp;gt;https://github.com/jiahao/planso.jl/tree/master/external/PLAN/plan К сожалению, ссылка в описании пакета на github, ведущая на сайт National Energy Research Scientific Computing Center (NERSC), с более подробной информацией о данной программе больше не активна и выдаёт результат &#039;&#039;Page not found&#039;&#039;&amp;lt;/ref&amp;gt; &lt;br /&gt;
* &#039;&#039;Lanczos.cpp in the Vienna Computing Library&#039;&#039;  (&#039;&#039;&#039;C++&#039;&#039;&#039;, частичная реортогонализация, без реализации распараллеливания) &amp;lt;ref&amp;gt;http://viennacl.sourceforge.net/doc/lanczos_8cpp_source.html&amp;lt;/ref&amp;gt;&lt;br /&gt;
* &#039;&#039;Parallel Eigen Values code using C++ AMP on microsoft msdn blog&#039;&#039; (&#039;&#039;&#039;C++&#039;&#039;&#039;; ? ; распараллеливание есть и реализовано через C++ AMP) &amp;lt;ref&amp;gt;https://blogs.msdn.microsoft.com/nativeconcurrency/2013/12/20/eigen-values/ Подробнее о C++ Accelerated Massive Parallelism можно почитать здесь: https://msdn.microsoft.com/ru-ru/library/hh265137(v=vs.140).aspx или здесь: http://professorweb.ru/my/csharp/optimization/level4/4_6.php &amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;br /&gt;
[[en:Description of algorithm properties and structure]]&lt;/div&gt;</summary>
		<author><name>AleksLevin</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%9E%D0%B1%D1%81%D1%83%D0%B6%D0%B4%D0%B5%D0%BD%D0%B8%D0%B5_%D1%83%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA%D0%B0:AleksLevin&amp;diff=20271</id>
		<title>Обсуждение участника:AleksLevin</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%9E%D0%B1%D1%81%D1%83%D0%B6%D0%B4%D0%B5%D0%BD%D0%B8%D0%B5_%D1%83%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA%D0%B0:AleksLevin&amp;diff=20271"/>
		<updated>2016-12-07T19:04:22Z</updated>

		<summary type="html">&lt;p&gt;AleksLevin: /* Замечания */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Статья [[Участник:AleksLevin/Алгоритм Ланцоша вычисления собственных значений симметричной матрицы для точной арифметики (без переортогонализации)]] ==&lt;br /&gt;
&lt;br /&gt;
=== Отсутствующие части ===&lt;br /&gt;
* Не заполнен раздел 2.4 описания. [[Участник:ASA|Александр Сергеевич Антонов]] ([[Обсуждение участника:ASA|обсуждение]]) 15:12, 16 ноября 2016 (MSK)&lt;br /&gt;
&lt;br /&gt;
=== Замечания ===&lt;br /&gt;
* убрать подробности (&amp;quot;студент, ...&amp;quot;) со страницы алгоритма, но оставить на самой странице автора&lt;br /&gt;
* убрать &amp;quot;все описанные разделы самостоятельно&amp;quot;&lt;br /&gt;
* во врезке про высоту ЯПФ убрать слова, оставив множитель &amp;quot;k&amp;quot; (все слова переместить в основной текст)&lt;br /&gt;
* 1.2 &amp;quot;Для лучшего понимания описания, данного в этом пункте статьи, рекомендуется ознакомиться с параграфом ...&amp;quot; представьте, что Вы пишете научную статью для профессоров другого университета для которых [2] не является достаточным авторитетом. Пишите более нейтрально и отстраненно.&lt;br /&gt;
* 1.3 чуть подробнее&lt;br /&gt;
* 1.4 &amp;quot;Вторая часть алгоритма&amp;quot; - здесь же или ниже рассказать об этой операции, не ограничиваясь отсылкой к ее нетривиальности.&lt;br /&gt;
* 1.5 не стоит выделять текст жирным &amp;quot;\mathbf{1.2}&amp;quot; (то же самое во свех остальных местах)&lt;br /&gt;
* 1.5 просьба заменить &amp;quot;j=\overline {1,k}&amp;quot; на более употребительное &amp;quot;j=1,...,k&amp;quot;&lt;br /&gt;
* 1.7 Рис. лучше пронумеровать, оставив короткую подпись, а теперешнюю подпись поместить в основной текст&lt;br /&gt;
* 1.8 хорошо написан этот важный пункт&lt;br /&gt;
* 2.1-2.6 отсутствуют...&lt;br /&gt;
* особенно хотелось бы узнать ваше мнение по п.2.6, это действительно, нетривиально и неоднозначно&lt;br /&gt;
* 3. не стоит разделять и противопоставлять [1]-[5] и 1.-13. Лучше все ссылки дать во втором стиле.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Сделал множество правок и учёл все вышеупомянутые замечания и пожелания! С уважением, Левин Александр.&#039;&#039;&#039;&lt;br /&gt;
&#039;&#039;По заданию, во второй части требовалось описать только разделы 2.4 и 2.7, прошу не спрашивать с меня все разделы 2.1-2.6. Надеюсь на понимание, мне физически не хватает времени на это задание + 2 других в течение семестра, стараюсь и делаю всё, что в моих силах :)&#039;&#039;&lt;/div&gt;</summary>
		<author><name>AleksLevin</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:AleksLevin/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%9B%D0%B0%D0%BD%D1%86%D0%BE%D1%88%D0%B0_%D0%B2%D1%8B%D1%87%D0%B8%D1%81%D0%BB%D0%B5%D0%BD%D0%B8%D1%8F_%D1%81%D0%BE%D0%B1%D1%81%D1%82%D0%B2%D0%B5%D0%BD%D0%BD%D1%8B%D1%85_%D0%B7%D0%BD%D0%B0%D1%87%D0%B5%D0%BD%D0%B8%D0%B9_%D1%81%D0%B8%D0%BC%D0%BC%D0%B5%D1%82%D1%80%D0%B8%D1%87%D0%BD%D0%BE%D0%B9_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86%D1%8B_%D0%B4%D0%BB%D1%8F_%D1%82%D0%BE%D1%87%D0%BD%D0%BE%D0%B9_%D0%B0%D1%80%D0%B8%D1%84%D0%BC%D0%B5%D1%82%D0%B8%D0%BA%D0%B8_(%D0%B1%D0%B5%D0%B7_%D0%BF%D0%B5%D1%80%D0%B5%D0%BE%D1%80%D1%82%D0%BE%D0%B3%D0%BE%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D0%B8)&amp;diff=20269</id>
		<title>Участник:AleksLevin/Алгоритм Ланцоша вычисления собственных значений симметричной матрицы для точной арифметики (без переортогонализации)</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:AleksLevin/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%9B%D0%B0%D0%BD%D1%86%D0%BE%D1%88%D0%B0_%D0%B2%D1%8B%D1%87%D0%B8%D1%81%D0%BB%D0%B5%D0%BD%D0%B8%D1%8F_%D1%81%D0%BE%D0%B1%D1%81%D1%82%D0%B2%D0%B5%D0%BD%D0%BD%D1%8B%D1%85_%D0%B7%D0%BD%D0%B0%D1%87%D0%B5%D0%BD%D0%B8%D0%B9_%D1%81%D0%B8%D0%BC%D0%BC%D0%B5%D1%82%D1%80%D0%B8%D1%87%D0%BD%D0%BE%D0%B9_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86%D1%8B_%D0%B4%D0%BB%D1%8F_%D1%82%D0%BE%D1%87%D0%BD%D0%BE%D0%B9_%D0%B0%D1%80%D0%B8%D1%84%D0%BC%D0%B5%D1%82%D0%B8%D0%BA%D0%B8_(%D0%B1%D0%B5%D0%B7_%D0%BF%D0%B5%D1%80%D0%B5%D0%BE%D1%80%D1%82%D0%BE%D0%B3%D0%BE%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D0%B8)&amp;diff=20269"/>
		<updated>2016-12-07T19:03:37Z</updated>

		<summary type="html">&lt;p&gt;AleksLevin: /* Выводы для классов архитектур */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Основные авторы описания: Левин А.Д.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{algorithm&lt;br /&gt;
| name              = Алгоритм Ланцоша для точной арифметики (без переортогонализации)&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(k\,n^2)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(k\log_2 n)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;\frac{n^2+3n}{2} + 1&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;k\;(n + 1)&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритмов =&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Данный алгоритм появился в 1950 г. и носит имя венгерского физика и математика Корнелия Ланцоша (венг. Lánczos Kornél). Алгоритм Ланцоша относится к итерационным методам вычисления собственных значений для матриц столь больших порядков &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt; n&amp;lt;/math&amp;gt;, что к ним нельзя применить прямые методы из-за ограничений по времени и памяти.&lt;br /&gt;
&lt;br /&gt;
Сам Ланцош указывал, что его метод предназначен для отыскания нескольких собственных векторов симметричных матриц, хотя к методу сразу было обращено внимание, как к способу приведения всей матрицы к трёхдиагональному виду. Двадцатью годами позже канадский математик Крис Пэж показал, что, несмотря на чувствительность к округлениям, алгоритм Ланцоша - эффективное средство вычисления некоторых &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; собственных чисел и соответствующих им собственных векторов. &amp;lt;ref&amp;gt;Парлетт Б. - Симметричная проблема собственных значений. Численные методы //М.: Мир. - 1983. (c. 276)&amp;lt;/ref&amp;gt;&lt;br /&gt;
Обычно число &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; берут в два раза больше, чем количество собственных значений матрицы, которые поставлена цель найти, и оно имеет порядок не более &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;10^2&amp;lt;/math&amp;gt;.&amp;lt;ref&amp;gt;Susan W. Bostic - Lanczos Eigensolution Method for High-Perfomance Computers, page 7&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Алгоритм Ланцоша для вычисления собственных значений симметричной матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; соединяет в себе метод Ланцоша для построения последовательности подпространств Крылова и ортонормированных векторов Ланцоша и процедуру Рэлея-Ритца получения оптимальных приближений собственных значений и соответствующих собственных векторов исходной матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt;.&amp;lt;ref&amp;gt;James W. Demmel - Вычислительная линейная алгебра. Теория и приложения //Мир. - 2001 (c. 381)&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
В данной статье рассматривается вариант алгоритма Ланцоша, в котором опущено влияние ошибок округления на вычислительный процесс, хотя на практике этому посвящается отдельное внимание и существуют различные методы решения данной проблемы, такие как частичная или полная переортогонализация. Этим модифицированным методам посвящены отдельные статьи на данном ресурсе.&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
Обозначения и формулы, используемые в данном разделе, взяты из литературы, указанной по ссылке.&amp;lt;ref&amp;gt;James W. Demmel - Вычислительная линейная алгебра. Теория и приложения //Мир. - 2001 (c. 313, &#039;&#039;&amp;lt;math&amp;gt; \S &amp;lt;/math&amp;gt; 6.6 Методы Крыловского подпространства&#039;&#039;)&amp;lt;/ref&amp;gt; &lt;br /&gt;
&lt;br /&gt;
Алгоритм Ланцоша для вычисления &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; собственных значений и собственных векторов вещественной симметричной матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A=A^T&amp;lt;/math&amp;gt; в точной арифметике: &amp;lt;ref&amp;gt;James W. Demmel - Вычислительная линейная алгебра. Теория и приложения //Мир. - 2001 (c. 381)&amp;lt;/ref&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{align}&lt;br /&gt;
q_1 = &amp;amp; \,\frac{b}{\|b\|_2},\; \beta_0 = 0,\; q_0 = 0\\&lt;br /&gt;
\mathbf{for} \; &amp;amp; j = 1 \; to \; k \,\; \mathbf{do} \\&lt;br /&gt;
&amp;amp; z = A\,q_j\\&lt;br /&gt;
&amp;amp; \alpha_j = q^T_j z\\&lt;br /&gt;
&amp;amp; z = z - \alpha_j q_j - \beta_{j-1}q_{j-1}\\&lt;br /&gt;
&amp;amp; \beta_j = \|z\|_2\\&lt;br /&gt;
&amp;amp; \mathbf{If} \; (\beta_j == 0) \; \mathbf{then}\; stop\; the\; algorithm \\ &lt;br /&gt;
&amp;amp; \;  q_{j+1} = \frac{z}{\beta_j} \\&lt;br /&gt;
&amp;amp; compute\; eigenvalues\; and \;eigenvectors\;of \;matrix \;\;T_j= Q^T_j A Q\;\;and\;estimate \;the\; errors\\&lt;br /&gt;
\mathbf{end} \; &amp;amp; \mathbf{for}&lt;br /&gt;
\end{align}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
В продемонстрированном выше алгоритме &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;b&amp;lt;/math&amp;gt; - заданный вещественный вектор. Также полагается известным алгоритм вычисления произведения матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; на вектор &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;x&amp;lt;/math&amp;gt;. &lt;br /&gt;
Введём матрицу Крылова, определяемую следующим соотношением: &amp;lt;math&amp;gt;K_j = [b,Ab,A^2b,...,A^{j-1}b]&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Далее, на практике, матрица &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;K&amp;lt;/math&amp;gt; заменяется матрицей &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;Q&amp;lt;/math&amp;gt;, такой, что при любом числе &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; линейные оболочки первых &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; столбцов в &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;K&amp;lt;/math&amp;gt; и &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;Q&amp;lt;/math&amp;gt; являются одним и тем же подпространством.&amp;lt;ref&amp;gt;James W. Demmel - Вычислительная линейная алгебра. Теория и приложения //Мир. - 2001 (c. 315)&amp;lt;/ref&amp;gt; &lt;br /&gt;
Тогда матрица &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;Q&amp;lt;/math&amp;gt;, в отличие от матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;K&amp;lt;/math&amp;gt;, хорошо обусловлена и легко обратима. В результате получаем матрицу &amp;lt;math&amp;gt;Q_j = [q_1, q_2, \dots, q_j]&amp;lt;/math&amp;gt; размерности &amp;lt;math&amp;gt;n\times j&amp;lt;/math&amp;gt;, столбцы которой ортогональны, являются базисом подпространства Крылова и называются векторами Ланцоша.&lt;br /&gt;
&lt;br /&gt;
В алгоритме Ланцоша вычислению подлежит столько первых столбцов в матрице &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;Q_j&amp;lt;/math&amp;gt;, сколько необходимо для получения требуемого приближения к решению &amp;lt;math&amp;gt;A\,x\,=b\,\,(A\,x=\lambda \, x)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Получение нулевого &amp;lt;math&amp;gt;\beta_j&amp;lt;/math&amp;gt; в итерационном процессе - событие, желательное в том смысле, что оно свидетельствует о том, что найдено некоторое подпространство, являющееся в точности инвариантным, а все собственные значения матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;T_j&amp;lt;/math&amp;gt; являются собственными значениями матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt;. На практике же нулевое и близкие к нулю значения получаются редко.&amp;lt;ref&amp;gt;Голуб Дж., Ван Лоун Ч. - Матричные вычисления//М.: Мир. - 1999 (c. 429)&amp;lt;/ref&amp;gt; &lt;br /&gt;
&lt;br /&gt;
Затем на каждом шаге цикла формируется симметричная трёхдиагональная матрица &amp;lt;math&amp;gt;T_j = Q^T_j A Q&amp;lt;/math&amp;gt;, к которой применяется процесс Рэлея-Ритца для поиска её собственных значений (на практике для поиска этих собственных значений можно использовать любой из специальных методов в параграфе книги по ссылке).&amp;lt;ref&amp;gt;Голуб Дж., Ван Лоун Ч. - Матричные вычисления//М.: Мир. - 1999 (&amp;lt;math&amp;gt;\S&amp;lt;/math&amp;gt; 8.4)&amp;lt;/ref&amp;gt;  &lt;br /&gt;
Эти собственные значения, они же числа Ритца, и полагаются приближёнными собственными значениями исходной матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt;.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Существует множество методов для отыскания собственных значений вещественной симметричной трехдиагональной матрицы. Большинство из них требует &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt; операций &amp;lt;ref&amp;gt;Парлетт Б. Симметричная проблема собственных значений. Численные методы.,: Мир, 1983. с. 179-182&amp;lt;/ref&amp;gt;, но существуют и быстрые алгоритмы, требующие лишь &amp;lt;math&amp;gt;O(n\ln n)&amp;lt;/math&amp;gt; операций.&amp;lt;ref&amp;gt;https://en.wikipedia.org/wiki/Tridiagonal_matrix#Eigenvalues  Раздел eigenvalues&amp;lt;/ref&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Одним из возможных способов отыскать собственные значения симметричной трехдиагональной матрицы - прямое вычисление корней характеристического полинома &amp;lt;math&amp;gt;p_n(\lambda)&amp;lt;/math&amp;gt; через метод деления пополам, где формируется последовательность Штурма и локализуются собственные числа, являющиеся корнями характеристического полинома. Нахождение всех &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; собственных значений матрицы этим способом требует &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;2n^2t&amp;lt;/math&amp;gt; умножений и вычитаний, где &amp;lt;math&amp;gt;t&amp;lt;/math&amp;gt; - число сделанных шагов с применением метода деления пополам.&amp;lt;ref&amp;gt;Уилкинсон Дж. X. Алгебраическая проблема собственныx значений. Изд-во &amp;quot;Наука&amp;quot;, 1970. - глава 5, с. 272-278&amp;lt;/ref&amp;gt; Соответствующие собственные вектора могут быть найдены посредством обратных итераций за &amp;lt;math&amp;gt; O(n) &amp;lt;/math&amp;gt; флопов. &amp;lt;ref&amp;gt;Голуб Дж., Ван Лоун Ч. - Матричные вычисления//М.: Мир. - 1999 (c. 394-395)&amp;lt;/ref&amp;gt; &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;На практике, если требуется только небольшая часть от всей совокупности собственных векторов и значений, и матрица имеет Хессенбергову или трёхдиагональную форму, очень эффективными будут методы факторизации, как, например, QR-алгоритм или QL-алгоритм со сдвигами (c целью ускорить алгоритм и сделать порядок сходимости квадратичным) или же без них.&amp;lt;ref&amp;gt;http://algorithm.narod.ru/ln/eigen/ETridiag.html&amp;lt;/ref&amp;gt; &amp;lt;br&amp;gt;&lt;br /&gt;
Весьма молодые и не менее актуальные конкуренты QR и QL алгоритмов, применяющиеся для поиска собственных значений:&lt;br /&gt;
*Методы divide-and-conquer (разделяй и властвуй), появившиеся в 1980-ых годах &amp;lt;ref&amp;gt;https://goo.gl/dapvbn ссылку пришлось сократить с помощью Google url shortener, так как символы подчеркивания портили её и не давали перейти по 1 клику&amp;lt;/ref&amp;gt;&lt;br /&gt;
*Relatively robust representation методы, появившиеся в 1990-ых и позволяющие найти собственные числа симметричной матрицы порядка &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;n&amp;lt;/math&amp;gt; за &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt; операций&lt;br /&gt;
&lt;br /&gt;
Если требуется вычислить собственные векторы, то необходимо хранить вычисляемые векторы Ланцоша. Если работа при этом производится только с оперативной памятью, то при большом порядке исходной матрицы (а именно для таких матриц и предназначен метод Ланцоша) число шагов  &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;j&amp;lt;/math&amp;gt;, которые могут быть выполнены до того момента, как оперативная память будет исчерпана, будет очень незначительно, а следовательно, искомые собственные пары могут не успеть сойтись с требуемой точностью. В этом случае метод Ланцоша можно использовать итерационным образом: после выполнения заданного числа шагов процесс прерывается и, если еще не все требуемые пары Ритца сошлись с требуемой точностью, то формируется новый начальный вектор &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;q_1&amp;lt;/math&amp;gt;, являющийся линейной комбинацией векторов Ритца, еще не сошедшихся с заданной точностью, и процесс начинается заново.&amp;lt;ref&amp;gt;http://num-anal.srcc.msu.ru/lib_na/int_ae/int_ae6.htm (пункт 6.5)&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
Вычислительное ядро рассматриваемого алгоритма (наиболее ресурсно-затратная часть алгоритма) -  формирование на каждом шаге цикла промежуточного вектора &amp;lt;math&amp;gt;z&amp;lt;/math&amp;gt;, вычисляемого по формуле: &amp;lt;math&amp;gt;z = A\,q_j&amp;lt;/math&amp;gt;. Данная операция, по сравнению с другими операциями алгоритма, затратна и требовательна, как с точки зрения количества производимых операций, так и с точки зрения объема оперируемых данных. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Например, умножение матрицы размера &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;n\times n&amp;lt;/math&amp;gt; на вектор длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; требует: &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;n^2+(n-1)n = 2n^2-n&amp;lt;/math&amp;gt; операций умножения и сложения. В свою очередь аналогичная операция умножения матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;(n+1)\times (n+1)&amp;lt;/math&amp;gt; на вектор длины &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;(n+1)&amp;lt;/math&amp;gt; требует: &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;2n^2+3n+1&amp;lt;/math&amp;gt;  операций умножения и сложения. То есть повышение размерности задачи всего на 1 увеличивает число необходимых действий в этом шаге алгоритма на: &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;4n+1&amp;lt;/math&amp;gt;. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Так же, стоит помнить, что, согласно разделу 1.2, данную операцию умножения матрицы на вектор необходимо выполнить &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;k&amp;lt;/math&amp;gt; раз. Нетрудно понять, насколько возрастает и колоссален масштаб операций, если в задачах, где критична точность, размерности &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; могут иметь порядок &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;10^5&amp;lt;/math&amp;gt; или даже более.&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
Как уже было упомянуто в данной статье в описании алгоритма, рассматриваемый алгоритм состоит из двух последовательно выполненных алгоритмов: метод Ланцоша для построения последовательности подпространств Крылова и ортонормированных векторов Ланцоша и процедура Рэлея-Ритца получения оптимальных приближений собственных значений и соответствующих собственных векторов исходной матрицы.&lt;br /&gt;
&lt;br /&gt;
В первой части алгоритма, где итерационно строятся Крыловское подпространство и трёхдиагональная матрица &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&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 style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; разреженная. Именно она подлежит оптимизации с использованием техник распараллеливания, поскольку она является вычислительным ядром алгоритма, а весь упомянутый процесс построения матрицы &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&amp;lt;/math&amp;gt; выполняется последовательно.&lt;br /&gt;
&lt;br /&gt;
Рассмотрим вторую часть алгоритма - поиск собственных значений сформированной матрицы &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&amp;lt;/math&amp;gt;.&amp;lt;br&amp;gt;&lt;br /&gt;
Далее, наглядно, в виде псевдокода, представлен, упомянутый в разделе 1.2, QR-алгоритм (аналогично можно рассмотреть и QL-алгоритм) со сдвигами Релэя, который весьма популярен на практике.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{align}&lt;br /&gt;
\mathbf{Input}: \;&amp;amp;tridiagonal\;\;matrix \;T\;with\;\;n\times n\;\;size\\&lt;br /&gt;
T^{(0)}&amp;amp;:=T\\&lt;br /&gt;
\mathbf{for}&amp;amp; \;\;m=n,...,2 \;\; \mathbf{do}\\&lt;br /&gt;
&amp;amp;k=0\\&lt;br /&gt;
&amp;amp; \mathbf{repeat}\\&lt;br /&gt;
&amp;amp; \quad \;\; k=k+1\\&lt;br /&gt;
&amp;amp; \quad \;\; \mu^{(k)}=T_{m,m}^{(k-1)}\\&lt;br /&gt;
&amp;amp; \quad \;\; Q^{(k)}R^{(k)}=T^{(k-1)}-\mu^{(k)}I\;\;using\;\;QR\;decomposition\\&lt;br /&gt;
&amp;amp; \quad \;\; T^{(k)}=R^{(k)}Q^{(k)}+\mu^{(k)}I\\&lt;br /&gt;
&amp;amp; \mathbf{until} \;\;\; |T_{m,m-1}^{(k)}| \;is\;\;small\;\;enough\\&lt;br /&gt;
&amp;amp; Save  \;\;T_{m,m}^{(k)} \;\;as\;\; converged\;\;eigenvalue\;of\;T\\ &lt;br /&gt;
&amp;amp; Remove \;\boldsymbol{n}\,th\;row\;and\;\boldsymbol{n}\,th\;column\;\;from \;T \\&lt;br /&gt;
&amp;amp; and\;take\;this\;new\;cropped\;matrix\;as\;new\;T^{(0)}\;with\;\;(n-1)\times (n-1)\;\;size\\&lt;br /&gt;
 \mathbf{end}&amp;amp;\; \mathbf{for}&lt;br /&gt;
\end{align}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Малость наддиагональных и поддиагональных элементов матрицы (фраза &#039;&#039;&amp;quot;small enough&amp;quot;&#039;&#039; в псевдокоде) подразумевает:&lt;br /&gt;
&amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt; |T_{m,m-1}^{(k)}| \leq \varepsilon\,|T_{m,m}^{(k)}| \quad\quad &amp;lt;/math&amp;gt; , где &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt; \varepsilon &amp;lt;/math&amp;gt; - заданная точность&amp;lt;br&amp;gt;&lt;br /&gt;
Также вместо сдвига Релэя, обозначенного в алгоритме через &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;\mu^{(k)}&amp;lt;/math&amp;gt;, часто на практике используется сдвиг по Уилкинсону, который даёт гарантированную сходимость внедиагональных элементов матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt; T^{(k)} &amp;lt;/math&amp;gt;, формируемой на каждом шаге, к нулю, при этом жертвуя монотонностью их убывания.&amp;lt;ref&amp;gt;Голуб Дж., Ван Лоун Ч. - Матричные вычисления//М.: Мир. - 1999 (c. 378, вторая половина страницы)&amp;lt;/ref&amp;gt;&amp;lt;ref&amp;gt;Парлетт Б. Симметричная проблема собственных значений. Численные методы.,: Мир, 1983. с. 169&amp;lt;/ref&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Подробнее с различными сдвигами и соответствующими оценками скоростей и количествами операций можно ознакомиться по указанной ссылке:&amp;lt;ref&amp;gt;Парлетт Б. Симметричная проблема собственных значений. Численные методы.,: Мир, 1983. с. 179-182&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;Для совершения QR-декомпозиции на каждом шаге может использоваться любой из алгоритмов по ссылке.&amp;lt;ref&amp;gt;https://en.wikipedia.org/wiki/QR_decomposition&amp;lt;/ref&amp;gt; Подробные описания этих алгоритмов также доступны на данном ресурсе algowiki-project.&amp;lt;br&amp;gt;&lt;br /&gt;
Так как мы оперируем не обычной матрицей и даже не Хессенберговой, а симметричной и трёхдиагональной, то скорость таких алгоритмов значительно возрастёт. Например, согласно данному ресурсу &amp;lt;ref&amp;gt;http://algorithm.narod.ru/ln/eigen/ETridiag.html&amp;lt;/ref&amp;gt;, для QL-алгоритма с неявными сдвигами:&amp;lt;br&amp;gt;&lt;br /&gt;
Для трёхдиагональной матрицы объем арифметических действий составляет &amp;lt;math&amp;gt; O(n)&amp;lt;/math&amp;gt; на одну итерацию вместо &amp;lt;math&amp;gt; O(n^3)&amp;lt;/math&amp;gt; для матрицы общего вида, а число итераций для нахождения первых собственных значений примерно равно 4 - 5. Но на этих итерациях также уменьшаются внедиагональные элементы правого нижнего угла. И, таким образом, дальнейшие собственные значения ищутся значительно быстрее. Среднее число итераций на каждое собственное значение обычно составляет 1.3 - 1.6.&amp;lt;br&amp;gt; &lt;br /&gt;
Аналогично QL, QR-разложение трёхдиагольной матрицы также требует &amp;lt;math&amp;gt; O(n)&amp;lt;/math&amp;gt; флопов&amp;lt;ref&amp;gt;Голуб Дж., Ван Лоун Ч. - Матричные вычисления//М.: Мир. - 1999 (c. 378, начало раздела 8.2.2)&amp;lt;/ref&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Подводя итог, во второй части алгоритма Ланцоша можно выделить следующие макрооперации:&lt;br /&gt;
* умножение матрицы на вещественное число;&lt;br /&gt;
* перемножение матриц;&lt;br /&gt;
* умножение и сравнение вещественных чисел;&lt;br /&gt;
* + набор других макроопераций в зависимости от выбора метода, с помощью которого будет совершаться сама QR или QL-декомпозиция (выше продемонстрированы, уже, как минимум, 3 разных способа).&lt;br /&gt;
Так же, важно заметить, что набор макропераций может быть несколько другим, если выбрать какой-либо иной современный метод поиска собственных чисел трёхдиагональной матрицы, не использующий QR и QL разложения(факторизацию). Два таких метода были упомянуты в пункте 1.2.&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
С целью полностью не дублировать раздел 1.2 данной статьи, где представлен наглядный и доступный для понимания псевдокод алгоритма, постараемся лишь коротко просуммировать и обобщить весь перечень последовательных действий в рассматриваемом алгоритме.&lt;br /&gt;
&lt;br /&gt;
В качестве входных данных имеем: вещественная симметричная матрица &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; размера &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;n\times n&amp;lt;/math&amp;gt;, известный вещественный вектор &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;b&amp;lt;/math&amp;gt; длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; и число &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;n&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Далее:&lt;br /&gt;
* Инициализируем вещественную константу &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;\beta_0&amp;lt;/math&amp;gt; и векторы &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;q_0&amp;lt;/math&amp;gt; и &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;q_1&amp;lt;/math&amp;gt;&lt;br /&gt;
* Итерационно для всех &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j=1,...,k&amp;lt;/math&amp;gt;:&lt;br /&gt;
** Вычисляем вспомогательный вектор &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt;, используя умножение матрицы на вектор&lt;br /&gt;
** Вычисляем, используя скалярное произведение векторов, значение &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;\alpha_j&amp;lt;/math&amp;gt; - элемент на главной диагонали трёхдиагональной матрицы &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&amp;lt;/math&amp;gt;&lt;br /&gt;
** Вычисляем по формуле новое значение и перезаписываем вектор &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt;&lt;br /&gt;
** Вычисляем значение &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;\beta_j&amp;lt;/math&amp;gt; - элементы непосредственно над и под главной диагональю той же матрицы &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&amp;lt;/math&amp;gt;&lt;br /&gt;
** Вычисляем, зная вектор &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt;,  очередной столбец матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;Q&amp;lt;/math&amp;gt;, он же вектор Ланцоша : &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;\,\,q_{j+1}&amp;lt;/math&amp;gt;&lt;br /&gt;
** Теперь, когда матрица &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&amp;lt;/math&amp;gt; сформирована на очередном шаге, находим её собственные значения и вектора любым доступным способом, о чём было подробно сказано в пункте 1.2&lt;br /&gt;
** Переходим на следующую итерацию: &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j&amp;lt;/math&amp;gt;++&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
Оценим количество операций и сложность последовательного алгоритма, изложенного в предыдущем разделе.&lt;br /&gt;
*Для вычисления вектора &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt; умножается матрица размера &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;n\times n&amp;lt;/math&amp;gt; на вектор длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt;, и потребуется &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n^2&amp;lt;/math&amp;gt; операций умножения и &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n^2&amp;lt;/math&amp;gt; операций сложения.&lt;br /&gt;
*Умножение векторов &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;q^T_j&amp;lt;/math&amp;gt; и &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt; длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; потребует &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; операций умножения и &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; операций сложения.&lt;br /&gt;
*При вычислении нового значения вектора &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt; поэлементное сложение двух векторов длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; требует &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; операций сложения.&lt;br /&gt;
*Умножение вектора длины &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; на вещественное число требует &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; операций умножения.&lt;br /&gt;
*Нахождение квадратичной нормы вектора &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt;  длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; требует &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; умножений и &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; сложений и ещё 1 операцию извлечения квадратного корня.&lt;br /&gt;
*Заключительное нахождение собственных значений и собственных векторов трёхдиагональной матрицы &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;T_j&amp;lt;/math&amp;gt; размера &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j\times j&amp;lt;/math&amp;gt; с помощью QR-алгоритма потребует в худшем случае &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(j^3)&amp;lt;/math&amp;gt; операций.&amp;lt;ref&amp;gt;http://num-anal.srcc.msu.ru/lib_na/int_ae/int_ae6.htm (пункт 6.2, &amp;quot;Скорость сходимости при этом всегда не хуже квадратичной и почти всегда лучше кубической.&amp;quot;)&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Посчитаем теперь суммарное количество простейших операций на одной итерации алгоритма (без учёта записей в память):&lt;br /&gt;
*&amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n^2+5\,n&amp;lt;/math&amp;gt; операций умножения/деления&lt;br /&gt;
*&amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n^2+4\,n&amp;lt;/math&amp;gt; операций сложения/вычитания&lt;br /&gt;
*1 операция извлечения квадратного корня&amp;lt;br&amp;gt;&lt;br /&gt;
Отдельно после всех итераций при &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j=k&amp;lt;/math&amp;gt; :&lt;br /&gt;
*&amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(k^3)&amp;lt;/math&amp;gt; операций для поиска собственных значений и собственных векторов трёхдиагональной матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_k&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Итого можно утверждать следующее:&lt;br /&gt;
&lt;br /&gt;
Последовательная сложность одной итерации рассматриваемого алгоритма:  &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(n ^ 2) &amp;lt;/math&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Суммарная сложность алгоритма (&amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;/math&amp;gt; итераций): &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(k\,n ^ 2) + O(k ^ 3)&amp;lt;/math&amp;gt; &amp;lt;ref&amp;gt;Здесь мы полагаем, что мы не вычисляем собственные значения и векторы матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_j&amp;lt;/math&amp;gt; на каждом промежуточном шаге, а лишь единожды затрачиваем &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;O(k ^ 3)&amp;lt;/math&amp;gt; действий в конце для нахождения &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;/math&amp;gt; собственных значений и векторов матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_k&amp;lt;/math&amp;gt;&amp;lt;/ref&amp;gt; &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
На практике же обычно рассматривается число &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;&amp;lt;n&amp;lt;/math&amp;gt;, поэтому второе слагаемое можно опустить.&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
На рис. 1 продемонстрирован граф одной итерации (при каком-либо произвольном значении итератора &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j&amp;lt;/math&amp;gt;) описанного алгоритма без отображения входных и выходных данных. Наглядно продемонстрированы связи между всеми действиями, и с помощью деления на &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; потоков показано, какие операции возможно выполнять параллельно на каждом шаге с целью оптимизации и экономии машинного времени. В результате, после параллельно выполненных операций &#039;&#039;&#039;Division&#039;&#039;&#039; на заключительном ярусе, на выходе имеем значение следующего вектора Ланцоша &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;q_{j+1}&amp;lt;/math&amp;gt;, после чего следует переход на следующую итерацию, и процесс повторяется.&lt;br /&gt;
&lt;br /&gt;
[[Файл:Levin_graph.png|600px|thumb|center|Рис. 1  Структура одной итерации алгоритма]] &amp;lt;br&amp;gt;&lt;br /&gt;
Обозначения на рисунке: &amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Simp&#039;&#039;&#039; (от англ. simple) - операции сложения и умножения вещественных чисел при вычислении произведения матрицы на вектор;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Vec mult&#039;&#039;&#039; (от англ. vectors multiplication) - операция скалярного умножения двух векторов;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Vec subtr&#039;&#039;&#039; (от англ. vectors subtraction, из-за использованных в операции вычитаний векторов) - операция умножения вектора на число (выполняется дважды) и формирование нового значения &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;z_{new}&amp;lt;/math&amp;gt; по формуле: &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;z_{new} = z - \alpha_j q_j - \beta_{j-1}q_{j-1} \;&amp;lt;/math&amp;gt;;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;||\cdot||&amp;lt;/math&amp;gt; - операция вычисления нормы вектора;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Division&#039;&#039;&#039; - операция деления вектора на вещественное число  &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;\beta_j&amp;lt;/math&amp;gt; &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Важно отметить, что упомянутые выше операции также легко поддаются оптимизации. Например, попарные умножения вещественных координат векторов при вычислении скалярного произведения также легко выполняются параллельно на &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; потоках, а затем можно применить суммирование методом сдваивания, о котором сказано в следующем разделе. Умножение или деление вектора на вещественное число являющееся, по определению, умножением или делением всех его координат на это число тоже может быть выполнено эффективнее, если мы используем &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; потоков, а не выполняем эти действия последовательно.&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
Параллельные операции возможны только внутри итераций, так как рассматриваемый алгоритм является итерационным, и сами итерации строго последовательны.&amp;lt;br&amp;gt;&lt;br /&gt;
Рассмотрим в этом разделе подробнее, какой выигрыш мы можем получить при распараллеливании операций внутри одной итерации согласно графу из предыдущего раздела.&lt;br /&gt;
&lt;br /&gt;
Умножение вещественной симметричной матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; размера &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;n\times n&amp;lt;/math&amp;gt; на вектор &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;b&amp;lt;/math&amp;gt; длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; требует последовательного выполнения &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; ярусов умножений и сложений. Сложение элементов вектора длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; на каждом шаге перемножения можно оптимизировать и выполнить за &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;\log_2 n&amp;lt;/math&amp;gt; действий, если применять метод сдваивания.&lt;br /&gt;
&lt;br /&gt;
Дальнейшие операции выполняются последовательно, а вычисление значений векторов происходит за один ярус операций сложения или умножения.&lt;br /&gt;
&lt;br /&gt;
Ресурс параллелизма алгоритма вычисления собственных значений построенной трёхдиагональной матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_k&amp;lt;/math&amp;gt; размера &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k\times k&amp;lt;/math&amp;gt; зависит от выбранного алгоритма (об этих алгоритмах подробнее было сказано в разделах 1.2 и 1.4). Будет очень затратно с точки зрения объёма материала пытаться рассмотреть пусть даже часть этих методов в этой статье, а так же тонкости их распараллеливания. Предлагаем читателям при желании самим ознакомиться с этими алгоритмами на данном ресурсе или прибегнув к иным источникам.&lt;br /&gt;
&lt;br /&gt;
При классификации по высоте ЯПФ, таким образом, алгоритм Ланцоша без переортогонализации относится к алгоритмам с &#039;&#039;логарифмической сложностью&#039;&#039;, и его сложность равна &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(\log_2 n)&amp;lt;/math&amp;gt; с важным замечанием, что это сложность только одной итерации, а максимум в алгоритме может быть выполнено последовательно &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;/math&amp;gt; таких однотипных итераций, если не будет осуществлён ранний выход из цикла. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Несмотря на то, что на графе в предыдущем разделе для лучшей визуализации и понимания было изображено &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; потоков (никаких допущений мы не делали и нарушений с точки зрения логики и математики нет, можно изобразить большее число потоков, просто часть времени некоторые из них могут бездействовать и не использоваться), на самом деле правильным и разумным будет реализовать начальное параллельное выполнение &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n^2&amp;lt;/math&amp;gt; операций умножения всех вещественных элементов матрицы &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;A&amp;lt;/math&amp;gt; на соответствующие элементы вектора &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;q_j&amp;lt;/math&amp;gt;, после чего применять тот же самый упомянутый метод сдваивания. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Поэтому при классификации по ширине ЯПФ его сложность будет &#039;&#039;квадратичной&#039;&#039; и равна &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(n^2)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
&#039;&#039;&#039;Входные данные алгоритма:&#039;&#039;&#039; вещественная симметричная &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; размера &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;n\times n&amp;lt;/math&amp;gt;, вещественный вектор &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;b&amp;lt;/math&amp;gt; длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt;, и одно целое число &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;k&amp;lt;/math&amp;gt;, означающее количество итераций.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём входных данных:&#039;&#039;&#039; &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;n^2 +n + 1 &amp;lt;/math&amp;gt;. Если учесть, что матрица симметричная и достаточно для её однозначного определения задать элементы на главной диагонали и элементы над или под ней, то можно сократить объём входных данных с целью экономии памяти до: &amp;lt;math&amp;gt;\ \frac{n^2-n}{2}+n+n+1 =\frac{n^2+3n}{2} + 1&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные алгоритма:&#039;&#039;&#039; вектор собственных значений &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;\Theta^k&amp;lt;/math&amp;gt; длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;/math&amp;gt;, матрица &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;S^k&amp;lt;/math&amp;gt; из соответствующих собственных векторов размера &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n\times k&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём выходных данных:&#039;&#039;&#039; &amp;lt;math&amp;gt;k\;(n + 1)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
В данном разделе перечислены без какой-либо хронологии или связи друг с другом наиболее важные и разнообразные свойства алгоритма, на которые стоит и полезно обратить внимание, а также которые выгодно отличают его от схожих алгоритмов, решающих ту же задачу.&amp;lt;br&amp;gt;&lt;br /&gt;
1) Отношение последовательной сложности алгоритма к параллельной,с учётом &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;/math&amp;gt; итераций, равно &amp;lt;math&amp;gt;\;\;\frac{kn^2}{k \log_2{n}}=\frac{n^2}{\log_2{n}}&amp;lt;/math&amp;gt;;&amp;lt;br&amp;gt;&lt;br /&gt;
2) Вычислительная мощность алгоритма, как отношение числа операций к суммарному объему входных и выходных данных, равна &amp;lt;math style=&amp;quot;vertical-align:-70%&amp;gt;\;\;\frac{k\,n^2}{0.5\,n^2+1.5\,n+k\,n+k+1}&amp;lt;/math&amp;gt; и &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;\approx 2\,k&amp;lt;/math&amp;gt;, так как на практике верно отношение &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;&amp;lt;n&amp;lt;/math&amp;gt; ;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
3) Для собственных значений формируемых матриц &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_j&amp;lt;/math&amp;gt; верно отношение (следствие теоремы Коши о перемежаемости): &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;\lambda_i(T_{k+1})\geq \lambda_i(T_{k})\geq \lambda_{i+1}(T_{k+1})\geq \lambda_{i+1}(T_{k})&amp;lt;/math&amp;gt; ;&amp;lt;ref&amp;gt;James W. Demmel - Вычислительная линейная алгебра. Теория и приложения //Мир. - 2001 (c. 383)&amp;lt;/ref&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
4) Крайние (наибольшие и наименьшие) собственные значения матриц &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_j&amp;lt;/math&amp;gt; сходятся к крайним собственным значениям матрицы &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;A&amp;lt;/math&amp;gt; первыми (это часто происходит уже на ранних шагах при &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j\approx 2\,\sqrt{n}&amp;lt;/math&amp;gt;&amp;lt;ref&amp;gt;http://num-anal.srcc.msu.ru/lib_na/int_ae/int_ae6.htm (пункт 6.5)&amp;lt;/ref&amp;gt;), а собственные значения в середине спектра - последними;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
5) Из-за ограниченной точности постепенно теряется ортогональность вектора Ланцоша &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;q_j&amp;lt;/math&amp;gt; к предыдущим векторам Ланцоша, поэтому необходимо примерно каждые 10-15 итераций проводить дорогостоящую операцию реортогонализации, но это уже будет иной алгоритм с очень малым различием в одной операции и в программном коде, реализующем его, соответственно; &amp;lt;ref&amp;gt;Sam Handler - The Lanczos Algorithm For Large-Scale Eigenvalue Problems (08.01.07), slide №8&amp;lt;/ref&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
6) Эффективность и быстрота выполнения алгоритма очень сильно зависит от скорости памяти (диска). Согласно тесту только &#039;&#039;6%&#039;&#039; времени работы программы приходится на вычисления, остальное время затрачивается на ожидание отклика диска;&amp;lt;ref&amp;gt;Sam Handler - The Lanczos Algorithm For Large-Scale Eigenvalue Problems (08.01.07), slide №10&amp;lt;/ref&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
7) Метод Ланцоша удобен тем, что не требует хранения исходной матрицы полным массивом: метод использует исходную матрицу только в операциях умножения матрицы на вектор, что позволяет эффективно использовать разреженность матрицы или регулярность структуры матрицы. Поэтому метод Ланцоша может быть использован для матриц таких больших порядков, когда методы вращений и отражений не могут быть применены.&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;
Для исследования масштабируемости рассматриваемого алгоритма Ланцоша без переортогонализации автором была реализована программа на языке С++ с использованием технологии MPI. &amp;lt;ref&amp;gt;https://goo.gl/pNOFmW  или альтернативная ссылка с прикреплённым кодом: https://goo.gl/9AapM6 , по просьбе на почту я (автор статьи) готов предоставить желающим доступ к проекту с этим кодом на ресурсе Bitbucket&amp;lt;/ref&amp;gt; Дальнейшее исследование было проведено на суперкомпьютере &amp;quot;Ломоносов&amp;quot; Суперкомпьютерного комплекса МГУ. &amp;lt;br&amp;gt; Важно отметить, что реализованная программа выполняет только первую часть алгоритма - формирование матрицы &amp;lt;math &amp;gt;T_j&amp;lt;/math&amp;gt;. Вторая часть алгоритма (задача поиска собственных значений матрицы &amp;lt;math &amp;gt;T_j&amp;lt;/math&amp;gt;) может быть решена несколькими методами, каждый из которых обладает своей эффективностью распараллеливания и характерными свойствами. Подробно этот вопрос уже обсуждался в статье раннее, поэтому не будем ещё раз заострять на этом внимание и останавливаться.&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Сборка осуществлялась со следующими параметрами:&lt;br /&gt;
* Компилятор intel/15.0.090 &lt;br /&gt;
* Openmpi/1.8.4-icc&lt;br /&gt;
В серии проведённых расчётов рассматривались следующие числовые значения параметров:&lt;br /&gt;
* Размер &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;n&amp;lt;/math&amp;gt; задачи и, соответственно, матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt;, задействованной в операции умножения на вектор: [2000 : 30000] с шагом 1000&lt;br /&gt;
* Число процессоров: 1, 2, 4, 16, 32, 48, 64, 96, 128&lt;br /&gt;
* Число итераций в алгоритме: &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k=350&amp;lt;/math&amp;gt;&lt;br /&gt;
Число &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; взято таким вопреки информации в начале статьи, где говорится, что значение &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; редко превышает &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;10^2&amp;lt;/math&amp;gt; (хоть мы и имеем право брать его любым по нашему усмотрению). Это сделано исключительно для лучшей визуализации пиков на графиках в данном разделе и наглядности получаемых результатов, так как при меньших на порядок значениях параметра &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; времена выполнения программ были слишком малы даже при минимальных числах процессоров и максимальных размерах &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;n&amp;lt;/math&amp;gt; задачи.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
На рис. 2 изображён график зависимости времени выполнения программы от числа процессоров и размера &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;n&amp;lt;/math&amp;gt; задачи. &amp;lt;br&amp;gt;&lt;br /&gt;
[[Файл:Levin604 Lanzcos result execTIME.png|580px|thumb|center|Рис. 2  График зависимости времени выполнения программы]] &amp;lt;br&amp;gt;&lt;br /&gt;
Многочисленные тесты показали при малых количествах ядер уменьшение времени выполнения программы почти в 2 раза при увеличении числа ядер в 2 раза на всём диапазоне размеров матриц, что и отражает сильный излом на предоставленом графике. Изменение значения времени можно легко оценить по предоставленной цветовой шкале.&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;
Перечислим далее некоторые из них, указывая язык программирования, лежащий в их основе, и некоторые важные характеристики, которые обсуждались в статье ранее:&lt;br /&gt;
*&#039;&#039;Code on netlib.org by Jane Cullum and Ralph Willoughby&#039;&#039; (&#039;&#039;&#039;Fortran 77&#039;&#039;&#039;; без реортогонализации векторов; без реализации распараллеливания)&amp;lt;ref&amp;gt;http://www.netlib.org/lanczos/leval&amp;lt;/ref&amp;gt;&lt;br /&gt;
*&#039;&#039;Lanczos algorithm on freesourcecode.net&#039;&#039; (&#039;&#039;&#039;Matlab&#039;&#039;&#039;; присутствует реортогонализация векторов; без реализации распараллеливания)&amp;lt;ref&amp;gt;http://freesourcecode.net/matlabprojects/61741/lanczos-algorithm--in-matlab&amp;lt;/ref&amp;gt;&lt;br /&gt;
*&#039;&#039;Lanczos for eigenvalues in Numerical Linear Algebra, Spring 2007&#039;&#039; (&#039;&#039;&#039;Matlab&#039;&#039;&#039;; частичная или полная реортогонализация - доступны оба варианта; без реализации распараллеливания)&amp;lt;ref&amp;gt;Ссылки на файлы lanso.m и lanfu.m можно найти на https://www.nada.kth.se/~ruhe/2D5219/labs2007.html&amp;lt;/ref&amp;gt;&lt;br /&gt;
*&#039;&#039;Planso&#039;&#039; (название происходит от parallel Lanso.f) &#039;&#039;code by Kesheng Wu and Horst D. Simon&#039;&#039; (&#039;&#039;&#039;Fortran 77&#039;&#039;&#039;; частичная реортогонализация векторов; использование MPI для коммуникаций)&amp;lt;ref&amp;gt;https://github.com/jiahao/planso.jl/tree/master/external/PLAN/plan К сожалению, ссылка в описании пакета на github, ведущая на сайт National Energy Research Scientific Computing Center (NERSC), с более подробной информацией о данной программе больше не активна и выдаёт результат &#039;&#039;Page not found&#039;&#039;&amp;lt;/ref&amp;gt; &lt;br /&gt;
* &#039;&#039;Lanczos.cpp in the Vienna Computing Library&#039;&#039;  (&#039;&#039;&#039;C++&#039;&#039;&#039;, частичная реортогонализация, без реализации распараллеливания) &amp;lt;ref&amp;gt;http://viennacl.sourceforge.net/doc/lanczos_8cpp_source.html&amp;lt;/ref&amp;gt;&lt;br /&gt;
* &#039;&#039;Parallel Eigen Values code using C++ AMP on microsoft msdn blog&#039;&#039; (&#039;&#039;&#039;C++&#039;&#039;&#039;; ? ; распараллеливание есть и реализовано через C++ AMP) &amp;lt;ref&amp;gt;https://blogs.msdn.microsoft.com/nativeconcurrency/2013/12/20/eigen-values/ Подробнее о C++ Accelerated Massive Parallelism можно почитать здесь: https://msdn.microsoft.com/ru-ru/library/hh265137(v=vs.140).aspx или здесь: http://professorweb.ru/my/csharp/optimization/level4/4_6.php &amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;br /&gt;
[[en:Description of algorithm properties and structure]]&lt;/div&gt;</summary>
		<author><name>AleksLevin</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:AleksLevin/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%9B%D0%B0%D0%BD%D1%86%D0%BE%D1%88%D0%B0_%D0%B2%D1%8B%D1%87%D0%B8%D1%81%D0%BB%D0%B5%D0%BD%D0%B8%D1%8F_%D1%81%D0%BE%D0%B1%D1%81%D1%82%D0%B2%D0%B5%D0%BD%D0%BD%D1%8B%D1%85_%D0%B7%D0%BD%D0%B0%D1%87%D0%B5%D0%BD%D0%B8%D0%B9_%D1%81%D0%B8%D0%BC%D0%BC%D0%B5%D1%82%D1%80%D0%B8%D1%87%D0%BD%D0%BE%D0%B9_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86%D1%8B_%D0%B4%D0%BB%D1%8F_%D1%82%D0%BE%D1%87%D0%BD%D0%BE%D0%B9_%D0%B0%D1%80%D0%B8%D1%84%D0%BC%D0%B5%D1%82%D0%B8%D0%BA%D0%B8_(%D0%B1%D0%B5%D0%B7_%D0%BF%D0%B5%D1%80%D0%B5%D0%BE%D1%80%D1%82%D0%BE%D0%B3%D0%BE%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D0%B8)&amp;diff=20262</id>
		<title>Участник:AleksLevin/Алгоритм Ланцоша вычисления собственных значений симметричной матрицы для точной арифметики (без переортогонализации)</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:AleksLevin/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%9B%D0%B0%D0%BD%D1%86%D0%BE%D1%88%D0%B0_%D0%B2%D1%8B%D1%87%D0%B8%D1%81%D0%BB%D0%B5%D0%BD%D0%B8%D1%8F_%D1%81%D0%BE%D0%B1%D1%81%D1%82%D0%B2%D0%B5%D0%BD%D0%BD%D1%8B%D1%85_%D0%B7%D0%BD%D0%B0%D1%87%D0%B5%D0%BD%D0%B8%D0%B9_%D1%81%D0%B8%D0%BC%D0%BC%D0%B5%D1%82%D1%80%D0%B8%D1%87%D0%BD%D0%BE%D0%B9_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86%D1%8B_%D0%B4%D0%BB%D1%8F_%D1%82%D0%BE%D1%87%D0%BD%D0%BE%D0%B9_%D0%B0%D1%80%D0%B8%D1%84%D0%BC%D0%B5%D1%82%D0%B8%D0%BA%D0%B8_(%D0%B1%D0%B5%D0%B7_%D0%BF%D0%B5%D1%80%D0%B5%D0%BE%D1%80%D1%82%D0%BE%D0%B3%D0%BE%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D0%B8)&amp;diff=20262"/>
		<updated>2016-12-07T18:06:17Z</updated>

		<summary type="html">&lt;p&gt;AleksLevin: /* Масштабируемость алгоритма и его реализации */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Основные авторы описания: Левин А.Д.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{algorithm&lt;br /&gt;
| name              = Алгоритм Ланцоша для точной арифметики (без переортогонализации)&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(k\,n^2)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(k\log_2 n)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;\frac{n^2+3n}{2} + 1&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;k\;(n + 1)&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритмов =&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Данный алгоритм появился в 1950 г. и носит имя венгерского физика и математика Корнелия Ланцоша (венг. Lánczos Kornél). Алгоритм Ланцоша относится к итерационным методам вычисления собственных значений для матриц столь больших порядков &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt; n&amp;lt;/math&amp;gt;, что к ним нельзя применить прямые методы из-за ограничений по времени и памяти.&lt;br /&gt;
&lt;br /&gt;
Сам Ланцош указывал, что его метод предназначен для отыскания нескольких собственных векторов симметричных матриц, хотя к методу сразу было обращено внимание, как к способу приведения всей матрицы к трёхдиагональному виду. Двадцатью годами позже канадский математик Крис Пэж показал, что, несмотря на чувствительность к округлениям, алгоритм Ланцоша - эффективное средство вычисления некоторых &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; собственных чисел и соответствующих им собственных векторов. &amp;lt;ref&amp;gt;Парлетт Б. - Симметричная проблема собственных значений. Численные методы //М.: Мир. - 1983. (c. 276)&amp;lt;/ref&amp;gt;&lt;br /&gt;
Обычно число &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; берут в два раза больше, чем количество собственных значений матрицы, которые поставлена цель найти, и оно имеет порядок не более &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;10^2&amp;lt;/math&amp;gt;.&amp;lt;ref&amp;gt;Susan W. Bostic - Lanczos Eigensolution Method for High-Perfomance Computers, page 7&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Алгоритм Ланцоша для вычисления собственных значений симметричной матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; соединяет в себе метод Ланцоша для построения последовательности подпространств Крылова и ортонормированных векторов Ланцоша и процедуру Рэлея-Ритца получения оптимальных приближений собственных значений и соответствующих собственных векторов исходной матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt;.&amp;lt;ref&amp;gt;James W. Demmel - Вычислительная линейная алгебра. Теория и приложения //Мир. - 2001 (c. 381)&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
В данной статье рассматривается вариант алгоритма Ланцоша, в котором опущено влияние ошибок округления на вычислительный процесс, хотя на практике этому посвящается отдельное внимание и существуют различные методы решения данной проблемы, такие как частичная или полная переортогонализация. Этим модифицированным методам посвящены отдельные статьи на данном ресурсе.&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
Обозначения и формулы, используемые в данном разделе, взяты из литературы, указанной по ссылке.&amp;lt;ref&amp;gt;James W. Demmel - Вычислительная линейная алгебра. Теория и приложения //Мир. - 2001 (c. 313, &#039;&#039;&amp;lt;math&amp;gt; \S &amp;lt;/math&amp;gt; 6.6 Методы Крыловского подпространства&#039;&#039;)&amp;lt;/ref&amp;gt; &lt;br /&gt;
&lt;br /&gt;
Алгоритм Ланцоша для вычисления &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; собственных значений и собственных векторов вещественной симметричной матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A=A^T&amp;lt;/math&amp;gt; в точной арифметике: &amp;lt;ref&amp;gt;James W. Demmel - Вычислительная линейная алгебра. Теория и приложения //Мир. - 2001 (c. 381)&amp;lt;/ref&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{align}&lt;br /&gt;
q_1 = &amp;amp; \,\frac{b}{\|b\|_2},\; \beta_0 = 0,\; q_0 = 0\\&lt;br /&gt;
\mathbf{for} \; &amp;amp; j = 1 \; to \; k \,\; \mathbf{do} \\&lt;br /&gt;
&amp;amp; z = A\,q_j\\&lt;br /&gt;
&amp;amp; \alpha_j = q^T_j z\\&lt;br /&gt;
&amp;amp; z = z - \alpha_j q_j - \beta_{j-1}q_{j-1}\\&lt;br /&gt;
&amp;amp; \beta_j = \|z\|_2\\&lt;br /&gt;
&amp;amp; \mathbf{If} \; (\beta_j == 0) \; \mathbf{then}\; stop\; the\; algorithm \\ &lt;br /&gt;
&amp;amp; \;  q_{j+1} = \frac{z}{\beta_j} \\&lt;br /&gt;
&amp;amp; compute\; eigenvalues\; and \;eigenvectors\;of \;matrix \;\;T_j= Q^T_j A Q\;\;and\;estimate \;the\; errors\\&lt;br /&gt;
\mathbf{end} \; &amp;amp; \mathbf{for}&lt;br /&gt;
\end{align}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
В продемонстрированном выше алгоритме &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;b&amp;lt;/math&amp;gt; - заданный вещественный вектор. Также полагается известным алгоритм вычисления произведения матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; на вектор &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;x&amp;lt;/math&amp;gt;. &lt;br /&gt;
Введём матрицу Крылова, определяемую следующим соотношением: &amp;lt;math&amp;gt;K_j = [b,Ab,A^2b,...,A^{j-1}b]&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Далее, на практике, матрица &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;K&amp;lt;/math&amp;gt; заменяется матрицей &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;Q&amp;lt;/math&amp;gt;, такой, что при любом числе &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; линейные оболочки первых &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; столбцов в &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;K&amp;lt;/math&amp;gt; и &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;Q&amp;lt;/math&amp;gt; являются одним и тем же подпространством.&amp;lt;ref&amp;gt;James W. Demmel - Вычислительная линейная алгебра. Теория и приложения //Мир. - 2001 (c. 315)&amp;lt;/ref&amp;gt; &lt;br /&gt;
Тогда матрица &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;Q&amp;lt;/math&amp;gt;, в отличие от матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;K&amp;lt;/math&amp;gt;, хорошо обусловлена и легко обратима. В результате получаем матрицу &amp;lt;math&amp;gt;Q_j = [q_1, q_2, \dots, q_j]&amp;lt;/math&amp;gt; размерности &amp;lt;math&amp;gt;n\times j&amp;lt;/math&amp;gt;, столбцы которой ортогональны, являются базисом подпространства Крылова и называются векторами Ланцоша.&lt;br /&gt;
&lt;br /&gt;
В алгоритме Ланцоша вычислению подлежит столько первых столбцов в матрице &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;Q_j&amp;lt;/math&amp;gt;, сколько необходимо для получения требуемого приближения к решению &amp;lt;math&amp;gt;A\,x\,=b\,\,(A\,x=\lambda \, x)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Получение нулевого &amp;lt;math&amp;gt;\beta_j&amp;lt;/math&amp;gt; в итерационном процессе - событие, желательное в том смысле, что оно свидетельствует о том, что найдено некоторое подпространство, являющееся в точности инвариантным, а все собственные значения матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;T_j&amp;lt;/math&amp;gt; являются собственными значениями матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt;. На практике же нулевое и близкие к нулю значения получаются редко.&amp;lt;ref&amp;gt;Голуб Дж., Ван Лоун Ч. - Матричные вычисления//М.: Мир. - 1999 (c. 429)&amp;lt;/ref&amp;gt; &lt;br /&gt;
&lt;br /&gt;
Затем на каждом шаге цикла формируется симметричная трёхдиагональная матрица &amp;lt;math&amp;gt;T_j = Q^T_j A Q&amp;lt;/math&amp;gt;, к которой применяется процесс Рэлея-Ритца для поиска её собственных значений (на практике для поиска этих собственных значений можно использовать любой из специальных методов в параграфе книги по ссылке).&amp;lt;ref&amp;gt;Голуб Дж., Ван Лоун Ч. - Матричные вычисления//М.: Мир. - 1999 (&amp;lt;math&amp;gt;\S&amp;lt;/math&amp;gt; 8.4)&amp;lt;/ref&amp;gt;  &lt;br /&gt;
Эти собственные значения, они же числа Ритца, и полагаются приближёнными собственными значениями исходной матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt;.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Существует множество методов для отыскания собственных значений вещественной симметричной трехдиагональной матрицы. Большинство из них требует &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt; операций &amp;lt;ref&amp;gt;Парлетт Б. Симметричная проблема собственных значений. Численные методы.,: Мир, 1983. с. 179-182&amp;lt;/ref&amp;gt;, но существуют и быстрые алгоритмы, требующие лишь &amp;lt;math&amp;gt;O(n\ln n)&amp;lt;/math&amp;gt; операций.&amp;lt;ref&amp;gt;https://en.wikipedia.org/wiki/Tridiagonal_matrix#Eigenvalues  Раздел eigenvalues&amp;lt;/ref&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Одним из возможных способов отыскать собственные значения симметричной трехдиагональной матрицы - прямое вычисление корней характеристического полинома &amp;lt;math&amp;gt;p_n(\lambda)&amp;lt;/math&amp;gt; через метод деления пополам, где формируется последовательность Штурма и локализуются собственные числа, являющиеся корнями характеристического полинома. Нахождение всех &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; собственных значений матрицы этим способом требует &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;2n^2t&amp;lt;/math&amp;gt; умножений и вычитаний, где &amp;lt;math&amp;gt;t&amp;lt;/math&amp;gt; - число сделанных шагов с применением метода деления пополам.&amp;lt;ref&amp;gt;Уилкинсон Дж. X. Алгебраическая проблема собственныx значений. Изд-во &amp;quot;Наука&amp;quot;, 1970. - глава 5, с. 272-278&amp;lt;/ref&amp;gt; Соответствующие собственные вектора могут быть найдены посредством обратных итераций за &amp;lt;math&amp;gt; O(n) &amp;lt;/math&amp;gt; флопов. &amp;lt;ref&amp;gt;Голуб Дж., Ван Лоун Ч. - Матричные вычисления//М.: Мир. - 1999 (c. 394-395)&amp;lt;/ref&amp;gt; &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;На практике, если требуется только небольшая часть от всей совокупности собственных векторов и значений, и матрица имеет Хессенбергову или трёхдиагональную форму, очень эффективными будут методы факторизации, как, например, QR-алгоритм или QL-алгоритм со сдвигами (c целью ускорить алгоритм и сделать порядок сходимости квадратичным) или же без них.&amp;lt;ref&amp;gt;http://algorithm.narod.ru/ln/eigen/ETridiag.html&amp;lt;/ref&amp;gt; &amp;lt;br&amp;gt;&lt;br /&gt;
Весьма молодые и не менее актуальные конкуренты QR и QL алгоритмов, применяющиеся для поиска собственных значений:&lt;br /&gt;
*Методы divide-and-conquer (разделяй и властвуй), появившиеся в 1980-ых годах &amp;lt;ref&amp;gt;https://goo.gl/dapvbn ссылку пришлось сократить с помощью Google url shortener, так как символы подчеркивания портили её и не давали перейти по 1 клику&amp;lt;/ref&amp;gt;&lt;br /&gt;
*Relatively robust representation методы, появившиеся в 1990-ых и позволяющие найти собственные числа симметричной матрицы порядка &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;n&amp;lt;/math&amp;gt; за &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt; операций&lt;br /&gt;
&lt;br /&gt;
Если требуется вычислить собственные векторы, то необходимо хранить вычисляемые векторы Ланцоша. Если работа при этом производится только с оперативной памятью, то при большом порядке исходной матрицы (а именно для таких матриц и предназначен метод Ланцоша) число шагов  &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;j&amp;lt;/math&amp;gt;, которые могут быть выполнены до того момента, как оперативная память будет исчерпана, будет очень незначительно, а следовательно, искомые собственные пары могут не успеть сойтись с требуемой точностью. В этом случае метод Ланцоша можно использовать итерационным образом: после выполнения заданного числа шагов процесс прерывается и, если еще не все требуемые пары Ритца сошлись с требуемой точностью, то формируется новый начальный вектор &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;q_1&amp;lt;/math&amp;gt;, являющийся линейной комбинацией векторов Ритца, еще не сошедшихся с заданной точностью, и процесс начинается заново.&amp;lt;ref&amp;gt;http://num-anal.srcc.msu.ru/lib_na/int_ae/int_ae6.htm (пункт 6.5)&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
Вычислительное ядро рассматриваемого алгоритма (наиболее ресурсно-затратная часть алгоритма) -  формирование на каждом шаге цикла промежуточного вектора &amp;lt;math&amp;gt;z&amp;lt;/math&amp;gt;, вычисляемого по формуле: &amp;lt;math&amp;gt;z = A\,q_j&amp;lt;/math&amp;gt;. Данная операция, по сравнению с другими операциями алгоритма, затратна и требовательна, как с точки зрения количества производимых операций, так и с точки зрения объема оперируемых данных. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Например, умножение матрицы размера &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;n\times n&amp;lt;/math&amp;gt; на вектор длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; требует: &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;n^2+(n-1)n = 2n^2-n&amp;lt;/math&amp;gt; операций умножения и сложения. В свою очередь аналогичная операция умножения матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;(n+1)\times (n+1)&amp;lt;/math&amp;gt; на вектор длины &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;(n+1)&amp;lt;/math&amp;gt; требует: &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;2n^2+3n+1&amp;lt;/math&amp;gt;  операций умножения и сложения. То есть повышение размерности задачи всего на 1 увеличивает число необходимых действий в этом шаге алгоритма на: &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;4n+1&amp;lt;/math&amp;gt;. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Так же, стоит помнить, что, согласно разделу 1.2, данную операцию умножения матрицы на вектор необходимо выполнить &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;k&amp;lt;/math&amp;gt; раз. Нетрудно понять, насколько возрастает и колоссален масштаб операций, если в задачах, где критична точность, размерности &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; могут иметь порядок &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;10^5&amp;lt;/math&amp;gt; или даже более.&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
Как уже было упомянуто в данной статье в описании алгоритма, рассматриваемый алгоритм состоит из двух последовательно выполненных алгоритмов: метод Ланцоша для построения последовательности подпространств Крылова и ортонормированных векторов Ланцоша и процедура Рэлея-Ритца получения оптимальных приближений собственных значений и соответствующих собственных векторов исходной матрицы.&lt;br /&gt;
&lt;br /&gt;
В первой части алгоритма, где итерационно строятся Крыловское подпространство и трёхдиагональная матрица &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&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 style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; разреженная. Именно она подлежит оптимизации с использованием техник распараллеливания, поскольку она является вычислительным ядром алгоритма, а весь упомянутый процесс построения матрицы &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&amp;lt;/math&amp;gt; выполняется последовательно.&lt;br /&gt;
&lt;br /&gt;
Рассмотрим вторую часть алгоритма - поиск собственных значений сформированной матрицы &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&amp;lt;/math&amp;gt;.&amp;lt;br&amp;gt;&lt;br /&gt;
Далее, наглядно, в виде псевдокода, представлен, упомянутый в разделе 1.2, QR-алгоритм (аналогично можно рассмотреть и QL-алгоритм) со сдвигами Релэя, который весьма популярен на практике.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{align}&lt;br /&gt;
\mathbf{Input}: \;&amp;amp;tridiagonal\;\;matrix \;T\;with\;\;n\times n\;\;size\\&lt;br /&gt;
T^{(0)}&amp;amp;:=T\\&lt;br /&gt;
\mathbf{for}&amp;amp; \;\;m=n,...,2 \;\; \mathbf{do}\\&lt;br /&gt;
&amp;amp;k=0\\&lt;br /&gt;
&amp;amp; \mathbf{repeat}\\&lt;br /&gt;
&amp;amp; \quad \;\; k=k+1\\&lt;br /&gt;
&amp;amp; \quad \;\; \mu^{(k)}=T_{m,m}^{(k-1)}\\&lt;br /&gt;
&amp;amp; \quad \;\; Q^{(k)}R^{(k)}=T^{(k-1)}-\mu^{(k)}I\;\;using\;\;QR\;decomposition\\&lt;br /&gt;
&amp;amp; \quad \;\; T^{(k)}=R^{(k)}Q^{(k)}+\mu^{(k)}I\\&lt;br /&gt;
&amp;amp; \mathbf{until} \;\;\; |T_{m,m-1}^{(k)}| \;is\;\;small\;\;enough\\&lt;br /&gt;
&amp;amp; Save  \;\;T_{m,m}^{(k)} \;\;as\;\; converged\;\;eigenvalue\;of\;T\\ &lt;br /&gt;
&amp;amp; Remove \;\boldsymbol{n}\,th\;row\;and\;\boldsymbol{n}\,th\;column\;\;from \;T \\&lt;br /&gt;
&amp;amp; and\;take\;this\;new\;cropped\;matrix\;as\;new\;T^{(0)}\;with\;\;(n-1)\times (n-1)\;\;size\\&lt;br /&gt;
 \mathbf{end}&amp;amp;\; \mathbf{for}&lt;br /&gt;
\end{align}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Малость наддиагональных и поддиагональных элементов матрицы (фраза &#039;&#039;&amp;quot;small enough&amp;quot;&#039;&#039; в псевдокоде) подразумевает:&lt;br /&gt;
&amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt; |T_{m,m-1}^{(k)}| \leq \varepsilon\,|T_{m,m}^{(k)}| \quad\quad &amp;lt;/math&amp;gt; , где &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt; \varepsilon &amp;lt;/math&amp;gt; - заданная точность&amp;lt;br&amp;gt;&lt;br /&gt;
Также вместо сдвига Релэя, обозначенного в алгоритме через &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;\mu^{(k)}&amp;lt;/math&amp;gt;, часто на практике используется сдвиг по Уилкинсону, который даёт гарантированную сходимость внедиагональных элементов матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt; T^{(k)} &amp;lt;/math&amp;gt;, формируемой на каждом шаге, к нулю, при этом жертвуя монотонностью их убывания.&amp;lt;ref&amp;gt;Голуб Дж., Ван Лоун Ч. - Матричные вычисления//М.: Мир. - 1999 (c. 378, вторая половина страницы)&amp;lt;/ref&amp;gt;&amp;lt;ref&amp;gt;Парлетт Б. Симметричная проблема собственных значений. Численные методы.,: Мир, 1983. с. 169&amp;lt;/ref&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Подробнее с различными сдвигами и соответствующими оценками скоростей и количествами операций можно ознакомиться по указанной ссылке:&amp;lt;ref&amp;gt;Парлетт Б. Симметричная проблема собственных значений. Численные методы.,: Мир, 1983. с. 179-182&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;Для совершения QR-декомпозиции на каждом шаге может использоваться любой из алгоритмов по ссылке.&amp;lt;ref&amp;gt;https://en.wikipedia.org/wiki/QR_decomposition&amp;lt;/ref&amp;gt; Подробные описания этих алгоритмов также доступны на данном ресурсе algowiki-project.&amp;lt;br&amp;gt;&lt;br /&gt;
Так как мы оперируем не обычной матрицей и даже не Хессенберговой, а симметричной и трёхдиагональной, то скорость таких алгоритмов значительно возрастёт. Например, согласно данному ресурсу &amp;lt;ref&amp;gt;http://algorithm.narod.ru/ln/eigen/ETridiag.html&amp;lt;/ref&amp;gt;, для QL-алгоритма с неявными сдвигами:&amp;lt;br&amp;gt;&lt;br /&gt;
Для трёхдиагональной матрицы объем арифметических действий составляет &amp;lt;math&amp;gt; O(n)&amp;lt;/math&amp;gt; на одну итерацию вместо &amp;lt;math&amp;gt; O(n^3)&amp;lt;/math&amp;gt; для матрицы общего вида, а число итераций для нахождения первых собственных значений примерно равно 4 - 5. Но на этих итерациях также уменьшаются внедиагональные элементы правого нижнего угла. И, таким образом, дальнейшие собственные значения ищутся значительно быстрее. Среднее число итераций на каждое собственное значение обычно составляет 1.3 - 1.6.&amp;lt;br&amp;gt; &lt;br /&gt;
Аналогично QL, QR-разложение трёхдиагольной матрицы также требует &amp;lt;math&amp;gt; O(n)&amp;lt;/math&amp;gt; флопов&amp;lt;ref&amp;gt;Голуб Дж., Ван Лоун Ч. - Матричные вычисления//М.: Мир. - 1999 (c. 378, начало раздела 8.2.2)&amp;lt;/ref&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Подводя итог, во второй части алгоритма Ланцоша можно выделить следующие макрооперации:&lt;br /&gt;
* умножение матрицы на вещественное число;&lt;br /&gt;
* перемножение матриц;&lt;br /&gt;
* умножение и сравнение вещественных чисел;&lt;br /&gt;
* + набор других макроопераций в зависимости от выбора метода, с помощью которого будет совершаться сама QR или QL-декомпозиция (выше продемонстрированы, уже, как минимум, 3 разных способа).&lt;br /&gt;
Так же, важно заметить, что набор макропераций может быть несколько другим, если выбрать какой-либо иной современный метод поиска собственных чисел трёхдиагональной матрицы, не использующий QR и QL разложения(факторизацию). Два таких метода были упомянуты в пункте 1.2.&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
С целью полностью не дублировать раздел 1.2 данной статьи, где представлен наглядный и доступный для понимания псевдокод алгоритма, постараемся лишь коротко просуммировать и обобщить весь перечень последовательных действий в рассматриваемом алгоритме.&lt;br /&gt;
&lt;br /&gt;
В качестве входных данных имеем: вещественная симметричная матрица &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; размера &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;n\times n&amp;lt;/math&amp;gt;, известный вещественный вектор &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;b&amp;lt;/math&amp;gt; длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; и число &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;n&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Далее:&lt;br /&gt;
* Инициализируем вещественную константу &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;\beta_0&amp;lt;/math&amp;gt; и векторы &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;q_0&amp;lt;/math&amp;gt; и &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;q_1&amp;lt;/math&amp;gt;&lt;br /&gt;
* Итерационно для всех &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j=1,...,k&amp;lt;/math&amp;gt;:&lt;br /&gt;
** Вычисляем вспомогательный вектор &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt;, используя умножение матрицы на вектор&lt;br /&gt;
** Вычисляем, используя скалярное произведение векторов, значение &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;\alpha_j&amp;lt;/math&amp;gt; - элемент на главной диагонали трёхдиагональной матрицы &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&amp;lt;/math&amp;gt;&lt;br /&gt;
** Вычисляем по формуле новое значение и перезаписываем вектор &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt;&lt;br /&gt;
** Вычисляем значение &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;\beta_j&amp;lt;/math&amp;gt; - элементы непосредственно над и под главной диагональю той же матрицы &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&amp;lt;/math&amp;gt;&lt;br /&gt;
** Вычисляем, зная вектор &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt;,  очередной столбец матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;Q&amp;lt;/math&amp;gt;, он же вектор Ланцоша : &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;\,\,q_{j+1}&amp;lt;/math&amp;gt;&lt;br /&gt;
** Теперь, когда матрица &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&amp;lt;/math&amp;gt; сформирована на очередном шаге, находим её собственные значения и вектора любым доступным способом, о чём было подробно сказано в пункте 1.2&lt;br /&gt;
** Переходим на следующую итерацию: &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j&amp;lt;/math&amp;gt;++&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
Оценим количество операций и сложность последовательного алгоритма, изложенного в предыдущем разделе.&lt;br /&gt;
*Для вычисления вектора &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt; умножается матрица размера &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;n\times n&amp;lt;/math&amp;gt; на вектор длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt;, и потребуется &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n^2&amp;lt;/math&amp;gt; операций умножения и &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n^2&amp;lt;/math&amp;gt; операций сложения.&lt;br /&gt;
*Умножение векторов &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;q^T_j&amp;lt;/math&amp;gt; и &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt; длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; потребует &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; операций умножения и &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; операций сложения.&lt;br /&gt;
*При вычислении нового значения вектора &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt; поэлементное сложение двух векторов длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; требует &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; операций сложения.&lt;br /&gt;
*Умножение вектора длины &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; на вещественное число требует &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; операций умножения.&lt;br /&gt;
*Нахождение квадратичной нормы вектора &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt;  длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; требует &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; умножений и &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; сложений и ещё 1 операцию извлечения квадратного корня.&lt;br /&gt;
*Заключительное нахождение собственных значений и собственных векторов трёхдиагональной матрицы &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;T_j&amp;lt;/math&amp;gt; размера &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j\times j&amp;lt;/math&amp;gt; с помощью QR-алгоритма потребует в худшем случае &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(j^3)&amp;lt;/math&amp;gt; операций.&amp;lt;ref&amp;gt;http://num-anal.srcc.msu.ru/lib_na/int_ae/int_ae6.htm (пункт 6.2, &amp;quot;Скорость сходимости при этом всегда не хуже квадратичной и почти всегда лучше кубической.&amp;quot;)&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Посчитаем теперь суммарное количество простейших операций на одной итерации алгоритма (без учёта записей в память):&lt;br /&gt;
*&amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n^2+5\,n&amp;lt;/math&amp;gt; операций умножения/деления&lt;br /&gt;
*&amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n^2+4\,n&amp;lt;/math&amp;gt; операций сложения/вычитания&lt;br /&gt;
*1 операция извлечения квадратного корня&amp;lt;br&amp;gt;&lt;br /&gt;
Отдельно после всех итераций при &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j=k&amp;lt;/math&amp;gt; :&lt;br /&gt;
*&amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(k^3)&amp;lt;/math&amp;gt; операций для поиска собственных значений и собственных векторов трёхдиагональной матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_k&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Итого можно утверждать следующее:&lt;br /&gt;
&lt;br /&gt;
Последовательная сложность одной итерации рассматриваемого алгоритма:  &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(n ^ 2) &amp;lt;/math&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Суммарная сложность алгоритма (&amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;/math&amp;gt; итераций): &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(k\,n ^ 2) + O(k ^ 3)&amp;lt;/math&amp;gt; &amp;lt;ref&amp;gt;Здесь мы полагаем, что мы не вычисляем собственные значения и векторы матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_j&amp;lt;/math&amp;gt; на каждом промежуточном шаге, а лишь единожды затрачиваем &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;O(k ^ 3)&amp;lt;/math&amp;gt; действий в конце для нахождения &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;/math&amp;gt; собственных значений и векторов матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_k&amp;lt;/math&amp;gt;&amp;lt;/ref&amp;gt; &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
На практике же обычно рассматривается число &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;&amp;lt;n&amp;lt;/math&amp;gt;, поэтому второе слагаемое можно опустить.&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
На рис. 1 продемонстрирован граф одной итерации (при каком-либо произвольном значении итератора &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j&amp;lt;/math&amp;gt;) описанного алгоритма без отображения входных и выходных данных. Наглядно продемонстрированы связи между всеми действиями, и с помощью деления на &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; потоков показано, какие операции возможно выполнять параллельно на каждом шаге с целью оптимизации и экономии машинного времени. В результате, после параллельно выполненных операций &#039;&#039;&#039;Division&#039;&#039;&#039; на заключительном ярусе, на выходе имеем значение следующего вектора Ланцоша &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;q_{j+1}&amp;lt;/math&amp;gt;, после чего следует переход на следующую итерацию, и процесс повторяется.&lt;br /&gt;
&lt;br /&gt;
[[Файл:Levin_graph.png|600px|thumb|center|Рис. 1  Структура одной итерации алгоритма]] &amp;lt;br&amp;gt;&lt;br /&gt;
Обозначения на рисунке: &amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Simp&#039;&#039;&#039; (от англ. simple) - операции сложения и умножения вещественных чисел при вычислении произведения матрицы на вектор;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Vec mult&#039;&#039;&#039; (от англ. vectors multiplication) - операция скалярного умножения двух векторов;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Vec subtr&#039;&#039;&#039; (от англ. vectors subtraction, из-за использованных в операции вычитаний векторов) - операция умножения вектора на число (выполняется дважды) и формирование нового значения &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;z_{new}&amp;lt;/math&amp;gt; по формуле: &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;z_{new} = z - \alpha_j q_j - \beta_{j-1}q_{j-1} \;&amp;lt;/math&amp;gt;;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;||\cdot||&amp;lt;/math&amp;gt; - операция вычисления нормы вектора;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Division&#039;&#039;&#039; - операция деления вектора на вещественное число  &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;\beta_j&amp;lt;/math&amp;gt; &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Важно отметить, что упомянутые выше операции также легко поддаются оптимизации. Например, попарные умножения вещественных координат векторов при вычислении скалярного произведения также легко выполняются параллельно на &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; потоках, а затем можно применить суммирование методом сдваивания, о котором сказано в следующем разделе. Умножение или деление вектора на вещественное число являющееся, по определению, умножением или делением всех его координат на это число тоже может быть выполнено эффективнее, если мы используем &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; потоков, а не выполняем эти действия последовательно.&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
Параллельные операции возможны только внутри итераций, так как рассматриваемый алгоритм является итерационным, и сами итерации строго последовательны.&amp;lt;br&amp;gt;&lt;br /&gt;
Рассмотрим в этом разделе подробнее, какой выигрыш мы можем получить при распараллеливании операций внутри одной итерации согласно графу из предыдущего раздела.&lt;br /&gt;
&lt;br /&gt;
Умножение вещественной симметричной матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; размера &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;n\times n&amp;lt;/math&amp;gt; на вектор &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;b&amp;lt;/math&amp;gt; длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; требует последовательного выполнения &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; ярусов умножений и сложений. Сложение элементов вектора длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; на каждом шаге перемножения можно оптимизировать и выполнить за &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;\log_2 n&amp;lt;/math&amp;gt; действий, если применять метод сдваивания.&lt;br /&gt;
&lt;br /&gt;
Дальнейшие операции выполняются последовательно, а вычисление значений векторов происходит за один ярус операций сложения или умножения.&lt;br /&gt;
&lt;br /&gt;
Ресурс параллелизма алгоритма вычисления собственных значений построенной трёхдиагональной матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_k&amp;lt;/math&amp;gt; размера &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k\times k&amp;lt;/math&amp;gt; зависит от выбранного алгоритма (об этих алгоритмах подробнее было сказано в разделах 1.2 и 1.4). Будет очень затратно с точки зрения объёма материала пытаться рассмотреть пусть даже часть этих методов в этой статье, а так же тонкости их распараллеливания. Предлагаем читателям при желании самим ознакомиться с этими алгоритмами на данном ресурсе или прибегнув к иным источникам.&lt;br /&gt;
&lt;br /&gt;
При классификации по высоте ЯПФ, таким образом, алгоритм Ланцоша без переортогонализации относится к алгоритмам с &#039;&#039;логарифмической сложностью&#039;&#039;, и его сложность равна &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(\log_2 n)&amp;lt;/math&amp;gt; с важным замечанием, что это сложность только одной итерации, а максимум в алгоритме может быть выполнено последовательно &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;/math&amp;gt; таких однотипных итераций, если не будет осуществлён ранний выход из цикла. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Несмотря на то, что на графе в предыдущем разделе для лучшей визуализации и понимания было изображено &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; потоков (никаких допущений мы не делали и нарушений с точки зрения логики и математики нет, можно изобразить большее число потоков, просто часть времени некоторые из них могут бездействовать и не использоваться), на самом деле правильным и разумным будет реализовать начальное параллельное выполнение &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n^2&amp;lt;/math&amp;gt; операций умножения всех вещественных элементов матрицы &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;A&amp;lt;/math&amp;gt; на соответствующие элементы вектора &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;q_j&amp;lt;/math&amp;gt;, после чего применять тот же самый упомянутый метод сдваивания. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Поэтому при классификации по ширине ЯПФ его сложность будет &#039;&#039;квадратичной&#039;&#039; и равна &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(n^2)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
&#039;&#039;&#039;Входные данные алгоритма:&#039;&#039;&#039; вещественная симметричная &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; размера &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;n\times n&amp;lt;/math&amp;gt;, вещественный вектор &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;b&amp;lt;/math&amp;gt; длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt;, и одно целое число &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;k&amp;lt;/math&amp;gt;, означающее количество итераций.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём входных данных:&#039;&#039;&#039; &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;n^2 +n + 1 &amp;lt;/math&amp;gt;. Если учесть, что матрица симметричная и достаточно для её однозначного определения задать элементы на главной диагонали и элементы над или под ней, то можно сократить объём входных данных с целью экономии памяти до: &amp;lt;math&amp;gt;\ \frac{n^2-n}{2}+n+n+1 =\frac{n^2+3n}{2} + 1&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные алгоритма:&#039;&#039;&#039; вектор собственных значений &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;\Theta^k&amp;lt;/math&amp;gt; длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;/math&amp;gt;, матрица &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;S^k&amp;lt;/math&amp;gt; из соответствующих собственных векторов размера &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n\times k&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём выходных данных:&#039;&#039;&#039; &amp;lt;math&amp;gt;k\;(n + 1)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
В данном разделе перечислены без какой-либо хронологии или связи друг с другом наиболее важные и разнообразные свойства алгоритма, на которые стоит и полезно обратить внимание, а также которые выгодно отличают его от схожих алгоритмов, решающих ту же задачу.&amp;lt;br&amp;gt;&lt;br /&gt;
1) Отношение последовательной сложности алгоритма к параллельной,с учётом &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;/math&amp;gt; итераций, равно &amp;lt;math&amp;gt;\;\;\frac{kn^2}{k \log_2{n}}=\frac{n^2}{\log_2{n}}&amp;lt;/math&amp;gt;;&amp;lt;br&amp;gt;&lt;br /&gt;
2) Вычислительная мощность алгоритма, как отношение числа операций к суммарному объему входных и выходных данных, равна &amp;lt;math style=&amp;quot;vertical-align:-70%&amp;gt;\;\;\frac{k\,n^2}{0.5\,n^2+1.5\,n+k\,n+k+1}&amp;lt;/math&amp;gt; и &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;\approx 2\,k&amp;lt;/math&amp;gt;, так как на практике верно отношение &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;&amp;lt;n&amp;lt;/math&amp;gt; ;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
3) Для собственных значений формируемых матриц &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_j&amp;lt;/math&amp;gt; верно отношение (следствие теоремы Коши о перемежаемости): &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;\lambda_i(T_{k+1})\geq \lambda_i(T_{k})\geq \lambda_{i+1}(T_{k+1})\geq \lambda_{i+1}(T_{k})&amp;lt;/math&amp;gt; ;&amp;lt;ref&amp;gt;James W. Demmel - Вычислительная линейная алгебра. Теория и приложения //Мир. - 2001 (c. 383)&amp;lt;/ref&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
4) Крайние (наибольшие и наименьшие) собственные значения матриц &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_j&amp;lt;/math&amp;gt; сходятся к крайним собственным значениям матрицы &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;A&amp;lt;/math&amp;gt; первыми (это часто происходит уже на ранних шагах при &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j\approx 2\,\sqrt{n}&amp;lt;/math&amp;gt;&amp;lt;ref&amp;gt;http://num-anal.srcc.msu.ru/lib_na/int_ae/int_ae6.htm (пункт 6.5)&amp;lt;/ref&amp;gt;), а собственные значения в середине спектра - последними;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
5) Из-за ограниченной точности постепенно теряется ортогональность вектора Ланцоша &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;q_j&amp;lt;/math&amp;gt; к предыдущим векторам Ланцоша, поэтому необходимо примерно каждые 10-15 итераций проводить дорогостоящую операцию реортогонализации, но это уже будет иной алгоритм с очень малым различием в одной операции и в программном коде, реализующем его, соответственно; &amp;lt;ref&amp;gt;Sam Handler - The Lanczos Algorithm For Large-Scale Eigenvalue Problems (08.01.07), slide №8&amp;lt;/ref&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
6) Эффективность и быстрота выполнения алгоритма очень сильно зависит от скорости памяти (диска). Согласно тесту только &#039;&#039;6%&#039;&#039; времени работы программы приходится на вычисления, остальное время затрачивается на ожидание отклика диска;&amp;lt;ref&amp;gt;Sam Handler - The Lanczos Algorithm For Large-Scale Eigenvalue Problems (08.01.07), slide №10&amp;lt;/ref&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
7) Метод Ланцоша удобен тем, что не требует хранения исходной матрицы полным массивом: метод использует исходную матрицу только в операциях умножения матрицы на вектор, что позволяет эффективно использовать разреженность матрицы или регулярность структуры матрицы. Поэтому метод Ланцоша может быть использован для матриц таких больших порядков, когда методы вращений и отражений не могут быть применены.&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;
Для исследования масштабируемости рассматриваемого алгоритма Ланцоша без переортогонализации автором была реализована программа на языке С++ с использованием технологии MPI. &amp;lt;ref&amp;gt;https://goo.gl/pNOFmW  или альтернативная ссылка с прикреплённым кодом: https://goo.gl/9AapM6 , по просьбе на почту я (автор статьи) готов предоставить желающим доступ к проекту с этим кодом на ресурсе Bitbucket&amp;lt;/ref&amp;gt; Дальнейшее исследование было проведено на суперкомпьютере &amp;quot;Ломоносов&amp;quot; Суперкомпьютерного комплекса МГУ. &amp;lt;br&amp;gt; Важно отметить, что реализованная программа выполняет только первую часть алгоритма - формирование матрицы &amp;lt;math &amp;gt;T_j&amp;lt;/math&amp;gt;. Вторая часть алгоритма (задача поиска собственных значений матрицы &amp;lt;math &amp;gt;T_j&amp;lt;/math&amp;gt;) может быть решена несколькими методами, каждый из которых обладает своей эффективностью распараллеливания и характерными свойствами. Подробно этот вопрос уже обсуждался в статье раннее, поэтому не будем ещё раз заострять на этом внимание и останавливаться.&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Сборка осуществлялась со следующими параметрами:&lt;br /&gt;
* Компилятор intel/15.0.090 &lt;br /&gt;
* Openmpi/1.8.4-icc&lt;br /&gt;
В серии проведённых расчётов рассматривались следующие числовые значения параметров:&lt;br /&gt;
* Размер &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;n&amp;lt;/math&amp;gt; задачи и, соответственно, матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt;, задействованной в операции умножения на вектор: [2000 : 30000] с шагом 1000&lt;br /&gt;
* Число процессоров: 1, 2, 4, 16, 32, 48, 64, 96, 128&lt;br /&gt;
* Число итераций в алгоритме: &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k=350&amp;lt;/math&amp;gt;&lt;br /&gt;
Число &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; взято таким вопреки информации в начале статьи, где говорится, что значение &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; редко превышает &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;10^2&amp;lt;/math&amp;gt; (хоть мы и имеем право брать его любым по нашему усмотрению). Это сделано исключительно для лучшей визуализации пиков на графиках в данном разделе и наглядности получаемых результатов, так как при меньших на порядок значениях параметра &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; времена выполнения программ были слишком малы даже при минимальных числах процессоров и максимальных размерах &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;n&amp;lt;/math&amp;gt; задачи.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
На рис. 2 изображён график зависимости времени выполнения программы от числа процессоров и размера &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;n&amp;lt;/math&amp;gt; задачи. &amp;lt;br&amp;gt;&lt;br /&gt;
[[Файл:Levin604 Lanzcos result execTIME.png|580px|thumb|center|Рис. 2  График зависимости времени выполнения программы]] &amp;lt;br&amp;gt;&lt;br /&gt;
Многочисленные тесты показали при малых количествах ядер уменьшение времени выполнения программы почти в 2 раза при увеличении числа ядер в 2 раза на всём диапазоне размеров матриц, что и отражает сильный излом на предоставленом графике. Изменение значения времени можно легко оценить по предоставленной цветовой шкале.&lt;br /&gt;
&lt;br /&gt;
== Динамические характеристики и эффективность реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Выводы для классов архитектур ==&lt;br /&gt;
По заданию, во второй части требовалось описать только разделы 2.4 и 2.7, прошу не спрашивать с меня все разделы 2.1-2.6. Надеюсь на понимание, мне физически не хватает времени на это задание + 2 других в течение семестра, делаю всё, что в моих силах :)&lt;br /&gt;
&lt;br /&gt;
== Существующие реализации алгоритма ==&lt;br /&gt;
Несмотря на то, что алгоритм является далеко не самым популярным, алгоритмом, про который нельзя сказать, что он всегда «на слуху», на сегодняшний день существует множество реализаций на различных популярных языках.&amp;lt;br&amp;gt;&lt;br /&gt;
Перечислим далее некоторые из них, указывая язык программирования, лежащий в их основе, и некоторые важные характеристики, которые обсуждались в статье ранее:&lt;br /&gt;
*&#039;&#039;Code on netlib.org by Jane Cullum and Ralph Willoughby&#039;&#039; (&#039;&#039;&#039;Fortran 77&#039;&#039;&#039;; без реортогонализации векторов; без реализации распараллеливания)&amp;lt;ref&amp;gt;http://www.netlib.org/lanczos/leval&amp;lt;/ref&amp;gt;&lt;br /&gt;
*&#039;&#039;Lanczos algorithm on freesourcecode.net&#039;&#039; (&#039;&#039;&#039;Matlab&#039;&#039;&#039;; присутствует реортогонализация векторов; без реализации распараллеливания)&amp;lt;ref&amp;gt;http://freesourcecode.net/matlabprojects/61741/lanczos-algorithm--in-matlab&amp;lt;/ref&amp;gt;&lt;br /&gt;
*&#039;&#039;Lanczos for eigenvalues in Numerical Linear Algebra, Spring 2007&#039;&#039; (&#039;&#039;&#039;Matlab&#039;&#039;&#039;; частичная или полная реортогонализация - доступны оба варианта; без реализации распараллеливания)&amp;lt;ref&amp;gt;Ссылки на файлы lanso.m и lanfu.m можно найти на https://www.nada.kth.se/~ruhe/2D5219/labs2007.html&amp;lt;/ref&amp;gt;&lt;br /&gt;
*&#039;&#039;Planso&#039;&#039; (название происходит от parallel Lanso.f) &#039;&#039;code by Kesheng Wu and Horst D. Simon&#039;&#039; (&#039;&#039;&#039;Fortran 77&#039;&#039;&#039;; частичная реортогонализация векторов; использование MPI для коммуникаций)&amp;lt;ref&amp;gt;https://github.com/jiahao/planso.jl/tree/master/external/PLAN/plan К сожалению, ссылка в описании пакета на github, ведущая на сайт National Energy Research Scientific Computing Center (NERSC), с более подробной информацией о данной программе больше не активна и выдаёт результат &#039;&#039;Page not found&#039;&#039;&amp;lt;/ref&amp;gt; &lt;br /&gt;
* &#039;&#039;Lanczos.cpp in the Vienna Computing Library&#039;&#039;  (&#039;&#039;&#039;C++&#039;&#039;&#039;, частичная реортогонализация, без реализации распараллеливания) &amp;lt;ref&amp;gt;http://viennacl.sourceforge.net/doc/lanczos_8cpp_source.html&amp;lt;/ref&amp;gt;&lt;br /&gt;
* &#039;&#039;Parallel Eigen Values code using C++ AMP on microsoft msdn blog&#039;&#039; (&#039;&#039;&#039;C++&#039;&#039;&#039;; ? ; распараллеливание есть и реализовано через C++ AMP) &amp;lt;ref&amp;gt;https://blogs.msdn.microsoft.com/nativeconcurrency/2013/12/20/eigen-values/ Подробнее о C++ Accelerated Massive Parallelism можно почитать здесь: https://msdn.microsoft.com/ru-ru/library/hh265137(v=vs.140).aspx или здесь: http://professorweb.ru/my/csharp/optimization/level4/4_6.php &amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;br /&gt;
[[en:Description of algorithm properties and structure]]&lt;/div&gt;</summary>
		<author><name>AleksLevin</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:AleksLevin/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%9B%D0%B0%D0%BD%D1%86%D0%BE%D1%88%D0%B0_%D0%B2%D1%8B%D1%87%D0%B8%D1%81%D0%BB%D0%B5%D0%BD%D0%B8%D1%8F_%D1%81%D0%BE%D0%B1%D1%81%D1%82%D0%B2%D0%B5%D0%BD%D0%BD%D1%8B%D1%85_%D0%B7%D0%BD%D0%B0%D1%87%D0%B5%D0%BD%D0%B8%D0%B9_%D1%81%D0%B8%D0%BC%D0%BC%D0%B5%D1%82%D1%80%D0%B8%D1%87%D0%BD%D0%BE%D0%B9_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86%D1%8B_%D0%B4%D0%BB%D1%8F_%D1%82%D0%BE%D1%87%D0%BD%D0%BE%D0%B9_%D0%B0%D1%80%D0%B8%D1%84%D0%BC%D0%B5%D1%82%D0%B8%D0%BA%D0%B8_(%D0%B1%D0%B5%D0%B7_%D0%BF%D0%B5%D1%80%D0%B5%D0%BE%D1%80%D1%82%D0%BE%D0%B3%D0%BE%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D0%B8)&amp;diff=20244</id>
		<title>Участник:AleksLevin/Алгоритм Ланцоша вычисления собственных значений симметричной матрицы для точной арифметики (без переортогонализации)</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:AleksLevin/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%9B%D0%B0%D0%BD%D1%86%D0%BE%D1%88%D0%B0_%D0%B2%D1%8B%D1%87%D0%B8%D1%81%D0%BB%D0%B5%D0%BD%D0%B8%D1%8F_%D1%81%D0%BE%D0%B1%D1%81%D1%82%D0%B2%D0%B5%D0%BD%D0%BD%D1%8B%D1%85_%D0%B7%D0%BD%D0%B0%D1%87%D0%B5%D0%BD%D0%B8%D0%B9_%D1%81%D0%B8%D0%BC%D0%BC%D0%B5%D1%82%D1%80%D0%B8%D1%87%D0%BD%D0%BE%D0%B9_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86%D1%8B_%D0%B4%D0%BB%D1%8F_%D1%82%D0%BE%D1%87%D0%BD%D0%BE%D0%B9_%D0%B0%D1%80%D0%B8%D1%84%D0%BC%D0%B5%D1%82%D0%B8%D0%BA%D0%B8_(%D0%B1%D0%B5%D0%B7_%D0%BF%D0%B5%D1%80%D0%B5%D0%BE%D1%80%D1%82%D0%BE%D0%B3%D0%BE%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D0%B8)&amp;diff=20244"/>
		<updated>2016-12-07T13:20:11Z</updated>

		<summary type="html">&lt;p&gt;AleksLevin: /* Масштабируемость алгоритма и его реализации */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Основные авторы описания: Левин А.Д.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{algorithm&lt;br /&gt;
| name              = Алгоритм Ланцоша для точной арифметики (без переортогонализации)&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(k\,n^2)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(k\log_2 n)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;\frac{n^2+3n}{2} + 1&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;k\;(n + 1)&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритмов =&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Данный алгоритм появился в 1950 г. и носит имя венгерского физика и математика Корнелия Ланцоша (венг. Lánczos Kornél). Алгоритм Ланцоша относится к итерационным методам вычисления собственных значений для матриц столь больших порядков &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt; n&amp;lt;/math&amp;gt;, что к ним нельзя применить прямые методы из-за ограничений по времени и памяти.&lt;br /&gt;
&lt;br /&gt;
Сам Ланцош указывал, что его метод предназначен для отыскания нескольких собственных векторов симметричных матриц, хотя к методу сразу было обращено внимание, как к способу приведения всей матрицы к трёхдиагональному виду. Двадцатью годами позже канадский математик Крис Пэж показал, что, несмотря на чувствительность к округлениям, алгоритм Ланцоша - эффективное средство вычисления некоторых &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; собственных чисел и соответствующих им собственных векторов. &amp;lt;ref&amp;gt;Парлетт Б. - Симметричная проблема собственных значений. Численные методы //М.: Мир. - 1983. (c. 276)&amp;lt;/ref&amp;gt;&lt;br /&gt;
Обычно число &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; берут в два раза больше, чем количество собственных значений матрицы, которые поставлена цель найти, и оно имеет порядок не более &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;10^2&amp;lt;/math&amp;gt;.&amp;lt;ref&amp;gt;Susan W. Bostic - Lanczos Eigensolution Method for High-Perfomance Computers, page 7&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Алгоритм Ланцоша для вычисления собственных значений симметричной матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; соединяет в себе метод Ланцоша для построения последовательности подпространств Крылова и ортонормированных векторов Ланцоша и процедуру Рэлея-Ритца получения оптимальных приближений собственных значений и соответствующих собственных векторов исходной матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt;.&amp;lt;ref&amp;gt;James W. Demmel - Вычислительная линейная алгебра. Теория и приложения //Мир. - 2001 (c. 381)&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
В данной статье рассматривается вариант алгоритма Ланцоша, в котором опущено влияние ошибок округления на вычислительный процесс, хотя на практике этому посвящается отдельное внимание и существуют различные методы решения данной проблемы, такие как частичная или полная переортогонализация. Этим модифицированным методам посвящены отдельные статьи на данном ресурсе.&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
Обозначения и формулы, используемые в данном разделе, взяты из литературы, указанной по ссылке.&amp;lt;ref&amp;gt;James W. Demmel - Вычислительная линейная алгебра. Теория и приложения //Мир. - 2001 (c. 313, &#039;&#039;&amp;lt;math&amp;gt; \S &amp;lt;/math&amp;gt; 6.6 Методы Крыловского подпространства&#039;&#039;)&amp;lt;/ref&amp;gt; &lt;br /&gt;
&lt;br /&gt;
Алгоритм Ланцоша для вычисления &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; собственных значений и собственных векторов вещественной симметричной матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A=A^T&amp;lt;/math&amp;gt; в точной арифметике: &amp;lt;ref&amp;gt;James W. Demmel - Вычислительная линейная алгебра. Теория и приложения //Мир. - 2001 (c. 381)&amp;lt;/ref&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{align}&lt;br /&gt;
q_1 = &amp;amp; \,\frac{b}{\|b\|_2},\; \beta_0 = 0,\; q_0 = 0\\&lt;br /&gt;
\mathbf{for} \; &amp;amp; j = 1 \; to \; k \,\; \mathbf{do} \\&lt;br /&gt;
&amp;amp; z = A\,q_j\\&lt;br /&gt;
&amp;amp; \alpha_j = q^T_j z\\&lt;br /&gt;
&amp;amp; z = z - \alpha_j q_j - \beta_{j-1}q_{j-1}\\&lt;br /&gt;
&amp;amp; \beta_j = \|z\|_2\\&lt;br /&gt;
&amp;amp; \mathbf{If} \; (\beta_j == 0) \; \mathbf{then}\; stop\; the\; algorithm \\ &lt;br /&gt;
&amp;amp; \;  q_{j+1} = \frac{z}{\beta_j} \\&lt;br /&gt;
&amp;amp; compute\; eigenvalues\; and \;eigenvectors\;of \;matrix \;\;T_j= Q^T_j A Q\;\;and\;estimate \;the\; errors\\&lt;br /&gt;
\mathbf{end} \; &amp;amp; \mathbf{for}&lt;br /&gt;
\end{align}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
В продемонстрированном выше алгоритме &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;b&amp;lt;/math&amp;gt; - заданный вещественный вектор. Также полагается известным алгоритм вычисления произведения матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; на вектор &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;x&amp;lt;/math&amp;gt;. &lt;br /&gt;
Введём матрицу Крылова, определяемую следующим соотношением: &amp;lt;math&amp;gt;K_j = [b,Ab,A^2b,...,A^{j-1}b]&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Далее, на практике, матрица &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;K&amp;lt;/math&amp;gt; заменяется матрицей &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;Q&amp;lt;/math&amp;gt;, такой, что при любом числе &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; линейные оболочки первых &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; столбцов в &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;K&amp;lt;/math&amp;gt; и &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;Q&amp;lt;/math&amp;gt; являются одним и тем же подпространством.&amp;lt;ref&amp;gt;James W. Demmel - Вычислительная линейная алгебра. Теория и приложения //Мир. - 2001 (c. 315)&amp;lt;/ref&amp;gt; &lt;br /&gt;
Тогда матрица &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;Q&amp;lt;/math&amp;gt;, в отличие от матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;K&amp;lt;/math&amp;gt;, хорошо обусловлена и легко обратима. В результате получаем матрицу &amp;lt;math&amp;gt;Q_j = [q_1, q_2, \dots, q_j]&amp;lt;/math&amp;gt; размерности &amp;lt;math&amp;gt;n\times j&amp;lt;/math&amp;gt;, столбцы которой ортогональны, являются базисом подпространства Крылова и называются векторами Ланцоша.&lt;br /&gt;
&lt;br /&gt;
В алгоритме Ланцоша вычислению подлежит столько первых столбцов в матрице &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;Q_j&amp;lt;/math&amp;gt;, сколько необходимо для получения требуемого приближения к решению &amp;lt;math&amp;gt;A\,x\,=b\,\,(A\,x=\lambda \, x)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Получение нулевого &amp;lt;math&amp;gt;\beta_j&amp;lt;/math&amp;gt; в итерационном процессе - событие, желательное в том смысле, что оно свидетельствует о том, что найдено некоторое подпространство, являющееся в точности инвариантным, а все собственные значения матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;T_j&amp;lt;/math&amp;gt; являются собственными значениями матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt;. На практике же нулевое и близкие к нулю значения получаются редко.&amp;lt;ref&amp;gt;Голуб Дж., Ван Лоун Ч. - Матричные вычисления//М.: Мир. - 1999 (c. 429)&amp;lt;/ref&amp;gt; &lt;br /&gt;
&lt;br /&gt;
Затем на каждом шаге цикла формируется симметричная трёхдиагональная матрица &amp;lt;math&amp;gt;T_j = Q^T_j A Q&amp;lt;/math&amp;gt;, к которой применяется процесс Рэлея-Ритца для поиска её собственных значений (на практике для поиска этих собственных значений можно использовать любой из специальных методов в параграфе книги по ссылке).&amp;lt;ref&amp;gt;Голуб Дж., Ван Лоун Ч. - Матричные вычисления//М.: Мир. - 1999 (&amp;lt;math&amp;gt;\S&amp;lt;/math&amp;gt; 8.4)&amp;lt;/ref&amp;gt;  &lt;br /&gt;
Эти собственные значения, они же числа Ритца, и полагаются приближёнными собственными значениями исходной матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt;.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Существует множество методов для отыскания собственных значений вещественной симметричной трехдиагональной матрицы. Большинство из них требует &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt; операций &amp;lt;ref&amp;gt;Парлетт Б. Симметричная проблема собственных значений. Численные методы.,: Мир, 1983. с. 179-182&amp;lt;/ref&amp;gt;, но существуют и быстрые алгоритмы, требующие лишь &amp;lt;math&amp;gt;O(n\ln n)&amp;lt;/math&amp;gt; операций.&amp;lt;ref&amp;gt;https://en.wikipedia.org/wiki/Tridiagonal_matrix#Eigenvalues  Раздел eigenvalues&amp;lt;/ref&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Одним из возможных способов отыскать собственные значения симметричной трехдиагональной матрицы - прямое вычисление корней характеристического полинома &amp;lt;math&amp;gt;p_n(\lambda)&amp;lt;/math&amp;gt; через метод деления пополам, где формируется последовательность Штурма и локализуются собственные числа, являющиеся корнями характеристического полинома. Нахождение всех &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; собственных значений матрицы этим способом требует &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;2n^2t&amp;lt;/math&amp;gt; умножений и вычитаний, где &amp;lt;math&amp;gt;t&amp;lt;/math&amp;gt; - число сделанных шагов с применением метода деления пополам.&amp;lt;ref&amp;gt;Уилкинсон Дж. X. Алгебраическая проблема собственныx значений. Изд-во &amp;quot;Наука&amp;quot;, 1970. - глава 5, с. 272-278&amp;lt;/ref&amp;gt; Соответствующие собственные вектора могут быть найдены посредством обратных итераций за &amp;lt;math&amp;gt; O(n) &amp;lt;/math&amp;gt; флопов. &amp;lt;ref&amp;gt;Голуб Дж., Ван Лоун Ч. - Матричные вычисления//М.: Мир. - 1999 (c. 394-395)&amp;lt;/ref&amp;gt; &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;На практике, если требуется только небольшая часть от всей совокупности собственных векторов и значений, и матрица имеет Хессенбергову или трёхдиагональную форму, очень эффективными будут методы факторизации, как, например, QR-алгоритм или QL-алгоритм со сдвигами (c целью ускорить алгоритм и сделать порядок сходимости квадратичным) или же без них.&amp;lt;ref&amp;gt;http://algorithm.narod.ru/ln/eigen/ETridiag.html&amp;lt;/ref&amp;gt; &amp;lt;br&amp;gt;&lt;br /&gt;
Весьма молодые и не менее актуальные конкуренты QR и QL алгоритмов, применяющиеся для поиска собственных значений:&lt;br /&gt;
*Методы divide-and-conquer (разделяй и властвуй), появившиеся в 1980-ых годах &amp;lt;ref&amp;gt;https://goo.gl/dapvbn ссылку пришлось сократить с помощью Google url shortener, так как символы подчеркивания портили её и не давали перейти по 1 клику&amp;lt;/ref&amp;gt;&lt;br /&gt;
*Relatively robust representation методы, появившиеся в 1990-ых и позволяющие найти собственные числа симметричной матрицы порядка &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;n&amp;lt;/math&amp;gt; за &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt; операций&lt;br /&gt;
&lt;br /&gt;
Если требуется вычислить собственные векторы, то необходимо хранить вычисляемые векторы Ланцоша. Если работа при этом производится только с оперативной памятью, то при большом порядке исходной матрицы (а именно для таких матриц и предназначен метод Ланцоша) число шагов  &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;j&amp;lt;/math&amp;gt;, которые могут быть выполнены до того момента, как оперативная память будет исчерпана, будет очень незначительно, а следовательно, искомые собственные пары могут не успеть сойтись с требуемой точностью. В этом случае метод Ланцоша можно использовать итерационным образом: после выполнения заданного числа шагов процесс прерывается и, если еще не все требуемые пары Ритца сошлись с требуемой точностью, то формируется новый начальный вектор &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;q_1&amp;lt;/math&amp;gt;, являющийся линейной комбинацией векторов Ритца, еще не сошедшихся с заданной точностью, и процесс начинается заново.&amp;lt;ref&amp;gt;http://num-anal.srcc.msu.ru/lib_na/int_ae/int_ae6.htm (пункт 6.5)&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
Вычислительное ядро рассматриваемого алгоритма (наиболее ресурсно-затратная часть алгоритма) -  формирование на каждом шаге цикла промежуточного вектора &amp;lt;math&amp;gt;z&amp;lt;/math&amp;gt;, вычисляемого по формуле: &amp;lt;math&amp;gt;z = A\,q_j&amp;lt;/math&amp;gt;. Данная операция, по сравнению с другими операциями алгоритма, затратна и требовательна, как с точки зрения количества производимых операций, так и с точки зрения объема оперируемых данных. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Например, умножение матрицы размера &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;n\times n&amp;lt;/math&amp;gt; на вектор длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; требует: &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;n^2+(n-1)n = 2n^2-n&amp;lt;/math&amp;gt; операций умножения и сложения. В свою очередь аналогичная операция умножения матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;(n+1)\times (n+1)&amp;lt;/math&amp;gt; на вектор длины &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;(n+1)&amp;lt;/math&amp;gt; требует: &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;2n^2+3n+1&amp;lt;/math&amp;gt;  операций умножения и сложения. То есть повышение размерности задачи всего на 1 увеличивает число необходимых действий в этом шаге алгоритма на: &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;4n+1&amp;lt;/math&amp;gt;. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Так же, стоит помнить, что, согласно разделу 1.2, данную операцию умножения матрицы на вектор необходимо выполнить &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;k&amp;lt;/math&amp;gt; раз. Нетрудно понять, насколько возрастает и колоссален масштаб операций, если в задачах, где критична точность, размерности &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; могут иметь порядок &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;10^5&amp;lt;/math&amp;gt; или даже более.&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
Как уже было упомянуто в данной статье в описании алгоритма, рассматриваемый алгоритм состоит из двух последовательно выполненных алгоритмов: метод Ланцоша для построения последовательности подпространств Крылова и ортонормированных векторов Ланцоша и процедура Рэлея-Ритца получения оптимальных приближений собственных значений и соответствующих собственных векторов исходной матрицы.&lt;br /&gt;
&lt;br /&gt;
В первой части алгоритма, где итерационно строятся Крыловское подпространство и трёхдиагональная матрица &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&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 style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; разреженная. Именно она подлежит оптимизации с использованием техник распараллеливания, поскольку она является вычислительным ядром алгоритма, а весь упомянутый процесс построения матрицы &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&amp;lt;/math&amp;gt; выполняется последовательно.&lt;br /&gt;
&lt;br /&gt;
Рассмотрим вторую часть алгоритма - поиск собственных значений сформированной матрицы &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&amp;lt;/math&amp;gt;.&amp;lt;br&amp;gt;&lt;br /&gt;
Далее, наглядно, в виде псевдокода, представлен, упомянутый в разделе 1.2, QR-алгоритм (аналогично можно рассмотреть и QL-алгоритм) со сдвигами Релэя, который весьма популярен на практике.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{align}&lt;br /&gt;
\mathbf{Input}: \;&amp;amp;tridiagonal\;\;matrix \;T\;with\;\;n\times n\;\;size\\&lt;br /&gt;
T^{(0)}&amp;amp;:=T\\&lt;br /&gt;
\mathbf{for}&amp;amp; \;\;m=n,...,2 \;\; \mathbf{do}\\&lt;br /&gt;
&amp;amp;k=0\\&lt;br /&gt;
&amp;amp; \mathbf{repeat}\\&lt;br /&gt;
&amp;amp; \quad \;\; k=k+1\\&lt;br /&gt;
&amp;amp; \quad \;\; \mu^{(k)}=T_{m,m}^{(k-1)}\\&lt;br /&gt;
&amp;amp; \quad \;\; Q^{(k)}R^{(k)}=T^{(k-1)}-\mu^{(k)}I\;\;using\;\;QR\;decomposition\\&lt;br /&gt;
&amp;amp; \quad \;\; T^{(k)}=R^{(k)}Q^{(k)}+\mu^{(k)}I\\&lt;br /&gt;
&amp;amp; \mathbf{until} \;\;\; |T_{m,m-1}^{(k)}| \;is\;\;small\;\;enough\\&lt;br /&gt;
&amp;amp; Save  \;\;T_{m,m}^{(k)} \;\;as\;\; converged\;\;eigenvalue\;of\;T\\ &lt;br /&gt;
&amp;amp; Remove \;\boldsymbol{n}\,th\;row\;and\;\boldsymbol{n}\,th\;column\;\;from \;T \\&lt;br /&gt;
&amp;amp; and\;take\;this\;new\;cropped\;matrix\;as\;new\;T^{(0)}\;with\;\;(n-1)\times (n-1)\;\;size\\&lt;br /&gt;
 \mathbf{end}&amp;amp;\; \mathbf{for}&lt;br /&gt;
\end{align}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Малость наддиагональных и поддиагональных элементов матрицы (фраза &#039;&#039;&amp;quot;small enough&amp;quot;&#039;&#039; в псевдокоде) подразумевает:&lt;br /&gt;
&amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt; |T_{m,m-1}^{(k)}| \leq \varepsilon\,|T_{m,m}^{(k)}| \quad\quad &amp;lt;/math&amp;gt; , где &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt; \varepsilon &amp;lt;/math&amp;gt; - заданная точность&amp;lt;br&amp;gt;&lt;br /&gt;
Также вместо сдвига Релэя, обозначенного в алгоритме через &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;\mu^{(k)}&amp;lt;/math&amp;gt;, часто на практике используется сдвиг по Уилкинсону, который даёт гарантированную сходимость внедиагональных элементов матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt; T^{(k)} &amp;lt;/math&amp;gt;, формируемой на каждом шаге, к нулю, при этом жертвуя монотонностью их убывания.&amp;lt;ref&amp;gt;Голуб Дж., Ван Лоун Ч. - Матричные вычисления//М.: Мир. - 1999 (c. 378, вторая половина страницы)&amp;lt;/ref&amp;gt;&amp;lt;ref&amp;gt;Парлетт Б. Симметричная проблема собственных значений. Численные методы.,: Мир, 1983. с. 169&amp;lt;/ref&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Подробнее с различными сдвигами и соответствующими оценками скоростей и количествами операций можно ознакомиться по указанной ссылке:&amp;lt;ref&amp;gt;Парлетт Б. Симметричная проблема собственных значений. Численные методы.,: Мир, 1983. с. 179-182&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;Для совершения QR-декомпозиции на каждом шаге может использоваться любой из алгоритмов по ссылке.&amp;lt;ref&amp;gt;https://en.wikipedia.org/wiki/QR_decomposition&amp;lt;/ref&amp;gt; Подробные описания этих алгоритмов также доступны на данном ресурсе algowiki-project.&amp;lt;br&amp;gt;&lt;br /&gt;
Так как мы оперируем не обычной матрицей и даже не Хессенберговой, а симметричной и трёхдиагональной, то скорость таких алгоритмов значительно возрастёт. Например, согласно данному ресурсу &amp;lt;ref&amp;gt;http://algorithm.narod.ru/ln/eigen/ETridiag.html&amp;lt;/ref&amp;gt;, для QL-алгоритма с неявными сдвигами:&amp;lt;br&amp;gt;&lt;br /&gt;
Для трёхдиагональной матрицы объем арифметических действий составляет &amp;lt;math&amp;gt; O(n)&amp;lt;/math&amp;gt; на одну итерацию вместо &amp;lt;math&amp;gt; O(n^3)&amp;lt;/math&amp;gt; для матрицы общего вида, а число итераций для нахождения первых собственных значений примерно равно 4 - 5. Но на этих итерациях также уменьшаются внедиагональные элементы правого нижнего угла. И, таким образом, дальнейшие собственные значения ищутся значительно быстрее. Среднее число итераций на каждое собственное значение обычно составляет 1.3 - 1.6.&amp;lt;br&amp;gt; &lt;br /&gt;
Аналогично QL, QR-разложение трёхдиагольной матрицы также требует &amp;lt;math&amp;gt; O(n)&amp;lt;/math&amp;gt; флопов&amp;lt;ref&amp;gt;Голуб Дж., Ван Лоун Ч. - Матричные вычисления//М.: Мир. - 1999 (c. 378, начало раздела 8.2.2)&amp;lt;/ref&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Подводя итог, во второй части алгоритма Ланцоша можно выделить следующие макрооперации:&lt;br /&gt;
* умножение матрицы на вещественное число;&lt;br /&gt;
* перемножение матриц;&lt;br /&gt;
* умножение и сравнение вещественных чисел;&lt;br /&gt;
* + набор других макроопераций в зависимости от выбора метода, с помощью которого будет совершаться сама QR или QL-декомпозиция (выше продемонстрированы, уже, как минимум, 3 разных способа).&lt;br /&gt;
Так же, важно заметить, что набор макропераций может быть несколько другим, если выбрать какой-либо иной современный метод поиска собственных чисел трёхдиагональной матрицы, не использующий QR и QL разложения(факторизацию). Два таких метода были упомянуты в пункте 1.2.&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
С целью полностью не дублировать раздел 1.2 данной статьи, где представлен наглядный и доступный для понимания псевдокод алгоритма, постараемся лишь коротко просуммировать и обобщить весь перечень последовательных действий в рассматриваемом алгоритме.&lt;br /&gt;
&lt;br /&gt;
В качестве входных данных имеем: вещественная симметричная матрица &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; размера &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;n\times n&amp;lt;/math&amp;gt;, известный вещественный вектор &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;b&amp;lt;/math&amp;gt; длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; и число &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;n&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Далее:&lt;br /&gt;
* Инициализируем вещественную константу &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;\beta_0&amp;lt;/math&amp;gt; и векторы &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;q_0&amp;lt;/math&amp;gt; и &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;q_1&amp;lt;/math&amp;gt;&lt;br /&gt;
* Итерационно для всех &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j=1,...,k&amp;lt;/math&amp;gt;:&lt;br /&gt;
** Вычисляем вспомогательный вектор &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt;, используя умножение матрицы на вектор&lt;br /&gt;
** Вычисляем, используя скалярное произведение векторов, значение &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;\alpha_j&amp;lt;/math&amp;gt; - элемент на главной диагонали трёхдиагональной матрицы &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&amp;lt;/math&amp;gt;&lt;br /&gt;
** Вычисляем по формуле новое значение и перезаписываем вектор &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt;&lt;br /&gt;
** Вычисляем значение &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;\beta_j&amp;lt;/math&amp;gt; - элементы непосредственно над и под главной диагональю той же матрицы &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&amp;lt;/math&amp;gt;&lt;br /&gt;
** Вычисляем, зная вектор &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt;,  очередной столбец матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;Q&amp;lt;/math&amp;gt;, он же вектор Ланцоша : &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;\,\,q_{j+1}&amp;lt;/math&amp;gt;&lt;br /&gt;
** Теперь, когда матрица &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&amp;lt;/math&amp;gt; сформирована на очередном шаге, находим её собственные значения и вектора любым доступным способом, о чём было подробно сказано в пункте 1.2&lt;br /&gt;
** Переходим на следующую итерацию: &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j&amp;lt;/math&amp;gt;++&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
Оценим количество операций и сложность последовательного алгоритма, изложенного в предыдущем разделе.&lt;br /&gt;
*Для вычисления вектора &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt; умножается матрица размера &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;n\times n&amp;lt;/math&amp;gt; на вектор длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt;, и потребуется &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n^2&amp;lt;/math&amp;gt; операций умножения и &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n^2&amp;lt;/math&amp;gt; операций сложения.&lt;br /&gt;
*Умножение векторов &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;q^T_j&amp;lt;/math&amp;gt; и &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt; длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; потребует &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; операций умножения и &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; операций сложения.&lt;br /&gt;
*При вычислении нового значения вектора &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt; поэлементное сложение двух векторов длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; требует &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; операций сложения.&lt;br /&gt;
*Умножение вектора длины &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; на вещественное число требует &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; операций умножения.&lt;br /&gt;
*Нахождение квадратичной нормы вектора &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt;  длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; требует &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; умножений и &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; сложений и ещё 1 операцию извлечения квадратного корня.&lt;br /&gt;
*Заключительное нахождение собственных значений и собственных векторов трёхдиагональной матрицы &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;T_j&amp;lt;/math&amp;gt; размера &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j\times j&amp;lt;/math&amp;gt; с помощью QR-алгоритма потребует в худшем случае &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(j^3)&amp;lt;/math&amp;gt; операций.&amp;lt;ref&amp;gt;http://num-anal.srcc.msu.ru/lib_na/int_ae/int_ae6.htm (пункт 6.2, &amp;quot;Скорость сходимости при этом всегда не хуже квадратичной и почти всегда лучше кубической.&amp;quot;)&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Посчитаем теперь суммарное количество простейших операций на одной итерации алгоритма (без учёта записей в память):&lt;br /&gt;
*&amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n^2+5\,n&amp;lt;/math&amp;gt; операций умножения/деления&lt;br /&gt;
*&amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n^2+4\,n&amp;lt;/math&amp;gt; операций сложения/вычитания&lt;br /&gt;
*1 операция извлечения квадратного корня&amp;lt;br&amp;gt;&lt;br /&gt;
Отдельно после всех итераций при &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j=k&amp;lt;/math&amp;gt; :&lt;br /&gt;
*&amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(k^3)&amp;lt;/math&amp;gt; операций для поиска собственных значений и собственных векторов трёхдиагональной матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_k&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Итого можно утверждать следующее:&lt;br /&gt;
&lt;br /&gt;
Последовательная сложность одной итерации рассматриваемого алгоритма:  &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(n ^ 2) &amp;lt;/math&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Суммарная сложность алгоритма (&amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;/math&amp;gt; итераций): &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(k\,n ^ 2) + O(k ^ 3)&amp;lt;/math&amp;gt; &amp;lt;ref&amp;gt;Здесь мы полагаем, что мы не вычисляем собственные значения и векторы матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_j&amp;lt;/math&amp;gt; на каждом промежуточном шаге, а лишь единожды затрачиваем &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;O(k ^ 3)&amp;lt;/math&amp;gt; действий в конце для нахождения &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;/math&amp;gt; собственных значений и векторов матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_k&amp;lt;/math&amp;gt;&amp;lt;/ref&amp;gt; &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
На практике же обычно рассматривается число &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;&amp;lt;n&amp;lt;/math&amp;gt;, поэтому второе слагаемое можно опустить.&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
На рис. 1 продемонстрирован граф одной итерации (при каком-либо произвольном значении итератора &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j&amp;lt;/math&amp;gt;) описанного алгоритма без отображения входных и выходных данных. Наглядно продемонстрированы связи между всеми действиями, и с помощью деления на &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; потоков показано, какие операции возможно выполнять параллельно на каждом шаге с целью оптимизации и экономии машинного времени. В результате, после параллельно выполненных операций &#039;&#039;&#039;Division&#039;&#039;&#039; на заключительном ярусе, на выходе имеем значение следующего вектора Ланцоша &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;q_{j+1}&amp;lt;/math&amp;gt;, после чего следует переход на следующую итерацию, и процесс повторяется.&lt;br /&gt;
&lt;br /&gt;
[[Файл:Levin_graph.png|600px|thumb|center|Рис. 1  Структура одной итерации алгоритма]] &amp;lt;br&amp;gt;&lt;br /&gt;
Обозначения на рисунке: &amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Simp&#039;&#039;&#039; (от англ. simple) - операции сложения и умножения вещественных чисел при вычислении произведения матрицы на вектор;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Vec mult&#039;&#039;&#039; (от англ. vectors multiplication) - операция скалярного умножения двух векторов;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Vec subtr&#039;&#039;&#039; (от англ. vectors subtraction, из-за использованных в операции вычитаний векторов) - операция умножения вектора на число (выполняется дважды) и формирование нового значения &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;z_{new}&amp;lt;/math&amp;gt; по формуле: &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;z_{new} = z - \alpha_j q_j - \beta_{j-1}q_{j-1} \;&amp;lt;/math&amp;gt;;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;||\cdot||&amp;lt;/math&amp;gt; - операция вычисления нормы вектора;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Division&#039;&#039;&#039; - операция деления вектора на вещественное число  &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;\beta_j&amp;lt;/math&amp;gt; &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Важно отметить, что упомянутые выше операции также легко поддаются оптимизации. Например, попарные умножения вещественных координат векторов при вычислении скалярного произведения также легко выполняются параллельно на &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; потоках, а затем можно применить суммирование методом сдваивания, о котором сказано в следующем разделе. Умножение или деление вектора на вещественное число являющееся, по определению, умножением или делением всех его координат на это число тоже может быть выполнено эффективнее, если мы используем &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; потоков, а не выполняем эти действия последовательно.&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
Параллельные операции возможны только внутри итераций, так как рассматриваемый алгоритм является итерационным, и сами итерации строго последовательны.&amp;lt;br&amp;gt;&lt;br /&gt;
Рассмотрим в этом разделе подробнее, какой выигрыш мы можем получить при распараллеливании операций внутри одной итерации согласно графу из предыдущего раздела.&lt;br /&gt;
&lt;br /&gt;
Умножение вещественной симметричной матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; размера &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;n\times n&amp;lt;/math&amp;gt; на вектор &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;b&amp;lt;/math&amp;gt; длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; требует последовательного выполнения &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; ярусов умножений и сложений. Сложение элементов вектора длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; на каждом шаге перемножения можно оптимизировать и выполнить за &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;\log_2 n&amp;lt;/math&amp;gt; действий, если применять метод сдваивания.&lt;br /&gt;
&lt;br /&gt;
Дальнейшие операции выполняются последовательно, а вычисление значений векторов происходит за один ярус операций сложения или умножения.&lt;br /&gt;
&lt;br /&gt;
Ресурс параллелизма алгоритма вычисления собственных значений построенной трёхдиагональной матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_k&amp;lt;/math&amp;gt; размера &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k\times k&amp;lt;/math&amp;gt; зависит от выбранного алгоритма (об этих алгоритмах подробнее было сказано в разделах 1.2 и 1.4). Будет очень затратно с точки зрения объёма материала пытаться рассмотреть пусть даже часть этих методов в этой статье, а так же тонкости их распараллеливания. Предлагаем читателям при желании самим ознакомиться с этими алгоритмами на данном ресурсе или прибегнув к иным источникам.&lt;br /&gt;
&lt;br /&gt;
При классификации по высоте ЯПФ, таким образом, алгоритм Ланцоша без переортогонализации относится к алгоритмам с &#039;&#039;логарифмической сложностью&#039;&#039;, и его сложность равна &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(\log_2 n)&amp;lt;/math&amp;gt; с важным замечанием, что это сложность только одной итерации, а максимум в алгоритме может быть выполнено последовательно &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;/math&amp;gt; таких однотипных итераций, если не будет осуществлён ранний выход из цикла. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Несмотря на то, что на графе в предыдущем разделе для лучшей визуализации и понимания было изображено &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; потоков (никаких допущений мы не делали и нарушений с точки зрения логики и математики нет, можно изобразить большее число потоков, просто часть времени некоторые из них могут бездействовать и не использоваться), на самом деле правильным и разумным будет реализовать начальное параллельное выполнение &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n^2&amp;lt;/math&amp;gt; операций умножения всех вещественных элементов матрицы &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;A&amp;lt;/math&amp;gt; на соответствующие элементы вектора &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;q_j&amp;lt;/math&amp;gt;, после чего применять тот же самый упомянутый метод сдваивания. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Поэтому при классификации по ширине ЯПФ его сложность будет &#039;&#039;квадратичной&#039;&#039; и равна &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(n^2)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
&#039;&#039;&#039;Входные данные алгоритма:&#039;&#039;&#039; вещественная симметричная &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; размера &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;n\times n&amp;lt;/math&amp;gt;, вещественный вектор &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;b&amp;lt;/math&amp;gt; длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt;, и одно целое число &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;k&amp;lt;/math&amp;gt;, означающее количество итераций.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём входных данных:&#039;&#039;&#039; &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;n^2 +n + 1 &amp;lt;/math&amp;gt;. Если учесть, что матрица симметричная и достаточно для её однозначного определения задать элементы на главной диагонали и элементы над или под ней, то можно сократить объём входных данных с целью экономии памяти до: &amp;lt;math&amp;gt;\ \frac{n^2-n}{2}+n+n+1 =\frac{n^2+3n}{2} + 1&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные алгоритма:&#039;&#039;&#039; вектор собственных значений &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;\Theta^k&amp;lt;/math&amp;gt; длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;/math&amp;gt;, матрица &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;S^k&amp;lt;/math&amp;gt; из соответствующих собственных векторов размера &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n\times k&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём выходных данных:&#039;&#039;&#039; &amp;lt;math&amp;gt;k\;(n + 1)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
В данном разделе перечислены без какой-либо хронологии или связи друг с другом наиболее важные и разнообразные свойства алгоритма, на которые стоит и полезно обратить внимание, а также которые выгодно отличают его от схожих алгоритмов, решающих ту же задачу.&amp;lt;br&amp;gt;&lt;br /&gt;
1) Отношение последовательной сложности алгоритма к параллельной,с учётом &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;/math&amp;gt; итераций, равно &amp;lt;math&amp;gt;\;\;\frac{kn^2}{k \log_2{n}}=\frac{n^2}{\log_2{n}}&amp;lt;/math&amp;gt;;&amp;lt;br&amp;gt;&lt;br /&gt;
2) Вычислительная мощность алгоритма, как отношение числа операций к суммарному объему входных и выходных данных, равна &amp;lt;math style=&amp;quot;vertical-align:-70%&amp;gt;\;\;\frac{k\,n^2}{0.5\,n^2+1.5\,n+k\,n+k+1}&amp;lt;/math&amp;gt; и &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;\approx 2\,k&amp;lt;/math&amp;gt;, так как на практике верно отношение &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;&amp;lt;n&amp;lt;/math&amp;gt; ;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
3) Для собственных значений формируемых матриц &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_j&amp;lt;/math&amp;gt; верно отношение (следствие теоремы Коши о перемежаемости): &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;\lambda_i(T_{k+1})\geq \lambda_i(T_{k})\geq \lambda_{i+1}(T_{k+1})\geq \lambda_{i+1}(T_{k})&amp;lt;/math&amp;gt; ;&amp;lt;ref&amp;gt;James W. Demmel - Вычислительная линейная алгебра. Теория и приложения //Мир. - 2001 (c. 383)&amp;lt;/ref&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
4) Крайние (наибольшие и наименьшие) собственные значения матриц &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_j&amp;lt;/math&amp;gt; сходятся к крайним собственным значениям матрицы &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;A&amp;lt;/math&amp;gt; первыми (это часто происходит уже на ранних шагах при &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j\approx 2\,\sqrt{n}&amp;lt;/math&amp;gt;&amp;lt;ref&amp;gt;http://num-anal.srcc.msu.ru/lib_na/int_ae/int_ae6.htm (пункт 6.5)&amp;lt;/ref&amp;gt;), а собственные значения в середине спектра - последними;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
5) Из-за ограниченной точности постепенно теряется ортогональность вектора Ланцоша &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;q_j&amp;lt;/math&amp;gt; к предыдущим векторам Ланцоша, поэтому необходимо примерно каждые 10-15 итераций проводить дорогостоящую операцию реортогонализации, но это уже будет иной алгоритм с очень малым различием в одной операции и в программном коде, реализующем его, соответственно; &amp;lt;ref&amp;gt;Sam Handler - The Lanczos Algorithm For Large-Scale Eigenvalue Problems (08.01.07), slide №8&amp;lt;/ref&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
6) Эффективность и быстрота выполнения алгоритма очень сильно зависит от скорости памяти (диска). Согласно тесту только &#039;&#039;6%&#039;&#039; времени работы программы приходится на вычисления, остальное время затрачивается на ожидание отклика диска;&amp;lt;ref&amp;gt;Sam Handler - The Lanczos Algorithm For Large-Scale Eigenvalue Problems (08.01.07), slide №10&amp;lt;/ref&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
7) Метод Ланцоша удобен тем, что не требует хранения исходной матрицы полным массивом: метод использует исходную матрицу только в операциях умножения матрицы на вектор, что позволяет эффективно использовать разреженность матрицы или регулярность структуры матрицы. Поэтому метод Ланцоша может быть использован для матриц таких больших порядков, когда методы вращений и отражений не могут быть применены.&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;
Для исследования масштабируемости рассматриваемого алгоритма Ланцоша без переортогонализации автором была реализована программа на языке С++ с использованием технологии MPI. &amp;lt;ref&amp;gt;https://goo.gl/rcZ9cq  или альтернативная ссылка с прикреплённым кодом: https://goo.gl/jWezim , по просьбе на почту я (автор статьи) готов предоставить желающим доступ к проекту с этим кодом на ресурсе Bitbucket&amp;lt;/ref&amp;gt; Дальнейшее исследование было проведено на суперкомпьютере &amp;quot;Ломоносов&amp;quot; Суперкомпьютерного комплекса МГУ. &amp;lt;br&amp;gt; Важно отметить, что реализованная программа выполняет только первую часть алгоритма - формирование матрицы &amp;lt;math &amp;gt;T_j&amp;lt;/math&amp;gt;. Вторая часть алгоритма (задача поиска собственных значений матрицы &amp;lt;math &amp;gt;T_j&amp;lt;/math&amp;gt;) может быть решена несколькими методами, каждый из которых обладает своей эффективностью распараллеливания и характерными свойствами. Подробно этот вопрос уже обсуждался в статье раннее, поэтому не будем ещё раз заострять на этом внимание и останавливаться.&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Сборка осуществлялась со следующими параметрами:&lt;br /&gt;
* Компилятор intel/15.0.090 &lt;br /&gt;
* Openmpi/1.8.4-icc&lt;br /&gt;
В серии проведённых расчётов рассматривались следующие числовые значения параметров:&lt;br /&gt;
* Размер &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;n&amp;lt;/math&amp;gt; задачи и, соответственно, матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt;, задействованной в операции умножения на вектор: [2000 : 30000] с шагом 1000&lt;br /&gt;
* Число процессоров: 1, 2, 4, 16, 32, 48, 64, 96, 128&lt;br /&gt;
* Число итераций в алгоритме: &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k=350&amp;lt;/math&amp;gt;&lt;br /&gt;
Число &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; взято таким вопреки информации в начале статьи, где говорится, что значение &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; редко превышает &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;10^2&amp;lt;/math&amp;gt; (хоть мы и имеем право брать его любым по нашему усмотрению). Это сделано исключительно для лучшей визуализации пиков на графиках в данном разделе и наглядности получаемых результатов, так как при меньших на порядок значениях параметра &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; времена выполнения программ были слишком малы даже при минимальных числах процессоров и максимальных размерах &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;n&amp;lt;/math&amp;gt; задачи.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
На рис. 2 изображён график зависимости времени выполнения программы от числа процессоров и размера &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;n&amp;lt;/math&amp;gt; задачи. &amp;lt;br&amp;gt;&lt;br /&gt;
[[Файл:Levin604 Lanzcos result execTIME.png|580px|thumb|center|Рис. 2  График зависимости времени выполнения программы]] &amp;lt;br&amp;gt;&lt;br /&gt;
Многочисленные тесты показали при малых количествах ядер уменьшение времени выполнения программы почти в 2 раза при увеличении числа ядер в 2 раза на всём диапазоне размеров матриц, что и отражает сильный излом на предоставленом графике. Изменение значения времени можно легко оценить по предоставленной цветовой шкале.&lt;br /&gt;
&lt;br /&gt;
== Динамические характеристики и эффективность реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Выводы для классов архитектур ==&lt;br /&gt;
По заданию, во второй части требовалось описать только разделы 2.4 и 2.7, прошу не спрашивать с меня все разделы 2.1-2.6. Надеюсь на понимание, мне физически не хватает времени на это задание + 2 других в течение семестра, делаю всё, что в моих силах :)&lt;br /&gt;
&lt;br /&gt;
== Существующие реализации алгоритма ==&lt;br /&gt;
Несмотря на то, что алгоритм является далеко не самым популярным, алгоритмом, про который нельзя сказать, что он всегда «на слуху», на сегодняшний день существует множество реализаций на различных популярных языках.&amp;lt;br&amp;gt;&lt;br /&gt;
Перечислим далее некоторые из них, указывая язык программирования, лежащий в их основе, и некоторые важные характеристики, которые обсуждались в статье ранее:&lt;br /&gt;
*&#039;&#039;Code on netlib.org by Jane Cullum and Ralph Willoughby&#039;&#039; (&#039;&#039;&#039;Fortran 77&#039;&#039;&#039;; без реортогонализации векторов; без реализации распараллеливания)&amp;lt;ref&amp;gt;http://www.netlib.org/lanczos/leval&amp;lt;/ref&amp;gt;&lt;br /&gt;
*&#039;&#039;Lanczos algorithm on freesourcecode.net&#039;&#039; (&#039;&#039;&#039;Matlab&#039;&#039;&#039;; присутствует реортогонализация векторов; без реализации распараллеливания)&amp;lt;ref&amp;gt;http://freesourcecode.net/matlabprojects/61741/lanczos-algorithm--in-matlab&amp;lt;/ref&amp;gt;&lt;br /&gt;
*&#039;&#039;Lanczos for eigenvalues in Numerical Linear Algebra, Spring 2007&#039;&#039; (&#039;&#039;&#039;Matlab&#039;&#039;&#039;; частичная или полная реортогонализация - доступны оба варианта; без реализации распараллеливания)&amp;lt;ref&amp;gt;Ссылки на файлы lanso.m и lanfu.m можно найти на https://www.nada.kth.se/~ruhe/2D5219/labs2007.html&amp;lt;/ref&amp;gt;&lt;br /&gt;
*&#039;&#039;Planso&#039;&#039; (название происходит от parallel Lanso.f) &#039;&#039;code by Kesheng Wu and Horst D. Simon&#039;&#039; (&#039;&#039;&#039;Fortran 77&#039;&#039;&#039;; частичная реортогонализация векторов; использование MPI для коммуникаций)&amp;lt;ref&amp;gt;https://github.com/jiahao/planso.jl/tree/master/external/PLAN/plan К сожалению, ссылка в описании пакета на github, ведущая на сайт National Energy Research Scientific Computing Center (NERSC), с более подробной информацией о данной программе больше не активна и выдаёт результат &#039;&#039;Page not found&#039;&#039;&amp;lt;/ref&amp;gt; &lt;br /&gt;
* &#039;&#039;Lanczos.cpp in the Vienna Computing Library&#039;&#039;  (&#039;&#039;&#039;C++&#039;&#039;&#039;, частичная реортогонализация, без реализации распараллеливания) &amp;lt;ref&amp;gt;http://viennacl.sourceforge.net/doc/lanczos_8cpp_source.html&amp;lt;/ref&amp;gt;&lt;br /&gt;
* &#039;&#039;Parallel Eigen Values code using C++ AMP on microsoft msdn blog&#039;&#039; (&#039;&#039;&#039;C++&#039;&#039;&#039;; ? ; распараллеливание есть и реализовано через C++ AMP) &amp;lt;ref&amp;gt;https://blogs.msdn.microsoft.com/nativeconcurrency/2013/12/20/eigen-values/ Подробнее о C++ Accelerated Massive Parallelism можно почитать здесь: https://msdn.microsoft.com/ru-ru/library/hh265137(v=vs.140).aspx или здесь: http://professorweb.ru/my/csharp/optimization/level4/4_6.php &amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;br /&gt;
[[en:Description of algorithm properties and structure]]&lt;/div&gt;</summary>
		<author><name>AleksLevin</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:AleksLevin/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%9B%D0%B0%D0%BD%D1%86%D0%BE%D1%88%D0%B0_%D0%B2%D1%8B%D1%87%D0%B8%D1%81%D0%BB%D0%B5%D0%BD%D0%B8%D1%8F_%D1%81%D0%BE%D0%B1%D1%81%D1%82%D0%B2%D0%B5%D0%BD%D0%BD%D1%8B%D1%85_%D0%B7%D0%BD%D0%B0%D1%87%D0%B5%D0%BD%D0%B8%D0%B9_%D1%81%D0%B8%D0%BC%D0%BC%D0%B5%D1%82%D1%80%D0%B8%D1%87%D0%BD%D0%BE%D0%B9_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86%D1%8B_%D0%B4%D0%BB%D1%8F_%D1%82%D0%BE%D1%87%D0%BD%D0%BE%D0%B9_%D0%B0%D1%80%D0%B8%D1%84%D0%BC%D0%B5%D1%82%D0%B8%D0%BA%D0%B8_(%D0%B1%D0%B5%D0%B7_%D0%BF%D0%B5%D1%80%D0%B5%D0%BE%D1%80%D1%82%D0%BE%D0%B3%D0%BE%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D0%B8)&amp;diff=20227</id>
		<title>Участник:AleksLevin/Алгоритм Ланцоша вычисления собственных значений симметричной матрицы для точной арифметики (без переортогонализации)</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:AleksLevin/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%9B%D0%B0%D0%BD%D1%86%D0%BE%D1%88%D0%B0_%D0%B2%D1%8B%D1%87%D0%B8%D1%81%D0%BB%D0%B5%D0%BD%D0%B8%D1%8F_%D1%81%D0%BE%D0%B1%D1%81%D1%82%D0%B2%D0%B5%D0%BD%D0%BD%D1%8B%D1%85_%D0%B7%D0%BD%D0%B0%D1%87%D0%B5%D0%BD%D0%B8%D0%B9_%D1%81%D0%B8%D0%BC%D0%BC%D0%B5%D1%82%D1%80%D0%B8%D1%87%D0%BD%D0%BE%D0%B9_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86%D1%8B_%D0%B4%D0%BB%D1%8F_%D1%82%D0%BE%D1%87%D0%BD%D0%BE%D0%B9_%D0%B0%D1%80%D0%B8%D1%84%D0%BC%D0%B5%D1%82%D0%B8%D0%BA%D0%B8_(%D0%B1%D0%B5%D0%B7_%D0%BF%D0%B5%D1%80%D0%B5%D0%BE%D1%80%D1%82%D0%BE%D0%B3%D0%BE%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D0%B8)&amp;diff=20227"/>
		<updated>2016-12-07T00:53:28Z</updated>

		<summary type="html">&lt;p&gt;AleksLevin: /* Масштабируемость алгоритма и его реализации */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Основные авторы описания: Левин А.Д.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{algorithm&lt;br /&gt;
| name              = Алгоритм Ланцоша для точной арифметики (без переортогонализации)&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(k\,n^2)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(k\log_2 n)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;\frac{n^2+3n}{2} + 1&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;k\;(n + 1)&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритмов =&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Данный алгоритм появился в 1950 г. и носит имя венгерского физика и математика Корнелия Ланцоша (венг. Lánczos Kornél). Алгоритм Ланцоша относится к итерационным методам вычисления собственных значений для матриц столь больших порядков &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt; n&amp;lt;/math&amp;gt;, что к ним нельзя применить прямые методы из-за ограничений по времени и памяти.&lt;br /&gt;
&lt;br /&gt;
Сам Ланцош указывал, что его метод предназначен для отыскания нескольких собственных векторов симметричных матриц, хотя к методу сразу было обращено внимание, как к способу приведения всей матрицы к трёхдиагональному виду. Двадцатью годами позже канадский математик Крис Пэж показал, что, несмотря на чувствительность к округлениям, алгоритм Ланцоша - эффективное средство вычисления некоторых &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; собственных чисел и соответствующих им собственных векторов. &amp;lt;ref&amp;gt;Парлетт Б. - Симметричная проблема собственных значений. Численные методы //М.: Мир. - 1983. (c. 276)&amp;lt;/ref&amp;gt;&lt;br /&gt;
Обычно число &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; берут в два раза больше, чем количество собственных значений матрицы, которые поставлена цель найти, и оно имеет порядок не более &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;10^2&amp;lt;/math&amp;gt;.&amp;lt;ref&amp;gt;Susan W. Bostic - Lanczos Eigensolution Method for High-Perfomance Computers, page 7&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Алгоритм Ланцоша для вычисления собственных значений симметричной матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; соединяет в себе метод Ланцоша для построения последовательности подпространств Крылова и ортонормированных векторов Ланцоша и процедуру Рэлея-Ритца получения оптимальных приближений собственных значений и соответствующих собственных векторов исходной матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt;.&amp;lt;ref&amp;gt;James W. Demmel - Вычислительная линейная алгебра. Теория и приложения //Мир. - 2001 (c. 381)&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
В данной статье рассматривается вариант алгоритма Ланцоша, в котором опущено влияние ошибок округления на вычислительный процесс, хотя на практике этому посвящается отдельное внимание и существуют различные методы решения данной проблемы, такие как частичная или полная переортогонализация. Этим модифицированным методам посвящены отдельные статьи на данном ресурсе.&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
Обозначения и формулы, используемые в данном разделе, взяты из литературы, указанной по ссылке.&amp;lt;ref&amp;gt;James W. Demmel - Вычислительная линейная алгебра. Теория и приложения //Мир. - 2001 (c. 313, &#039;&#039;&amp;lt;math&amp;gt; \S &amp;lt;/math&amp;gt; 6.6 Методы Крыловского подпространства&#039;&#039;)&amp;lt;/ref&amp;gt; &lt;br /&gt;
&lt;br /&gt;
Алгоритм Ланцоша для вычисления &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; собственных значений и собственных векторов вещественной симметричной матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A=A^T&amp;lt;/math&amp;gt; в точной арифметике: &amp;lt;ref&amp;gt;James W. Demmel - Вычислительная линейная алгебра. Теория и приложения //Мир. - 2001 (c. 381)&amp;lt;/ref&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{align}&lt;br /&gt;
q_1 = &amp;amp; \,\frac{b}{\|b\|_2},\; \beta_0 = 0,\; q_0 = 0\\&lt;br /&gt;
\mathbf{for} \; &amp;amp; j = 1 \; to \; k \,\; \mathbf{do} \\&lt;br /&gt;
&amp;amp; z = A\,q_j\\&lt;br /&gt;
&amp;amp; \alpha_j = q^T_j z\\&lt;br /&gt;
&amp;amp; z = z - \alpha_j q_j - \beta_{j-1}q_{j-1}\\&lt;br /&gt;
&amp;amp; \beta_j = \|z\|_2\\&lt;br /&gt;
&amp;amp; \mathbf{If} \; (\beta_j == 0) \; \mathbf{then}\; stop\; the\; algorithm \\ &lt;br /&gt;
&amp;amp; \;  q_{j+1} = \frac{z}{\beta_j} \\&lt;br /&gt;
&amp;amp; compute\; eigenvalues\; and \;eigenvectors\;of \;matrix \;\;T_j= Q^T_j A Q\;\;and\;estimate \;the\; errors\\&lt;br /&gt;
\mathbf{end} \; &amp;amp; \mathbf{for}&lt;br /&gt;
\end{align}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
В продемонстрированном выше алгоритме &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;b&amp;lt;/math&amp;gt; - заданный вещественный вектор. Также полагается известным алгоритм вычисления произведения матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; на вектор &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;x&amp;lt;/math&amp;gt;. &lt;br /&gt;
Введём матрицу Крылова, определяемую следующим соотношением: &amp;lt;math&amp;gt;K_j = [b,Ab,A^2b,...,A^{j-1}b]&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Далее, на практике, матрица &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;K&amp;lt;/math&amp;gt; заменяется матрицей &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;Q&amp;lt;/math&amp;gt;, такой, что при любом числе &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; линейные оболочки первых &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; столбцов в &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;K&amp;lt;/math&amp;gt; и &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;Q&amp;lt;/math&amp;gt; являются одним и тем же подпространством.&amp;lt;ref&amp;gt;James W. Demmel - Вычислительная линейная алгебра. Теория и приложения //Мир. - 2001 (c. 315)&amp;lt;/ref&amp;gt; &lt;br /&gt;
Тогда матрица &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;Q&amp;lt;/math&amp;gt;, в отличие от матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;K&amp;lt;/math&amp;gt;, хорошо обусловлена и легко обратима. В результате получаем матрицу &amp;lt;math&amp;gt;Q_j = [q_1, q_2, \dots, q_j]&amp;lt;/math&amp;gt; размерности &amp;lt;math&amp;gt;n\times j&amp;lt;/math&amp;gt;, столбцы которой ортогональны, являются базисом подпространства Крылова и называются векторами Ланцоша.&lt;br /&gt;
&lt;br /&gt;
В алгоритме Ланцоша вычислению подлежит столько первых столбцов в матрице &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;Q_j&amp;lt;/math&amp;gt;, сколько необходимо для получения требуемого приближения к решению &amp;lt;math&amp;gt;A\,x\,=b\,\,(A\,x=\lambda \, x)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Получение нулевого &amp;lt;math&amp;gt;\beta_j&amp;lt;/math&amp;gt; в итерационном процессе - событие, желательное в том смысле, что оно свидетельствует о том, что найдено некоторое подпространство, являющееся в точности инвариантным, а все собственные значения матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;T_j&amp;lt;/math&amp;gt; являются собственными значениями матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt;. На практике же нулевое и близкие к нулю значения получаются редко.&amp;lt;ref&amp;gt;Голуб Дж., Ван Лоун Ч. - Матричные вычисления//М.: Мир. - 1999 (c. 429)&amp;lt;/ref&amp;gt; &lt;br /&gt;
&lt;br /&gt;
Затем на каждом шаге цикла формируется симметричная трёхдиагональная матрица &amp;lt;math&amp;gt;T_j = Q^T_j A Q&amp;lt;/math&amp;gt;, к которой применяется процесс Рэлея-Ритца для поиска её собственных значений (на практике для поиска этих собственных значений можно использовать любой из специальных методов в параграфе книги по ссылке).&amp;lt;ref&amp;gt;Голуб Дж., Ван Лоун Ч. - Матричные вычисления//М.: Мир. - 1999 (&amp;lt;math&amp;gt;\S&amp;lt;/math&amp;gt; 8.4)&amp;lt;/ref&amp;gt;  &lt;br /&gt;
Эти собственные значения, они же числа Ритца, и полагаются приближёнными собственными значениями исходной матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt;.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Существует множество методов для отыскания собственных значений вещественной симметричной трехдиагональной матрицы. Большинство из них требует &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt; операций &amp;lt;ref&amp;gt;Парлетт Б. Симметричная проблема собственных значений. Численные методы.,: Мир, 1983. с. 179-182&amp;lt;/ref&amp;gt;, но существуют и быстрые алгоритмы, требующие лишь &amp;lt;math&amp;gt;O(n\ln n)&amp;lt;/math&amp;gt; операций.&amp;lt;ref&amp;gt;https://en.wikipedia.org/wiki/Tridiagonal_matrix#Eigenvalues  Раздел eigenvalues&amp;lt;/ref&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Одним из возможных способов отыскать собственные значения симметричной трехдиагональной матрицы - прямое вычисление корней характеристического полинома &amp;lt;math&amp;gt;p_n(\lambda)&amp;lt;/math&amp;gt; через метод деления пополам, где формируется последовательность Штурма и локализуются собственные числа, являющиеся корнями характеристического полинома. Нахождение всех &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; собственных значений матрицы этим способом требует &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;2n^2t&amp;lt;/math&amp;gt; умножений и вычитаний, где &amp;lt;math&amp;gt;t&amp;lt;/math&amp;gt; - число сделанных шагов с применением метода деления пополам.&amp;lt;ref&amp;gt;Уилкинсон Дж. X. Алгебраическая проблема собственныx значений. Изд-во &amp;quot;Наука&amp;quot;, 1970. - глава 5, с. 272-278&amp;lt;/ref&amp;gt; Соответствующие собственные вектора могут быть найдены посредством обратных итераций за &amp;lt;math&amp;gt; O(n) &amp;lt;/math&amp;gt; флопов. &amp;lt;ref&amp;gt;Голуб Дж., Ван Лоун Ч. - Матричные вычисления//М.: Мир. - 1999 (c. 394-395)&amp;lt;/ref&amp;gt; &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;На практике, если требуется только небольшая часть от всей совокупности собственных векторов и значений, и матрица имеет Хессенбергову или трёхдиагональную форму, очень эффективными будут методы факторизации, как, например, QR-алгоритм или QL-алгоритм со сдвигами (c целью ускорить алгоритм и сделать порядок сходимости квадратичным) или же без них.&amp;lt;ref&amp;gt;http://algorithm.narod.ru/ln/eigen/ETridiag.html&amp;lt;/ref&amp;gt; &amp;lt;br&amp;gt;&lt;br /&gt;
Весьма молодые и не менее актуальные конкуренты QR и QL алгоритмов, применяющиеся для поиска собственных значений:&lt;br /&gt;
*Методы divide-and-conquer (разделяй и властвуй), появившиеся в 1980-ых годах &amp;lt;ref&amp;gt;https://goo.gl/dapvbn ссылку пришлось сократить с помощью Google url shortener, так как символы подчеркивания портили её и не давали перейти по 1 клику&amp;lt;/ref&amp;gt;&lt;br /&gt;
*Relatively robust representation методы, появившиеся в 1990-ых и позволяющие найти собственные числа симметричной матрицы порядка &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;n&amp;lt;/math&amp;gt; за &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt; операций&lt;br /&gt;
&lt;br /&gt;
Если требуется вычислить собственные векторы, то необходимо хранить вычисляемые векторы Ланцоша. Если работа при этом производится только с оперативной памятью, то при большом порядке исходной матрицы (а именно для таких матриц и предназначен метод Ланцоша) число шагов  &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;j&amp;lt;/math&amp;gt;, которые могут быть выполнены до того момента, как оперативная память будет исчерпана, будет очень незначительно, а следовательно, искомые собственные пары могут не успеть сойтись с требуемой точностью. В этом случае метод Ланцоша можно использовать итерационным образом: после выполнения заданного числа шагов процесс прерывается и, если еще не все требуемые пары Ритца сошлись с требуемой точностью, то формируется новый начальный вектор &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;q_1&amp;lt;/math&amp;gt;, являющийся линейной комбинацией векторов Ритца, еще не сошедшихся с заданной точностью, и процесс начинается заново.&amp;lt;ref&amp;gt;http://num-anal.srcc.msu.ru/lib_na/int_ae/int_ae6.htm (пункт 6.5)&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
Вычислительное ядро рассматриваемого алгоритма (наиболее ресурсно-затратная часть алгоритма) -  формирование на каждом шаге цикла промежуточного вектора &amp;lt;math&amp;gt;z&amp;lt;/math&amp;gt;, вычисляемого по формуле: &amp;lt;math&amp;gt;z = A\,q_j&amp;lt;/math&amp;gt;. Данная операция, по сравнению с другими операциями алгоритма, затратна и требовательна, как с точки зрения количества производимых операций, так и с точки зрения объема оперируемых данных. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Например, умножение матрицы размера &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;n\times n&amp;lt;/math&amp;gt; на вектор длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; требует: &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;n^2+(n-1)n = 2n^2-n&amp;lt;/math&amp;gt; операций умножения и сложения. В свою очередь аналогичная операция умножения матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;(n+1)\times (n+1)&amp;lt;/math&amp;gt; на вектор длины &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;(n+1)&amp;lt;/math&amp;gt; требует: &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;2n^2+3n+1&amp;lt;/math&amp;gt;  операций умножения и сложения. То есть повышение размерности задачи всего на 1 увеличивает число необходимых действий в этом шаге алгоритма на: &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;4n+1&amp;lt;/math&amp;gt;. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Так же, стоит помнить, что, согласно разделу 1.2, данную операцию умножения матрицы на вектор необходимо выполнить &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;k&amp;lt;/math&amp;gt; раз. Нетрудно понять, насколько возрастает и колоссален масштаб операций, если в задачах, где критична точность, размерности &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; могут иметь порядок &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;10^5&amp;lt;/math&amp;gt; или даже более.&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
Как уже было упомянуто в данной статье в описании алгоритма, рассматриваемый алгоритм состоит из двух последовательно выполненных алгоритмов: метод Ланцоша для построения последовательности подпространств Крылова и ортонормированных векторов Ланцоша и процедура Рэлея-Ритца получения оптимальных приближений собственных значений и соответствующих собственных векторов исходной матрицы.&lt;br /&gt;
&lt;br /&gt;
В первой части алгоритма, где итерационно строятся Крыловское подпространство и трёхдиагональная матрица &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&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 style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; разреженная. Именно она подлежит оптимизации с использованием техник распараллеливания, поскольку она является вычислительным ядром алгоритма, а весь упомянутый процесс построения матрицы &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&amp;lt;/math&amp;gt; выполняется последовательно.&lt;br /&gt;
&lt;br /&gt;
Рассмотрим вторую часть алгоритма - поиск собственных значений сформированной матрицы &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&amp;lt;/math&amp;gt;.&amp;lt;br&amp;gt;&lt;br /&gt;
Далее, наглядно, в виде псевдокода, представлен, упомянутый в разделе 1.2, QR-алгоритм (аналогично можно рассмотреть и QL-алгоритм) со сдвигами Релэя, который весьма популярен на практике.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{align}&lt;br /&gt;
\mathbf{Input}: \;&amp;amp;tridiagonal\;\;matrix \;T\;with\;\;n\times n\;\;size\\&lt;br /&gt;
T^{(0)}&amp;amp;:=T\\&lt;br /&gt;
\mathbf{for}&amp;amp; \;\;m=n,...,2 \;\; \mathbf{do}\\&lt;br /&gt;
&amp;amp;k=0\\&lt;br /&gt;
&amp;amp; \mathbf{repeat}\\&lt;br /&gt;
&amp;amp; \quad \;\; k=k+1\\&lt;br /&gt;
&amp;amp; \quad \;\; \mu^{(k)}=T_{m,m}^{(k-1)}\\&lt;br /&gt;
&amp;amp; \quad \;\; Q^{(k)}R^{(k)}=T^{(k-1)}-\mu^{(k)}I\;\;using\;\;QR\;decomposition\\&lt;br /&gt;
&amp;amp; \quad \;\; T^{(k)}=R^{(k)}Q^{(k)}+\mu^{(k)}I\\&lt;br /&gt;
&amp;amp; \mathbf{until} \;\;\; |T_{m,m-1}^{(k)}| \;is\;\;small\;\;enough\\&lt;br /&gt;
&amp;amp; Save  \;\;T_{m,m}^{(k)} \;\;as\;\; converged\;\;eigenvalue\;of\;T\\ &lt;br /&gt;
&amp;amp; Remove \;\boldsymbol{n}\,th\;row\;and\;\boldsymbol{n}\,th\;column\;\;from \;T \\&lt;br /&gt;
&amp;amp; and\;take\;this\;new\;cropped\;matrix\;as\;new\;T^{(0)}\;with\;\;(n-1)\times (n-1)\;\;size\\&lt;br /&gt;
 \mathbf{end}&amp;amp;\; \mathbf{for}&lt;br /&gt;
\end{align}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Малость наддиагональных и поддиагональных элементов матрицы (фраза &#039;&#039;&amp;quot;small enough&amp;quot;&#039;&#039; в псевдокоде) подразумевает:&lt;br /&gt;
&amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt; |T_{m,m-1}^{(k)}| \leq \varepsilon\,|T_{m,m}^{(k)}| \quad\quad &amp;lt;/math&amp;gt; , где &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt; \varepsilon &amp;lt;/math&amp;gt; - заданная точность&amp;lt;br&amp;gt;&lt;br /&gt;
Также вместо сдвига Релэя, обозначенного в алгоритме через &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;\mu^{(k)}&amp;lt;/math&amp;gt;, часто на практике используется сдвиг по Уилкинсону, который даёт гарантированную сходимость внедиагональных элементов матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt; T^{(k)} &amp;lt;/math&amp;gt;, формируемой на каждом шаге, к нулю, при этом жертвуя монотонностью их убывания.&amp;lt;ref&amp;gt;Голуб Дж., Ван Лоун Ч. - Матричные вычисления//М.: Мир. - 1999 (c. 378, вторая половина страницы)&amp;lt;/ref&amp;gt;&amp;lt;ref&amp;gt;Парлетт Б. Симметричная проблема собственных значений. Численные методы.,: Мир, 1983. с. 169&amp;lt;/ref&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Подробнее с различными сдвигами и соответствующими оценками скоростей и количествами операций можно ознакомиться по указанной ссылке:&amp;lt;ref&amp;gt;Парлетт Б. Симметричная проблема собственных значений. Численные методы.,: Мир, 1983. с. 179-182&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;Для совершения QR-декомпозиции на каждом шаге может использоваться любой из алгоритмов по ссылке.&amp;lt;ref&amp;gt;https://en.wikipedia.org/wiki/QR_decomposition&amp;lt;/ref&amp;gt; Подробные описания этих алгоритмов также доступны на данном ресурсе algowiki-project.&amp;lt;br&amp;gt;&lt;br /&gt;
Так как мы оперируем не обычной матрицей и даже не Хессенберговой, а симметричной и трёхдиагональной, то скорость таких алгоритмов значительно возрастёт. Например, согласно данному ресурсу &amp;lt;ref&amp;gt;http://algorithm.narod.ru/ln/eigen/ETridiag.html&amp;lt;/ref&amp;gt;, для QL-алгоритма с неявными сдвигами:&amp;lt;br&amp;gt;&lt;br /&gt;
Для трёхдиагональной матрицы объем арифметических действий составляет &amp;lt;math&amp;gt; O(n)&amp;lt;/math&amp;gt; на одну итерацию вместо &amp;lt;math&amp;gt; O(n^3)&amp;lt;/math&amp;gt; для матрицы общего вида, а число итераций для нахождения первых собственных значений примерно равно 4 - 5. Но на этих итерациях также уменьшаются внедиагональные элементы правого нижнего угла. И, таким образом, дальнейшие собственные значения ищутся значительно быстрее. Среднее число итераций на каждое собственное значение обычно составляет 1.3 - 1.6.&amp;lt;br&amp;gt; &lt;br /&gt;
Аналогично QL, QR-разложение трёхдиагольной матрицы также требует &amp;lt;math&amp;gt; O(n)&amp;lt;/math&amp;gt; флопов&amp;lt;ref&amp;gt;Голуб Дж., Ван Лоун Ч. - Матричные вычисления//М.: Мир. - 1999 (c. 378, начало раздела 8.2.2)&amp;lt;/ref&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Подводя итог, во второй части алгоритма Ланцоша можно выделить следующие макрооперации:&lt;br /&gt;
* умножение матрицы на вещественное число;&lt;br /&gt;
* перемножение матриц;&lt;br /&gt;
* умножение и сравнение вещественных чисел;&lt;br /&gt;
* + набор других макроопераций в зависимости от выбора метода, с помощью которого будет совершаться сама QR или QL-декомпозиция (выше продемонстрированы, уже, как минимум, 3 разных способа).&lt;br /&gt;
Так же, важно заметить, что набор макропераций может быть несколько другим, если выбрать какой-либо иной современный метод поиска собственных чисел трёхдиагональной матрицы, не использующий QR и QL разложения(факторизацию). Два таких метода были упомянуты в пункте 1.2.&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
С целью полностью не дублировать раздел 1.2 данной статьи, где представлен наглядный и доступный для понимания псевдокод алгоритма, постараемся лишь коротко просуммировать и обобщить весь перечень последовательных действий в рассматриваемом алгоритме.&lt;br /&gt;
&lt;br /&gt;
В качестве входных данных имеем: вещественная симметричная матрица &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; размера &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;n\times n&amp;lt;/math&amp;gt;, известный вещественный вектор &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;b&amp;lt;/math&amp;gt; длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; и число &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;n&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Далее:&lt;br /&gt;
* Инициализируем вещественную константу &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;\beta_0&amp;lt;/math&amp;gt; и векторы &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;q_0&amp;lt;/math&amp;gt; и &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;q_1&amp;lt;/math&amp;gt;&lt;br /&gt;
* Итерационно для всех &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j=1,...,k&amp;lt;/math&amp;gt;:&lt;br /&gt;
** Вычисляем вспомогательный вектор &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt;, используя умножение матрицы на вектор&lt;br /&gt;
** Вычисляем, используя скалярное произведение векторов, значение &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;\alpha_j&amp;lt;/math&amp;gt; - элемент на главной диагонали трёхдиагональной матрицы &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&amp;lt;/math&amp;gt;&lt;br /&gt;
** Вычисляем по формуле новое значение и перезаписываем вектор &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt;&lt;br /&gt;
** Вычисляем значение &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;\beta_j&amp;lt;/math&amp;gt; - элементы непосредственно над и под главной диагональю той же матрицы &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&amp;lt;/math&amp;gt;&lt;br /&gt;
** Вычисляем, зная вектор &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt;,  очередной столбец матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;Q&amp;lt;/math&amp;gt;, он же вектор Ланцоша : &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;\,\,q_{j+1}&amp;lt;/math&amp;gt;&lt;br /&gt;
** Теперь, когда матрица &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&amp;lt;/math&amp;gt; сформирована на очередном шаге, находим её собственные значения и вектора любым доступным способом, о чём было подробно сказано в пункте 1.2&lt;br /&gt;
** Переходим на следующую итерацию: &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j&amp;lt;/math&amp;gt;++&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
Оценим количество операций и сложность последовательного алгоритма, изложенного в предыдущем разделе.&lt;br /&gt;
*Для вычисления вектора &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt; умножается матрица размера &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;n\times n&amp;lt;/math&amp;gt; на вектор длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt;, и потребуется &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n^2&amp;lt;/math&amp;gt; операций умножения и &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n^2&amp;lt;/math&amp;gt; операций сложения.&lt;br /&gt;
*Умножение векторов &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;q^T_j&amp;lt;/math&amp;gt; и &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt; длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; потребует &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; операций умножения и &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; операций сложения.&lt;br /&gt;
*При вычислении нового значения вектора &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt; поэлементное сложение двух векторов длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; требует &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; операций сложения.&lt;br /&gt;
*Умножение вектора длины &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; на вещественное число требует &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; операций умножения.&lt;br /&gt;
*Нахождение квадратичной нормы вектора &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt;  длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; требует &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; умножений и &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; сложений и ещё 1 операцию извлечения квадратного корня.&lt;br /&gt;
*Заключительное нахождение собственных значений и собственных векторов трёхдиагональной матрицы &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;T_j&amp;lt;/math&amp;gt; размера &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j\times j&amp;lt;/math&amp;gt; с помощью QR-алгоритма потребует в худшем случае &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(j^3)&amp;lt;/math&amp;gt; операций.&amp;lt;ref&amp;gt;http://num-anal.srcc.msu.ru/lib_na/int_ae/int_ae6.htm (пункт 6.2, &amp;quot;Скорость сходимости при этом всегда не хуже квадратичной и почти всегда лучше кубической.&amp;quot;)&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Посчитаем теперь суммарное количество простейших операций на одной итерации алгоритма (без учёта записей в память):&lt;br /&gt;
*&amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n^2+5\,n&amp;lt;/math&amp;gt; операций умножения/деления&lt;br /&gt;
*&amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n^2+4\,n&amp;lt;/math&amp;gt; операций сложения/вычитания&lt;br /&gt;
*1 операция извлечения квадратного корня&amp;lt;br&amp;gt;&lt;br /&gt;
Отдельно после всех итераций при &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j=k&amp;lt;/math&amp;gt; :&lt;br /&gt;
*&amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(k^3)&amp;lt;/math&amp;gt; операций для поиска собственных значений и собственных векторов трёхдиагональной матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_k&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Итого можно утверждать следующее:&lt;br /&gt;
&lt;br /&gt;
Последовательная сложность одной итерации рассматриваемого алгоритма:  &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(n ^ 2) &amp;lt;/math&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Суммарная сложность алгоритма (&amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;/math&amp;gt; итераций): &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(k\,n ^ 2) + O(k ^ 3)&amp;lt;/math&amp;gt; &amp;lt;ref&amp;gt;Здесь мы полагаем, что мы не вычисляем собственные значения и векторы матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_j&amp;lt;/math&amp;gt; на каждом промежуточном шаге, а лишь единожды затрачиваем &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;O(k ^ 3)&amp;lt;/math&amp;gt; действий в конце для нахождения &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;/math&amp;gt; собственных значений и векторов матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_k&amp;lt;/math&amp;gt;&amp;lt;/ref&amp;gt; &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
На практике же обычно рассматривается число &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;&amp;lt;n&amp;lt;/math&amp;gt;, поэтому второе слагаемое можно опустить.&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
На рис. 1 продемонстрирован граф одной итерации (при каком-либо произвольном значении итератора &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j&amp;lt;/math&amp;gt;) описанного алгоритма без отображения входных и выходных данных. Наглядно продемонстрированы связи между всеми действиями, и с помощью деления на &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; потоков показано, какие операции возможно выполнять параллельно на каждом шаге с целью оптимизации и экономии машинного времени. В результате, после параллельно выполненных операций &#039;&#039;&#039;Division&#039;&#039;&#039; на заключительном ярусе, на выходе имеем значение следующего вектора Ланцоша &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;q_{j+1}&amp;lt;/math&amp;gt;, после чего следует переход на следующую итерацию, и процесс повторяется.&lt;br /&gt;
&lt;br /&gt;
[[Файл:Levin_graph.png|600px|thumb|center|Рис. 1  Структура одной итерации алгоритма]] &amp;lt;br&amp;gt;&lt;br /&gt;
Обозначения на рисунке: &amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Simp&#039;&#039;&#039; (от англ. simple) - операции сложения и умножения вещественных чисел при вычислении произведения матрицы на вектор;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Vec mult&#039;&#039;&#039; (от англ. vectors multiplication) - операция скалярного умножения двух векторов;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Vec subtr&#039;&#039;&#039; (от англ. vectors subtraction, из-за использованных в операции вычитаний векторов) - операция умножения вектора на число (выполняется дважды) и формирование нового значения &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;z_{new}&amp;lt;/math&amp;gt; по формуле: &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;z_{new} = z - \alpha_j q_j - \beta_{j-1}q_{j-1} \;&amp;lt;/math&amp;gt;;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;||\cdot||&amp;lt;/math&amp;gt; - операция вычисления нормы вектора;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Division&#039;&#039;&#039; - операция деления вектора на вещественное число  &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;\beta_j&amp;lt;/math&amp;gt; &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Важно отметить, что упомянутые выше операции также легко поддаются оптимизации. Например, попарные умножения вещественных координат векторов при вычислении скалярного произведения также легко выполняются параллельно на &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; потоках, а затем можно применить суммирование методом сдваивания, о котором сказано в следующем разделе. Умножение или деление вектора на вещественное число являющееся, по определению, умножением или делением всех его координат на это число тоже может быть выполнено эффективнее, если мы используем &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; потоков, а не выполняем эти действия последовательно.&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
Параллельные операции возможны только внутри итераций, так как рассматриваемый алгоритм является итерационным, и сами итерации строго последовательны.&amp;lt;br&amp;gt;&lt;br /&gt;
Рассмотрим в этом разделе подробнее, какой выигрыш мы можем получить при распараллеливании операций внутри одной итерации согласно графу из предыдущего раздела.&lt;br /&gt;
&lt;br /&gt;
Умножение вещественной симметричной матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; размера &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;n\times n&amp;lt;/math&amp;gt; на вектор &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;b&amp;lt;/math&amp;gt; длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; требует последовательного выполнения &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; ярусов умножений и сложений. Сложение элементов вектора длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; на каждом шаге перемножения можно оптимизировать и выполнить за &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;\log_2 n&amp;lt;/math&amp;gt; действий, если применять метод сдваивания.&lt;br /&gt;
&lt;br /&gt;
Дальнейшие операции выполняются последовательно, а вычисление значений векторов происходит за один ярус операций сложения или умножения.&lt;br /&gt;
&lt;br /&gt;
Ресурс параллелизма алгоритма вычисления собственных значений построенной трёхдиагональной матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_k&amp;lt;/math&amp;gt; размера &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k\times k&amp;lt;/math&amp;gt; зависит от выбранного алгоритма (об этих алгоритмах подробнее было сказано в разделах 1.2 и 1.4). Будет очень затратно с точки зрения объёма материала пытаться рассмотреть пусть даже часть этих методов в этой статье, а так же тонкости их распараллеливания. Предлагаем читателям при желании самим ознакомиться с этими алгоритмами на данном ресурсе или прибегнув к иным источникам.&lt;br /&gt;
&lt;br /&gt;
При классификации по высоте ЯПФ, таким образом, алгоритм Ланцоша без переортогонализации относится к алгоритмам с &#039;&#039;логарифмической сложностью&#039;&#039;, и его сложность равна &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(\log_2 n)&amp;lt;/math&amp;gt; с важным замечанием, что это сложность только одной итерации, а максимум в алгоритме может быть выполнено последовательно &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;/math&amp;gt; таких однотипных итераций, если не будет осуществлён ранний выход из цикла. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Несмотря на то, что на графе в предыдущем разделе для лучшей визуализации и понимания было изображено &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; потоков (никаких допущений мы не делали и нарушений с точки зрения логики и математики нет, можно изобразить большее число потоков, просто часть времени некоторые из них могут бездействовать и не использоваться), на самом деле правильным и разумным будет реализовать начальное параллельное выполнение &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n^2&amp;lt;/math&amp;gt; операций умножения всех вещественных элементов матрицы &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;A&amp;lt;/math&amp;gt; на соответствующие элементы вектора &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;q_j&amp;lt;/math&amp;gt;, после чего применять тот же самый упомянутый метод сдваивания. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Поэтому при классификации по ширине ЯПФ его сложность будет &#039;&#039;квадратичной&#039;&#039; и равна &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(n^2)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
&#039;&#039;&#039;Входные данные алгоритма:&#039;&#039;&#039; вещественная симметричная &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; размера &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;n\times n&amp;lt;/math&amp;gt;, вещественный вектор &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;b&amp;lt;/math&amp;gt; длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt;, и одно целое число &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;k&amp;lt;/math&amp;gt;, означающее количество итераций.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём входных данных:&#039;&#039;&#039; &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;n^2 +n + 1 &amp;lt;/math&amp;gt;. Если учесть, что матрица симметричная и достаточно для её однозначного определения задать элементы на главной диагонали и элементы над или под ней, то можно сократить объём входных данных с целью экономии памяти до: &amp;lt;math&amp;gt;\ \frac{n^2-n}{2}+n+n+1 =\frac{n^2+3n}{2} + 1&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные алгоритма:&#039;&#039;&#039; вектор собственных значений &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;\Theta^k&amp;lt;/math&amp;gt; длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;/math&amp;gt;, матрица &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;S^k&amp;lt;/math&amp;gt; из соответствующих собственных векторов размера &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n\times k&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём выходных данных:&#039;&#039;&#039; &amp;lt;math&amp;gt;k\;(n + 1)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
В данном разделе перечислены без какой-либо хронологии или связи друг с другом наиболее важные и разнообразные свойства алгоритма, на которые стоит и полезно обратить внимание, а также которые выгодно отличают его от схожих алгоритмов, решающих ту же задачу.&amp;lt;br&amp;gt;&lt;br /&gt;
1) Отношение последовательной сложности алгоритма к параллельной,с учётом &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;/math&amp;gt; итераций, равно &amp;lt;math&amp;gt;\;\;\frac{kn^2}{k \log_2{n}}=\frac{n^2}{\log_2{n}}&amp;lt;/math&amp;gt;;&amp;lt;br&amp;gt;&lt;br /&gt;
2) Вычислительная мощность алгоритма, как отношение числа операций к суммарному объему входных и выходных данных, равна &amp;lt;math style=&amp;quot;vertical-align:-70%&amp;gt;\;\;\frac{k\,n^2}{0.5\,n^2+1.5\,n+k\,n+k+1}&amp;lt;/math&amp;gt; и &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;\approx 2\,k&amp;lt;/math&amp;gt;, так как на практике верно отношение &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;&amp;lt;n&amp;lt;/math&amp;gt; ;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
3) Для собственных значений формируемых матриц &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_j&amp;lt;/math&amp;gt; верно отношение (следствие теоремы Коши о перемежаемости): &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;\lambda_i(T_{k+1})\geq \lambda_i(T_{k})\geq \lambda_{i+1}(T_{k+1})\geq \lambda_{i+1}(T_{k})&amp;lt;/math&amp;gt; ;&amp;lt;ref&amp;gt;James W. Demmel - Вычислительная линейная алгебра. Теория и приложения //Мир. - 2001 (c. 383)&amp;lt;/ref&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
4) Крайние (наибольшие и наименьшие) собственные значения матриц &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_j&amp;lt;/math&amp;gt; сходятся к крайним собственным значениям матрицы &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;A&amp;lt;/math&amp;gt; первыми (это часто происходит уже на ранних шагах при &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j\approx 2\,\sqrt{n}&amp;lt;/math&amp;gt;&amp;lt;ref&amp;gt;http://num-anal.srcc.msu.ru/lib_na/int_ae/int_ae6.htm (пункт 6.5)&amp;lt;/ref&amp;gt;), а собственные значения в середине спектра - последними;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
5) Из-за ограниченной точности постепенно теряется ортогональность вектора Ланцоша &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;q_j&amp;lt;/math&amp;gt; к предыдущим векторам Ланцоша, поэтому необходимо примерно каждые 10-15 итераций проводить дорогостоящую операцию реортогонализации, но это уже будет иной алгоритм с очень малым различием в одной операции и в программном коде, реализующем его, соответственно; &amp;lt;ref&amp;gt;Sam Handler - The Lanczos Algorithm For Large-Scale Eigenvalue Problems (08.01.07), slide №8&amp;lt;/ref&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
6) Эффективность и быстрота выполнения алгоритма очень сильно зависит от скорости памяти (диска). Согласно тесту только &#039;&#039;6%&#039;&#039; времени работы программы приходится на вычисления, остальное время затрачивается на ожидание отклика диска;&amp;lt;ref&amp;gt;Sam Handler - The Lanczos Algorithm For Large-Scale Eigenvalue Problems (08.01.07), slide №10&amp;lt;/ref&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
7) Метод Ланцоша удобен тем, что не требует хранения исходной матрицы полным массивом: метод использует исходную матрицу только в операциях умножения матрицы на вектор, что позволяет эффективно использовать разреженность матрицы или регулярность структуры матрицы. Поэтому метод Ланцоша может быть использован для матриц таких больших порядков, когда методы вращений и отражений не могут быть применены.&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;
Для исследования масштабируемости рассматриваемого алгоритма Ланцоша без переортогонализации автором была реализована программа на языке С++ с использованием технологии MPI. &amp;lt;ref&amp;gt;https://goo.gl/dGfzOD  или альтернативная ссылка с прикреплённым кодом: https://goo.gl/lFziv0 , по просьбе на почту я (автор статьи) готов предоставить желающим доступ к проекту с этим кодом на ресурсе Bitbucket&amp;lt;/ref&amp;gt; Дальнейшее исследование было проведено на суперкомпьютере &amp;quot;Ломоносов&amp;quot; Суперкомпьютерного комплекса МГУ. &amp;lt;br&amp;gt; Важно отметить, что реализованная программа выполняет только первую часть алгоритма - формирование матрицы &amp;lt;math &amp;gt;T_j&amp;lt;/math&amp;gt;. Вторая часть алгоритма (задача поиска собственных значений матрицы &amp;lt;math &amp;gt;T_j&amp;lt;/math&amp;gt;) может быть решена несколькими методами, каждый из которых обладает своей эффективностью распараллеливания и характерными свойствами. Подробно этот вопрос уже обсуждался в статье раннее, поэтому не будем ещё раз заострять на этом внимание и останавливаться.&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Сборка осуществлялась со следующими параметрами:&lt;br /&gt;
* Компилятор intel/15.0.090 &lt;br /&gt;
* Openmpi/1.8.4-icc&lt;br /&gt;
В серии проведённых расчётов рассматривались следующие числовые значения параметров:&lt;br /&gt;
* Размер &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;n&amp;lt;/math&amp;gt; задачи и, соответственно, матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt;, задействованной в операции умножения на вектор: [2000 : 30000] с шагом 1000&lt;br /&gt;
* Число процессоров: 1, 2, 4, 16, 32, 48, 64, 96, 128&lt;br /&gt;
* Число итераций в алгоритме: &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k=350&amp;lt;/math&amp;gt;&lt;br /&gt;
Число &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; взято таким вопреки информации в начале статьи, где говорится, что значение &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; редко превышает &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;10^2&amp;lt;/math&amp;gt; (хоть мы и имеем право брать его любым по нашему усмотрению). Это сделано исключительно для лучшей визуализации пиков на графиках в данном разделе и наглядности получаемых результатов, так как при меньших на порядок значениях параметра &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; времена выполнения программ были слишком малы даже при минимальных числах процессоров и максимальных размерах &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;n&amp;lt;/math&amp;gt; задачи.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
На рис. 2 изображён график зависимости времени выполнения программы от числа процессоров и размера &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;n&amp;lt;/math&amp;gt; задачи. &amp;lt;br&amp;gt;&lt;br /&gt;
[[Файл:Levin604 Lanzcos result execTIME.png|580px|thumb|center|Рис. 2  График зависимости времени выполнения программы]] &amp;lt;br&amp;gt;&lt;br /&gt;
Многочисленные тесты показали при малых количествах ядер уменьшение времени выполнения программы почти в 2 раза при увеличении числа ядер в 2 раза на всём диапазоне размеров матриц, что и отражает сильный излом на предоставленом графике. Изменение значения времени можно легко оценить по предоставленной цветовой шкале.&lt;br /&gt;
&lt;br /&gt;
== Динамические характеристики и эффективность реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Выводы для классов архитектур ==&lt;br /&gt;
По заданию, во второй части требовалось описать только разделы 2.4 и 2.7, прошу не спрашивать с меня все разделы 2.1-2.6. Надеюсь на понимание, мне физически не хватает времени на это задание + 2 других в течение семестра, делаю всё, что в моих силах :)&lt;br /&gt;
&lt;br /&gt;
== Существующие реализации алгоритма ==&lt;br /&gt;
Несмотря на то, что алгоритм является далеко не самым популярным, алгоритмом, про который нельзя сказать, что он всегда «на слуху», на сегодняшний день существует множество реализаций на различных популярных языках.&amp;lt;br&amp;gt;&lt;br /&gt;
Перечислим далее некоторые из них, указывая язык программирования, лежащий в их основе, и некоторые важные характеристики, которые обсуждались в статье ранее:&lt;br /&gt;
*&#039;&#039;Code on netlib.org by Jane Cullum and Ralph Willoughby&#039;&#039; (&#039;&#039;&#039;Fortran 77&#039;&#039;&#039;; без реортогонализации векторов; без реализации распараллеливания)&amp;lt;ref&amp;gt;http://www.netlib.org/lanczos/leval&amp;lt;/ref&amp;gt;&lt;br /&gt;
*&#039;&#039;Lanczos algorithm on freesourcecode.net&#039;&#039; (&#039;&#039;&#039;Matlab&#039;&#039;&#039;; присутствует реортогонализация векторов; без реализации распараллеливания)&amp;lt;ref&amp;gt;http://freesourcecode.net/matlabprojects/61741/lanczos-algorithm--in-matlab&amp;lt;/ref&amp;gt;&lt;br /&gt;
*&#039;&#039;Lanczos for eigenvalues in Numerical Linear Algebra, Spring 2007&#039;&#039; (&#039;&#039;&#039;Matlab&#039;&#039;&#039;; частичная или полная реортогонализация - доступны оба варианта; без реализации распараллеливания)&amp;lt;ref&amp;gt;Ссылки на файлы lanso.m и lanfu.m можно найти на https://www.nada.kth.se/~ruhe/2D5219/labs2007.html&amp;lt;/ref&amp;gt;&lt;br /&gt;
*&#039;&#039;Planso&#039;&#039; (название происходит от parallel Lanso.f) &#039;&#039;code by Kesheng Wu and Horst D. Simon&#039;&#039; (&#039;&#039;&#039;Fortran 77&#039;&#039;&#039;; частичная реортогонализация векторов; использование MPI для коммуникаций)&amp;lt;ref&amp;gt;https://github.com/jiahao/planso.jl/tree/master/external/PLAN/plan К сожалению, ссылка в описании пакета на github, ведущая на сайт National Energy Research Scientific Computing Center (NERSC), с более подробной информацией о данной программе больше не активна и выдаёт результат &#039;&#039;Page not found&#039;&#039;&amp;lt;/ref&amp;gt; &lt;br /&gt;
* &#039;&#039;Lanczos.cpp in the Vienna Computing Library&#039;&#039;  (&#039;&#039;&#039;C++&#039;&#039;&#039;, частичная реортогонализация, без реализации распараллеливания) &amp;lt;ref&amp;gt;http://viennacl.sourceforge.net/doc/lanczos_8cpp_source.html&amp;lt;/ref&amp;gt;&lt;br /&gt;
* &#039;&#039;Parallel Eigen Values code using C++ AMP on microsoft msdn blog&#039;&#039; (&#039;&#039;&#039;C++&#039;&#039;&#039;; ? ; распараллеливание есть и реализовано через C++ AMP) &amp;lt;ref&amp;gt;https://blogs.msdn.microsoft.com/nativeconcurrency/2013/12/20/eigen-values/ Подробнее о C++ Accelerated Massive Parallelism можно почитать здесь: https://msdn.microsoft.com/ru-ru/library/hh265137(v=vs.140).aspx или здесь: http://professorweb.ru/my/csharp/optimization/level4/4_6.php &amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;br /&gt;
[[en:Description of algorithm properties and structure]]&lt;/div&gt;</summary>
		<author><name>AleksLevin</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:AleksLevin/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%9B%D0%B0%D0%BD%D1%86%D0%BE%D1%88%D0%B0_%D0%B2%D1%8B%D1%87%D0%B8%D1%81%D0%BB%D0%B5%D0%BD%D0%B8%D1%8F_%D1%81%D0%BE%D0%B1%D1%81%D1%82%D0%B2%D0%B5%D0%BD%D0%BD%D1%8B%D1%85_%D0%B7%D0%BD%D0%B0%D1%87%D0%B5%D0%BD%D0%B8%D0%B9_%D1%81%D0%B8%D0%BC%D0%BC%D0%B5%D1%82%D1%80%D0%B8%D1%87%D0%BD%D0%BE%D0%B9_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86%D1%8B_%D0%B4%D0%BB%D1%8F_%D1%82%D0%BE%D1%87%D0%BD%D0%BE%D0%B9_%D0%B0%D1%80%D0%B8%D1%84%D0%BC%D0%B5%D1%82%D0%B8%D0%BA%D0%B8_(%D0%B1%D0%B5%D0%B7_%D0%BF%D0%B5%D1%80%D0%B5%D0%BE%D1%80%D1%82%D0%BE%D0%B3%D0%BE%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D0%B8)&amp;diff=20226</id>
		<title>Участник:AleksLevin/Алгоритм Ланцоша вычисления собственных значений симметричной матрицы для точной арифметики (без переортогонализации)</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:AleksLevin/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%9B%D0%B0%D0%BD%D1%86%D0%BE%D1%88%D0%B0_%D0%B2%D1%8B%D1%87%D0%B8%D1%81%D0%BB%D0%B5%D0%BD%D0%B8%D1%8F_%D1%81%D0%BE%D0%B1%D1%81%D1%82%D0%B2%D0%B5%D0%BD%D0%BD%D1%8B%D1%85_%D0%B7%D0%BD%D0%B0%D1%87%D0%B5%D0%BD%D0%B8%D0%B9_%D1%81%D0%B8%D0%BC%D0%BC%D0%B5%D1%82%D1%80%D0%B8%D1%87%D0%BD%D0%BE%D0%B9_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86%D1%8B_%D0%B4%D0%BB%D1%8F_%D1%82%D0%BE%D1%87%D0%BD%D0%BE%D0%B9_%D0%B0%D1%80%D0%B8%D1%84%D0%BC%D0%B5%D1%82%D0%B8%D0%BA%D0%B8_(%D0%B1%D0%B5%D0%B7_%D0%BF%D0%B5%D1%80%D0%B5%D0%BE%D1%80%D1%82%D0%BE%D0%B3%D0%BE%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D0%B8)&amp;diff=20226"/>
		<updated>2016-12-07T00:52:14Z</updated>

		<summary type="html">&lt;p&gt;AleksLevin: /* Масштабируемость алгоритма и его реализации */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Основные авторы описания: Левин А.Д.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{algorithm&lt;br /&gt;
| name              = Алгоритм Ланцоша для точной арифметики (без переортогонализации)&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(k\,n^2)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(k\log_2 n)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;\frac{n^2+3n}{2} + 1&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;k\;(n + 1)&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритмов =&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Данный алгоритм появился в 1950 г. и носит имя венгерского физика и математика Корнелия Ланцоша (венг. Lánczos Kornél). Алгоритм Ланцоша относится к итерационным методам вычисления собственных значений для матриц столь больших порядков &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt; n&amp;lt;/math&amp;gt;, что к ним нельзя применить прямые методы из-за ограничений по времени и памяти.&lt;br /&gt;
&lt;br /&gt;
Сам Ланцош указывал, что его метод предназначен для отыскания нескольких собственных векторов симметричных матриц, хотя к методу сразу было обращено внимание, как к способу приведения всей матрицы к трёхдиагональному виду. Двадцатью годами позже канадский математик Крис Пэж показал, что, несмотря на чувствительность к округлениям, алгоритм Ланцоша - эффективное средство вычисления некоторых &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; собственных чисел и соответствующих им собственных векторов. &amp;lt;ref&amp;gt;Парлетт Б. - Симметричная проблема собственных значений. Численные методы //М.: Мир. - 1983. (c. 276)&amp;lt;/ref&amp;gt;&lt;br /&gt;
Обычно число &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; берут в два раза больше, чем количество собственных значений матрицы, которые поставлена цель найти, и оно имеет порядок не более &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;10^2&amp;lt;/math&amp;gt;.&amp;lt;ref&amp;gt;Susan W. Bostic - Lanczos Eigensolution Method for High-Perfomance Computers, page 7&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Алгоритм Ланцоша для вычисления собственных значений симметричной матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; соединяет в себе метод Ланцоша для построения последовательности подпространств Крылова и ортонормированных векторов Ланцоша и процедуру Рэлея-Ритца получения оптимальных приближений собственных значений и соответствующих собственных векторов исходной матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt;.&amp;lt;ref&amp;gt;James W. Demmel - Вычислительная линейная алгебра. Теория и приложения //Мир. - 2001 (c. 381)&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
В данной статье рассматривается вариант алгоритма Ланцоша, в котором опущено влияние ошибок округления на вычислительный процесс, хотя на практике этому посвящается отдельное внимание и существуют различные методы решения данной проблемы, такие как частичная или полная переортогонализация. Этим модифицированным методам посвящены отдельные статьи на данном ресурсе.&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
Обозначения и формулы, используемые в данном разделе, взяты из литературы, указанной по ссылке.&amp;lt;ref&amp;gt;James W. Demmel - Вычислительная линейная алгебра. Теория и приложения //Мир. - 2001 (c. 313, &#039;&#039;&amp;lt;math&amp;gt; \S &amp;lt;/math&amp;gt; 6.6 Методы Крыловского подпространства&#039;&#039;)&amp;lt;/ref&amp;gt; &lt;br /&gt;
&lt;br /&gt;
Алгоритм Ланцоша для вычисления &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; собственных значений и собственных векторов вещественной симметричной матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A=A^T&amp;lt;/math&amp;gt; в точной арифметике: &amp;lt;ref&amp;gt;James W. Demmel - Вычислительная линейная алгебра. Теория и приложения //Мир. - 2001 (c. 381)&amp;lt;/ref&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{align}&lt;br /&gt;
q_1 = &amp;amp; \,\frac{b}{\|b\|_2},\; \beta_0 = 0,\; q_0 = 0\\&lt;br /&gt;
\mathbf{for} \; &amp;amp; j = 1 \; to \; k \,\; \mathbf{do} \\&lt;br /&gt;
&amp;amp; z = A\,q_j\\&lt;br /&gt;
&amp;amp; \alpha_j = q^T_j z\\&lt;br /&gt;
&amp;amp; z = z - \alpha_j q_j - \beta_{j-1}q_{j-1}\\&lt;br /&gt;
&amp;amp; \beta_j = \|z\|_2\\&lt;br /&gt;
&amp;amp; \mathbf{If} \; (\beta_j == 0) \; \mathbf{then}\; stop\; the\; algorithm \\ &lt;br /&gt;
&amp;amp; \;  q_{j+1} = \frac{z}{\beta_j} \\&lt;br /&gt;
&amp;amp; compute\; eigenvalues\; and \;eigenvectors\;of \;matrix \;\;T_j= Q^T_j A Q\;\;and\;estimate \;the\; errors\\&lt;br /&gt;
\mathbf{end} \; &amp;amp; \mathbf{for}&lt;br /&gt;
\end{align}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
В продемонстрированном выше алгоритме &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;b&amp;lt;/math&amp;gt; - заданный вещественный вектор. Также полагается известным алгоритм вычисления произведения матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; на вектор &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;x&amp;lt;/math&amp;gt;. &lt;br /&gt;
Введём матрицу Крылова, определяемую следующим соотношением: &amp;lt;math&amp;gt;K_j = [b,Ab,A^2b,...,A^{j-1}b]&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Далее, на практике, матрица &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;K&amp;lt;/math&amp;gt; заменяется матрицей &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;Q&amp;lt;/math&amp;gt;, такой, что при любом числе &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; линейные оболочки первых &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; столбцов в &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;K&amp;lt;/math&amp;gt; и &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;Q&amp;lt;/math&amp;gt; являются одним и тем же подпространством.&amp;lt;ref&amp;gt;James W. Demmel - Вычислительная линейная алгебра. Теория и приложения //Мир. - 2001 (c. 315)&amp;lt;/ref&amp;gt; &lt;br /&gt;
Тогда матрица &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;Q&amp;lt;/math&amp;gt;, в отличие от матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;K&amp;lt;/math&amp;gt;, хорошо обусловлена и легко обратима. В результате получаем матрицу &amp;lt;math&amp;gt;Q_j = [q_1, q_2, \dots, q_j]&amp;lt;/math&amp;gt; размерности &amp;lt;math&amp;gt;n\times j&amp;lt;/math&amp;gt;, столбцы которой ортогональны, являются базисом подпространства Крылова и называются векторами Ланцоша.&lt;br /&gt;
&lt;br /&gt;
В алгоритме Ланцоша вычислению подлежит столько первых столбцов в матрице &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;Q_j&amp;lt;/math&amp;gt;, сколько необходимо для получения требуемого приближения к решению &amp;lt;math&amp;gt;A\,x\,=b\,\,(A\,x=\lambda \, x)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Получение нулевого &amp;lt;math&amp;gt;\beta_j&amp;lt;/math&amp;gt; в итерационном процессе - событие, желательное в том смысле, что оно свидетельствует о том, что найдено некоторое подпространство, являющееся в точности инвариантным, а все собственные значения матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;T_j&amp;lt;/math&amp;gt; являются собственными значениями матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt;. На практике же нулевое и близкие к нулю значения получаются редко.&amp;lt;ref&amp;gt;Голуб Дж., Ван Лоун Ч. - Матричные вычисления//М.: Мир. - 1999 (c. 429)&amp;lt;/ref&amp;gt; &lt;br /&gt;
&lt;br /&gt;
Затем на каждом шаге цикла формируется симметричная трёхдиагональная матрица &amp;lt;math&amp;gt;T_j = Q^T_j A Q&amp;lt;/math&amp;gt;, к которой применяется процесс Рэлея-Ритца для поиска её собственных значений (на практике для поиска этих собственных значений можно использовать любой из специальных методов в параграфе книги по ссылке).&amp;lt;ref&amp;gt;Голуб Дж., Ван Лоун Ч. - Матричные вычисления//М.: Мир. - 1999 (&amp;lt;math&amp;gt;\S&amp;lt;/math&amp;gt; 8.4)&amp;lt;/ref&amp;gt;  &lt;br /&gt;
Эти собственные значения, они же числа Ритца, и полагаются приближёнными собственными значениями исходной матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt;.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Существует множество методов для отыскания собственных значений вещественной симметричной трехдиагональной матрицы. Большинство из них требует &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt; операций &amp;lt;ref&amp;gt;Парлетт Б. Симметричная проблема собственных значений. Численные методы.,: Мир, 1983. с. 179-182&amp;lt;/ref&amp;gt;, но существуют и быстрые алгоритмы, требующие лишь &amp;lt;math&amp;gt;O(n\ln n)&amp;lt;/math&amp;gt; операций.&amp;lt;ref&amp;gt;https://en.wikipedia.org/wiki/Tridiagonal_matrix#Eigenvalues  Раздел eigenvalues&amp;lt;/ref&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Одним из возможных способов отыскать собственные значения симметричной трехдиагональной матрицы - прямое вычисление корней характеристического полинома &amp;lt;math&amp;gt;p_n(\lambda)&amp;lt;/math&amp;gt; через метод деления пополам, где формируется последовательность Штурма и локализуются собственные числа, являющиеся корнями характеристического полинома. Нахождение всех &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; собственных значений матрицы этим способом требует &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;2n^2t&amp;lt;/math&amp;gt; умножений и вычитаний, где &amp;lt;math&amp;gt;t&amp;lt;/math&amp;gt; - число сделанных шагов с применением метода деления пополам.&amp;lt;ref&amp;gt;Уилкинсон Дж. X. Алгебраическая проблема собственныx значений. Изд-во &amp;quot;Наука&amp;quot;, 1970. - глава 5, с. 272-278&amp;lt;/ref&amp;gt; Соответствующие собственные вектора могут быть найдены посредством обратных итераций за &amp;lt;math&amp;gt; O(n) &amp;lt;/math&amp;gt; флопов. &amp;lt;ref&amp;gt;Голуб Дж., Ван Лоун Ч. - Матричные вычисления//М.: Мир. - 1999 (c. 394-395)&amp;lt;/ref&amp;gt; &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;На практике, если требуется только небольшая часть от всей совокупности собственных векторов и значений, и матрица имеет Хессенбергову или трёхдиагональную форму, очень эффективными будут методы факторизации, как, например, QR-алгоритм или QL-алгоритм со сдвигами (c целью ускорить алгоритм и сделать порядок сходимости квадратичным) или же без них.&amp;lt;ref&amp;gt;http://algorithm.narod.ru/ln/eigen/ETridiag.html&amp;lt;/ref&amp;gt; &amp;lt;br&amp;gt;&lt;br /&gt;
Весьма молодые и не менее актуальные конкуренты QR и QL алгоритмов, применяющиеся для поиска собственных значений:&lt;br /&gt;
*Методы divide-and-conquer (разделяй и властвуй), появившиеся в 1980-ых годах &amp;lt;ref&amp;gt;https://goo.gl/dapvbn ссылку пришлось сократить с помощью Google url shortener, так как символы подчеркивания портили её и не давали перейти по 1 клику&amp;lt;/ref&amp;gt;&lt;br /&gt;
*Relatively robust representation методы, появившиеся в 1990-ых и позволяющие найти собственные числа симметричной матрицы порядка &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;n&amp;lt;/math&amp;gt; за &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt; операций&lt;br /&gt;
&lt;br /&gt;
Если требуется вычислить собственные векторы, то необходимо хранить вычисляемые векторы Ланцоша. Если работа при этом производится только с оперативной памятью, то при большом порядке исходной матрицы (а именно для таких матриц и предназначен метод Ланцоша) число шагов  &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;j&amp;lt;/math&amp;gt;, которые могут быть выполнены до того момента, как оперативная память будет исчерпана, будет очень незначительно, а следовательно, искомые собственные пары могут не успеть сойтись с требуемой точностью. В этом случае метод Ланцоша можно использовать итерационным образом: после выполнения заданного числа шагов процесс прерывается и, если еще не все требуемые пары Ритца сошлись с требуемой точностью, то формируется новый начальный вектор &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;q_1&amp;lt;/math&amp;gt;, являющийся линейной комбинацией векторов Ритца, еще не сошедшихся с заданной точностью, и процесс начинается заново.&amp;lt;ref&amp;gt;http://num-anal.srcc.msu.ru/lib_na/int_ae/int_ae6.htm (пункт 6.5)&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
Вычислительное ядро рассматриваемого алгоритма (наиболее ресурсно-затратная часть алгоритма) -  формирование на каждом шаге цикла промежуточного вектора &amp;lt;math&amp;gt;z&amp;lt;/math&amp;gt;, вычисляемого по формуле: &amp;lt;math&amp;gt;z = A\,q_j&amp;lt;/math&amp;gt;. Данная операция, по сравнению с другими операциями алгоритма, затратна и требовательна, как с точки зрения количества производимых операций, так и с точки зрения объема оперируемых данных. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Например, умножение матрицы размера &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;n\times n&amp;lt;/math&amp;gt; на вектор длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; требует: &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;n^2+(n-1)n = 2n^2-n&amp;lt;/math&amp;gt; операций умножения и сложения. В свою очередь аналогичная операция умножения матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;(n+1)\times (n+1)&amp;lt;/math&amp;gt; на вектор длины &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;(n+1)&amp;lt;/math&amp;gt; требует: &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;2n^2+3n+1&amp;lt;/math&amp;gt;  операций умножения и сложения. То есть повышение размерности задачи всего на 1 увеличивает число необходимых действий в этом шаге алгоритма на: &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;4n+1&amp;lt;/math&amp;gt;. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Так же, стоит помнить, что, согласно разделу 1.2, данную операцию умножения матрицы на вектор необходимо выполнить &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;k&amp;lt;/math&amp;gt; раз. Нетрудно понять, насколько возрастает и колоссален масштаб операций, если в задачах, где критична точность, размерности &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; могут иметь порядок &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;10^5&amp;lt;/math&amp;gt; или даже более.&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
Как уже было упомянуто в данной статье в описании алгоритма, рассматриваемый алгоритм состоит из двух последовательно выполненных алгоритмов: метод Ланцоша для построения последовательности подпространств Крылова и ортонормированных векторов Ланцоша и процедура Рэлея-Ритца получения оптимальных приближений собственных значений и соответствующих собственных векторов исходной матрицы.&lt;br /&gt;
&lt;br /&gt;
В первой части алгоритма, где итерационно строятся Крыловское подпространство и трёхдиагональная матрица &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&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 style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; разреженная. Именно она подлежит оптимизации с использованием техник распараллеливания, поскольку она является вычислительным ядром алгоритма, а весь упомянутый процесс построения матрицы &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&amp;lt;/math&amp;gt; выполняется последовательно.&lt;br /&gt;
&lt;br /&gt;
Рассмотрим вторую часть алгоритма - поиск собственных значений сформированной матрицы &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&amp;lt;/math&amp;gt;.&amp;lt;br&amp;gt;&lt;br /&gt;
Далее, наглядно, в виде псевдокода, представлен, упомянутый в разделе 1.2, QR-алгоритм (аналогично можно рассмотреть и QL-алгоритм) со сдвигами Релэя, который весьма популярен на практике.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{align}&lt;br /&gt;
\mathbf{Input}: \;&amp;amp;tridiagonal\;\;matrix \;T\;with\;\;n\times n\;\;size\\&lt;br /&gt;
T^{(0)}&amp;amp;:=T\\&lt;br /&gt;
\mathbf{for}&amp;amp; \;\;m=n,...,2 \;\; \mathbf{do}\\&lt;br /&gt;
&amp;amp;k=0\\&lt;br /&gt;
&amp;amp; \mathbf{repeat}\\&lt;br /&gt;
&amp;amp; \quad \;\; k=k+1\\&lt;br /&gt;
&amp;amp; \quad \;\; \mu^{(k)}=T_{m,m}^{(k-1)}\\&lt;br /&gt;
&amp;amp; \quad \;\; Q^{(k)}R^{(k)}=T^{(k-1)}-\mu^{(k)}I\;\;using\;\;QR\;decomposition\\&lt;br /&gt;
&amp;amp; \quad \;\; T^{(k)}=R^{(k)}Q^{(k)}+\mu^{(k)}I\\&lt;br /&gt;
&amp;amp; \mathbf{until} \;\;\; |T_{m,m-1}^{(k)}| \;is\;\;small\;\;enough\\&lt;br /&gt;
&amp;amp; Save  \;\;T_{m,m}^{(k)} \;\;as\;\; converged\;\;eigenvalue\;of\;T\\ &lt;br /&gt;
&amp;amp; Remove \;\boldsymbol{n}\,th\;row\;and\;\boldsymbol{n}\,th\;column\;\;from \;T \\&lt;br /&gt;
&amp;amp; and\;take\;this\;new\;cropped\;matrix\;as\;new\;T^{(0)}\;with\;\;(n-1)\times (n-1)\;\;size\\&lt;br /&gt;
 \mathbf{end}&amp;amp;\; \mathbf{for}&lt;br /&gt;
\end{align}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Малость наддиагональных и поддиагональных элементов матрицы (фраза &#039;&#039;&amp;quot;small enough&amp;quot;&#039;&#039; в псевдокоде) подразумевает:&lt;br /&gt;
&amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt; |T_{m,m-1}^{(k)}| \leq \varepsilon\,|T_{m,m}^{(k)}| \quad\quad &amp;lt;/math&amp;gt; , где &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt; \varepsilon &amp;lt;/math&amp;gt; - заданная точность&amp;lt;br&amp;gt;&lt;br /&gt;
Также вместо сдвига Релэя, обозначенного в алгоритме через &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;\mu^{(k)}&amp;lt;/math&amp;gt;, часто на практике используется сдвиг по Уилкинсону, который даёт гарантированную сходимость внедиагональных элементов матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt; T^{(k)} &amp;lt;/math&amp;gt;, формируемой на каждом шаге, к нулю, при этом жертвуя монотонностью их убывания.&amp;lt;ref&amp;gt;Голуб Дж., Ван Лоун Ч. - Матричные вычисления//М.: Мир. - 1999 (c. 378, вторая половина страницы)&amp;lt;/ref&amp;gt;&amp;lt;ref&amp;gt;Парлетт Б. Симметричная проблема собственных значений. Численные методы.,: Мир, 1983. с. 169&amp;lt;/ref&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Подробнее с различными сдвигами и соответствующими оценками скоростей и количествами операций можно ознакомиться по указанной ссылке:&amp;lt;ref&amp;gt;Парлетт Б. Симметричная проблема собственных значений. Численные методы.,: Мир, 1983. с. 179-182&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;Для совершения QR-декомпозиции на каждом шаге может использоваться любой из алгоритмов по ссылке.&amp;lt;ref&amp;gt;https://en.wikipedia.org/wiki/QR_decomposition&amp;lt;/ref&amp;gt; Подробные описания этих алгоритмов также доступны на данном ресурсе algowiki-project.&amp;lt;br&amp;gt;&lt;br /&gt;
Так как мы оперируем не обычной матрицей и даже не Хессенберговой, а симметричной и трёхдиагональной, то скорость таких алгоритмов значительно возрастёт. Например, согласно данному ресурсу &amp;lt;ref&amp;gt;http://algorithm.narod.ru/ln/eigen/ETridiag.html&amp;lt;/ref&amp;gt;, для QL-алгоритма с неявными сдвигами:&amp;lt;br&amp;gt;&lt;br /&gt;
Для трёхдиагональной матрицы объем арифметических действий составляет &amp;lt;math&amp;gt; O(n)&amp;lt;/math&amp;gt; на одну итерацию вместо &amp;lt;math&amp;gt; O(n^3)&amp;lt;/math&amp;gt; для матрицы общего вида, а число итераций для нахождения первых собственных значений примерно равно 4 - 5. Но на этих итерациях также уменьшаются внедиагональные элементы правого нижнего угла. И, таким образом, дальнейшие собственные значения ищутся значительно быстрее. Среднее число итераций на каждое собственное значение обычно составляет 1.3 - 1.6.&amp;lt;br&amp;gt; &lt;br /&gt;
Аналогично QL, QR-разложение трёхдиагольной матрицы также требует &amp;lt;math&amp;gt; O(n)&amp;lt;/math&amp;gt; флопов&amp;lt;ref&amp;gt;Голуб Дж., Ван Лоун Ч. - Матричные вычисления//М.: Мир. - 1999 (c. 378, начало раздела 8.2.2)&amp;lt;/ref&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Подводя итог, во второй части алгоритма Ланцоша можно выделить следующие макрооперации:&lt;br /&gt;
* умножение матрицы на вещественное число;&lt;br /&gt;
* перемножение матриц;&lt;br /&gt;
* умножение и сравнение вещественных чисел;&lt;br /&gt;
* + набор других макроопераций в зависимости от выбора метода, с помощью которого будет совершаться сама QR или QL-декомпозиция (выше продемонстрированы, уже, как минимум, 3 разных способа).&lt;br /&gt;
Так же, важно заметить, что набор макропераций может быть несколько другим, если выбрать какой-либо иной современный метод поиска собственных чисел трёхдиагональной матрицы, не использующий QR и QL разложения(факторизацию). Два таких метода были упомянуты в пункте 1.2.&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
С целью полностью не дублировать раздел 1.2 данной статьи, где представлен наглядный и доступный для понимания псевдокод алгоритма, постараемся лишь коротко просуммировать и обобщить весь перечень последовательных действий в рассматриваемом алгоритме.&lt;br /&gt;
&lt;br /&gt;
В качестве входных данных имеем: вещественная симметричная матрица &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; размера &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;n\times n&amp;lt;/math&amp;gt;, известный вещественный вектор &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;b&amp;lt;/math&amp;gt; длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; и число &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;n&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Далее:&lt;br /&gt;
* Инициализируем вещественную константу &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;\beta_0&amp;lt;/math&amp;gt; и векторы &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;q_0&amp;lt;/math&amp;gt; и &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;q_1&amp;lt;/math&amp;gt;&lt;br /&gt;
* Итерационно для всех &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j=1,...,k&amp;lt;/math&amp;gt;:&lt;br /&gt;
** Вычисляем вспомогательный вектор &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt;, используя умножение матрицы на вектор&lt;br /&gt;
** Вычисляем, используя скалярное произведение векторов, значение &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;\alpha_j&amp;lt;/math&amp;gt; - элемент на главной диагонали трёхдиагональной матрицы &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&amp;lt;/math&amp;gt;&lt;br /&gt;
** Вычисляем по формуле новое значение и перезаписываем вектор &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt;&lt;br /&gt;
** Вычисляем значение &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;\beta_j&amp;lt;/math&amp;gt; - элементы непосредственно над и под главной диагональю той же матрицы &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&amp;lt;/math&amp;gt;&lt;br /&gt;
** Вычисляем, зная вектор &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt;,  очередной столбец матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;Q&amp;lt;/math&amp;gt;, он же вектор Ланцоша : &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;\,\,q_{j+1}&amp;lt;/math&amp;gt;&lt;br /&gt;
** Теперь, когда матрица &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&amp;lt;/math&amp;gt; сформирована на очередном шаге, находим её собственные значения и вектора любым доступным способом, о чём было подробно сказано в пункте 1.2&lt;br /&gt;
** Переходим на следующую итерацию: &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j&amp;lt;/math&amp;gt;++&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
Оценим количество операций и сложность последовательного алгоритма, изложенного в предыдущем разделе.&lt;br /&gt;
*Для вычисления вектора &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt; умножается матрица размера &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;n\times n&amp;lt;/math&amp;gt; на вектор длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt;, и потребуется &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n^2&amp;lt;/math&amp;gt; операций умножения и &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n^2&amp;lt;/math&amp;gt; операций сложения.&lt;br /&gt;
*Умножение векторов &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;q^T_j&amp;lt;/math&amp;gt; и &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt; длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; потребует &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; операций умножения и &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; операций сложения.&lt;br /&gt;
*При вычислении нового значения вектора &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt; поэлементное сложение двух векторов длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; требует &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; операций сложения.&lt;br /&gt;
*Умножение вектора длины &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; на вещественное число требует &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; операций умножения.&lt;br /&gt;
*Нахождение квадратичной нормы вектора &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt;  длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; требует &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; умножений и &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; сложений и ещё 1 операцию извлечения квадратного корня.&lt;br /&gt;
*Заключительное нахождение собственных значений и собственных векторов трёхдиагональной матрицы &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;T_j&amp;lt;/math&amp;gt; размера &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j\times j&amp;lt;/math&amp;gt; с помощью QR-алгоритма потребует в худшем случае &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(j^3)&amp;lt;/math&amp;gt; операций.&amp;lt;ref&amp;gt;http://num-anal.srcc.msu.ru/lib_na/int_ae/int_ae6.htm (пункт 6.2, &amp;quot;Скорость сходимости при этом всегда не хуже квадратичной и почти всегда лучше кубической.&amp;quot;)&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Посчитаем теперь суммарное количество простейших операций на одной итерации алгоритма (без учёта записей в память):&lt;br /&gt;
*&amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n^2+5\,n&amp;lt;/math&amp;gt; операций умножения/деления&lt;br /&gt;
*&amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n^2+4\,n&amp;lt;/math&amp;gt; операций сложения/вычитания&lt;br /&gt;
*1 операция извлечения квадратного корня&amp;lt;br&amp;gt;&lt;br /&gt;
Отдельно после всех итераций при &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j=k&amp;lt;/math&amp;gt; :&lt;br /&gt;
*&amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(k^3)&amp;lt;/math&amp;gt; операций для поиска собственных значений и собственных векторов трёхдиагональной матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_k&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Итого можно утверждать следующее:&lt;br /&gt;
&lt;br /&gt;
Последовательная сложность одной итерации рассматриваемого алгоритма:  &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(n ^ 2) &amp;lt;/math&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Суммарная сложность алгоритма (&amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;/math&amp;gt; итераций): &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(k\,n ^ 2) + O(k ^ 3)&amp;lt;/math&amp;gt; &amp;lt;ref&amp;gt;Здесь мы полагаем, что мы не вычисляем собственные значения и векторы матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_j&amp;lt;/math&amp;gt; на каждом промежуточном шаге, а лишь единожды затрачиваем &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;O(k ^ 3)&amp;lt;/math&amp;gt; действий в конце для нахождения &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;/math&amp;gt; собственных значений и векторов матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_k&amp;lt;/math&amp;gt;&amp;lt;/ref&amp;gt; &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
На практике же обычно рассматривается число &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;&amp;lt;n&amp;lt;/math&amp;gt;, поэтому второе слагаемое можно опустить.&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
На рис. 1 продемонстрирован граф одной итерации (при каком-либо произвольном значении итератора &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j&amp;lt;/math&amp;gt;) описанного алгоритма без отображения входных и выходных данных. Наглядно продемонстрированы связи между всеми действиями, и с помощью деления на &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; потоков показано, какие операции возможно выполнять параллельно на каждом шаге с целью оптимизации и экономии машинного времени. В результате, после параллельно выполненных операций &#039;&#039;&#039;Division&#039;&#039;&#039; на заключительном ярусе, на выходе имеем значение следующего вектора Ланцоша &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;q_{j+1}&amp;lt;/math&amp;gt;, после чего следует переход на следующую итерацию, и процесс повторяется.&lt;br /&gt;
&lt;br /&gt;
[[Файл:Levin_graph.png|600px|thumb|center|Рис. 1  Структура одной итерации алгоритма]] &amp;lt;br&amp;gt;&lt;br /&gt;
Обозначения на рисунке: &amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Simp&#039;&#039;&#039; (от англ. simple) - операции сложения и умножения вещественных чисел при вычислении произведения матрицы на вектор;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Vec mult&#039;&#039;&#039; (от англ. vectors multiplication) - операция скалярного умножения двух векторов;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Vec subtr&#039;&#039;&#039; (от англ. vectors subtraction, из-за использованных в операции вычитаний векторов) - операция умножения вектора на число (выполняется дважды) и формирование нового значения &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;z_{new}&amp;lt;/math&amp;gt; по формуле: &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;z_{new} = z - \alpha_j q_j - \beta_{j-1}q_{j-1} \;&amp;lt;/math&amp;gt;;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;||\cdot||&amp;lt;/math&amp;gt; - операция вычисления нормы вектора;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Division&#039;&#039;&#039; - операция деления вектора на вещественное число  &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;\beta_j&amp;lt;/math&amp;gt; &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Важно отметить, что упомянутые выше операции также легко поддаются оптимизации. Например, попарные умножения вещественных координат векторов при вычислении скалярного произведения также легко выполняются параллельно на &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; потоках, а затем можно применить суммирование методом сдваивания, о котором сказано в следующем разделе. Умножение или деление вектора на вещественное число являющееся, по определению, умножением или делением всех его координат на это число тоже может быть выполнено эффективнее, если мы используем &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; потоков, а не выполняем эти действия последовательно.&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
Параллельные операции возможны только внутри итераций, так как рассматриваемый алгоритм является итерационным, и сами итерации строго последовательны.&amp;lt;br&amp;gt;&lt;br /&gt;
Рассмотрим в этом разделе подробнее, какой выигрыш мы можем получить при распараллеливании операций внутри одной итерации согласно графу из предыдущего раздела.&lt;br /&gt;
&lt;br /&gt;
Умножение вещественной симметричной матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; размера &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;n\times n&amp;lt;/math&amp;gt; на вектор &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;b&amp;lt;/math&amp;gt; длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; требует последовательного выполнения &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; ярусов умножений и сложений. Сложение элементов вектора длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; на каждом шаге перемножения можно оптимизировать и выполнить за &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;\log_2 n&amp;lt;/math&amp;gt; действий, если применять метод сдваивания.&lt;br /&gt;
&lt;br /&gt;
Дальнейшие операции выполняются последовательно, а вычисление значений векторов происходит за один ярус операций сложения или умножения.&lt;br /&gt;
&lt;br /&gt;
Ресурс параллелизма алгоритма вычисления собственных значений построенной трёхдиагональной матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_k&amp;lt;/math&amp;gt; размера &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k\times k&amp;lt;/math&amp;gt; зависит от выбранного алгоритма (об этих алгоритмах подробнее было сказано в разделах 1.2 и 1.4). Будет очень затратно с точки зрения объёма материала пытаться рассмотреть пусть даже часть этих методов в этой статье, а так же тонкости их распараллеливания. Предлагаем читателям при желании самим ознакомиться с этими алгоритмами на данном ресурсе или прибегнув к иным источникам.&lt;br /&gt;
&lt;br /&gt;
При классификации по высоте ЯПФ, таким образом, алгоритм Ланцоша без переортогонализации относится к алгоритмам с &#039;&#039;логарифмической сложностью&#039;&#039;, и его сложность равна &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(\log_2 n)&amp;lt;/math&amp;gt; с важным замечанием, что это сложность только одной итерации, а максимум в алгоритме может быть выполнено последовательно &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;/math&amp;gt; таких однотипных итераций, если не будет осуществлён ранний выход из цикла. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Несмотря на то, что на графе в предыдущем разделе для лучшей визуализации и понимания было изображено &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; потоков (никаких допущений мы не делали и нарушений с точки зрения логики и математики нет, можно изобразить большее число потоков, просто часть времени некоторые из них могут бездействовать и не использоваться), на самом деле правильным и разумным будет реализовать начальное параллельное выполнение &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n^2&amp;lt;/math&amp;gt; операций умножения всех вещественных элементов матрицы &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;A&amp;lt;/math&amp;gt; на соответствующие элементы вектора &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;q_j&amp;lt;/math&amp;gt;, после чего применять тот же самый упомянутый метод сдваивания. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Поэтому при классификации по ширине ЯПФ его сложность будет &#039;&#039;квадратичной&#039;&#039; и равна &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(n^2)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
&#039;&#039;&#039;Входные данные алгоритма:&#039;&#039;&#039; вещественная симметричная &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; размера &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;n\times n&amp;lt;/math&amp;gt;, вещественный вектор &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;b&amp;lt;/math&amp;gt; длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt;, и одно целое число &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;k&amp;lt;/math&amp;gt;, означающее количество итераций.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём входных данных:&#039;&#039;&#039; &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;n^2 +n + 1 &amp;lt;/math&amp;gt;. Если учесть, что матрица симметричная и достаточно для её однозначного определения задать элементы на главной диагонали и элементы над или под ней, то можно сократить объём входных данных с целью экономии памяти до: &amp;lt;math&amp;gt;\ \frac{n^2-n}{2}+n+n+1 =\frac{n^2+3n}{2} + 1&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные алгоритма:&#039;&#039;&#039; вектор собственных значений &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;\Theta^k&amp;lt;/math&amp;gt; длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;/math&amp;gt;, матрица &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;S^k&amp;lt;/math&amp;gt; из соответствующих собственных векторов размера &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n\times k&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём выходных данных:&#039;&#039;&#039; &amp;lt;math&amp;gt;k\;(n + 1)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
В данном разделе перечислены без какой-либо хронологии или связи друг с другом наиболее важные и разнообразные свойства алгоритма, на которые стоит и полезно обратить внимание, а также которые выгодно отличают его от схожих алгоритмов, решающих ту же задачу.&amp;lt;br&amp;gt;&lt;br /&gt;
1) Отношение последовательной сложности алгоритма к параллельной,с учётом &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;/math&amp;gt; итераций, равно &amp;lt;math&amp;gt;\;\;\frac{kn^2}{k \log_2{n}}=\frac{n^2}{\log_2{n}}&amp;lt;/math&amp;gt;;&amp;lt;br&amp;gt;&lt;br /&gt;
2) Вычислительная мощность алгоритма, как отношение числа операций к суммарному объему входных и выходных данных, равна &amp;lt;math style=&amp;quot;vertical-align:-70%&amp;gt;\;\;\frac{k\,n^2}{0.5\,n^2+1.5\,n+k\,n+k+1}&amp;lt;/math&amp;gt; и &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;\approx 2\,k&amp;lt;/math&amp;gt;, так как на практике верно отношение &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;&amp;lt;n&amp;lt;/math&amp;gt; ;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
3) Для собственных значений формируемых матриц &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_j&amp;lt;/math&amp;gt; верно отношение (следствие теоремы Коши о перемежаемости): &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;\lambda_i(T_{k+1})\geq \lambda_i(T_{k})\geq \lambda_{i+1}(T_{k+1})\geq \lambda_{i+1}(T_{k})&amp;lt;/math&amp;gt; ;&amp;lt;ref&amp;gt;James W. Demmel - Вычислительная линейная алгебра. Теория и приложения //Мир. - 2001 (c. 383)&amp;lt;/ref&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
4) Крайние (наибольшие и наименьшие) собственные значения матриц &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_j&amp;lt;/math&amp;gt; сходятся к крайним собственным значениям матрицы &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;A&amp;lt;/math&amp;gt; первыми (это часто происходит уже на ранних шагах при &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j\approx 2\,\sqrt{n}&amp;lt;/math&amp;gt;&amp;lt;ref&amp;gt;http://num-anal.srcc.msu.ru/lib_na/int_ae/int_ae6.htm (пункт 6.5)&amp;lt;/ref&amp;gt;), а собственные значения в середине спектра - последними;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
5) Из-за ограниченной точности постепенно теряется ортогональность вектора Ланцоша &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;q_j&amp;lt;/math&amp;gt; к предыдущим векторам Ланцоша, поэтому необходимо примерно каждые 10-15 итераций проводить дорогостоящую операцию реортогонализации, но это уже будет иной алгоритм с очень малым различием в одной операции и в программном коде, реализующем его, соответственно; &amp;lt;ref&amp;gt;Sam Handler - The Lanczos Algorithm For Large-Scale Eigenvalue Problems (08.01.07), slide №8&amp;lt;/ref&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
6) Эффективность и быстрота выполнения алгоритма очень сильно зависит от скорости памяти (диска). Согласно тесту только &#039;&#039;6%&#039;&#039; времени работы программы приходится на вычисления, остальное время затрачивается на ожидание отклика диска;&amp;lt;ref&amp;gt;Sam Handler - The Lanczos Algorithm For Large-Scale Eigenvalue Problems (08.01.07), slide №10&amp;lt;/ref&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
7) Метод Ланцоша удобен тем, что не требует хранения исходной матрицы полным массивом: метод использует исходную матрицу только в операциях умножения матрицы на вектор, что позволяет эффективно использовать разреженность матрицы или регулярность структуры матрицы. Поэтому метод Ланцоша может быть использован для матриц таких больших порядков, когда методы вращений и отражений не могут быть применены.&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;
Для исследования масштабируемости рассматриваемого алгоритма Ланцоша без переортогонализации автором была реализована программа на языке С++ с использованием технологии MPI. &amp;lt;ref&amp;gt;https://goo.gl/dGfzOD  или альтернативная ссылка с прикреплённым кодом: https://goo.gl/lFziv0 , по просьбе на почту я (автор статьи) готов предоставить желающим доступ к проекту с этим кодом на ресурсе Bitbucket&amp;lt;/ref&amp;gt; Дальнейшее исследование было проведено на суперкомпьютере &amp;quot;Ломоносов&amp;quot; Суперкомпьютерного комплекса МГУ. &amp;lt;br&amp;gt; Важно отметить, что реализованная программа выполняет только первую часть алгоритма - формирование матрицы &amp;lt;math &amp;gt;T_j&amp;lt;/math&amp;gt;. Вторая часть алгоритма (задача поиска собственных значений матрицы &amp;lt;math &amp;gt;T_j&amp;lt;/math&amp;gt;) может быть решена несколькими методами, каждый из которых обладает своей эффективностью распараллеливании и характерными свойствами. Подробно этот вопрос уже обсуждался в статье раннее, поэтому не будем ещё раз заострять на этом внимание и останавливаться.&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Сборка осуществлялась со следующими параметрами:&lt;br /&gt;
* Компилятор intel/15.0.090 &lt;br /&gt;
* Openmpi/1.8.4-icc&lt;br /&gt;
В серии проведённых расчётов рассматривались следующие числовые значения параметров:&lt;br /&gt;
* Размер &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;n&amp;lt;/math&amp;gt; задачи и, соответственно, матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt;, задействованной в операции умножения на вектор: [2000 : 30000] с шагом 1000&lt;br /&gt;
* Число процессоров: 1, 2, 4, 16, 32, 48, 64, 96, 128&lt;br /&gt;
* Число итераций в алгоритме: &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k=350&amp;lt;/math&amp;gt;&lt;br /&gt;
Число &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; взято таким вопреки информации в начале статьи, где говорится, что значение &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; редко превышает &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;10^2&amp;lt;/math&amp;gt; (хоть мы и имеем право брать его любым по нашему усмотрению). Это сделано исключительно для лучшей визуализации пиков на графиках в данном разделе и наглядности получаемых результатов, так как при меньших на порядок значениях параметра &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; времена выполнения программ были слишком малы даже при минимальных числах процессоров и максимальных размерах &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;n&amp;lt;/math&amp;gt; задачи.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
На рис. 2 изображён график зависимости времени выполнения программы от числа процессоров и размера &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;n&amp;lt;/math&amp;gt; задачи. &amp;lt;br&amp;gt;&lt;br /&gt;
[[Файл:Levin604 Lanzcos result execTIME.png|580px|thumb|center|Рис. 2  График зависимости времени выполнения программы]] &amp;lt;br&amp;gt;&lt;br /&gt;
Многочисленные тесты показали при малых количествах ядер уменьшение времени выполнения программы почти в 2 раза при увеличении числа ядер в 2 раза на всём диапазоне размеров матриц, что и отражает сильный излом на предоставленом графике. Изменение значения времени можно легко оценить по предоставленной цветовой шкале.&lt;br /&gt;
&lt;br /&gt;
== Динамические характеристики и эффективность реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Выводы для классов архитектур ==&lt;br /&gt;
По заданию, во второй части требовалось описать только разделы 2.4 и 2.7, прошу не спрашивать с меня все разделы 2.1-2.6. Надеюсь на понимание, мне физически не хватает времени на это задание + 2 других в течение семестра, делаю всё, что в моих силах :)&lt;br /&gt;
&lt;br /&gt;
== Существующие реализации алгоритма ==&lt;br /&gt;
Несмотря на то, что алгоритм является далеко не самым популярным, алгоритмом, про который нельзя сказать, что он всегда «на слуху», на сегодняшний день существует множество реализаций на различных популярных языках.&amp;lt;br&amp;gt;&lt;br /&gt;
Перечислим далее некоторые из них, указывая язык программирования, лежащий в их основе, и некоторые важные характеристики, которые обсуждались в статье ранее:&lt;br /&gt;
*&#039;&#039;Code on netlib.org by Jane Cullum and Ralph Willoughby&#039;&#039; (&#039;&#039;&#039;Fortran 77&#039;&#039;&#039;; без реортогонализации векторов; без реализации распараллеливания)&amp;lt;ref&amp;gt;http://www.netlib.org/lanczos/leval&amp;lt;/ref&amp;gt;&lt;br /&gt;
*&#039;&#039;Lanczos algorithm on freesourcecode.net&#039;&#039; (&#039;&#039;&#039;Matlab&#039;&#039;&#039;; присутствует реортогонализация векторов; без реализации распараллеливания)&amp;lt;ref&amp;gt;http://freesourcecode.net/matlabprojects/61741/lanczos-algorithm--in-matlab&amp;lt;/ref&amp;gt;&lt;br /&gt;
*&#039;&#039;Lanczos for eigenvalues in Numerical Linear Algebra, Spring 2007&#039;&#039; (&#039;&#039;&#039;Matlab&#039;&#039;&#039;; частичная или полная реортогонализация - доступны оба варианта; без реализации распараллеливания)&amp;lt;ref&amp;gt;Ссылки на файлы lanso.m и lanfu.m можно найти на https://www.nada.kth.se/~ruhe/2D5219/labs2007.html&amp;lt;/ref&amp;gt;&lt;br /&gt;
*&#039;&#039;Planso&#039;&#039; (название происходит от parallel Lanso.f) &#039;&#039;code by Kesheng Wu and Horst D. Simon&#039;&#039; (&#039;&#039;&#039;Fortran 77&#039;&#039;&#039;; частичная реортогонализация векторов; использование MPI для коммуникаций)&amp;lt;ref&amp;gt;https://github.com/jiahao/planso.jl/tree/master/external/PLAN/plan К сожалению, ссылка в описании пакета на github, ведущая на сайт National Energy Research Scientific Computing Center (NERSC), с более подробной информацией о данной программе больше не активна и выдаёт результат &#039;&#039;Page not found&#039;&#039;&amp;lt;/ref&amp;gt; &lt;br /&gt;
* &#039;&#039;Lanczos.cpp in the Vienna Computing Library&#039;&#039;  (&#039;&#039;&#039;C++&#039;&#039;&#039;, частичная реортогонализация, без реализации распараллеливания) &amp;lt;ref&amp;gt;http://viennacl.sourceforge.net/doc/lanczos_8cpp_source.html&amp;lt;/ref&amp;gt;&lt;br /&gt;
* &#039;&#039;Parallel Eigen Values code using C++ AMP on microsoft msdn blog&#039;&#039; (&#039;&#039;&#039;C++&#039;&#039;&#039;; ? ; распараллеливание есть и реализовано через C++ AMP) &amp;lt;ref&amp;gt;https://blogs.msdn.microsoft.com/nativeconcurrency/2013/12/20/eigen-values/ Подробнее о C++ Accelerated Massive Parallelism можно почитать здесь: https://msdn.microsoft.com/ru-ru/library/hh265137(v=vs.140).aspx или здесь: http://professorweb.ru/my/csharp/optimization/level4/4_6.php &amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;br /&gt;
[[en:Description of algorithm properties and structure]]&lt;/div&gt;</summary>
		<author><name>AleksLevin</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:AleksLevin/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%9B%D0%B0%D0%BD%D1%86%D0%BE%D1%88%D0%B0_%D0%B2%D1%8B%D1%87%D0%B8%D1%81%D0%BB%D0%B5%D0%BD%D0%B8%D1%8F_%D1%81%D0%BE%D0%B1%D1%81%D1%82%D0%B2%D0%B5%D0%BD%D0%BD%D1%8B%D1%85_%D0%B7%D0%BD%D0%B0%D1%87%D0%B5%D0%BD%D0%B8%D0%B9_%D1%81%D0%B8%D0%BC%D0%BC%D0%B5%D1%82%D1%80%D0%B8%D1%87%D0%BD%D0%BE%D0%B9_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86%D1%8B_%D0%B4%D0%BB%D1%8F_%D1%82%D0%BE%D1%87%D0%BD%D0%BE%D0%B9_%D0%B0%D1%80%D0%B8%D1%84%D0%BC%D0%B5%D1%82%D0%B8%D0%BA%D0%B8_(%D0%B1%D0%B5%D0%B7_%D0%BF%D0%B5%D1%80%D0%B5%D0%BE%D1%80%D1%82%D0%BE%D0%B3%D0%BE%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D0%B8)&amp;diff=20225</id>
		<title>Участник:AleksLevin/Алгоритм Ланцоша вычисления собственных значений симметричной матрицы для точной арифметики (без переортогонализации)</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:AleksLevin/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%9B%D0%B0%D0%BD%D1%86%D0%BE%D1%88%D0%B0_%D0%B2%D1%8B%D1%87%D0%B8%D1%81%D0%BB%D0%B5%D0%BD%D0%B8%D1%8F_%D1%81%D0%BE%D0%B1%D1%81%D1%82%D0%B2%D0%B5%D0%BD%D0%BD%D1%8B%D1%85_%D0%B7%D0%BD%D0%B0%D1%87%D0%B5%D0%BD%D0%B8%D0%B9_%D1%81%D0%B8%D0%BC%D0%BC%D0%B5%D1%82%D1%80%D0%B8%D1%87%D0%BD%D0%BE%D0%B9_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86%D1%8B_%D0%B4%D0%BB%D1%8F_%D1%82%D0%BE%D1%87%D0%BD%D0%BE%D0%B9_%D0%B0%D1%80%D0%B8%D1%84%D0%BC%D0%B5%D1%82%D0%B8%D0%BA%D0%B8_(%D0%B1%D0%B5%D0%B7_%D0%BF%D0%B5%D1%80%D0%B5%D0%BE%D1%80%D1%82%D0%BE%D0%B3%D0%BE%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D0%B8)&amp;diff=20225"/>
		<updated>2016-12-07T00:51:00Z</updated>

		<summary type="html">&lt;p&gt;AleksLevin: /* Масштабируемость алгоритма и его реализации */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Основные авторы описания: Левин А.Д.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{algorithm&lt;br /&gt;
| name              = Алгоритм Ланцоша для точной арифметики (без переортогонализации)&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(k\,n^2)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(k\log_2 n)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;\frac{n^2+3n}{2} + 1&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;k\;(n + 1)&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритмов =&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Данный алгоритм появился в 1950 г. и носит имя венгерского физика и математика Корнелия Ланцоша (венг. Lánczos Kornél). Алгоритм Ланцоша относится к итерационным методам вычисления собственных значений для матриц столь больших порядков &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt; n&amp;lt;/math&amp;gt;, что к ним нельзя применить прямые методы из-за ограничений по времени и памяти.&lt;br /&gt;
&lt;br /&gt;
Сам Ланцош указывал, что его метод предназначен для отыскания нескольких собственных векторов симметричных матриц, хотя к методу сразу было обращено внимание, как к способу приведения всей матрицы к трёхдиагональному виду. Двадцатью годами позже канадский математик Крис Пэж показал, что, несмотря на чувствительность к округлениям, алгоритм Ланцоша - эффективное средство вычисления некоторых &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; собственных чисел и соответствующих им собственных векторов. &amp;lt;ref&amp;gt;Парлетт Б. - Симметричная проблема собственных значений. Численные методы //М.: Мир. - 1983. (c. 276)&amp;lt;/ref&amp;gt;&lt;br /&gt;
Обычно число &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; берут в два раза больше, чем количество собственных значений матрицы, которые поставлена цель найти, и оно имеет порядок не более &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;10^2&amp;lt;/math&amp;gt;.&amp;lt;ref&amp;gt;Susan W. Bostic - Lanczos Eigensolution Method for High-Perfomance Computers, page 7&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Алгоритм Ланцоша для вычисления собственных значений симметричной матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; соединяет в себе метод Ланцоша для построения последовательности подпространств Крылова и ортонормированных векторов Ланцоша и процедуру Рэлея-Ритца получения оптимальных приближений собственных значений и соответствующих собственных векторов исходной матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt;.&amp;lt;ref&amp;gt;James W. Demmel - Вычислительная линейная алгебра. Теория и приложения //Мир. - 2001 (c. 381)&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
В данной статье рассматривается вариант алгоритма Ланцоша, в котором опущено влияние ошибок округления на вычислительный процесс, хотя на практике этому посвящается отдельное внимание и существуют различные методы решения данной проблемы, такие как частичная или полная переортогонализация. Этим модифицированным методам посвящены отдельные статьи на данном ресурсе.&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
Обозначения и формулы, используемые в данном разделе, взяты из литературы, указанной по ссылке.&amp;lt;ref&amp;gt;James W. Demmel - Вычислительная линейная алгебра. Теория и приложения //Мир. - 2001 (c. 313, &#039;&#039;&amp;lt;math&amp;gt; \S &amp;lt;/math&amp;gt; 6.6 Методы Крыловского подпространства&#039;&#039;)&amp;lt;/ref&amp;gt; &lt;br /&gt;
&lt;br /&gt;
Алгоритм Ланцоша для вычисления &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; собственных значений и собственных векторов вещественной симметричной матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A=A^T&amp;lt;/math&amp;gt; в точной арифметике: &amp;lt;ref&amp;gt;James W. Demmel - Вычислительная линейная алгебра. Теория и приложения //Мир. - 2001 (c. 381)&amp;lt;/ref&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{align}&lt;br /&gt;
q_1 = &amp;amp; \,\frac{b}{\|b\|_2},\; \beta_0 = 0,\; q_0 = 0\\&lt;br /&gt;
\mathbf{for} \; &amp;amp; j = 1 \; to \; k \,\; \mathbf{do} \\&lt;br /&gt;
&amp;amp; z = A\,q_j\\&lt;br /&gt;
&amp;amp; \alpha_j = q^T_j z\\&lt;br /&gt;
&amp;amp; z = z - \alpha_j q_j - \beta_{j-1}q_{j-1}\\&lt;br /&gt;
&amp;amp; \beta_j = \|z\|_2\\&lt;br /&gt;
&amp;amp; \mathbf{If} \; (\beta_j == 0) \; \mathbf{then}\; stop\; the\; algorithm \\ &lt;br /&gt;
&amp;amp; \;  q_{j+1} = \frac{z}{\beta_j} \\&lt;br /&gt;
&amp;amp; compute\; eigenvalues\; and \;eigenvectors\;of \;matrix \;\;T_j= Q^T_j A Q\;\;and\;estimate \;the\; errors\\&lt;br /&gt;
\mathbf{end} \; &amp;amp; \mathbf{for}&lt;br /&gt;
\end{align}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
В продемонстрированном выше алгоритме &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;b&amp;lt;/math&amp;gt; - заданный вещественный вектор. Также полагается известным алгоритм вычисления произведения матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; на вектор &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;x&amp;lt;/math&amp;gt;. &lt;br /&gt;
Введём матрицу Крылова, определяемую следующим соотношением: &amp;lt;math&amp;gt;K_j = [b,Ab,A^2b,...,A^{j-1}b]&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Далее, на практике, матрица &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;K&amp;lt;/math&amp;gt; заменяется матрицей &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;Q&amp;lt;/math&amp;gt;, такой, что при любом числе &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; линейные оболочки первых &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; столбцов в &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;K&amp;lt;/math&amp;gt; и &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;Q&amp;lt;/math&amp;gt; являются одним и тем же подпространством.&amp;lt;ref&amp;gt;James W. Demmel - Вычислительная линейная алгебра. Теория и приложения //Мир. - 2001 (c. 315)&amp;lt;/ref&amp;gt; &lt;br /&gt;
Тогда матрица &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;Q&amp;lt;/math&amp;gt;, в отличие от матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;K&amp;lt;/math&amp;gt;, хорошо обусловлена и легко обратима. В результате получаем матрицу &amp;lt;math&amp;gt;Q_j = [q_1, q_2, \dots, q_j]&amp;lt;/math&amp;gt; размерности &amp;lt;math&amp;gt;n\times j&amp;lt;/math&amp;gt;, столбцы которой ортогональны, являются базисом подпространства Крылова и называются векторами Ланцоша.&lt;br /&gt;
&lt;br /&gt;
В алгоритме Ланцоша вычислению подлежит столько первых столбцов в матрице &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;Q_j&amp;lt;/math&amp;gt;, сколько необходимо для получения требуемого приближения к решению &amp;lt;math&amp;gt;A\,x\,=b\,\,(A\,x=\lambda \, x)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Получение нулевого &amp;lt;math&amp;gt;\beta_j&amp;lt;/math&amp;gt; в итерационном процессе - событие, желательное в том смысле, что оно свидетельствует о том, что найдено некоторое подпространство, являющееся в точности инвариантным, а все собственные значения матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;T_j&amp;lt;/math&amp;gt; являются собственными значениями матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt;. На практике же нулевое и близкие к нулю значения получаются редко.&amp;lt;ref&amp;gt;Голуб Дж., Ван Лоун Ч. - Матричные вычисления//М.: Мир. - 1999 (c. 429)&amp;lt;/ref&amp;gt; &lt;br /&gt;
&lt;br /&gt;
Затем на каждом шаге цикла формируется симметричная трёхдиагональная матрица &amp;lt;math&amp;gt;T_j = Q^T_j A Q&amp;lt;/math&amp;gt;, к которой применяется процесс Рэлея-Ритца для поиска её собственных значений (на практике для поиска этих собственных значений можно использовать любой из специальных методов в параграфе книги по ссылке).&amp;lt;ref&amp;gt;Голуб Дж., Ван Лоун Ч. - Матричные вычисления//М.: Мир. - 1999 (&amp;lt;math&amp;gt;\S&amp;lt;/math&amp;gt; 8.4)&amp;lt;/ref&amp;gt;  &lt;br /&gt;
Эти собственные значения, они же числа Ритца, и полагаются приближёнными собственными значениями исходной матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt;.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Существует множество методов для отыскания собственных значений вещественной симметричной трехдиагональной матрицы. Большинство из них требует &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt; операций &amp;lt;ref&amp;gt;Парлетт Б. Симметричная проблема собственных значений. Численные методы.,: Мир, 1983. с. 179-182&amp;lt;/ref&amp;gt;, но существуют и быстрые алгоритмы, требующие лишь &amp;lt;math&amp;gt;O(n\ln n)&amp;lt;/math&amp;gt; операций.&amp;lt;ref&amp;gt;https://en.wikipedia.org/wiki/Tridiagonal_matrix#Eigenvalues  Раздел eigenvalues&amp;lt;/ref&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Одним из возможных способов отыскать собственные значения симметричной трехдиагональной матрицы - прямое вычисление корней характеристического полинома &amp;lt;math&amp;gt;p_n(\lambda)&amp;lt;/math&amp;gt; через метод деления пополам, где формируется последовательность Штурма и локализуются собственные числа, являющиеся корнями характеристического полинома. Нахождение всех &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; собственных значений матрицы этим способом требует &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;2n^2t&amp;lt;/math&amp;gt; умножений и вычитаний, где &amp;lt;math&amp;gt;t&amp;lt;/math&amp;gt; - число сделанных шагов с применением метода деления пополам.&amp;lt;ref&amp;gt;Уилкинсон Дж. X. Алгебраическая проблема собственныx значений. Изд-во &amp;quot;Наука&amp;quot;, 1970. - глава 5, с. 272-278&amp;lt;/ref&amp;gt; Соответствующие собственные вектора могут быть найдены посредством обратных итераций за &amp;lt;math&amp;gt; O(n) &amp;lt;/math&amp;gt; флопов. &amp;lt;ref&amp;gt;Голуб Дж., Ван Лоун Ч. - Матричные вычисления//М.: Мир. - 1999 (c. 394-395)&amp;lt;/ref&amp;gt; &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;На практике, если требуется только небольшая часть от всей совокупности собственных векторов и значений, и матрица имеет Хессенбергову или трёхдиагональную форму, очень эффективными будут методы факторизации, как, например, QR-алгоритм или QL-алгоритм со сдвигами (c целью ускорить алгоритм и сделать порядок сходимости квадратичным) или же без них.&amp;lt;ref&amp;gt;http://algorithm.narod.ru/ln/eigen/ETridiag.html&amp;lt;/ref&amp;gt; &amp;lt;br&amp;gt;&lt;br /&gt;
Весьма молодые и не менее актуальные конкуренты QR и QL алгоритмов, применяющиеся для поиска собственных значений:&lt;br /&gt;
*Методы divide-and-conquer (разделяй и властвуй), появившиеся в 1980-ых годах &amp;lt;ref&amp;gt;https://goo.gl/dapvbn ссылку пришлось сократить с помощью Google url shortener, так как символы подчеркивания портили её и не давали перейти по 1 клику&amp;lt;/ref&amp;gt;&lt;br /&gt;
*Relatively robust representation методы, появившиеся в 1990-ых и позволяющие найти собственные числа симметричной матрицы порядка &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;n&amp;lt;/math&amp;gt; за &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt; операций&lt;br /&gt;
&lt;br /&gt;
Если требуется вычислить собственные векторы, то необходимо хранить вычисляемые векторы Ланцоша. Если работа при этом производится только с оперативной памятью, то при большом порядке исходной матрицы (а именно для таких матриц и предназначен метод Ланцоша) число шагов  &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;j&amp;lt;/math&amp;gt;, которые могут быть выполнены до того момента, как оперативная память будет исчерпана, будет очень незначительно, а следовательно, искомые собственные пары могут не успеть сойтись с требуемой точностью. В этом случае метод Ланцоша можно использовать итерационным образом: после выполнения заданного числа шагов процесс прерывается и, если еще не все требуемые пары Ритца сошлись с требуемой точностью, то формируется новый начальный вектор &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;q_1&amp;lt;/math&amp;gt;, являющийся линейной комбинацией векторов Ритца, еще не сошедшихся с заданной точностью, и процесс начинается заново.&amp;lt;ref&amp;gt;http://num-anal.srcc.msu.ru/lib_na/int_ae/int_ae6.htm (пункт 6.5)&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
Вычислительное ядро рассматриваемого алгоритма (наиболее ресурсно-затратная часть алгоритма) -  формирование на каждом шаге цикла промежуточного вектора &amp;lt;math&amp;gt;z&amp;lt;/math&amp;gt;, вычисляемого по формуле: &amp;lt;math&amp;gt;z = A\,q_j&amp;lt;/math&amp;gt;. Данная операция, по сравнению с другими операциями алгоритма, затратна и требовательна, как с точки зрения количества производимых операций, так и с точки зрения объема оперируемых данных. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Например, умножение матрицы размера &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;n\times n&amp;lt;/math&amp;gt; на вектор длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; требует: &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;n^2+(n-1)n = 2n^2-n&amp;lt;/math&amp;gt; операций умножения и сложения. В свою очередь аналогичная операция умножения матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;(n+1)\times (n+1)&amp;lt;/math&amp;gt; на вектор длины &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;(n+1)&amp;lt;/math&amp;gt; требует: &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;2n^2+3n+1&amp;lt;/math&amp;gt;  операций умножения и сложения. То есть повышение размерности задачи всего на 1 увеличивает число необходимых действий в этом шаге алгоритма на: &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;4n+1&amp;lt;/math&amp;gt;. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Так же, стоит помнить, что, согласно разделу 1.2, данную операцию умножения матрицы на вектор необходимо выполнить &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;k&amp;lt;/math&amp;gt; раз. Нетрудно понять, насколько возрастает и колоссален масштаб операций, если в задачах, где критична точность, размерности &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; могут иметь порядок &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;10^5&amp;lt;/math&amp;gt; или даже более.&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
Как уже было упомянуто в данной статье в описании алгоритма, рассматриваемый алгоритм состоит из двух последовательно выполненных алгоритмов: метод Ланцоша для построения последовательности подпространств Крылова и ортонормированных векторов Ланцоша и процедура Рэлея-Ритца получения оптимальных приближений собственных значений и соответствующих собственных векторов исходной матрицы.&lt;br /&gt;
&lt;br /&gt;
В первой части алгоритма, где итерационно строятся Крыловское подпространство и трёхдиагональная матрица &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&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 style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; разреженная. Именно она подлежит оптимизации с использованием техник распараллеливания, поскольку она является вычислительным ядром алгоритма, а весь упомянутый процесс построения матрицы &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&amp;lt;/math&amp;gt; выполняется последовательно.&lt;br /&gt;
&lt;br /&gt;
Рассмотрим вторую часть алгоритма - поиск собственных значений сформированной матрицы &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&amp;lt;/math&amp;gt;.&amp;lt;br&amp;gt;&lt;br /&gt;
Далее, наглядно, в виде псевдокода, представлен, упомянутый в разделе 1.2, QR-алгоритм (аналогично можно рассмотреть и QL-алгоритм) со сдвигами Релэя, который весьма популярен на практике.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{align}&lt;br /&gt;
\mathbf{Input}: \;&amp;amp;tridiagonal\;\;matrix \;T\;with\;\;n\times n\;\;size\\&lt;br /&gt;
T^{(0)}&amp;amp;:=T\\&lt;br /&gt;
\mathbf{for}&amp;amp; \;\;m=n,...,2 \;\; \mathbf{do}\\&lt;br /&gt;
&amp;amp;k=0\\&lt;br /&gt;
&amp;amp; \mathbf{repeat}\\&lt;br /&gt;
&amp;amp; \quad \;\; k=k+1\\&lt;br /&gt;
&amp;amp; \quad \;\; \mu^{(k)}=T_{m,m}^{(k-1)}\\&lt;br /&gt;
&amp;amp; \quad \;\; Q^{(k)}R^{(k)}=T^{(k-1)}-\mu^{(k)}I\;\;using\;\;QR\;decomposition\\&lt;br /&gt;
&amp;amp; \quad \;\; T^{(k)}=R^{(k)}Q^{(k)}+\mu^{(k)}I\\&lt;br /&gt;
&amp;amp; \mathbf{until} \;\;\; |T_{m,m-1}^{(k)}| \;is\;\;small\;\;enough\\&lt;br /&gt;
&amp;amp; Save  \;\;T_{m,m}^{(k)} \;\;as\;\; converged\;\;eigenvalue\;of\;T\\ &lt;br /&gt;
&amp;amp; Remove \;\boldsymbol{n}\,th\;row\;and\;\boldsymbol{n}\,th\;column\;\;from \;T \\&lt;br /&gt;
&amp;amp; and\;take\;this\;new\;cropped\;matrix\;as\;new\;T^{(0)}\;with\;\;(n-1)\times (n-1)\;\;size\\&lt;br /&gt;
 \mathbf{end}&amp;amp;\; \mathbf{for}&lt;br /&gt;
\end{align}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Малость наддиагональных и поддиагональных элементов матрицы (фраза &#039;&#039;&amp;quot;small enough&amp;quot;&#039;&#039; в псевдокоде) подразумевает:&lt;br /&gt;
&amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt; |T_{m,m-1}^{(k)}| \leq \varepsilon\,|T_{m,m}^{(k)}| \quad\quad &amp;lt;/math&amp;gt; , где &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt; \varepsilon &amp;lt;/math&amp;gt; - заданная точность&amp;lt;br&amp;gt;&lt;br /&gt;
Также вместо сдвига Релэя, обозначенного в алгоритме через &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;\mu^{(k)}&amp;lt;/math&amp;gt;, часто на практике используется сдвиг по Уилкинсону, который даёт гарантированную сходимость внедиагональных элементов матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt; T^{(k)} &amp;lt;/math&amp;gt;, формируемой на каждом шаге, к нулю, при этом жертвуя монотонностью их убывания.&amp;lt;ref&amp;gt;Голуб Дж., Ван Лоун Ч. - Матричные вычисления//М.: Мир. - 1999 (c. 378, вторая половина страницы)&amp;lt;/ref&amp;gt;&amp;lt;ref&amp;gt;Парлетт Б. Симметричная проблема собственных значений. Численные методы.,: Мир, 1983. с. 169&amp;lt;/ref&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Подробнее с различными сдвигами и соответствующими оценками скоростей и количествами операций можно ознакомиться по указанной ссылке:&amp;lt;ref&amp;gt;Парлетт Б. Симметричная проблема собственных значений. Численные методы.,: Мир, 1983. с. 179-182&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;Для совершения QR-декомпозиции на каждом шаге может использоваться любой из алгоритмов по ссылке.&amp;lt;ref&amp;gt;https://en.wikipedia.org/wiki/QR_decomposition&amp;lt;/ref&amp;gt; Подробные описания этих алгоритмов также доступны на данном ресурсе algowiki-project.&amp;lt;br&amp;gt;&lt;br /&gt;
Так как мы оперируем не обычной матрицей и даже не Хессенберговой, а симметричной и трёхдиагональной, то скорость таких алгоритмов значительно возрастёт. Например, согласно данному ресурсу &amp;lt;ref&amp;gt;http://algorithm.narod.ru/ln/eigen/ETridiag.html&amp;lt;/ref&amp;gt;, для QL-алгоритма с неявными сдвигами:&amp;lt;br&amp;gt;&lt;br /&gt;
Для трёхдиагональной матрицы объем арифметических действий составляет &amp;lt;math&amp;gt; O(n)&amp;lt;/math&amp;gt; на одну итерацию вместо &amp;lt;math&amp;gt; O(n^3)&amp;lt;/math&amp;gt; для матрицы общего вида, а число итераций для нахождения первых собственных значений примерно равно 4 - 5. Но на этих итерациях также уменьшаются внедиагональные элементы правого нижнего угла. И, таким образом, дальнейшие собственные значения ищутся значительно быстрее. Среднее число итераций на каждое собственное значение обычно составляет 1.3 - 1.6.&amp;lt;br&amp;gt; &lt;br /&gt;
Аналогично QL, QR-разложение трёхдиагольной матрицы также требует &amp;lt;math&amp;gt; O(n)&amp;lt;/math&amp;gt; флопов&amp;lt;ref&amp;gt;Голуб Дж., Ван Лоун Ч. - Матричные вычисления//М.: Мир. - 1999 (c. 378, начало раздела 8.2.2)&amp;lt;/ref&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Подводя итог, во второй части алгоритма Ланцоша можно выделить следующие макрооперации:&lt;br /&gt;
* умножение матрицы на вещественное число;&lt;br /&gt;
* перемножение матриц;&lt;br /&gt;
* умножение и сравнение вещественных чисел;&lt;br /&gt;
* + набор других макроопераций в зависимости от выбора метода, с помощью которого будет совершаться сама QR или QL-декомпозиция (выше продемонстрированы, уже, как минимум, 3 разных способа).&lt;br /&gt;
Так же, важно заметить, что набор макропераций может быть несколько другим, если выбрать какой-либо иной современный метод поиска собственных чисел трёхдиагональной матрицы, не использующий QR и QL разложения(факторизацию). Два таких метода были упомянуты в пункте 1.2.&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
С целью полностью не дублировать раздел 1.2 данной статьи, где представлен наглядный и доступный для понимания псевдокод алгоритма, постараемся лишь коротко просуммировать и обобщить весь перечень последовательных действий в рассматриваемом алгоритме.&lt;br /&gt;
&lt;br /&gt;
В качестве входных данных имеем: вещественная симметричная матрица &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; размера &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;n\times n&amp;lt;/math&amp;gt;, известный вещественный вектор &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;b&amp;lt;/math&amp;gt; длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; и число &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;n&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Далее:&lt;br /&gt;
* Инициализируем вещественную константу &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;\beta_0&amp;lt;/math&amp;gt; и векторы &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;q_0&amp;lt;/math&amp;gt; и &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;q_1&amp;lt;/math&amp;gt;&lt;br /&gt;
* Итерационно для всех &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j=1,...,k&amp;lt;/math&amp;gt;:&lt;br /&gt;
** Вычисляем вспомогательный вектор &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt;, используя умножение матрицы на вектор&lt;br /&gt;
** Вычисляем, используя скалярное произведение векторов, значение &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;\alpha_j&amp;lt;/math&amp;gt; - элемент на главной диагонали трёхдиагональной матрицы &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&amp;lt;/math&amp;gt;&lt;br /&gt;
** Вычисляем по формуле новое значение и перезаписываем вектор &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt;&lt;br /&gt;
** Вычисляем значение &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;\beta_j&amp;lt;/math&amp;gt; - элементы непосредственно над и под главной диагональю той же матрицы &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&amp;lt;/math&amp;gt;&lt;br /&gt;
** Вычисляем, зная вектор &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt;,  очередной столбец матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;Q&amp;lt;/math&amp;gt;, он же вектор Ланцоша : &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;\,\,q_{j+1}&amp;lt;/math&amp;gt;&lt;br /&gt;
** Теперь, когда матрица &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&amp;lt;/math&amp;gt; сформирована на очередном шаге, находим её собственные значения и вектора любым доступным способом, о чём было подробно сказано в пункте 1.2&lt;br /&gt;
** Переходим на следующую итерацию: &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j&amp;lt;/math&amp;gt;++&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
Оценим количество операций и сложность последовательного алгоритма, изложенного в предыдущем разделе.&lt;br /&gt;
*Для вычисления вектора &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt; умножается матрица размера &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;n\times n&amp;lt;/math&amp;gt; на вектор длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt;, и потребуется &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n^2&amp;lt;/math&amp;gt; операций умножения и &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n^2&amp;lt;/math&amp;gt; операций сложения.&lt;br /&gt;
*Умножение векторов &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;q^T_j&amp;lt;/math&amp;gt; и &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt; длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; потребует &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; операций умножения и &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; операций сложения.&lt;br /&gt;
*При вычислении нового значения вектора &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt; поэлементное сложение двух векторов длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; требует &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; операций сложения.&lt;br /&gt;
*Умножение вектора длины &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; на вещественное число требует &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; операций умножения.&lt;br /&gt;
*Нахождение квадратичной нормы вектора &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt;  длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; требует &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; умножений и &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; сложений и ещё 1 операцию извлечения квадратного корня.&lt;br /&gt;
*Заключительное нахождение собственных значений и собственных векторов трёхдиагональной матрицы &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;T_j&amp;lt;/math&amp;gt; размера &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j\times j&amp;lt;/math&amp;gt; с помощью QR-алгоритма потребует в худшем случае &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(j^3)&amp;lt;/math&amp;gt; операций.&amp;lt;ref&amp;gt;http://num-anal.srcc.msu.ru/lib_na/int_ae/int_ae6.htm (пункт 6.2, &amp;quot;Скорость сходимости при этом всегда не хуже квадратичной и почти всегда лучше кубической.&amp;quot;)&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Посчитаем теперь суммарное количество простейших операций на одной итерации алгоритма (без учёта записей в память):&lt;br /&gt;
*&amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n^2+5\,n&amp;lt;/math&amp;gt; операций умножения/деления&lt;br /&gt;
*&amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n^2+4\,n&amp;lt;/math&amp;gt; операций сложения/вычитания&lt;br /&gt;
*1 операция извлечения квадратного корня&amp;lt;br&amp;gt;&lt;br /&gt;
Отдельно после всех итераций при &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j=k&amp;lt;/math&amp;gt; :&lt;br /&gt;
*&amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(k^3)&amp;lt;/math&amp;gt; операций для поиска собственных значений и собственных векторов трёхдиагональной матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_k&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Итого можно утверждать следующее:&lt;br /&gt;
&lt;br /&gt;
Последовательная сложность одной итерации рассматриваемого алгоритма:  &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(n ^ 2) &amp;lt;/math&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Суммарная сложность алгоритма (&amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;/math&amp;gt; итераций): &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(k\,n ^ 2) + O(k ^ 3)&amp;lt;/math&amp;gt; &amp;lt;ref&amp;gt;Здесь мы полагаем, что мы не вычисляем собственные значения и векторы матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_j&amp;lt;/math&amp;gt; на каждом промежуточном шаге, а лишь единожды затрачиваем &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;O(k ^ 3)&amp;lt;/math&amp;gt; действий в конце для нахождения &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;/math&amp;gt; собственных значений и векторов матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_k&amp;lt;/math&amp;gt;&amp;lt;/ref&amp;gt; &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
На практике же обычно рассматривается число &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;&amp;lt;n&amp;lt;/math&amp;gt;, поэтому второе слагаемое можно опустить.&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
На рис. 1 продемонстрирован граф одной итерации (при каком-либо произвольном значении итератора &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j&amp;lt;/math&amp;gt;) описанного алгоритма без отображения входных и выходных данных. Наглядно продемонстрированы связи между всеми действиями, и с помощью деления на &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; потоков показано, какие операции возможно выполнять параллельно на каждом шаге с целью оптимизации и экономии машинного времени. В результате, после параллельно выполненных операций &#039;&#039;&#039;Division&#039;&#039;&#039; на заключительном ярусе, на выходе имеем значение следующего вектора Ланцоша &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;q_{j+1}&amp;lt;/math&amp;gt;, после чего следует переход на следующую итерацию, и процесс повторяется.&lt;br /&gt;
&lt;br /&gt;
[[Файл:Levin_graph.png|600px|thumb|center|Рис. 1  Структура одной итерации алгоритма]] &amp;lt;br&amp;gt;&lt;br /&gt;
Обозначения на рисунке: &amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Simp&#039;&#039;&#039; (от англ. simple) - операции сложения и умножения вещественных чисел при вычислении произведения матрицы на вектор;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Vec mult&#039;&#039;&#039; (от англ. vectors multiplication) - операция скалярного умножения двух векторов;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Vec subtr&#039;&#039;&#039; (от англ. vectors subtraction, из-за использованных в операции вычитаний векторов) - операция умножения вектора на число (выполняется дважды) и формирование нового значения &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;z_{new}&amp;lt;/math&amp;gt; по формуле: &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;z_{new} = z - \alpha_j q_j - \beta_{j-1}q_{j-1} \;&amp;lt;/math&amp;gt;;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;||\cdot||&amp;lt;/math&amp;gt; - операция вычисления нормы вектора;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Division&#039;&#039;&#039; - операция деления вектора на вещественное число  &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;\beta_j&amp;lt;/math&amp;gt; &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Важно отметить, что упомянутые выше операции также легко поддаются оптимизации. Например, попарные умножения вещественных координат векторов при вычислении скалярного произведения также легко выполняются параллельно на &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; потоках, а затем можно применить суммирование методом сдваивания, о котором сказано в следующем разделе. Умножение или деление вектора на вещественное число являющееся, по определению, умножением или делением всех его координат на это число тоже может быть выполнено эффективнее, если мы используем &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; потоков, а не выполняем эти действия последовательно.&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
Параллельные операции возможны только внутри итераций, так как рассматриваемый алгоритм является итерационным, и сами итерации строго последовательны.&amp;lt;br&amp;gt;&lt;br /&gt;
Рассмотрим в этом разделе подробнее, какой выигрыш мы можем получить при распараллеливании операций внутри одной итерации согласно графу из предыдущего раздела.&lt;br /&gt;
&lt;br /&gt;
Умножение вещественной симметричной матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; размера &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;n\times n&amp;lt;/math&amp;gt; на вектор &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;b&amp;lt;/math&amp;gt; длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; требует последовательного выполнения &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; ярусов умножений и сложений. Сложение элементов вектора длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; на каждом шаге перемножения можно оптимизировать и выполнить за &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;\log_2 n&amp;lt;/math&amp;gt; действий, если применять метод сдваивания.&lt;br /&gt;
&lt;br /&gt;
Дальнейшие операции выполняются последовательно, а вычисление значений векторов происходит за один ярус операций сложения или умножения.&lt;br /&gt;
&lt;br /&gt;
Ресурс параллелизма алгоритма вычисления собственных значений построенной трёхдиагональной матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_k&amp;lt;/math&amp;gt; размера &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k\times k&amp;lt;/math&amp;gt; зависит от выбранного алгоритма (об этих алгоритмах подробнее было сказано в разделах 1.2 и 1.4). Будет очень затратно с точки зрения объёма материала пытаться рассмотреть пусть даже часть этих методов в этой статье, а так же тонкости их распараллеливания. Предлагаем читателям при желании самим ознакомиться с этими алгоритмами на данном ресурсе или прибегнув к иным источникам.&lt;br /&gt;
&lt;br /&gt;
При классификации по высоте ЯПФ, таким образом, алгоритм Ланцоша без переортогонализации относится к алгоритмам с &#039;&#039;логарифмической сложностью&#039;&#039;, и его сложность равна &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(\log_2 n)&amp;lt;/math&amp;gt; с важным замечанием, что это сложность только одной итерации, а максимум в алгоритме может быть выполнено последовательно &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;/math&amp;gt; таких однотипных итераций, если не будет осуществлён ранний выход из цикла. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Несмотря на то, что на графе в предыдущем разделе для лучшей визуализации и понимания было изображено &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; потоков (никаких допущений мы не делали и нарушений с точки зрения логики и математики нет, можно изобразить большее число потоков, просто часть времени некоторые из них могут бездействовать и не использоваться), на самом деле правильным и разумным будет реализовать начальное параллельное выполнение &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n^2&amp;lt;/math&amp;gt; операций умножения всех вещественных элементов матрицы &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;A&amp;lt;/math&amp;gt; на соответствующие элементы вектора &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;q_j&amp;lt;/math&amp;gt;, после чего применять тот же самый упомянутый метод сдваивания. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Поэтому при классификации по ширине ЯПФ его сложность будет &#039;&#039;квадратичной&#039;&#039; и равна &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(n^2)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
&#039;&#039;&#039;Входные данные алгоритма:&#039;&#039;&#039; вещественная симметричная &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; размера &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;n\times n&amp;lt;/math&amp;gt;, вещественный вектор &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;b&amp;lt;/math&amp;gt; длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt;, и одно целое число &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;k&amp;lt;/math&amp;gt;, означающее количество итераций.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём входных данных:&#039;&#039;&#039; &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;n^2 +n + 1 &amp;lt;/math&amp;gt;. Если учесть, что матрица симметричная и достаточно для её однозначного определения задать элементы на главной диагонали и элементы над или под ней, то можно сократить объём входных данных с целью экономии памяти до: &amp;lt;math&amp;gt;\ \frac{n^2-n}{2}+n+n+1 =\frac{n^2+3n}{2} + 1&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные алгоритма:&#039;&#039;&#039; вектор собственных значений &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;\Theta^k&amp;lt;/math&amp;gt; длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;/math&amp;gt;, матрица &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;S^k&amp;lt;/math&amp;gt; из соответствующих собственных векторов размера &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n\times k&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём выходных данных:&#039;&#039;&#039; &amp;lt;math&amp;gt;k\;(n + 1)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
В данном разделе перечислены без какой-либо хронологии или связи друг с другом наиболее важные и разнообразные свойства алгоритма, на которые стоит и полезно обратить внимание, а также которые выгодно отличают его от схожих алгоритмов, решающих ту же задачу.&amp;lt;br&amp;gt;&lt;br /&gt;
1) Отношение последовательной сложности алгоритма к параллельной,с учётом &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;/math&amp;gt; итераций, равно &amp;lt;math&amp;gt;\;\;\frac{kn^2}{k \log_2{n}}=\frac{n^2}{\log_2{n}}&amp;lt;/math&amp;gt;;&amp;lt;br&amp;gt;&lt;br /&gt;
2) Вычислительная мощность алгоритма, как отношение числа операций к суммарному объему входных и выходных данных, равна &amp;lt;math style=&amp;quot;vertical-align:-70%&amp;gt;\;\;\frac{k\,n^2}{0.5\,n^2+1.5\,n+k\,n+k+1}&amp;lt;/math&amp;gt; и &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;\approx 2\,k&amp;lt;/math&amp;gt;, так как на практике верно отношение &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;&amp;lt;n&amp;lt;/math&amp;gt; ;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
3) Для собственных значений формируемых матриц &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_j&amp;lt;/math&amp;gt; верно отношение (следствие теоремы Коши о перемежаемости): &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;\lambda_i(T_{k+1})\geq \lambda_i(T_{k})\geq \lambda_{i+1}(T_{k+1})\geq \lambda_{i+1}(T_{k})&amp;lt;/math&amp;gt; ;&amp;lt;ref&amp;gt;James W. Demmel - Вычислительная линейная алгебра. Теория и приложения //Мир. - 2001 (c. 383)&amp;lt;/ref&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
4) Крайние (наибольшие и наименьшие) собственные значения матриц &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_j&amp;lt;/math&amp;gt; сходятся к крайним собственным значениям матрицы &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;A&amp;lt;/math&amp;gt; первыми (это часто происходит уже на ранних шагах при &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j\approx 2\,\sqrt{n}&amp;lt;/math&amp;gt;&amp;lt;ref&amp;gt;http://num-anal.srcc.msu.ru/lib_na/int_ae/int_ae6.htm (пункт 6.5)&amp;lt;/ref&amp;gt;), а собственные значения в середине спектра - последними;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
5) Из-за ограниченной точности постепенно теряется ортогональность вектора Ланцоша &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;q_j&amp;lt;/math&amp;gt; к предыдущим векторам Ланцоша, поэтому необходимо примерно каждые 10-15 итераций проводить дорогостоящую операцию реортогонализации, но это уже будет иной алгоритм с очень малым различием в одной операции и в программном коде, реализующем его, соответственно; &amp;lt;ref&amp;gt;Sam Handler - The Lanczos Algorithm For Large-Scale Eigenvalue Problems (08.01.07), slide №8&amp;lt;/ref&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
6) Эффективность и быстрота выполнения алгоритма очень сильно зависит от скорости памяти (диска). Согласно тесту только &#039;&#039;6%&#039;&#039; времени работы программы приходится на вычисления, остальное время затрачивается на ожидание отклика диска;&amp;lt;ref&amp;gt;Sam Handler - The Lanczos Algorithm For Large-Scale Eigenvalue Problems (08.01.07), slide №10&amp;lt;/ref&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
7) Метод Ланцоша удобен тем, что не требует хранения исходной матрицы полным массивом: метод использует исходную матрицу только в операциях умножения матрицы на вектор, что позволяет эффективно использовать разреженность матрицы или регулярность структуры матрицы. Поэтому метод Ланцоша может быть использован для матриц таких больших порядков, когда методы вращений и отражений не могут быть применены.&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;
Для исследования масштабируемости рассматриваемого алгоритма Ланцоша без переортогонализации автором была реализована программа на языке С++ с использованием технологии MPI. &amp;lt;ref&amp;gt;https://goo.gl/dGfzOD  или альтернативная ссылка с прикреплённым кодом: https://goo.gl/lFziv0 , по просьбе на почту я (автор статьи) готов предоставить желающим доступ к проекту с этим кодом на ресурсе Bitbucket&amp;lt;/ref&amp;gt; Дальнейшее исследование было проведено на суперкомпьютере &amp;quot;Ломоносов&amp;quot; Суперкомпьютерного комплекса МГУ. &amp;lt;br&amp;gt; Важно отметить, что реализованная программа выполняет только первую часть алгоритма - формирование матрицы &amp;lt;math &amp;gt;T_j&amp;lt;/math&amp;gt;. Вторая часть алгоритма (задача поиска собственных значений матрицы &amp;lt;math &amp;gt;T_j&amp;lt;/math&amp;gt;) может быть решена несколькими методами, каждый из которых обладает своей эффективностью распараллеливании и характерными свойствами. Подробно этот вопрос уже обсуждался в статье раннее, поэтому не будем ещё раз заострять на этом внимание и останавливаться.&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Сборка осуществлялась со следующими параметрами:&lt;br /&gt;
* Компилятор intel/15.0.090 &lt;br /&gt;
* Openmpi/1.8.4-icc&lt;br /&gt;
В серии проведённых расчётов рассматривались следующие числовые значения параметров:&lt;br /&gt;
* Размер &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;n&amp;lt;/math&amp;gt; задачи и, соответственно, матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt;, задействованной в операции умножения на вектор: [2000 : 30000] с шагом 1000&lt;br /&gt;
* Число процессоров: 1, 2, 4, 16, 32, 48, 64, 96, 128&lt;br /&gt;
* Число итераций в алгоритме: &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k=350&amp;lt;/math&amp;gt;&lt;br /&gt;
Число &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; взято таким вопреки информации в начале статьи, где говорится, что значение &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; редко превышает &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;10^2&amp;lt;/math&amp;gt; (хоть мы и имеем право брать его любым по нашему усмотрению). Это сделано исключительно для лучшей визуализации пиков на графиках в данном разделе и наглядности получаемых результатов, так как при меньших на порядок значениях параметра &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; времена выполнения программ были слишком малы даже при минимальных числах процессоров и максимальных размерах &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;n&amp;lt;/math&amp;gt; задачи.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
На рис. 2 изображён график зависимости времени выполнения программы от числа процессоров и размера &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;n&amp;lt;/math&amp;gt; задачи. &amp;lt;br&amp;gt;&lt;br /&gt;
[[Файл:Levin604 Lanzcos result execTIME.png|580px|thumb|center|Рис. 2  График зависимости времени выполнения программы]] &amp;lt;br&amp;gt;&lt;br /&gt;
Многочисленные тесты показали при малых количествах ядер уменьшение времени выполнения программы почти в 2 раза при увеличении числа ядер в 2 раза на всём диапазоне размеров матриц, то есть можно судить о хорошей эффективности, что и отражает сильный излом на предоставленом графике.&lt;br /&gt;
&lt;br /&gt;
== Динамические характеристики и эффективность реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Выводы для классов архитектур ==&lt;br /&gt;
По заданию, во второй части требовалось описать только разделы 2.4 и 2.7, прошу не спрашивать с меня все разделы 2.1-2.6. Надеюсь на понимание, мне физически не хватает времени на это задание + 2 других в течение семестра, делаю всё, что в моих силах :)&lt;br /&gt;
&lt;br /&gt;
== Существующие реализации алгоритма ==&lt;br /&gt;
Несмотря на то, что алгоритм является далеко не самым популярным, алгоритмом, про который нельзя сказать, что он всегда «на слуху», на сегодняшний день существует множество реализаций на различных популярных языках.&amp;lt;br&amp;gt;&lt;br /&gt;
Перечислим далее некоторые из них, указывая язык программирования, лежащий в их основе, и некоторые важные характеристики, которые обсуждались в статье ранее:&lt;br /&gt;
*&#039;&#039;Code on netlib.org by Jane Cullum and Ralph Willoughby&#039;&#039; (&#039;&#039;&#039;Fortran 77&#039;&#039;&#039;; без реортогонализации векторов; без реализации распараллеливания)&amp;lt;ref&amp;gt;http://www.netlib.org/lanczos/leval&amp;lt;/ref&amp;gt;&lt;br /&gt;
*&#039;&#039;Lanczos algorithm on freesourcecode.net&#039;&#039; (&#039;&#039;&#039;Matlab&#039;&#039;&#039;; присутствует реортогонализация векторов; без реализации распараллеливания)&amp;lt;ref&amp;gt;http://freesourcecode.net/matlabprojects/61741/lanczos-algorithm--in-matlab&amp;lt;/ref&amp;gt;&lt;br /&gt;
*&#039;&#039;Lanczos for eigenvalues in Numerical Linear Algebra, Spring 2007&#039;&#039; (&#039;&#039;&#039;Matlab&#039;&#039;&#039;; частичная или полная реортогонализация - доступны оба варианта; без реализации распараллеливания)&amp;lt;ref&amp;gt;Ссылки на файлы lanso.m и lanfu.m можно найти на https://www.nada.kth.se/~ruhe/2D5219/labs2007.html&amp;lt;/ref&amp;gt;&lt;br /&gt;
*&#039;&#039;Planso&#039;&#039; (название происходит от parallel Lanso.f) &#039;&#039;code by Kesheng Wu and Horst D. Simon&#039;&#039; (&#039;&#039;&#039;Fortran 77&#039;&#039;&#039;; частичная реортогонализация векторов; использование MPI для коммуникаций)&amp;lt;ref&amp;gt;https://github.com/jiahao/planso.jl/tree/master/external/PLAN/plan К сожалению, ссылка в описании пакета на github, ведущая на сайт National Energy Research Scientific Computing Center (NERSC), с более подробной информацией о данной программе больше не активна и выдаёт результат &#039;&#039;Page not found&#039;&#039;&amp;lt;/ref&amp;gt; &lt;br /&gt;
* &#039;&#039;Lanczos.cpp in the Vienna Computing Library&#039;&#039;  (&#039;&#039;&#039;C++&#039;&#039;&#039;, частичная реортогонализация, без реализации распараллеливания) &amp;lt;ref&amp;gt;http://viennacl.sourceforge.net/doc/lanczos_8cpp_source.html&amp;lt;/ref&amp;gt;&lt;br /&gt;
* &#039;&#039;Parallel Eigen Values code using C++ AMP on microsoft msdn blog&#039;&#039; (&#039;&#039;&#039;C++&#039;&#039;&#039;; ? ; распараллеливание есть и реализовано через C++ AMP) &amp;lt;ref&amp;gt;https://blogs.msdn.microsoft.com/nativeconcurrency/2013/12/20/eigen-values/ Подробнее о C++ Accelerated Massive Parallelism можно почитать здесь: https://msdn.microsoft.com/ru-ru/library/hh265137(v=vs.140).aspx или здесь: http://professorweb.ru/my/csharp/optimization/level4/4_6.php &amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;br /&gt;
[[en:Description of algorithm properties and structure]]&lt;/div&gt;</summary>
		<author><name>AleksLevin</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:AleksLevin/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%9B%D0%B0%D0%BD%D1%86%D0%BE%D1%88%D0%B0_%D0%B2%D1%8B%D1%87%D0%B8%D1%81%D0%BB%D0%B5%D0%BD%D0%B8%D1%8F_%D1%81%D0%BE%D0%B1%D1%81%D1%82%D0%B2%D0%B5%D0%BD%D0%BD%D1%8B%D1%85_%D0%B7%D0%BD%D0%B0%D1%87%D0%B5%D0%BD%D0%B8%D0%B9_%D1%81%D0%B8%D0%BC%D0%BC%D0%B5%D1%82%D1%80%D0%B8%D1%87%D0%BD%D0%BE%D0%B9_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86%D1%8B_%D0%B4%D0%BB%D1%8F_%D1%82%D0%BE%D1%87%D0%BD%D0%BE%D0%B9_%D0%B0%D1%80%D0%B8%D1%84%D0%BC%D0%B5%D1%82%D0%B8%D0%BA%D0%B8_(%D0%B1%D0%B5%D0%B7_%D0%BF%D0%B5%D1%80%D0%B5%D0%BE%D1%80%D1%82%D0%BE%D0%B3%D0%BE%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D0%B8)&amp;diff=20224</id>
		<title>Участник:AleksLevin/Алгоритм Ланцоша вычисления собственных значений симметричной матрицы для точной арифметики (без переортогонализации)</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:AleksLevin/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%9B%D0%B0%D0%BD%D1%86%D0%BE%D1%88%D0%B0_%D0%B2%D1%8B%D1%87%D0%B8%D1%81%D0%BB%D0%B5%D0%BD%D0%B8%D1%8F_%D1%81%D0%BE%D0%B1%D1%81%D1%82%D0%B2%D0%B5%D0%BD%D0%BD%D1%8B%D1%85_%D0%B7%D0%BD%D0%B0%D1%87%D0%B5%D0%BD%D0%B8%D0%B9_%D1%81%D0%B8%D0%BC%D0%BC%D0%B5%D1%82%D1%80%D0%B8%D1%87%D0%BD%D0%BE%D0%B9_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86%D1%8B_%D0%B4%D0%BB%D1%8F_%D1%82%D0%BE%D1%87%D0%BD%D0%BE%D0%B9_%D0%B0%D1%80%D0%B8%D1%84%D0%BC%D0%B5%D1%82%D0%B8%D0%BA%D0%B8_(%D0%B1%D0%B5%D0%B7_%D0%BF%D0%B5%D1%80%D0%B5%D0%BE%D1%80%D1%82%D0%BE%D0%B3%D0%BE%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D0%B8)&amp;diff=20224"/>
		<updated>2016-12-07T00:50:43Z</updated>

		<summary type="html">&lt;p&gt;AleksLevin: /* Масштабируемость алгоритма и его реализации */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Основные авторы описания: Левин А.Д.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{algorithm&lt;br /&gt;
| name              = Алгоритм Ланцоша для точной арифметики (без переортогонализации)&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(k\,n^2)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(k\log_2 n)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;\frac{n^2+3n}{2} + 1&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;k\;(n + 1)&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритмов =&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Данный алгоритм появился в 1950 г. и носит имя венгерского физика и математика Корнелия Ланцоша (венг. Lánczos Kornél). Алгоритм Ланцоша относится к итерационным методам вычисления собственных значений для матриц столь больших порядков &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt; n&amp;lt;/math&amp;gt;, что к ним нельзя применить прямые методы из-за ограничений по времени и памяти.&lt;br /&gt;
&lt;br /&gt;
Сам Ланцош указывал, что его метод предназначен для отыскания нескольких собственных векторов симметричных матриц, хотя к методу сразу было обращено внимание, как к способу приведения всей матрицы к трёхдиагональному виду. Двадцатью годами позже канадский математик Крис Пэж показал, что, несмотря на чувствительность к округлениям, алгоритм Ланцоша - эффективное средство вычисления некоторых &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; собственных чисел и соответствующих им собственных векторов. &amp;lt;ref&amp;gt;Парлетт Б. - Симметричная проблема собственных значений. Численные методы //М.: Мир. - 1983. (c. 276)&amp;lt;/ref&amp;gt;&lt;br /&gt;
Обычно число &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; берут в два раза больше, чем количество собственных значений матрицы, которые поставлена цель найти, и оно имеет порядок не более &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;10^2&amp;lt;/math&amp;gt;.&amp;lt;ref&amp;gt;Susan W. Bostic - Lanczos Eigensolution Method for High-Perfomance Computers, page 7&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Алгоритм Ланцоша для вычисления собственных значений симметричной матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; соединяет в себе метод Ланцоша для построения последовательности подпространств Крылова и ортонормированных векторов Ланцоша и процедуру Рэлея-Ритца получения оптимальных приближений собственных значений и соответствующих собственных векторов исходной матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt;.&amp;lt;ref&amp;gt;James W. Demmel - Вычислительная линейная алгебра. Теория и приложения //Мир. - 2001 (c. 381)&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
В данной статье рассматривается вариант алгоритма Ланцоша, в котором опущено влияние ошибок округления на вычислительный процесс, хотя на практике этому посвящается отдельное внимание и существуют различные методы решения данной проблемы, такие как частичная или полная переортогонализация. Этим модифицированным методам посвящены отдельные статьи на данном ресурсе.&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
Обозначения и формулы, используемые в данном разделе, взяты из литературы, указанной по ссылке.&amp;lt;ref&amp;gt;James W. Demmel - Вычислительная линейная алгебра. Теория и приложения //Мир. - 2001 (c. 313, &#039;&#039;&amp;lt;math&amp;gt; \S &amp;lt;/math&amp;gt; 6.6 Методы Крыловского подпространства&#039;&#039;)&amp;lt;/ref&amp;gt; &lt;br /&gt;
&lt;br /&gt;
Алгоритм Ланцоша для вычисления &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; собственных значений и собственных векторов вещественной симметричной матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A=A^T&amp;lt;/math&amp;gt; в точной арифметике: &amp;lt;ref&amp;gt;James W. Demmel - Вычислительная линейная алгебра. Теория и приложения //Мир. - 2001 (c. 381)&amp;lt;/ref&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{align}&lt;br /&gt;
q_1 = &amp;amp; \,\frac{b}{\|b\|_2},\; \beta_0 = 0,\; q_0 = 0\\&lt;br /&gt;
\mathbf{for} \; &amp;amp; j = 1 \; to \; k \,\; \mathbf{do} \\&lt;br /&gt;
&amp;amp; z = A\,q_j\\&lt;br /&gt;
&amp;amp; \alpha_j = q^T_j z\\&lt;br /&gt;
&amp;amp; z = z - \alpha_j q_j - \beta_{j-1}q_{j-1}\\&lt;br /&gt;
&amp;amp; \beta_j = \|z\|_2\\&lt;br /&gt;
&amp;amp; \mathbf{If} \; (\beta_j == 0) \; \mathbf{then}\; stop\; the\; algorithm \\ &lt;br /&gt;
&amp;amp; \;  q_{j+1} = \frac{z}{\beta_j} \\&lt;br /&gt;
&amp;amp; compute\; eigenvalues\; and \;eigenvectors\;of \;matrix \;\;T_j= Q^T_j A Q\;\;and\;estimate \;the\; errors\\&lt;br /&gt;
\mathbf{end} \; &amp;amp; \mathbf{for}&lt;br /&gt;
\end{align}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
В продемонстрированном выше алгоритме &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;b&amp;lt;/math&amp;gt; - заданный вещественный вектор. Также полагается известным алгоритм вычисления произведения матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; на вектор &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;x&amp;lt;/math&amp;gt;. &lt;br /&gt;
Введём матрицу Крылова, определяемую следующим соотношением: &amp;lt;math&amp;gt;K_j = [b,Ab,A^2b,...,A^{j-1}b]&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Далее, на практике, матрица &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;K&amp;lt;/math&amp;gt; заменяется матрицей &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;Q&amp;lt;/math&amp;gt;, такой, что при любом числе &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; линейные оболочки первых &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; столбцов в &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;K&amp;lt;/math&amp;gt; и &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;Q&amp;lt;/math&amp;gt; являются одним и тем же подпространством.&amp;lt;ref&amp;gt;James W. Demmel - Вычислительная линейная алгебра. Теория и приложения //Мир. - 2001 (c. 315)&amp;lt;/ref&amp;gt; &lt;br /&gt;
Тогда матрица &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;Q&amp;lt;/math&amp;gt;, в отличие от матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;K&amp;lt;/math&amp;gt;, хорошо обусловлена и легко обратима. В результате получаем матрицу &amp;lt;math&amp;gt;Q_j = [q_1, q_2, \dots, q_j]&amp;lt;/math&amp;gt; размерности &amp;lt;math&amp;gt;n\times j&amp;lt;/math&amp;gt;, столбцы которой ортогональны, являются базисом подпространства Крылова и называются векторами Ланцоша.&lt;br /&gt;
&lt;br /&gt;
В алгоритме Ланцоша вычислению подлежит столько первых столбцов в матрице &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;Q_j&amp;lt;/math&amp;gt;, сколько необходимо для получения требуемого приближения к решению &amp;lt;math&amp;gt;A\,x\,=b\,\,(A\,x=\lambda \, x)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Получение нулевого &amp;lt;math&amp;gt;\beta_j&amp;lt;/math&amp;gt; в итерационном процессе - событие, желательное в том смысле, что оно свидетельствует о том, что найдено некоторое подпространство, являющееся в точности инвариантным, а все собственные значения матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;T_j&amp;lt;/math&amp;gt; являются собственными значениями матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt;. На практике же нулевое и близкие к нулю значения получаются редко.&amp;lt;ref&amp;gt;Голуб Дж., Ван Лоун Ч. - Матричные вычисления//М.: Мир. - 1999 (c. 429)&amp;lt;/ref&amp;gt; &lt;br /&gt;
&lt;br /&gt;
Затем на каждом шаге цикла формируется симметричная трёхдиагональная матрица &amp;lt;math&amp;gt;T_j = Q^T_j A Q&amp;lt;/math&amp;gt;, к которой применяется процесс Рэлея-Ритца для поиска её собственных значений (на практике для поиска этих собственных значений можно использовать любой из специальных методов в параграфе книги по ссылке).&amp;lt;ref&amp;gt;Голуб Дж., Ван Лоун Ч. - Матричные вычисления//М.: Мир. - 1999 (&amp;lt;math&amp;gt;\S&amp;lt;/math&amp;gt; 8.4)&amp;lt;/ref&amp;gt;  &lt;br /&gt;
Эти собственные значения, они же числа Ритца, и полагаются приближёнными собственными значениями исходной матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt;.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Существует множество методов для отыскания собственных значений вещественной симметричной трехдиагональной матрицы. Большинство из них требует &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt; операций &amp;lt;ref&amp;gt;Парлетт Б. Симметричная проблема собственных значений. Численные методы.,: Мир, 1983. с. 179-182&amp;lt;/ref&amp;gt;, но существуют и быстрые алгоритмы, требующие лишь &amp;lt;math&amp;gt;O(n\ln n)&amp;lt;/math&amp;gt; операций.&amp;lt;ref&amp;gt;https://en.wikipedia.org/wiki/Tridiagonal_matrix#Eigenvalues  Раздел eigenvalues&amp;lt;/ref&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Одним из возможных способов отыскать собственные значения симметричной трехдиагональной матрицы - прямое вычисление корней характеристического полинома &amp;lt;math&amp;gt;p_n(\lambda)&amp;lt;/math&amp;gt; через метод деления пополам, где формируется последовательность Штурма и локализуются собственные числа, являющиеся корнями характеристического полинома. Нахождение всех &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; собственных значений матрицы этим способом требует &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;2n^2t&amp;lt;/math&amp;gt; умножений и вычитаний, где &amp;lt;math&amp;gt;t&amp;lt;/math&amp;gt; - число сделанных шагов с применением метода деления пополам.&amp;lt;ref&amp;gt;Уилкинсон Дж. X. Алгебраическая проблема собственныx значений. Изд-во &amp;quot;Наука&amp;quot;, 1970. - глава 5, с. 272-278&amp;lt;/ref&amp;gt; Соответствующие собственные вектора могут быть найдены посредством обратных итераций за &amp;lt;math&amp;gt; O(n) &amp;lt;/math&amp;gt; флопов. &amp;lt;ref&amp;gt;Голуб Дж., Ван Лоун Ч. - Матричные вычисления//М.: Мир. - 1999 (c. 394-395)&amp;lt;/ref&amp;gt; &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;На практике, если требуется только небольшая часть от всей совокупности собственных векторов и значений, и матрица имеет Хессенбергову или трёхдиагональную форму, очень эффективными будут методы факторизации, как, например, QR-алгоритм или QL-алгоритм со сдвигами (c целью ускорить алгоритм и сделать порядок сходимости квадратичным) или же без них.&amp;lt;ref&amp;gt;http://algorithm.narod.ru/ln/eigen/ETridiag.html&amp;lt;/ref&amp;gt; &amp;lt;br&amp;gt;&lt;br /&gt;
Весьма молодые и не менее актуальные конкуренты QR и QL алгоритмов, применяющиеся для поиска собственных значений:&lt;br /&gt;
*Методы divide-and-conquer (разделяй и властвуй), появившиеся в 1980-ых годах &amp;lt;ref&amp;gt;https://goo.gl/dapvbn ссылку пришлось сократить с помощью Google url shortener, так как символы подчеркивания портили её и не давали перейти по 1 клику&amp;lt;/ref&amp;gt;&lt;br /&gt;
*Relatively robust representation методы, появившиеся в 1990-ых и позволяющие найти собственные числа симметричной матрицы порядка &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;n&amp;lt;/math&amp;gt; за &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt; операций&lt;br /&gt;
&lt;br /&gt;
Если требуется вычислить собственные векторы, то необходимо хранить вычисляемые векторы Ланцоша. Если работа при этом производится только с оперативной памятью, то при большом порядке исходной матрицы (а именно для таких матриц и предназначен метод Ланцоша) число шагов  &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;j&amp;lt;/math&amp;gt;, которые могут быть выполнены до того момента, как оперативная память будет исчерпана, будет очень незначительно, а следовательно, искомые собственные пары могут не успеть сойтись с требуемой точностью. В этом случае метод Ланцоша можно использовать итерационным образом: после выполнения заданного числа шагов процесс прерывается и, если еще не все требуемые пары Ритца сошлись с требуемой точностью, то формируется новый начальный вектор &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;q_1&amp;lt;/math&amp;gt;, являющийся линейной комбинацией векторов Ритца, еще не сошедшихся с заданной точностью, и процесс начинается заново.&amp;lt;ref&amp;gt;http://num-anal.srcc.msu.ru/lib_na/int_ae/int_ae6.htm (пункт 6.5)&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
Вычислительное ядро рассматриваемого алгоритма (наиболее ресурсно-затратная часть алгоритма) -  формирование на каждом шаге цикла промежуточного вектора &amp;lt;math&amp;gt;z&amp;lt;/math&amp;gt;, вычисляемого по формуле: &amp;lt;math&amp;gt;z = A\,q_j&amp;lt;/math&amp;gt;. Данная операция, по сравнению с другими операциями алгоритма, затратна и требовательна, как с точки зрения количества производимых операций, так и с точки зрения объема оперируемых данных. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Например, умножение матрицы размера &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;n\times n&amp;lt;/math&amp;gt; на вектор длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; требует: &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;n^2+(n-1)n = 2n^2-n&amp;lt;/math&amp;gt; операций умножения и сложения. В свою очередь аналогичная операция умножения матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;(n+1)\times (n+1)&amp;lt;/math&amp;gt; на вектор длины &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;(n+1)&amp;lt;/math&amp;gt; требует: &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;2n^2+3n+1&amp;lt;/math&amp;gt;  операций умножения и сложения. То есть повышение размерности задачи всего на 1 увеличивает число необходимых действий в этом шаге алгоритма на: &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;4n+1&amp;lt;/math&amp;gt;. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Так же, стоит помнить, что, согласно разделу 1.2, данную операцию умножения матрицы на вектор необходимо выполнить &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;k&amp;lt;/math&amp;gt; раз. Нетрудно понять, насколько возрастает и колоссален масштаб операций, если в задачах, где критична точность, размерности &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; могут иметь порядок &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;10^5&amp;lt;/math&amp;gt; или даже более.&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
Как уже было упомянуто в данной статье в описании алгоритма, рассматриваемый алгоритм состоит из двух последовательно выполненных алгоритмов: метод Ланцоша для построения последовательности подпространств Крылова и ортонормированных векторов Ланцоша и процедура Рэлея-Ритца получения оптимальных приближений собственных значений и соответствующих собственных векторов исходной матрицы.&lt;br /&gt;
&lt;br /&gt;
В первой части алгоритма, где итерационно строятся Крыловское подпространство и трёхдиагональная матрица &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&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 style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; разреженная. Именно она подлежит оптимизации с использованием техник распараллеливания, поскольку она является вычислительным ядром алгоритма, а весь упомянутый процесс построения матрицы &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&amp;lt;/math&amp;gt; выполняется последовательно.&lt;br /&gt;
&lt;br /&gt;
Рассмотрим вторую часть алгоритма - поиск собственных значений сформированной матрицы &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&amp;lt;/math&amp;gt;.&amp;lt;br&amp;gt;&lt;br /&gt;
Далее, наглядно, в виде псевдокода, представлен, упомянутый в разделе 1.2, QR-алгоритм (аналогично можно рассмотреть и QL-алгоритм) со сдвигами Релэя, который весьма популярен на практике.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{align}&lt;br /&gt;
\mathbf{Input}: \;&amp;amp;tridiagonal\;\;matrix \;T\;with\;\;n\times n\;\;size\\&lt;br /&gt;
T^{(0)}&amp;amp;:=T\\&lt;br /&gt;
\mathbf{for}&amp;amp; \;\;m=n,...,2 \;\; \mathbf{do}\\&lt;br /&gt;
&amp;amp;k=0\\&lt;br /&gt;
&amp;amp; \mathbf{repeat}\\&lt;br /&gt;
&amp;amp; \quad \;\; k=k+1\\&lt;br /&gt;
&amp;amp; \quad \;\; \mu^{(k)}=T_{m,m}^{(k-1)}\\&lt;br /&gt;
&amp;amp; \quad \;\; Q^{(k)}R^{(k)}=T^{(k-1)}-\mu^{(k)}I\;\;using\;\;QR\;decomposition\\&lt;br /&gt;
&amp;amp; \quad \;\; T^{(k)}=R^{(k)}Q^{(k)}+\mu^{(k)}I\\&lt;br /&gt;
&amp;amp; \mathbf{until} \;\;\; |T_{m,m-1}^{(k)}| \;is\;\;small\;\;enough\\&lt;br /&gt;
&amp;amp; Save  \;\;T_{m,m}^{(k)} \;\;as\;\; converged\;\;eigenvalue\;of\;T\\ &lt;br /&gt;
&amp;amp; Remove \;\boldsymbol{n}\,th\;row\;and\;\boldsymbol{n}\,th\;column\;\;from \;T \\&lt;br /&gt;
&amp;amp; and\;take\;this\;new\;cropped\;matrix\;as\;new\;T^{(0)}\;with\;\;(n-1)\times (n-1)\;\;size\\&lt;br /&gt;
 \mathbf{end}&amp;amp;\; \mathbf{for}&lt;br /&gt;
\end{align}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Малость наддиагональных и поддиагональных элементов матрицы (фраза &#039;&#039;&amp;quot;small enough&amp;quot;&#039;&#039; в псевдокоде) подразумевает:&lt;br /&gt;
&amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt; |T_{m,m-1}^{(k)}| \leq \varepsilon\,|T_{m,m}^{(k)}| \quad\quad &amp;lt;/math&amp;gt; , где &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt; \varepsilon &amp;lt;/math&amp;gt; - заданная точность&amp;lt;br&amp;gt;&lt;br /&gt;
Также вместо сдвига Релэя, обозначенного в алгоритме через &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;\mu^{(k)}&amp;lt;/math&amp;gt;, часто на практике используется сдвиг по Уилкинсону, который даёт гарантированную сходимость внедиагональных элементов матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt; T^{(k)} &amp;lt;/math&amp;gt;, формируемой на каждом шаге, к нулю, при этом жертвуя монотонностью их убывания.&amp;lt;ref&amp;gt;Голуб Дж., Ван Лоун Ч. - Матричные вычисления//М.: Мир. - 1999 (c. 378, вторая половина страницы)&amp;lt;/ref&amp;gt;&amp;lt;ref&amp;gt;Парлетт Б. Симметричная проблема собственных значений. Численные методы.,: Мир, 1983. с. 169&amp;lt;/ref&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Подробнее с различными сдвигами и соответствующими оценками скоростей и количествами операций можно ознакомиться по указанной ссылке:&amp;lt;ref&amp;gt;Парлетт Б. Симметричная проблема собственных значений. Численные методы.,: Мир, 1983. с. 179-182&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;Для совершения QR-декомпозиции на каждом шаге может использоваться любой из алгоритмов по ссылке.&amp;lt;ref&amp;gt;https://en.wikipedia.org/wiki/QR_decomposition&amp;lt;/ref&amp;gt; Подробные описания этих алгоритмов также доступны на данном ресурсе algowiki-project.&amp;lt;br&amp;gt;&lt;br /&gt;
Так как мы оперируем не обычной матрицей и даже не Хессенберговой, а симметричной и трёхдиагональной, то скорость таких алгоритмов значительно возрастёт. Например, согласно данному ресурсу &amp;lt;ref&amp;gt;http://algorithm.narod.ru/ln/eigen/ETridiag.html&amp;lt;/ref&amp;gt;, для QL-алгоритма с неявными сдвигами:&amp;lt;br&amp;gt;&lt;br /&gt;
Для трёхдиагональной матрицы объем арифметических действий составляет &amp;lt;math&amp;gt; O(n)&amp;lt;/math&amp;gt; на одну итерацию вместо &amp;lt;math&amp;gt; O(n^3)&amp;lt;/math&amp;gt; для матрицы общего вида, а число итераций для нахождения первых собственных значений примерно равно 4 - 5. Но на этих итерациях также уменьшаются внедиагональные элементы правого нижнего угла. И, таким образом, дальнейшие собственные значения ищутся значительно быстрее. Среднее число итераций на каждое собственное значение обычно составляет 1.3 - 1.6.&amp;lt;br&amp;gt; &lt;br /&gt;
Аналогично QL, QR-разложение трёхдиагольной матрицы также требует &amp;lt;math&amp;gt; O(n)&amp;lt;/math&amp;gt; флопов&amp;lt;ref&amp;gt;Голуб Дж., Ван Лоун Ч. - Матричные вычисления//М.: Мир. - 1999 (c. 378, начало раздела 8.2.2)&amp;lt;/ref&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Подводя итог, во второй части алгоритма Ланцоша можно выделить следующие макрооперации:&lt;br /&gt;
* умножение матрицы на вещественное число;&lt;br /&gt;
* перемножение матриц;&lt;br /&gt;
* умножение и сравнение вещественных чисел;&lt;br /&gt;
* + набор других макроопераций в зависимости от выбора метода, с помощью которого будет совершаться сама QR или QL-декомпозиция (выше продемонстрированы, уже, как минимум, 3 разных способа).&lt;br /&gt;
Так же, важно заметить, что набор макропераций может быть несколько другим, если выбрать какой-либо иной современный метод поиска собственных чисел трёхдиагональной матрицы, не использующий QR и QL разложения(факторизацию). Два таких метода были упомянуты в пункте 1.2.&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
С целью полностью не дублировать раздел 1.2 данной статьи, где представлен наглядный и доступный для понимания псевдокод алгоритма, постараемся лишь коротко просуммировать и обобщить весь перечень последовательных действий в рассматриваемом алгоритме.&lt;br /&gt;
&lt;br /&gt;
В качестве входных данных имеем: вещественная симметричная матрица &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; размера &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;n\times n&amp;lt;/math&amp;gt;, известный вещественный вектор &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;b&amp;lt;/math&amp;gt; длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; и число &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;n&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Далее:&lt;br /&gt;
* Инициализируем вещественную константу &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;\beta_0&amp;lt;/math&amp;gt; и векторы &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;q_0&amp;lt;/math&amp;gt; и &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;q_1&amp;lt;/math&amp;gt;&lt;br /&gt;
* Итерационно для всех &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j=1,...,k&amp;lt;/math&amp;gt;:&lt;br /&gt;
** Вычисляем вспомогательный вектор &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt;, используя умножение матрицы на вектор&lt;br /&gt;
** Вычисляем, используя скалярное произведение векторов, значение &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;\alpha_j&amp;lt;/math&amp;gt; - элемент на главной диагонали трёхдиагональной матрицы &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&amp;lt;/math&amp;gt;&lt;br /&gt;
** Вычисляем по формуле новое значение и перезаписываем вектор &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt;&lt;br /&gt;
** Вычисляем значение &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;\beta_j&amp;lt;/math&amp;gt; - элементы непосредственно над и под главной диагональю той же матрицы &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&amp;lt;/math&amp;gt;&lt;br /&gt;
** Вычисляем, зная вектор &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt;,  очередной столбец матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;Q&amp;lt;/math&amp;gt;, он же вектор Ланцоша : &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;\,\,q_{j+1}&amp;lt;/math&amp;gt;&lt;br /&gt;
** Теперь, когда матрица &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&amp;lt;/math&amp;gt; сформирована на очередном шаге, находим её собственные значения и вектора любым доступным способом, о чём было подробно сказано в пункте 1.2&lt;br /&gt;
** Переходим на следующую итерацию: &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j&amp;lt;/math&amp;gt;++&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
Оценим количество операций и сложность последовательного алгоритма, изложенного в предыдущем разделе.&lt;br /&gt;
*Для вычисления вектора &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt; умножается матрица размера &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;n\times n&amp;lt;/math&amp;gt; на вектор длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt;, и потребуется &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n^2&amp;lt;/math&amp;gt; операций умножения и &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n^2&amp;lt;/math&amp;gt; операций сложения.&lt;br /&gt;
*Умножение векторов &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;q^T_j&amp;lt;/math&amp;gt; и &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt; длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; потребует &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; операций умножения и &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; операций сложения.&lt;br /&gt;
*При вычислении нового значения вектора &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt; поэлементное сложение двух векторов длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; требует &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; операций сложения.&lt;br /&gt;
*Умножение вектора длины &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; на вещественное число требует &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; операций умножения.&lt;br /&gt;
*Нахождение квадратичной нормы вектора &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt;  длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; требует &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; умножений и &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; сложений и ещё 1 операцию извлечения квадратного корня.&lt;br /&gt;
*Заключительное нахождение собственных значений и собственных векторов трёхдиагональной матрицы &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;T_j&amp;lt;/math&amp;gt; размера &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j\times j&amp;lt;/math&amp;gt; с помощью QR-алгоритма потребует в худшем случае &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(j^3)&amp;lt;/math&amp;gt; операций.&amp;lt;ref&amp;gt;http://num-anal.srcc.msu.ru/lib_na/int_ae/int_ae6.htm (пункт 6.2, &amp;quot;Скорость сходимости при этом всегда не хуже квадратичной и почти всегда лучше кубической.&amp;quot;)&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Посчитаем теперь суммарное количество простейших операций на одной итерации алгоритма (без учёта записей в память):&lt;br /&gt;
*&amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n^2+5\,n&amp;lt;/math&amp;gt; операций умножения/деления&lt;br /&gt;
*&amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n^2+4\,n&amp;lt;/math&amp;gt; операций сложения/вычитания&lt;br /&gt;
*1 операция извлечения квадратного корня&amp;lt;br&amp;gt;&lt;br /&gt;
Отдельно после всех итераций при &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j=k&amp;lt;/math&amp;gt; :&lt;br /&gt;
*&amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(k^3)&amp;lt;/math&amp;gt; операций для поиска собственных значений и собственных векторов трёхдиагональной матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_k&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Итого можно утверждать следующее:&lt;br /&gt;
&lt;br /&gt;
Последовательная сложность одной итерации рассматриваемого алгоритма:  &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(n ^ 2) &amp;lt;/math&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Суммарная сложность алгоритма (&amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;/math&amp;gt; итераций): &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(k\,n ^ 2) + O(k ^ 3)&amp;lt;/math&amp;gt; &amp;lt;ref&amp;gt;Здесь мы полагаем, что мы не вычисляем собственные значения и векторы матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_j&amp;lt;/math&amp;gt; на каждом промежуточном шаге, а лишь единожды затрачиваем &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;O(k ^ 3)&amp;lt;/math&amp;gt; действий в конце для нахождения &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;/math&amp;gt; собственных значений и векторов матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_k&amp;lt;/math&amp;gt;&amp;lt;/ref&amp;gt; &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
На практике же обычно рассматривается число &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;&amp;lt;n&amp;lt;/math&amp;gt;, поэтому второе слагаемое можно опустить.&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
На рис. 1 продемонстрирован граф одной итерации (при каком-либо произвольном значении итератора &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j&amp;lt;/math&amp;gt;) описанного алгоритма без отображения входных и выходных данных. Наглядно продемонстрированы связи между всеми действиями, и с помощью деления на &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; потоков показано, какие операции возможно выполнять параллельно на каждом шаге с целью оптимизации и экономии машинного времени. В результате, после параллельно выполненных операций &#039;&#039;&#039;Division&#039;&#039;&#039; на заключительном ярусе, на выходе имеем значение следующего вектора Ланцоша &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;q_{j+1}&amp;lt;/math&amp;gt;, после чего следует переход на следующую итерацию, и процесс повторяется.&lt;br /&gt;
&lt;br /&gt;
[[Файл:Levin_graph.png|600px|thumb|center|Рис. 1  Структура одной итерации алгоритма]] &amp;lt;br&amp;gt;&lt;br /&gt;
Обозначения на рисунке: &amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Simp&#039;&#039;&#039; (от англ. simple) - операции сложения и умножения вещественных чисел при вычислении произведения матрицы на вектор;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Vec mult&#039;&#039;&#039; (от англ. vectors multiplication) - операция скалярного умножения двух векторов;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Vec subtr&#039;&#039;&#039; (от англ. vectors subtraction, из-за использованных в операции вычитаний векторов) - операция умножения вектора на число (выполняется дважды) и формирование нового значения &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;z_{new}&amp;lt;/math&amp;gt; по формуле: &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;z_{new} = z - \alpha_j q_j - \beta_{j-1}q_{j-1} \;&amp;lt;/math&amp;gt;;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;||\cdot||&amp;lt;/math&amp;gt; - операция вычисления нормы вектора;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Division&#039;&#039;&#039; - операция деления вектора на вещественное число  &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;\beta_j&amp;lt;/math&amp;gt; &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Важно отметить, что упомянутые выше операции также легко поддаются оптимизации. Например, попарные умножения вещественных координат векторов при вычислении скалярного произведения также легко выполняются параллельно на &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; потоках, а затем можно применить суммирование методом сдваивания, о котором сказано в следующем разделе. Умножение или деление вектора на вещественное число являющееся, по определению, умножением или делением всех его координат на это число тоже может быть выполнено эффективнее, если мы используем &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; потоков, а не выполняем эти действия последовательно.&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
Параллельные операции возможны только внутри итераций, так как рассматриваемый алгоритм является итерационным, и сами итерации строго последовательны.&amp;lt;br&amp;gt;&lt;br /&gt;
Рассмотрим в этом разделе подробнее, какой выигрыш мы можем получить при распараллеливании операций внутри одной итерации согласно графу из предыдущего раздела.&lt;br /&gt;
&lt;br /&gt;
Умножение вещественной симметричной матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; размера &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;n\times n&amp;lt;/math&amp;gt; на вектор &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;b&amp;lt;/math&amp;gt; длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; требует последовательного выполнения &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; ярусов умножений и сложений. Сложение элементов вектора длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; на каждом шаге перемножения можно оптимизировать и выполнить за &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;\log_2 n&amp;lt;/math&amp;gt; действий, если применять метод сдваивания.&lt;br /&gt;
&lt;br /&gt;
Дальнейшие операции выполняются последовательно, а вычисление значений векторов происходит за один ярус операций сложения или умножения.&lt;br /&gt;
&lt;br /&gt;
Ресурс параллелизма алгоритма вычисления собственных значений построенной трёхдиагональной матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_k&amp;lt;/math&amp;gt; размера &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k\times k&amp;lt;/math&amp;gt; зависит от выбранного алгоритма (об этих алгоритмах подробнее было сказано в разделах 1.2 и 1.4). Будет очень затратно с точки зрения объёма материала пытаться рассмотреть пусть даже часть этих методов в этой статье, а так же тонкости их распараллеливания. Предлагаем читателям при желании самим ознакомиться с этими алгоритмами на данном ресурсе или прибегнув к иным источникам.&lt;br /&gt;
&lt;br /&gt;
При классификации по высоте ЯПФ, таким образом, алгоритм Ланцоша без переортогонализации относится к алгоритмам с &#039;&#039;логарифмической сложностью&#039;&#039;, и его сложность равна &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(\log_2 n)&amp;lt;/math&amp;gt; с важным замечанием, что это сложность только одной итерации, а максимум в алгоритме может быть выполнено последовательно &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;/math&amp;gt; таких однотипных итераций, если не будет осуществлён ранний выход из цикла. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Несмотря на то, что на графе в предыдущем разделе для лучшей визуализации и понимания было изображено &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; потоков (никаких допущений мы не делали и нарушений с точки зрения логики и математики нет, можно изобразить большее число потоков, просто часть времени некоторые из них могут бездействовать и не использоваться), на самом деле правильным и разумным будет реализовать начальное параллельное выполнение &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n^2&amp;lt;/math&amp;gt; операций умножения всех вещественных элементов матрицы &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;A&amp;lt;/math&amp;gt; на соответствующие элементы вектора &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;q_j&amp;lt;/math&amp;gt;, после чего применять тот же самый упомянутый метод сдваивания. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Поэтому при классификации по ширине ЯПФ его сложность будет &#039;&#039;квадратичной&#039;&#039; и равна &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(n^2)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
&#039;&#039;&#039;Входные данные алгоритма:&#039;&#039;&#039; вещественная симметричная &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; размера &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;n\times n&amp;lt;/math&amp;gt;, вещественный вектор &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;b&amp;lt;/math&amp;gt; длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt;, и одно целое число &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;k&amp;lt;/math&amp;gt;, означающее количество итераций.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём входных данных:&#039;&#039;&#039; &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;n^2 +n + 1 &amp;lt;/math&amp;gt;. Если учесть, что матрица симметричная и достаточно для её однозначного определения задать элементы на главной диагонали и элементы над или под ней, то можно сократить объём входных данных с целью экономии памяти до: &amp;lt;math&amp;gt;\ \frac{n^2-n}{2}+n+n+1 =\frac{n^2+3n}{2} + 1&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные алгоритма:&#039;&#039;&#039; вектор собственных значений &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;\Theta^k&amp;lt;/math&amp;gt; длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;/math&amp;gt;, матрица &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;S^k&amp;lt;/math&amp;gt; из соответствующих собственных векторов размера &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n\times k&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём выходных данных:&#039;&#039;&#039; &amp;lt;math&amp;gt;k\;(n + 1)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
В данном разделе перечислены без какой-либо хронологии или связи друг с другом наиболее важные и разнообразные свойства алгоритма, на которые стоит и полезно обратить внимание, а также которые выгодно отличают его от схожих алгоритмов, решающих ту же задачу.&amp;lt;br&amp;gt;&lt;br /&gt;
1) Отношение последовательной сложности алгоритма к параллельной,с учётом &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;/math&amp;gt; итераций, равно &amp;lt;math&amp;gt;\;\;\frac{kn^2}{k \log_2{n}}=\frac{n^2}{\log_2{n}}&amp;lt;/math&amp;gt;;&amp;lt;br&amp;gt;&lt;br /&gt;
2) Вычислительная мощность алгоритма, как отношение числа операций к суммарному объему входных и выходных данных, равна &amp;lt;math style=&amp;quot;vertical-align:-70%&amp;gt;\;\;\frac{k\,n^2}{0.5\,n^2+1.5\,n+k\,n+k+1}&amp;lt;/math&amp;gt; и &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;\approx 2\,k&amp;lt;/math&amp;gt;, так как на практике верно отношение &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;&amp;lt;n&amp;lt;/math&amp;gt; ;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
3) Для собственных значений формируемых матриц &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_j&amp;lt;/math&amp;gt; верно отношение (следствие теоремы Коши о перемежаемости): &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;\lambda_i(T_{k+1})\geq \lambda_i(T_{k})\geq \lambda_{i+1}(T_{k+1})\geq \lambda_{i+1}(T_{k})&amp;lt;/math&amp;gt; ;&amp;lt;ref&amp;gt;James W. Demmel - Вычислительная линейная алгебра. Теория и приложения //Мир. - 2001 (c. 383)&amp;lt;/ref&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
4) Крайние (наибольшие и наименьшие) собственные значения матриц &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_j&amp;lt;/math&amp;gt; сходятся к крайним собственным значениям матрицы &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;A&amp;lt;/math&amp;gt; первыми (это часто происходит уже на ранних шагах при &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j\approx 2\,\sqrt{n}&amp;lt;/math&amp;gt;&amp;lt;ref&amp;gt;http://num-anal.srcc.msu.ru/lib_na/int_ae/int_ae6.htm (пункт 6.5)&amp;lt;/ref&amp;gt;), а собственные значения в середине спектра - последними;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
5) Из-за ограниченной точности постепенно теряется ортогональность вектора Ланцоша &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;q_j&amp;lt;/math&amp;gt; к предыдущим векторам Ланцоша, поэтому необходимо примерно каждые 10-15 итераций проводить дорогостоящую операцию реортогонализации, но это уже будет иной алгоритм с очень малым различием в одной операции и в программном коде, реализующем его, соответственно; &amp;lt;ref&amp;gt;Sam Handler - The Lanczos Algorithm For Large-Scale Eigenvalue Problems (08.01.07), slide №8&amp;lt;/ref&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
6) Эффективность и быстрота выполнения алгоритма очень сильно зависит от скорости памяти (диска). Согласно тесту только &#039;&#039;6%&#039;&#039; времени работы программы приходится на вычисления, остальное время затрачивается на ожидание отклика диска;&amp;lt;ref&amp;gt;Sam Handler - The Lanczos Algorithm For Large-Scale Eigenvalue Problems (08.01.07), slide №10&amp;lt;/ref&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
7) Метод Ланцоша удобен тем, что не требует хранения исходной матрицы полным массивом: метод использует исходную матрицу только в операциях умножения матрицы на вектор, что позволяет эффективно использовать разреженность матрицы или регулярность структуры матрицы. Поэтому метод Ланцоша может быть использован для матриц таких больших порядков, когда методы вращений и отражений не могут быть применены.&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;
Для исследования масштабируемости рассматриваемого алгоритма Ланцоша без переортогонализации автором была реализована программа на языке С++ с использованием технологии MPI. &amp;lt;ref&amp;gt;https://goo.gl/dGfzOD  или альтернативная ссылка с прикреплённым кодом: https://goo.gl/lFziv0 , по просьбе на почту я (автор статьи) готов предоставить желающим доступ к проекту с этим кодом на ресурсе Bitbucket&amp;lt;/ref&amp;gt; Дальнейшее исследование было проведено на суперкомпьютере &amp;quot;Ломоносов&amp;quot; Суперкомпьютерного комплекса МГУ. &amp;lt;br&amp;gt; Важно отметить, что реализованная программа выполняет только первую часть алгоритма - формирование матрицы &amp;lt;math &amp;gt;T_j&amp;lt;/math&amp;gt;. Вторая часть алгоритма (задача поиска собственных значений матрицы &amp;lt;math &amp;gt;T_j&amp;lt;/math&amp;gt;) может быть решена несколькими методами, каждый из которых обладает своей эффективностью распараллеливании и характерными свойствами. Подробно этот вопрос уже обсуждался в статье раннее, поэтому не будем ещё раз заострять на этом внимание и останавливаться.&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Сборка осуществлялась со следующими параметрами:&lt;br /&gt;
* Компилятор intel/15.0.090 &lt;br /&gt;
* Openmpi/1.8.4-icc&lt;br /&gt;
В серии проведённых расчётов рассматривались следующие числовые значения параметров:&lt;br /&gt;
* Размер &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;n&amp;lt;/math&amp;gt; задачи и, соответственно, матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt;, задействованной в операции умножения на вектор: [2000 : 30000] с шагом 1000&lt;br /&gt;
* Число процессоров: 1, 2, 4, 16, 32, 48, 64, 96, 128&lt;br /&gt;
* Число итераций в алгоритме: &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k=350&amp;lt;/math&amp;gt;&lt;br /&gt;
Число &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; взято таким вопреки информации в начале статьи, где говорится, что значение &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; редко превышает &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;10^2&amp;lt;/math&amp;gt; (хоть мы и имеем право брать его любым по нашему усмотрению). Это сделано исключительно для лучшей визуализации пиков на графиках в данном разделе и наглядности получаемых результатов, так как при меньших на порядок значениях параметра &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; времена выполнения программ были слишком малы даже при минимальных числах процессоров и максимальных размерах &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;n&amp;lt;/math&amp;gt; задачи.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
На рис. 2 изображён график зависимости времени выполнения программы от числа процессоров и размера &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;n&amp;lt;/math&amp;gt; задачи. &amp;lt;br&amp;gt;&lt;br /&gt;
[[Файл:Levin604 Lanzcos result execTIME.png|580px|thumb|left|Рис. 2  График зависимости времени выполнения программы]] &amp;lt;br&amp;gt;&lt;br /&gt;
Многочисленные тесты показали при малых количествах ядер уменьшение времени выполнения программы почти в 2 раза при увеличении числа ядер в 2 раза на всём диапазоне размеров матриц, то есть можно судить о хорошей эффективности, что и отражает сильный излом на предоставленом графике.&lt;br /&gt;
&lt;br /&gt;
== Динамические характеристики и эффективность реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Выводы для классов архитектур ==&lt;br /&gt;
По заданию, во второй части требовалось описать только разделы 2.4 и 2.7, прошу не спрашивать с меня все разделы 2.1-2.6. Надеюсь на понимание, мне физически не хватает времени на это задание + 2 других в течение семестра, делаю всё, что в моих силах :)&lt;br /&gt;
&lt;br /&gt;
== Существующие реализации алгоритма ==&lt;br /&gt;
Несмотря на то, что алгоритм является далеко не самым популярным, алгоритмом, про который нельзя сказать, что он всегда «на слуху», на сегодняшний день существует множество реализаций на различных популярных языках.&amp;lt;br&amp;gt;&lt;br /&gt;
Перечислим далее некоторые из них, указывая язык программирования, лежащий в их основе, и некоторые важные характеристики, которые обсуждались в статье ранее:&lt;br /&gt;
*&#039;&#039;Code on netlib.org by Jane Cullum and Ralph Willoughby&#039;&#039; (&#039;&#039;&#039;Fortran 77&#039;&#039;&#039;; без реортогонализации векторов; без реализации распараллеливания)&amp;lt;ref&amp;gt;http://www.netlib.org/lanczos/leval&amp;lt;/ref&amp;gt;&lt;br /&gt;
*&#039;&#039;Lanczos algorithm on freesourcecode.net&#039;&#039; (&#039;&#039;&#039;Matlab&#039;&#039;&#039;; присутствует реортогонализация векторов; без реализации распараллеливания)&amp;lt;ref&amp;gt;http://freesourcecode.net/matlabprojects/61741/lanczos-algorithm--in-matlab&amp;lt;/ref&amp;gt;&lt;br /&gt;
*&#039;&#039;Lanczos for eigenvalues in Numerical Linear Algebra, Spring 2007&#039;&#039; (&#039;&#039;&#039;Matlab&#039;&#039;&#039;; частичная или полная реортогонализация - доступны оба варианта; без реализации распараллеливания)&amp;lt;ref&amp;gt;Ссылки на файлы lanso.m и lanfu.m можно найти на https://www.nada.kth.se/~ruhe/2D5219/labs2007.html&amp;lt;/ref&amp;gt;&lt;br /&gt;
*&#039;&#039;Planso&#039;&#039; (название происходит от parallel Lanso.f) &#039;&#039;code by Kesheng Wu and Horst D. Simon&#039;&#039; (&#039;&#039;&#039;Fortran 77&#039;&#039;&#039;; частичная реортогонализация векторов; использование MPI для коммуникаций)&amp;lt;ref&amp;gt;https://github.com/jiahao/planso.jl/tree/master/external/PLAN/plan К сожалению, ссылка в описании пакета на github, ведущая на сайт National Energy Research Scientific Computing Center (NERSC), с более подробной информацией о данной программе больше не активна и выдаёт результат &#039;&#039;Page not found&#039;&#039;&amp;lt;/ref&amp;gt; &lt;br /&gt;
* &#039;&#039;Lanczos.cpp in the Vienna Computing Library&#039;&#039;  (&#039;&#039;&#039;C++&#039;&#039;&#039;, частичная реортогонализация, без реализации распараллеливания) &amp;lt;ref&amp;gt;http://viennacl.sourceforge.net/doc/lanczos_8cpp_source.html&amp;lt;/ref&amp;gt;&lt;br /&gt;
* &#039;&#039;Parallel Eigen Values code using C++ AMP on microsoft msdn blog&#039;&#039; (&#039;&#039;&#039;C++&#039;&#039;&#039;; ? ; распараллеливание есть и реализовано через C++ AMP) &amp;lt;ref&amp;gt;https://blogs.msdn.microsoft.com/nativeconcurrency/2013/12/20/eigen-values/ Подробнее о C++ Accelerated Massive Parallelism можно почитать здесь: https://msdn.microsoft.com/ru-ru/library/hh265137(v=vs.140).aspx или здесь: http://professorweb.ru/my/csharp/optimization/level4/4_6.php &amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;br /&gt;
[[en:Description of algorithm properties and structure]]&lt;/div&gt;</summary>
		<author><name>AleksLevin</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:AleksLevin/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%9B%D0%B0%D0%BD%D1%86%D0%BE%D1%88%D0%B0_%D0%B2%D1%8B%D1%87%D0%B8%D1%81%D0%BB%D0%B5%D0%BD%D0%B8%D1%8F_%D1%81%D0%BE%D0%B1%D1%81%D1%82%D0%B2%D0%B5%D0%BD%D0%BD%D1%8B%D1%85_%D0%B7%D0%BD%D0%B0%D1%87%D0%B5%D0%BD%D0%B8%D0%B9_%D1%81%D0%B8%D0%BC%D0%BC%D0%B5%D1%82%D1%80%D0%B8%D1%87%D0%BD%D0%BE%D0%B9_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86%D1%8B_%D0%B4%D0%BB%D1%8F_%D1%82%D0%BE%D1%87%D0%BD%D0%BE%D0%B9_%D0%B0%D1%80%D0%B8%D1%84%D0%BC%D0%B5%D1%82%D0%B8%D0%BA%D0%B8_(%D0%B1%D0%B5%D0%B7_%D0%BF%D0%B5%D1%80%D0%B5%D0%BE%D1%80%D1%82%D0%BE%D0%B3%D0%BE%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D0%B8)&amp;diff=20223</id>
		<title>Участник:AleksLevin/Алгоритм Ланцоша вычисления собственных значений симметричной матрицы для точной арифметики (без переортогонализации)</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:AleksLevin/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%9B%D0%B0%D0%BD%D1%86%D0%BE%D1%88%D0%B0_%D0%B2%D1%8B%D1%87%D0%B8%D1%81%D0%BB%D0%B5%D0%BD%D0%B8%D1%8F_%D1%81%D0%BE%D0%B1%D1%81%D1%82%D0%B2%D0%B5%D0%BD%D0%BD%D1%8B%D1%85_%D0%B7%D0%BD%D0%B0%D1%87%D0%B5%D0%BD%D0%B8%D0%B9_%D1%81%D0%B8%D0%BC%D0%BC%D0%B5%D1%82%D1%80%D0%B8%D1%87%D0%BD%D0%BE%D0%B9_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86%D1%8B_%D0%B4%D0%BB%D1%8F_%D1%82%D0%BE%D1%87%D0%BD%D0%BE%D0%B9_%D0%B0%D1%80%D0%B8%D1%84%D0%BC%D0%B5%D1%82%D0%B8%D0%BA%D0%B8_(%D0%B1%D0%B5%D0%B7_%D0%BF%D0%B5%D1%80%D0%B5%D0%BE%D1%80%D1%82%D0%BE%D0%B3%D0%BE%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D0%B8)&amp;diff=20223"/>
		<updated>2016-12-07T00:40:39Z</updated>

		<summary type="html">&lt;p&gt;AleksLevin: /* Масштабируемость алгоритма и его реализации */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Основные авторы описания: Левин А.Д.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{algorithm&lt;br /&gt;
| name              = Алгоритм Ланцоша для точной арифметики (без переортогонализации)&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(k\,n^2)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(k\log_2 n)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;\frac{n^2+3n}{2} + 1&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;k\;(n + 1)&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритмов =&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Данный алгоритм появился в 1950 г. и носит имя венгерского физика и математика Корнелия Ланцоша (венг. Lánczos Kornél). Алгоритм Ланцоша относится к итерационным методам вычисления собственных значений для матриц столь больших порядков &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt; n&amp;lt;/math&amp;gt;, что к ним нельзя применить прямые методы из-за ограничений по времени и памяти.&lt;br /&gt;
&lt;br /&gt;
Сам Ланцош указывал, что его метод предназначен для отыскания нескольких собственных векторов симметричных матриц, хотя к методу сразу было обращено внимание, как к способу приведения всей матрицы к трёхдиагональному виду. Двадцатью годами позже канадский математик Крис Пэж показал, что, несмотря на чувствительность к округлениям, алгоритм Ланцоша - эффективное средство вычисления некоторых &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; собственных чисел и соответствующих им собственных векторов. &amp;lt;ref&amp;gt;Парлетт Б. - Симметричная проблема собственных значений. Численные методы //М.: Мир. - 1983. (c. 276)&amp;lt;/ref&amp;gt;&lt;br /&gt;
Обычно число &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; берут в два раза больше, чем количество собственных значений матрицы, которые поставлена цель найти, и оно имеет порядок не более &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;10^2&amp;lt;/math&amp;gt;.&amp;lt;ref&amp;gt;Susan W. Bostic - Lanczos Eigensolution Method for High-Perfomance Computers, page 7&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Алгоритм Ланцоша для вычисления собственных значений симметричной матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; соединяет в себе метод Ланцоша для построения последовательности подпространств Крылова и ортонормированных векторов Ланцоша и процедуру Рэлея-Ритца получения оптимальных приближений собственных значений и соответствующих собственных векторов исходной матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt;.&amp;lt;ref&amp;gt;James W. Demmel - Вычислительная линейная алгебра. Теория и приложения //Мир. - 2001 (c. 381)&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
В данной статье рассматривается вариант алгоритма Ланцоша, в котором опущено влияние ошибок округления на вычислительный процесс, хотя на практике этому посвящается отдельное внимание и существуют различные методы решения данной проблемы, такие как частичная или полная переортогонализация. Этим модифицированным методам посвящены отдельные статьи на данном ресурсе.&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
Обозначения и формулы, используемые в данном разделе, взяты из литературы, указанной по ссылке.&amp;lt;ref&amp;gt;James W. Demmel - Вычислительная линейная алгебра. Теория и приложения //Мир. - 2001 (c. 313, &#039;&#039;&amp;lt;math&amp;gt; \S &amp;lt;/math&amp;gt; 6.6 Методы Крыловского подпространства&#039;&#039;)&amp;lt;/ref&amp;gt; &lt;br /&gt;
&lt;br /&gt;
Алгоритм Ланцоша для вычисления &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; собственных значений и собственных векторов вещественной симметричной матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A=A^T&amp;lt;/math&amp;gt; в точной арифметике: &amp;lt;ref&amp;gt;James W. Demmel - Вычислительная линейная алгебра. Теория и приложения //Мир. - 2001 (c. 381)&amp;lt;/ref&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{align}&lt;br /&gt;
q_1 = &amp;amp; \,\frac{b}{\|b\|_2},\; \beta_0 = 0,\; q_0 = 0\\&lt;br /&gt;
\mathbf{for} \; &amp;amp; j = 1 \; to \; k \,\; \mathbf{do} \\&lt;br /&gt;
&amp;amp; z = A\,q_j\\&lt;br /&gt;
&amp;amp; \alpha_j = q^T_j z\\&lt;br /&gt;
&amp;amp; z = z - \alpha_j q_j - \beta_{j-1}q_{j-1}\\&lt;br /&gt;
&amp;amp; \beta_j = \|z\|_2\\&lt;br /&gt;
&amp;amp; \mathbf{If} \; (\beta_j == 0) \; \mathbf{then}\; stop\; the\; algorithm \\ &lt;br /&gt;
&amp;amp; \;  q_{j+1} = \frac{z}{\beta_j} \\&lt;br /&gt;
&amp;amp; compute\; eigenvalues\; and \;eigenvectors\;of \;matrix \;\;T_j= Q^T_j A Q\;\;and\;estimate \;the\; errors\\&lt;br /&gt;
\mathbf{end} \; &amp;amp; \mathbf{for}&lt;br /&gt;
\end{align}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
В продемонстрированном выше алгоритме &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;b&amp;lt;/math&amp;gt; - заданный вещественный вектор. Также полагается известным алгоритм вычисления произведения матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; на вектор &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;x&amp;lt;/math&amp;gt;. &lt;br /&gt;
Введём матрицу Крылова, определяемую следующим соотношением: &amp;lt;math&amp;gt;K_j = [b,Ab,A^2b,...,A^{j-1}b]&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Далее, на практике, матрица &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;K&amp;lt;/math&amp;gt; заменяется матрицей &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;Q&amp;lt;/math&amp;gt;, такой, что при любом числе &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; линейные оболочки первых &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; столбцов в &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;K&amp;lt;/math&amp;gt; и &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;Q&amp;lt;/math&amp;gt; являются одним и тем же подпространством.&amp;lt;ref&amp;gt;James W. Demmel - Вычислительная линейная алгебра. Теория и приложения //Мир. - 2001 (c. 315)&amp;lt;/ref&amp;gt; &lt;br /&gt;
Тогда матрица &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;Q&amp;lt;/math&amp;gt;, в отличие от матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;K&amp;lt;/math&amp;gt;, хорошо обусловлена и легко обратима. В результате получаем матрицу &amp;lt;math&amp;gt;Q_j = [q_1, q_2, \dots, q_j]&amp;lt;/math&amp;gt; размерности &amp;lt;math&amp;gt;n\times j&amp;lt;/math&amp;gt;, столбцы которой ортогональны, являются базисом подпространства Крылова и называются векторами Ланцоша.&lt;br /&gt;
&lt;br /&gt;
В алгоритме Ланцоша вычислению подлежит столько первых столбцов в матрице &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;Q_j&amp;lt;/math&amp;gt;, сколько необходимо для получения требуемого приближения к решению &amp;lt;math&amp;gt;A\,x\,=b\,\,(A\,x=\lambda \, x)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Получение нулевого &amp;lt;math&amp;gt;\beta_j&amp;lt;/math&amp;gt; в итерационном процессе - событие, желательное в том смысле, что оно свидетельствует о том, что найдено некоторое подпространство, являющееся в точности инвариантным, а все собственные значения матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;T_j&amp;lt;/math&amp;gt; являются собственными значениями матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt;. На практике же нулевое и близкие к нулю значения получаются редко.&amp;lt;ref&amp;gt;Голуб Дж., Ван Лоун Ч. - Матричные вычисления//М.: Мир. - 1999 (c. 429)&amp;lt;/ref&amp;gt; &lt;br /&gt;
&lt;br /&gt;
Затем на каждом шаге цикла формируется симметричная трёхдиагональная матрица &amp;lt;math&amp;gt;T_j = Q^T_j A Q&amp;lt;/math&amp;gt;, к которой применяется процесс Рэлея-Ритца для поиска её собственных значений (на практике для поиска этих собственных значений можно использовать любой из специальных методов в параграфе книги по ссылке).&amp;lt;ref&amp;gt;Голуб Дж., Ван Лоун Ч. - Матричные вычисления//М.: Мир. - 1999 (&amp;lt;math&amp;gt;\S&amp;lt;/math&amp;gt; 8.4)&amp;lt;/ref&amp;gt;  &lt;br /&gt;
Эти собственные значения, они же числа Ритца, и полагаются приближёнными собственными значениями исходной матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt;.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Существует множество методов для отыскания собственных значений вещественной симметричной трехдиагональной матрицы. Большинство из них требует &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt; операций &amp;lt;ref&amp;gt;Парлетт Б. Симметричная проблема собственных значений. Численные методы.,: Мир, 1983. с. 179-182&amp;lt;/ref&amp;gt;, но существуют и быстрые алгоритмы, требующие лишь &amp;lt;math&amp;gt;O(n\ln n)&amp;lt;/math&amp;gt; операций.&amp;lt;ref&amp;gt;https://en.wikipedia.org/wiki/Tridiagonal_matrix#Eigenvalues  Раздел eigenvalues&amp;lt;/ref&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Одним из возможных способов отыскать собственные значения симметричной трехдиагональной матрицы - прямое вычисление корней характеристического полинома &amp;lt;math&amp;gt;p_n(\lambda)&amp;lt;/math&amp;gt; через метод деления пополам, где формируется последовательность Штурма и локализуются собственные числа, являющиеся корнями характеристического полинома. Нахождение всех &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; собственных значений матрицы этим способом требует &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;2n^2t&amp;lt;/math&amp;gt; умножений и вычитаний, где &amp;lt;math&amp;gt;t&amp;lt;/math&amp;gt; - число сделанных шагов с применением метода деления пополам.&amp;lt;ref&amp;gt;Уилкинсон Дж. X. Алгебраическая проблема собственныx значений. Изд-во &amp;quot;Наука&amp;quot;, 1970. - глава 5, с. 272-278&amp;lt;/ref&amp;gt; Соответствующие собственные вектора могут быть найдены посредством обратных итераций за &amp;lt;math&amp;gt; O(n) &amp;lt;/math&amp;gt; флопов. &amp;lt;ref&amp;gt;Голуб Дж., Ван Лоун Ч. - Матричные вычисления//М.: Мир. - 1999 (c. 394-395)&amp;lt;/ref&amp;gt; &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;На практике, если требуется только небольшая часть от всей совокупности собственных векторов и значений, и матрица имеет Хессенбергову или трёхдиагональную форму, очень эффективными будут методы факторизации, как, например, QR-алгоритм или QL-алгоритм со сдвигами (c целью ускорить алгоритм и сделать порядок сходимости квадратичным) или же без них.&amp;lt;ref&amp;gt;http://algorithm.narod.ru/ln/eigen/ETridiag.html&amp;lt;/ref&amp;gt; &amp;lt;br&amp;gt;&lt;br /&gt;
Весьма молодые и не менее актуальные конкуренты QR и QL алгоритмов, применяющиеся для поиска собственных значений:&lt;br /&gt;
*Методы divide-and-conquer (разделяй и властвуй), появившиеся в 1980-ых годах &amp;lt;ref&amp;gt;https://goo.gl/dapvbn ссылку пришлось сократить с помощью Google url shortener, так как символы подчеркивания портили её и не давали перейти по 1 клику&amp;lt;/ref&amp;gt;&lt;br /&gt;
*Relatively robust representation методы, появившиеся в 1990-ых и позволяющие найти собственные числа симметричной матрицы порядка &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;n&amp;lt;/math&amp;gt; за &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt; операций&lt;br /&gt;
&lt;br /&gt;
Если требуется вычислить собственные векторы, то необходимо хранить вычисляемые векторы Ланцоша. Если работа при этом производится только с оперативной памятью, то при большом порядке исходной матрицы (а именно для таких матриц и предназначен метод Ланцоша) число шагов  &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;j&amp;lt;/math&amp;gt;, которые могут быть выполнены до того момента, как оперативная память будет исчерпана, будет очень незначительно, а следовательно, искомые собственные пары могут не успеть сойтись с требуемой точностью. В этом случае метод Ланцоша можно использовать итерационным образом: после выполнения заданного числа шагов процесс прерывается и, если еще не все требуемые пары Ритца сошлись с требуемой точностью, то формируется новый начальный вектор &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;q_1&amp;lt;/math&amp;gt;, являющийся линейной комбинацией векторов Ритца, еще не сошедшихся с заданной точностью, и процесс начинается заново.&amp;lt;ref&amp;gt;http://num-anal.srcc.msu.ru/lib_na/int_ae/int_ae6.htm (пункт 6.5)&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
Вычислительное ядро рассматриваемого алгоритма (наиболее ресурсно-затратная часть алгоритма) -  формирование на каждом шаге цикла промежуточного вектора &amp;lt;math&amp;gt;z&amp;lt;/math&amp;gt;, вычисляемого по формуле: &amp;lt;math&amp;gt;z = A\,q_j&amp;lt;/math&amp;gt;. Данная операция, по сравнению с другими операциями алгоритма, затратна и требовательна, как с точки зрения количества производимых операций, так и с точки зрения объема оперируемых данных. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Например, умножение матрицы размера &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;n\times n&amp;lt;/math&amp;gt; на вектор длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; требует: &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;n^2+(n-1)n = 2n^2-n&amp;lt;/math&amp;gt; операций умножения и сложения. В свою очередь аналогичная операция умножения матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;(n+1)\times (n+1)&amp;lt;/math&amp;gt; на вектор длины &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;(n+1)&amp;lt;/math&amp;gt; требует: &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;2n^2+3n+1&amp;lt;/math&amp;gt;  операций умножения и сложения. То есть повышение размерности задачи всего на 1 увеличивает число необходимых действий в этом шаге алгоритма на: &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;4n+1&amp;lt;/math&amp;gt;. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Так же, стоит помнить, что, согласно разделу 1.2, данную операцию умножения матрицы на вектор необходимо выполнить &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;k&amp;lt;/math&amp;gt; раз. Нетрудно понять, насколько возрастает и колоссален масштаб операций, если в задачах, где критична точность, размерности &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; могут иметь порядок &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;10^5&amp;lt;/math&amp;gt; или даже более.&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
Как уже было упомянуто в данной статье в описании алгоритма, рассматриваемый алгоритм состоит из двух последовательно выполненных алгоритмов: метод Ланцоша для построения последовательности подпространств Крылова и ортонормированных векторов Ланцоша и процедура Рэлея-Ритца получения оптимальных приближений собственных значений и соответствующих собственных векторов исходной матрицы.&lt;br /&gt;
&lt;br /&gt;
В первой части алгоритма, где итерационно строятся Крыловское подпространство и трёхдиагональная матрица &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&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 style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; разреженная. Именно она подлежит оптимизации с использованием техник распараллеливания, поскольку она является вычислительным ядром алгоритма, а весь упомянутый процесс построения матрицы &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&amp;lt;/math&amp;gt; выполняется последовательно.&lt;br /&gt;
&lt;br /&gt;
Рассмотрим вторую часть алгоритма - поиск собственных значений сформированной матрицы &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&amp;lt;/math&amp;gt;.&amp;lt;br&amp;gt;&lt;br /&gt;
Далее, наглядно, в виде псевдокода, представлен, упомянутый в разделе 1.2, QR-алгоритм (аналогично можно рассмотреть и QL-алгоритм) со сдвигами Релэя, который весьма популярен на практике.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{align}&lt;br /&gt;
\mathbf{Input}: \;&amp;amp;tridiagonal\;\;matrix \;T\;with\;\;n\times n\;\;size\\&lt;br /&gt;
T^{(0)}&amp;amp;:=T\\&lt;br /&gt;
\mathbf{for}&amp;amp; \;\;m=n,...,2 \;\; \mathbf{do}\\&lt;br /&gt;
&amp;amp;k=0\\&lt;br /&gt;
&amp;amp; \mathbf{repeat}\\&lt;br /&gt;
&amp;amp; \quad \;\; k=k+1\\&lt;br /&gt;
&amp;amp; \quad \;\; \mu^{(k)}=T_{m,m}^{(k-1)}\\&lt;br /&gt;
&amp;amp; \quad \;\; Q^{(k)}R^{(k)}=T^{(k-1)}-\mu^{(k)}I\;\;using\;\;QR\;decomposition\\&lt;br /&gt;
&amp;amp; \quad \;\; T^{(k)}=R^{(k)}Q^{(k)}+\mu^{(k)}I\\&lt;br /&gt;
&amp;amp; \mathbf{until} \;\;\; |T_{m,m-1}^{(k)}| \;is\;\;small\;\;enough\\&lt;br /&gt;
&amp;amp; Save  \;\;T_{m,m}^{(k)} \;\;as\;\; converged\;\;eigenvalue\;of\;T\\ &lt;br /&gt;
&amp;amp; Remove \;\boldsymbol{n}\,th\;row\;and\;\boldsymbol{n}\,th\;column\;\;from \;T \\&lt;br /&gt;
&amp;amp; and\;take\;this\;new\;cropped\;matrix\;as\;new\;T^{(0)}\;with\;\;(n-1)\times (n-1)\;\;size\\&lt;br /&gt;
 \mathbf{end}&amp;amp;\; \mathbf{for}&lt;br /&gt;
\end{align}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Малость наддиагональных и поддиагональных элементов матрицы (фраза &#039;&#039;&amp;quot;small enough&amp;quot;&#039;&#039; в псевдокоде) подразумевает:&lt;br /&gt;
&amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt; |T_{m,m-1}^{(k)}| \leq \varepsilon\,|T_{m,m}^{(k)}| \quad\quad &amp;lt;/math&amp;gt; , где &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt; \varepsilon &amp;lt;/math&amp;gt; - заданная точность&amp;lt;br&amp;gt;&lt;br /&gt;
Также вместо сдвига Релэя, обозначенного в алгоритме через &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;\mu^{(k)}&amp;lt;/math&amp;gt;, часто на практике используется сдвиг по Уилкинсону, который даёт гарантированную сходимость внедиагональных элементов матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt; T^{(k)} &amp;lt;/math&amp;gt;, формируемой на каждом шаге, к нулю, при этом жертвуя монотонностью их убывания.&amp;lt;ref&amp;gt;Голуб Дж., Ван Лоун Ч. - Матричные вычисления//М.: Мир. - 1999 (c. 378, вторая половина страницы)&amp;lt;/ref&amp;gt;&amp;lt;ref&amp;gt;Парлетт Б. Симметричная проблема собственных значений. Численные методы.,: Мир, 1983. с. 169&amp;lt;/ref&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Подробнее с различными сдвигами и соответствующими оценками скоростей и количествами операций можно ознакомиться по указанной ссылке:&amp;lt;ref&amp;gt;Парлетт Б. Симметричная проблема собственных значений. Численные методы.,: Мир, 1983. с. 179-182&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;Для совершения QR-декомпозиции на каждом шаге может использоваться любой из алгоритмов по ссылке.&amp;lt;ref&amp;gt;https://en.wikipedia.org/wiki/QR_decomposition&amp;lt;/ref&amp;gt; Подробные описания этих алгоритмов также доступны на данном ресурсе algowiki-project.&amp;lt;br&amp;gt;&lt;br /&gt;
Так как мы оперируем не обычной матрицей и даже не Хессенберговой, а симметричной и трёхдиагональной, то скорость таких алгоритмов значительно возрастёт. Например, согласно данному ресурсу &amp;lt;ref&amp;gt;http://algorithm.narod.ru/ln/eigen/ETridiag.html&amp;lt;/ref&amp;gt;, для QL-алгоритма с неявными сдвигами:&amp;lt;br&amp;gt;&lt;br /&gt;
Для трёхдиагональной матрицы объем арифметических действий составляет &amp;lt;math&amp;gt; O(n)&amp;lt;/math&amp;gt; на одну итерацию вместо &amp;lt;math&amp;gt; O(n^3)&amp;lt;/math&amp;gt; для матрицы общего вида, а число итераций для нахождения первых собственных значений примерно равно 4 - 5. Но на этих итерациях также уменьшаются внедиагональные элементы правого нижнего угла. И, таким образом, дальнейшие собственные значения ищутся значительно быстрее. Среднее число итераций на каждое собственное значение обычно составляет 1.3 - 1.6.&amp;lt;br&amp;gt; &lt;br /&gt;
Аналогично QL, QR-разложение трёхдиагольной матрицы также требует &amp;lt;math&amp;gt; O(n)&amp;lt;/math&amp;gt; флопов&amp;lt;ref&amp;gt;Голуб Дж., Ван Лоун Ч. - Матричные вычисления//М.: Мир. - 1999 (c. 378, начало раздела 8.2.2)&amp;lt;/ref&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Подводя итог, во второй части алгоритма Ланцоша можно выделить следующие макрооперации:&lt;br /&gt;
* умножение матрицы на вещественное число;&lt;br /&gt;
* перемножение матриц;&lt;br /&gt;
* умножение и сравнение вещественных чисел;&lt;br /&gt;
* + набор других макроопераций в зависимости от выбора метода, с помощью которого будет совершаться сама QR или QL-декомпозиция (выше продемонстрированы, уже, как минимум, 3 разных способа).&lt;br /&gt;
Так же, важно заметить, что набор макропераций может быть несколько другим, если выбрать какой-либо иной современный метод поиска собственных чисел трёхдиагональной матрицы, не использующий QR и QL разложения(факторизацию). Два таких метода были упомянуты в пункте 1.2.&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
С целью полностью не дублировать раздел 1.2 данной статьи, где представлен наглядный и доступный для понимания псевдокод алгоритма, постараемся лишь коротко просуммировать и обобщить весь перечень последовательных действий в рассматриваемом алгоритме.&lt;br /&gt;
&lt;br /&gt;
В качестве входных данных имеем: вещественная симметричная матрица &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; размера &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;n\times n&amp;lt;/math&amp;gt;, известный вещественный вектор &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;b&amp;lt;/math&amp;gt; длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; и число &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;n&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Далее:&lt;br /&gt;
* Инициализируем вещественную константу &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;\beta_0&amp;lt;/math&amp;gt; и векторы &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;q_0&amp;lt;/math&amp;gt; и &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;q_1&amp;lt;/math&amp;gt;&lt;br /&gt;
* Итерационно для всех &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j=1,...,k&amp;lt;/math&amp;gt;:&lt;br /&gt;
** Вычисляем вспомогательный вектор &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt;, используя умножение матрицы на вектор&lt;br /&gt;
** Вычисляем, используя скалярное произведение векторов, значение &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;\alpha_j&amp;lt;/math&amp;gt; - элемент на главной диагонали трёхдиагональной матрицы &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&amp;lt;/math&amp;gt;&lt;br /&gt;
** Вычисляем по формуле новое значение и перезаписываем вектор &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt;&lt;br /&gt;
** Вычисляем значение &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;\beta_j&amp;lt;/math&amp;gt; - элементы непосредственно над и под главной диагональю той же матрицы &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&amp;lt;/math&amp;gt;&lt;br /&gt;
** Вычисляем, зная вектор &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt;,  очередной столбец матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;Q&amp;lt;/math&amp;gt;, он же вектор Ланцоша : &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;\,\,q_{j+1}&amp;lt;/math&amp;gt;&lt;br /&gt;
** Теперь, когда матрица &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&amp;lt;/math&amp;gt; сформирована на очередном шаге, находим её собственные значения и вектора любым доступным способом, о чём было подробно сказано в пункте 1.2&lt;br /&gt;
** Переходим на следующую итерацию: &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j&amp;lt;/math&amp;gt;++&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
Оценим количество операций и сложность последовательного алгоритма, изложенного в предыдущем разделе.&lt;br /&gt;
*Для вычисления вектора &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt; умножается матрица размера &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;n\times n&amp;lt;/math&amp;gt; на вектор длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt;, и потребуется &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n^2&amp;lt;/math&amp;gt; операций умножения и &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n^2&amp;lt;/math&amp;gt; операций сложения.&lt;br /&gt;
*Умножение векторов &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;q^T_j&amp;lt;/math&amp;gt; и &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt; длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; потребует &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; операций умножения и &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; операций сложения.&lt;br /&gt;
*При вычислении нового значения вектора &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt; поэлементное сложение двух векторов длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; требует &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; операций сложения.&lt;br /&gt;
*Умножение вектора длины &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; на вещественное число требует &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; операций умножения.&lt;br /&gt;
*Нахождение квадратичной нормы вектора &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt;  длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; требует &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; умножений и &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; сложений и ещё 1 операцию извлечения квадратного корня.&lt;br /&gt;
*Заключительное нахождение собственных значений и собственных векторов трёхдиагональной матрицы &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;T_j&amp;lt;/math&amp;gt; размера &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j\times j&amp;lt;/math&amp;gt; с помощью QR-алгоритма потребует в худшем случае &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(j^3)&amp;lt;/math&amp;gt; операций.&amp;lt;ref&amp;gt;http://num-anal.srcc.msu.ru/lib_na/int_ae/int_ae6.htm (пункт 6.2, &amp;quot;Скорость сходимости при этом всегда не хуже квадратичной и почти всегда лучше кубической.&amp;quot;)&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Посчитаем теперь суммарное количество простейших операций на одной итерации алгоритма (без учёта записей в память):&lt;br /&gt;
*&amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n^2+5\,n&amp;lt;/math&amp;gt; операций умножения/деления&lt;br /&gt;
*&amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n^2+4\,n&amp;lt;/math&amp;gt; операций сложения/вычитания&lt;br /&gt;
*1 операция извлечения квадратного корня&amp;lt;br&amp;gt;&lt;br /&gt;
Отдельно после всех итераций при &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j=k&amp;lt;/math&amp;gt; :&lt;br /&gt;
*&amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(k^3)&amp;lt;/math&amp;gt; операций для поиска собственных значений и собственных векторов трёхдиагональной матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_k&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Итого можно утверждать следующее:&lt;br /&gt;
&lt;br /&gt;
Последовательная сложность одной итерации рассматриваемого алгоритма:  &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(n ^ 2) &amp;lt;/math&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Суммарная сложность алгоритма (&amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;/math&amp;gt; итераций): &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(k\,n ^ 2) + O(k ^ 3)&amp;lt;/math&amp;gt; &amp;lt;ref&amp;gt;Здесь мы полагаем, что мы не вычисляем собственные значения и векторы матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_j&amp;lt;/math&amp;gt; на каждом промежуточном шаге, а лишь единожды затрачиваем &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;O(k ^ 3)&amp;lt;/math&amp;gt; действий в конце для нахождения &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;/math&amp;gt; собственных значений и векторов матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_k&amp;lt;/math&amp;gt;&amp;lt;/ref&amp;gt; &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
На практике же обычно рассматривается число &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;&amp;lt;n&amp;lt;/math&amp;gt;, поэтому второе слагаемое можно опустить.&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
На рис. 1 продемонстрирован граф одной итерации (при каком-либо произвольном значении итератора &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j&amp;lt;/math&amp;gt;) описанного алгоритма без отображения входных и выходных данных. Наглядно продемонстрированы связи между всеми действиями, и с помощью деления на &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; потоков показано, какие операции возможно выполнять параллельно на каждом шаге с целью оптимизации и экономии машинного времени. В результате, после параллельно выполненных операций &#039;&#039;&#039;Division&#039;&#039;&#039; на заключительном ярусе, на выходе имеем значение следующего вектора Ланцоша &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;q_{j+1}&amp;lt;/math&amp;gt;, после чего следует переход на следующую итерацию, и процесс повторяется.&lt;br /&gt;
&lt;br /&gt;
[[Файл:Levin_graph.png|600px|thumb|center|Рис. 1  Структура одной итерации алгоритма]] &amp;lt;br&amp;gt;&lt;br /&gt;
Обозначения на рисунке: &amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Simp&#039;&#039;&#039; (от англ. simple) - операции сложения и умножения вещественных чисел при вычислении произведения матрицы на вектор;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Vec mult&#039;&#039;&#039; (от англ. vectors multiplication) - операция скалярного умножения двух векторов;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Vec subtr&#039;&#039;&#039; (от англ. vectors subtraction, из-за использованных в операции вычитаний векторов) - операция умножения вектора на число (выполняется дважды) и формирование нового значения &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;z_{new}&amp;lt;/math&amp;gt; по формуле: &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;z_{new} = z - \alpha_j q_j - \beta_{j-1}q_{j-1} \;&amp;lt;/math&amp;gt;;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;||\cdot||&amp;lt;/math&amp;gt; - операция вычисления нормы вектора;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Division&#039;&#039;&#039; - операция деления вектора на вещественное число  &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;\beta_j&amp;lt;/math&amp;gt; &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Важно отметить, что упомянутые выше операции также легко поддаются оптимизации. Например, попарные умножения вещественных координат векторов при вычислении скалярного произведения также легко выполняются параллельно на &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; потоках, а затем можно применить суммирование методом сдваивания, о котором сказано в следующем разделе. Умножение или деление вектора на вещественное число являющееся, по определению, умножением или делением всех его координат на это число тоже может быть выполнено эффективнее, если мы используем &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; потоков, а не выполняем эти действия последовательно.&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
Параллельные операции возможны только внутри итераций, так как рассматриваемый алгоритм является итерационным, и сами итерации строго последовательны.&amp;lt;br&amp;gt;&lt;br /&gt;
Рассмотрим в этом разделе подробнее, какой выигрыш мы можем получить при распараллеливании операций внутри одной итерации согласно графу из предыдущего раздела.&lt;br /&gt;
&lt;br /&gt;
Умножение вещественной симметричной матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; размера &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;n\times n&amp;lt;/math&amp;gt; на вектор &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;b&amp;lt;/math&amp;gt; длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; требует последовательного выполнения &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; ярусов умножений и сложений. Сложение элементов вектора длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; на каждом шаге перемножения можно оптимизировать и выполнить за &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;\log_2 n&amp;lt;/math&amp;gt; действий, если применять метод сдваивания.&lt;br /&gt;
&lt;br /&gt;
Дальнейшие операции выполняются последовательно, а вычисление значений векторов происходит за один ярус операций сложения или умножения.&lt;br /&gt;
&lt;br /&gt;
Ресурс параллелизма алгоритма вычисления собственных значений построенной трёхдиагональной матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_k&amp;lt;/math&amp;gt; размера &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k\times k&amp;lt;/math&amp;gt; зависит от выбранного алгоритма (об этих алгоритмах подробнее было сказано в разделах 1.2 и 1.4). Будет очень затратно с точки зрения объёма материала пытаться рассмотреть пусть даже часть этих методов в этой статье, а так же тонкости их распараллеливания. Предлагаем читателям при желании самим ознакомиться с этими алгоритмами на данном ресурсе или прибегнув к иным источникам.&lt;br /&gt;
&lt;br /&gt;
При классификации по высоте ЯПФ, таким образом, алгоритм Ланцоша без переортогонализации относится к алгоритмам с &#039;&#039;логарифмической сложностью&#039;&#039;, и его сложность равна &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(\log_2 n)&amp;lt;/math&amp;gt; с важным замечанием, что это сложность только одной итерации, а максимум в алгоритме может быть выполнено последовательно &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;/math&amp;gt; таких однотипных итераций, если не будет осуществлён ранний выход из цикла. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Несмотря на то, что на графе в предыдущем разделе для лучшей визуализации и понимания было изображено &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; потоков (никаких допущений мы не делали и нарушений с точки зрения логики и математики нет, можно изобразить большее число потоков, просто часть времени некоторые из них могут бездействовать и не использоваться), на самом деле правильным и разумным будет реализовать начальное параллельное выполнение &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n^2&amp;lt;/math&amp;gt; операций умножения всех вещественных элементов матрицы &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;A&amp;lt;/math&amp;gt; на соответствующие элементы вектора &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;q_j&amp;lt;/math&amp;gt;, после чего применять тот же самый упомянутый метод сдваивания. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Поэтому при классификации по ширине ЯПФ его сложность будет &#039;&#039;квадратичной&#039;&#039; и равна &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(n^2)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
&#039;&#039;&#039;Входные данные алгоритма:&#039;&#039;&#039; вещественная симметричная &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; размера &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;n\times n&amp;lt;/math&amp;gt;, вещественный вектор &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;b&amp;lt;/math&amp;gt; длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt;, и одно целое число &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;k&amp;lt;/math&amp;gt;, означающее количество итераций.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём входных данных:&#039;&#039;&#039; &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;n^2 +n + 1 &amp;lt;/math&amp;gt;. Если учесть, что матрица симметричная и достаточно для её однозначного определения задать элементы на главной диагонали и элементы над или под ней, то можно сократить объём входных данных с целью экономии памяти до: &amp;lt;math&amp;gt;\ \frac{n^2-n}{2}+n+n+1 =\frac{n^2+3n}{2} + 1&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные алгоритма:&#039;&#039;&#039; вектор собственных значений &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;\Theta^k&amp;lt;/math&amp;gt; длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;/math&amp;gt;, матрица &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;S^k&amp;lt;/math&amp;gt; из соответствующих собственных векторов размера &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n\times k&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём выходных данных:&#039;&#039;&#039; &amp;lt;math&amp;gt;k\;(n + 1)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
В данном разделе перечислены без какой-либо хронологии или связи друг с другом наиболее важные и разнообразные свойства алгоритма, на которые стоит и полезно обратить внимание, а также которые выгодно отличают его от схожих алгоритмов, решающих ту же задачу.&amp;lt;br&amp;gt;&lt;br /&gt;
1) Отношение последовательной сложности алгоритма к параллельной,с учётом &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;/math&amp;gt; итераций, равно &amp;lt;math&amp;gt;\;\;\frac{kn^2}{k \log_2{n}}=\frac{n^2}{\log_2{n}}&amp;lt;/math&amp;gt;;&amp;lt;br&amp;gt;&lt;br /&gt;
2) Вычислительная мощность алгоритма, как отношение числа операций к суммарному объему входных и выходных данных, равна &amp;lt;math style=&amp;quot;vertical-align:-70%&amp;gt;\;\;\frac{k\,n^2}{0.5\,n^2+1.5\,n+k\,n+k+1}&amp;lt;/math&amp;gt; и &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;\approx 2\,k&amp;lt;/math&amp;gt;, так как на практике верно отношение &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;&amp;lt;n&amp;lt;/math&amp;gt; ;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
3) Для собственных значений формируемых матриц &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_j&amp;lt;/math&amp;gt; верно отношение (следствие теоремы Коши о перемежаемости): &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;\lambda_i(T_{k+1})\geq \lambda_i(T_{k})\geq \lambda_{i+1}(T_{k+1})\geq \lambda_{i+1}(T_{k})&amp;lt;/math&amp;gt; ;&amp;lt;ref&amp;gt;James W. Demmel - Вычислительная линейная алгебра. Теория и приложения //Мир. - 2001 (c. 383)&amp;lt;/ref&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
4) Крайние (наибольшие и наименьшие) собственные значения матриц &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_j&amp;lt;/math&amp;gt; сходятся к крайним собственным значениям матрицы &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;A&amp;lt;/math&amp;gt; первыми (это часто происходит уже на ранних шагах при &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j\approx 2\,\sqrt{n}&amp;lt;/math&amp;gt;&amp;lt;ref&amp;gt;http://num-anal.srcc.msu.ru/lib_na/int_ae/int_ae6.htm (пункт 6.5)&amp;lt;/ref&amp;gt;), а собственные значения в середине спектра - последними;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
5) Из-за ограниченной точности постепенно теряется ортогональность вектора Ланцоша &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;q_j&amp;lt;/math&amp;gt; к предыдущим векторам Ланцоша, поэтому необходимо примерно каждые 10-15 итераций проводить дорогостоящую операцию реортогонализации, но это уже будет иной алгоритм с очень малым различием в одной операции и в программном коде, реализующем его, соответственно; &amp;lt;ref&amp;gt;Sam Handler - The Lanczos Algorithm For Large-Scale Eigenvalue Problems (08.01.07), slide №8&amp;lt;/ref&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
6) Эффективность и быстрота выполнения алгоритма очень сильно зависит от скорости памяти (диска). Согласно тесту только &#039;&#039;6%&#039;&#039; времени работы программы приходится на вычисления, остальное время затрачивается на ожидание отклика диска;&amp;lt;ref&amp;gt;Sam Handler - The Lanczos Algorithm For Large-Scale Eigenvalue Problems (08.01.07), slide №10&amp;lt;/ref&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
7) Метод Ланцоша удобен тем, что не требует хранения исходной матрицы полным массивом: метод использует исходную матрицу только в операциях умножения матрицы на вектор, что позволяет эффективно использовать разреженность матрицы или регулярность структуры матрицы. Поэтому метод Ланцоша может быть использован для матриц таких больших порядков, когда методы вращений и отражений не могут быть применены.&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;
Для исследования масштабируемости рассматриваемого алгоритма Ланцоша без переортогонализации автором была реализована программа на языке С++ с использованием технологии MPI. &amp;lt;ref&amp;gt;https://goo.gl/dGfzOD  или альтернативная ссылка с прикреплённым кодом: https://goo.gl/lFziv0 , по просьбе на почту я (автор статьи) готов предоставить желающим доступ к проекту с этим кодом на ресурсе Bitbucket&amp;lt;/ref&amp;gt; Дальнейшее исследование было проведено на суперкомпьютере &amp;quot;Ломоносов&amp;quot; Суперкомпьютерного комплекса МГУ. &amp;lt;br&amp;gt; Важно отметить, что реализованная программа выполняет только первую часть алгоритма - формирование матрицы &amp;lt;math &amp;gt;T_j&amp;lt;/math&amp;gt;. Вторая часть алгоритма (задача поиска собственных значений матрицы &amp;lt;math &amp;gt;T_j&amp;lt;/math&amp;gt;) может быть решена несколькими методами, каждый из которых обладает своей эффективностью распараллеливании и характерными свойствами. Подробно этот вопрос уже обсуждался в статье раннее, поэтому не будем ещё раз заострять на этом внимание и останавливаться.&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Сборка осуществлялась со следующими параметрами:&lt;br /&gt;
* Компилятор intel/15.0.090 &lt;br /&gt;
* Openmpi/1.8.4-icc&lt;br /&gt;
В серии проведённых расчётов рассматривались следующие числовые значения параметров:&lt;br /&gt;
* Размер &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;n&amp;lt;/math&amp;gt; задачи и, соответственно, матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt;, задействованной в операции умножения на вектор: [2000 : 30000] с шагом 1000&lt;br /&gt;
* Число процессоров: 1, 2, 4, 16, 32, 48, 64, 96, 128&lt;br /&gt;
* Число итераций в алгоритме: &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k=350&amp;lt;/math&amp;gt;&lt;br /&gt;
Число &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; взято таким вопреки информации в начале статьи, где говорится, что значение &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; редко превышает &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;10^2&amp;lt;/math&amp;gt; (хоть мы и имеем право брать его любым по нашему усмотрению). Это сделано исключительно для лучшей визуализации пиков на графиках в данном разделе и наглядности получаемых результатов, так как при меньших на порядок значениях параметра &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; времена выполнения программ были слишком малы даже при минимальных числах процессоров и максимальных размерах &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;n&amp;lt;/math&amp;gt; задачи.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
На рис. 2 изображён график зависимости времени выполнения программы от числа процессоров и размера &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;n&amp;lt;/math&amp;gt; задачи.&lt;br /&gt;
&lt;br /&gt;
== Динамические характеристики и эффективность реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Выводы для классов архитектур ==&lt;br /&gt;
По заданию, во второй части требовалось описать только разделы 2.4 и 2.7, прошу не спрашивать с меня все разделы 2.1-2.6. Надеюсь на понимание, мне физически не хватает времени на это задание + 2 других в течение семестра, делаю всё, что в моих силах :)&lt;br /&gt;
&lt;br /&gt;
== Существующие реализации алгоритма ==&lt;br /&gt;
Несмотря на то, что алгоритм является далеко не самым популярным, алгоритмом, про который нельзя сказать, что он всегда «на слуху», на сегодняшний день существует множество реализаций на различных популярных языках.&amp;lt;br&amp;gt;&lt;br /&gt;
Перечислим далее некоторые из них, указывая язык программирования, лежащий в их основе, и некоторые важные характеристики, которые обсуждались в статье ранее:&lt;br /&gt;
*&#039;&#039;Code on netlib.org by Jane Cullum and Ralph Willoughby&#039;&#039; (&#039;&#039;&#039;Fortran 77&#039;&#039;&#039;; без реортогонализации векторов; без реализации распараллеливания)&amp;lt;ref&amp;gt;http://www.netlib.org/lanczos/leval&amp;lt;/ref&amp;gt;&lt;br /&gt;
*&#039;&#039;Lanczos algorithm on freesourcecode.net&#039;&#039; (&#039;&#039;&#039;Matlab&#039;&#039;&#039;; присутствует реортогонализация векторов; без реализации распараллеливания)&amp;lt;ref&amp;gt;http://freesourcecode.net/matlabprojects/61741/lanczos-algorithm--in-matlab&amp;lt;/ref&amp;gt;&lt;br /&gt;
*&#039;&#039;Lanczos for eigenvalues in Numerical Linear Algebra, Spring 2007&#039;&#039; (&#039;&#039;&#039;Matlab&#039;&#039;&#039;; частичная или полная реортогонализация - доступны оба варианта; без реализации распараллеливания)&amp;lt;ref&amp;gt;Ссылки на файлы lanso.m и lanfu.m можно найти на https://www.nada.kth.se/~ruhe/2D5219/labs2007.html&amp;lt;/ref&amp;gt;&lt;br /&gt;
*&#039;&#039;Planso&#039;&#039; (название происходит от parallel Lanso.f) &#039;&#039;code by Kesheng Wu and Horst D. Simon&#039;&#039; (&#039;&#039;&#039;Fortran 77&#039;&#039;&#039;; частичная реортогонализация векторов; использование MPI для коммуникаций)&amp;lt;ref&amp;gt;https://github.com/jiahao/planso.jl/tree/master/external/PLAN/plan К сожалению, ссылка в описании пакета на github, ведущая на сайт National Energy Research Scientific Computing Center (NERSC), с более подробной информацией о данной программе больше не активна и выдаёт результат &#039;&#039;Page not found&#039;&#039;&amp;lt;/ref&amp;gt; &lt;br /&gt;
* &#039;&#039;Lanczos.cpp in the Vienna Computing Library&#039;&#039;  (&#039;&#039;&#039;C++&#039;&#039;&#039;, частичная реортогонализация, без реализации распараллеливания) &amp;lt;ref&amp;gt;http://viennacl.sourceforge.net/doc/lanczos_8cpp_source.html&amp;lt;/ref&amp;gt;&lt;br /&gt;
* &#039;&#039;Parallel Eigen Values code using C++ AMP on microsoft msdn blog&#039;&#039; (&#039;&#039;&#039;C++&#039;&#039;&#039;; ? ; распараллеливание есть и реализовано через C++ AMP) &amp;lt;ref&amp;gt;https://blogs.msdn.microsoft.com/nativeconcurrency/2013/12/20/eigen-values/ Подробнее о C++ Accelerated Massive Parallelism можно почитать здесь: https://msdn.microsoft.com/ru-ru/library/hh265137(v=vs.140).aspx или здесь: http://professorweb.ru/my/csharp/optimization/level4/4_6.php &amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;br /&gt;
[[en:Description of algorithm properties and structure]]&lt;/div&gt;</summary>
		<author><name>AleksLevin</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:AleksLevin/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%9B%D0%B0%D0%BD%D1%86%D0%BE%D1%88%D0%B0_%D0%B2%D1%8B%D1%87%D0%B8%D1%81%D0%BB%D0%B5%D0%BD%D0%B8%D1%8F_%D1%81%D0%BE%D0%B1%D1%81%D1%82%D0%B2%D0%B5%D0%BD%D0%BD%D1%8B%D1%85_%D0%B7%D0%BD%D0%B0%D1%87%D0%B5%D0%BD%D0%B8%D0%B9_%D1%81%D0%B8%D0%BC%D0%BC%D0%B5%D1%82%D1%80%D0%B8%D1%87%D0%BD%D0%BE%D0%B9_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86%D1%8B_%D0%B4%D0%BB%D1%8F_%D1%82%D0%BE%D1%87%D0%BD%D0%BE%D0%B9_%D0%B0%D1%80%D0%B8%D1%84%D0%BC%D0%B5%D1%82%D0%B8%D0%BA%D0%B8_(%D0%B1%D0%B5%D0%B7_%D0%BF%D0%B5%D1%80%D0%B5%D0%BE%D1%80%D1%82%D0%BE%D0%B3%D0%BE%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D0%B8)&amp;diff=20222</id>
		<title>Участник:AleksLevin/Алгоритм Ланцоша вычисления собственных значений симметричной матрицы для точной арифметики (без переортогонализации)</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:AleksLevin/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%9B%D0%B0%D0%BD%D1%86%D0%BE%D1%88%D0%B0_%D0%B2%D1%8B%D1%87%D0%B8%D1%81%D0%BB%D0%B5%D0%BD%D0%B8%D1%8F_%D1%81%D0%BE%D0%B1%D1%81%D1%82%D0%B2%D0%B5%D0%BD%D0%BD%D1%8B%D1%85_%D0%B7%D0%BD%D0%B0%D1%87%D0%B5%D0%BD%D0%B8%D0%B9_%D1%81%D0%B8%D0%BC%D0%BC%D0%B5%D1%82%D1%80%D0%B8%D1%87%D0%BD%D0%BE%D0%B9_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86%D1%8B_%D0%B4%D0%BB%D1%8F_%D1%82%D0%BE%D1%87%D0%BD%D0%BE%D0%B9_%D0%B0%D1%80%D0%B8%D1%84%D0%BC%D0%B5%D1%82%D0%B8%D0%BA%D0%B8_(%D0%B1%D0%B5%D0%B7_%D0%BF%D0%B5%D1%80%D0%B5%D0%BE%D1%80%D1%82%D0%BE%D0%B3%D0%BE%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D0%B8)&amp;diff=20222"/>
		<updated>2016-12-07T00:30:56Z</updated>

		<summary type="html">&lt;p&gt;AleksLevin: /* Масштабируемость алгоритма и его реализации */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Основные авторы описания: Левин А.Д.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{algorithm&lt;br /&gt;
| name              = Алгоритм Ланцоша для точной арифметики (без переортогонализации)&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(k\,n^2)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(k\log_2 n)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;\frac{n^2+3n}{2} + 1&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;k\;(n + 1)&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритмов =&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Данный алгоритм появился в 1950 г. и носит имя венгерского физика и математика Корнелия Ланцоша (венг. Lánczos Kornél). Алгоритм Ланцоша относится к итерационным методам вычисления собственных значений для матриц столь больших порядков &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt; n&amp;lt;/math&amp;gt;, что к ним нельзя применить прямые методы из-за ограничений по времени и памяти.&lt;br /&gt;
&lt;br /&gt;
Сам Ланцош указывал, что его метод предназначен для отыскания нескольких собственных векторов симметричных матриц, хотя к методу сразу было обращено внимание, как к способу приведения всей матрицы к трёхдиагональному виду. Двадцатью годами позже канадский математик Крис Пэж показал, что, несмотря на чувствительность к округлениям, алгоритм Ланцоша - эффективное средство вычисления некоторых &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; собственных чисел и соответствующих им собственных векторов. &amp;lt;ref&amp;gt;Парлетт Б. - Симметричная проблема собственных значений. Численные методы //М.: Мир. - 1983. (c. 276)&amp;lt;/ref&amp;gt;&lt;br /&gt;
Обычно число &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; берут в два раза больше, чем количество собственных значений матрицы, которые поставлена цель найти, и оно имеет порядок не более &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;10^2&amp;lt;/math&amp;gt;.&amp;lt;ref&amp;gt;Susan W. Bostic - Lanczos Eigensolution Method for High-Perfomance Computers, page 7&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Алгоритм Ланцоша для вычисления собственных значений симметричной матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; соединяет в себе метод Ланцоша для построения последовательности подпространств Крылова и ортонормированных векторов Ланцоша и процедуру Рэлея-Ритца получения оптимальных приближений собственных значений и соответствующих собственных векторов исходной матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt;.&amp;lt;ref&amp;gt;James W. Demmel - Вычислительная линейная алгебра. Теория и приложения //Мир. - 2001 (c. 381)&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
В данной статье рассматривается вариант алгоритма Ланцоша, в котором опущено влияние ошибок округления на вычислительный процесс, хотя на практике этому посвящается отдельное внимание и существуют различные методы решения данной проблемы, такие как частичная или полная переортогонализация. Этим модифицированным методам посвящены отдельные статьи на данном ресурсе.&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
Обозначения и формулы, используемые в данном разделе, взяты из литературы, указанной по ссылке.&amp;lt;ref&amp;gt;James W. Demmel - Вычислительная линейная алгебра. Теория и приложения //Мир. - 2001 (c. 313, &#039;&#039;&amp;lt;math&amp;gt; \S &amp;lt;/math&amp;gt; 6.6 Методы Крыловского подпространства&#039;&#039;)&amp;lt;/ref&amp;gt; &lt;br /&gt;
&lt;br /&gt;
Алгоритм Ланцоша для вычисления &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; собственных значений и собственных векторов вещественной симметричной матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A=A^T&amp;lt;/math&amp;gt; в точной арифметике: &amp;lt;ref&amp;gt;James W. Demmel - Вычислительная линейная алгебра. Теория и приложения //Мир. - 2001 (c. 381)&amp;lt;/ref&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{align}&lt;br /&gt;
q_1 = &amp;amp; \,\frac{b}{\|b\|_2},\; \beta_0 = 0,\; q_0 = 0\\&lt;br /&gt;
\mathbf{for} \; &amp;amp; j = 1 \; to \; k \,\; \mathbf{do} \\&lt;br /&gt;
&amp;amp; z = A\,q_j\\&lt;br /&gt;
&amp;amp; \alpha_j = q^T_j z\\&lt;br /&gt;
&amp;amp; z = z - \alpha_j q_j - \beta_{j-1}q_{j-1}\\&lt;br /&gt;
&amp;amp; \beta_j = \|z\|_2\\&lt;br /&gt;
&amp;amp; \mathbf{If} \; (\beta_j == 0) \; \mathbf{then}\; stop\; the\; algorithm \\ &lt;br /&gt;
&amp;amp; \;  q_{j+1} = \frac{z}{\beta_j} \\&lt;br /&gt;
&amp;amp; compute\; eigenvalues\; and \;eigenvectors\;of \;matrix \;\;T_j= Q^T_j A Q\;\;and\;estimate \;the\; errors\\&lt;br /&gt;
\mathbf{end} \; &amp;amp; \mathbf{for}&lt;br /&gt;
\end{align}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
В продемонстрированном выше алгоритме &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;b&amp;lt;/math&amp;gt; - заданный вещественный вектор. Также полагается известным алгоритм вычисления произведения матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; на вектор &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;x&amp;lt;/math&amp;gt;. &lt;br /&gt;
Введём матрицу Крылова, определяемую следующим соотношением: &amp;lt;math&amp;gt;K_j = [b,Ab,A^2b,...,A^{j-1}b]&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Далее, на практике, матрица &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;K&amp;lt;/math&amp;gt; заменяется матрицей &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;Q&amp;lt;/math&amp;gt;, такой, что при любом числе &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; линейные оболочки первых &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; столбцов в &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;K&amp;lt;/math&amp;gt; и &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;Q&amp;lt;/math&amp;gt; являются одним и тем же подпространством.&amp;lt;ref&amp;gt;James W. Demmel - Вычислительная линейная алгебра. Теория и приложения //Мир. - 2001 (c. 315)&amp;lt;/ref&amp;gt; &lt;br /&gt;
Тогда матрица &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;Q&amp;lt;/math&amp;gt;, в отличие от матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;K&amp;lt;/math&amp;gt;, хорошо обусловлена и легко обратима. В результате получаем матрицу &amp;lt;math&amp;gt;Q_j = [q_1, q_2, \dots, q_j]&amp;lt;/math&amp;gt; размерности &amp;lt;math&amp;gt;n\times j&amp;lt;/math&amp;gt;, столбцы которой ортогональны, являются базисом подпространства Крылова и называются векторами Ланцоша.&lt;br /&gt;
&lt;br /&gt;
В алгоритме Ланцоша вычислению подлежит столько первых столбцов в матрице &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;Q_j&amp;lt;/math&amp;gt;, сколько необходимо для получения требуемого приближения к решению &amp;lt;math&amp;gt;A\,x\,=b\,\,(A\,x=\lambda \, x)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Получение нулевого &amp;lt;math&amp;gt;\beta_j&amp;lt;/math&amp;gt; в итерационном процессе - событие, желательное в том смысле, что оно свидетельствует о том, что найдено некоторое подпространство, являющееся в точности инвариантным, а все собственные значения матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;T_j&amp;lt;/math&amp;gt; являются собственными значениями матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt;. На практике же нулевое и близкие к нулю значения получаются редко.&amp;lt;ref&amp;gt;Голуб Дж., Ван Лоун Ч. - Матричные вычисления//М.: Мир. - 1999 (c. 429)&amp;lt;/ref&amp;gt; &lt;br /&gt;
&lt;br /&gt;
Затем на каждом шаге цикла формируется симметричная трёхдиагональная матрица &amp;lt;math&amp;gt;T_j = Q^T_j A Q&amp;lt;/math&amp;gt;, к которой применяется процесс Рэлея-Ритца для поиска её собственных значений (на практике для поиска этих собственных значений можно использовать любой из специальных методов в параграфе книги по ссылке).&amp;lt;ref&amp;gt;Голуб Дж., Ван Лоун Ч. - Матричные вычисления//М.: Мир. - 1999 (&amp;lt;math&amp;gt;\S&amp;lt;/math&amp;gt; 8.4)&amp;lt;/ref&amp;gt;  &lt;br /&gt;
Эти собственные значения, они же числа Ритца, и полагаются приближёнными собственными значениями исходной матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt;.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Существует множество методов для отыскания собственных значений вещественной симметричной трехдиагональной матрицы. Большинство из них требует &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt; операций &amp;lt;ref&amp;gt;Парлетт Б. Симметричная проблема собственных значений. Численные методы.,: Мир, 1983. с. 179-182&amp;lt;/ref&amp;gt;, но существуют и быстрые алгоритмы, требующие лишь &amp;lt;math&amp;gt;O(n\ln n)&amp;lt;/math&amp;gt; операций.&amp;lt;ref&amp;gt;https://en.wikipedia.org/wiki/Tridiagonal_matrix#Eigenvalues  Раздел eigenvalues&amp;lt;/ref&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Одним из возможных способов отыскать собственные значения симметричной трехдиагональной матрицы - прямое вычисление корней характеристического полинома &amp;lt;math&amp;gt;p_n(\lambda)&amp;lt;/math&amp;gt; через метод деления пополам, где формируется последовательность Штурма и локализуются собственные числа, являющиеся корнями характеристического полинома. Нахождение всех &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; собственных значений матрицы этим способом требует &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;2n^2t&amp;lt;/math&amp;gt; умножений и вычитаний, где &amp;lt;math&amp;gt;t&amp;lt;/math&amp;gt; - число сделанных шагов с применением метода деления пополам.&amp;lt;ref&amp;gt;Уилкинсон Дж. X. Алгебраическая проблема собственныx значений. Изд-во &amp;quot;Наука&amp;quot;, 1970. - глава 5, с. 272-278&amp;lt;/ref&amp;gt; Соответствующие собственные вектора могут быть найдены посредством обратных итераций за &amp;lt;math&amp;gt; O(n) &amp;lt;/math&amp;gt; флопов. &amp;lt;ref&amp;gt;Голуб Дж., Ван Лоун Ч. - Матричные вычисления//М.: Мир. - 1999 (c. 394-395)&amp;lt;/ref&amp;gt; &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;На практике, если требуется только небольшая часть от всей совокупности собственных векторов и значений, и матрица имеет Хессенбергову или трёхдиагональную форму, очень эффективными будут методы факторизации, как, например, QR-алгоритм или QL-алгоритм со сдвигами (c целью ускорить алгоритм и сделать порядок сходимости квадратичным) или же без них.&amp;lt;ref&amp;gt;http://algorithm.narod.ru/ln/eigen/ETridiag.html&amp;lt;/ref&amp;gt; &amp;lt;br&amp;gt;&lt;br /&gt;
Весьма молодые и не менее актуальные конкуренты QR и QL алгоритмов, применяющиеся для поиска собственных значений:&lt;br /&gt;
*Методы divide-and-conquer (разделяй и властвуй), появившиеся в 1980-ых годах &amp;lt;ref&amp;gt;https://goo.gl/dapvbn ссылку пришлось сократить с помощью Google url shortener, так как символы подчеркивания портили её и не давали перейти по 1 клику&amp;lt;/ref&amp;gt;&lt;br /&gt;
*Relatively robust representation методы, появившиеся в 1990-ых и позволяющие найти собственные числа симметричной матрицы порядка &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;n&amp;lt;/math&amp;gt; за &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt; операций&lt;br /&gt;
&lt;br /&gt;
Если требуется вычислить собственные векторы, то необходимо хранить вычисляемые векторы Ланцоша. Если работа при этом производится только с оперативной памятью, то при большом порядке исходной матрицы (а именно для таких матриц и предназначен метод Ланцоша) число шагов  &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;j&amp;lt;/math&amp;gt;, которые могут быть выполнены до того момента, как оперативная память будет исчерпана, будет очень незначительно, а следовательно, искомые собственные пары могут не успеть сойтись с требуемой точностью. В этом случае метод Ланцоша можно использовать итерационным образом: после выполнения заданного числа шагов процесс прерывается и, если еще не все требуемые пары Ритца сошлись с требуемой точностью, то формируется новый начальный вектор &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;q_1&amp;lt;/math&amp;gt;, являющийся линейной комбинацией векторов Ритца, еще не сошедшихся с заданной точностью, и процесс начинается заново.&amp;lt;ref&amp;gt;http://num-anal.srcc.msu.ru/lib_na/int_ae/int_ae6.htm (пункт 6.5)&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
Вычислительное ядро рассматриваемого алгоритма (наиболее ресурсно-затратная часть алгоритма) -  формирование на каждом шаге цикла промежуточного вектора &amp;lt;math&amp;gt;z&amp;lt;/math&amp;gt;, вычисляемого по формуле: &amp;lt;math&amp;gt;z = A\,q_j&amp;lt;/math&amp;gt;. Данная операция, по сравнению с другими операциями алгоритма, затратна и требовательна, как с точки зрения количества производимых операций, так и с точки зрения объема оперируемых данных. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Например, умножение матрицы размера &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;n\times n&amp;lt;/math&amp;gt; на вектор длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; требует: &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;n^2+(n-1)n = 2n^2-n&amp;lt;/math&amp;gt; операций умножения и сложения. В свою очередь аналогичная операция умножения матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;(n+1)\times (n+1)&amp;lt;/math&amp;gt; на вектор длины &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;(n+1)&amp;lt;/math&amp;gt; требует: &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;2n^2+3n+1&amp;lt;/math&amp;gt;  операций умножения и сложения. То есть повышение размерности задачи всего на 1 увеличивает число необходимых действий в этом шаге алгоритма на: &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;4n+1&amp;lt;/math&amp;gt;. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Так же, стоит помнить, что, согласно разделу 1.2, данную операцию умножения матрицы на вектор необходимо выполнить &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;k&amp;lt;/math&amp;gt; раз. Нетрудно понять, насколько возрастает и колоссален масштаб операций, если в задачах, где критична точность, размерности &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; могут иметь порядок &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;10^5&amp;lt;/math&amp;gt; или даже более.&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
Как уже было упомянуто в данной статье в описании алгоритма, рассматриваемый алгоритм состоит из двух последовательно выполненных алгоритмов: метод Ланцоша для построения последовательности подпространств Крылова и ортонормированных векторов Ланцоша и процедура Рэлея-Ритца получения оптимальных приближений собственных значений и соответствующих собственных векторов исходной матрицы.&lt;br /&gt;
&lt;br /&gt;
В первой части алгоритма, где итерационно строятся Крыловское подпространство и трёхдиагональная матрица &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&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 style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; разреженная. Именно она подлежит оптимизации с использованием техник распараллеливания, поскольку она является вычислительным ядром алгоритма, а весь упомянутый процесс построения матрицы &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&amp;lt;/math&amp;gt; выполняется последовательно.&lt;br /&gt;
&lt;br /&gt;
Рассмотрим вторую часть алгоритма - поиск собственных значений сформированной матрицы &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&amp;lt;/math&amp;gt;.&amp;lt;br&amp;gt;&lt;br /&gt;
Далее, наглядно, в виде псевдокода, представлен, упомянутый в разделе 1.2, QR-алгоритм (аналогично можно рассмотреть и QL-алгоритм) со сдвигами Релэя, который весьма популярен на практике.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{align}&lt;br /&gt;
\mathbf{Input}: \;&amp;amp;tridiagonal\;\;matrix \;T\;with\;\;n\times n\;\;size\\&lt;br /&gt;
T^{(0)}&amp;amp;:=T\\&lt;br /&gt;
\mathbf{for}&amp;amp; \;\;m=n,...,2 \;\; \mathbf{do}\\&lt;br /&gt;
&amp;amp;k=0\\&lt;br /&gt;
&amp;amp; \mathbf{repeat}\\&lt;br /&gt;
&amp;amp; \quad \;\; k=k+1\\&lt;br /&gt;
&amp;amp; \quad \;\; \mu^{(k)}=T_{m,m}^{(k-1)}\\&lt;br /&gt;
&amp;amp; \quad \;\; Q^{(k)}R^{(k)}=T^{(k-1)}-\mu^{(k)}I\;\;using\;\;QR\;decomposition\\&lt;br /&gt;
&amp;amp; \quad \;\; T^{(k)}=R^{(k)}Q^{(k)}+\mu^{(k)}I\\&lt;br /&gt;
&amp;amp; \mathbf{until} \;\;\; |T_{m,m-1}^{(k)}| \;is\;\;small\;\;enough\\&lt;br /&gt;
&amp;amp; Save  \;\;T_{m,m}^{(k)} \;\;as\;\; converged\;\;eigenvalue\;of\;T\\ &lt;br /&gt;
&amp;amp; Remove \;\boldsymbol{n}\,th\;row\;and\;\boldsymbol{n}\,th\;column\;\;from \;T \\&lt;br /&gt;
&amp;amp; and\;take\;this\;new\;cropped\;matrix\;as\;new\;T^{(0)}\;with\;\;(n-1)\times (n-1)\;\;size\\&lt;br /&gt;
 \mathbf{end}&amp;amp;\; \mathbf{for}&lt;br /&gt;
\end{align}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Малость наддиагональных и поддиагональных элементов матрицы (фраза &#039;&#039;&amp;quot;small enough&amp;quot;&#039;&#039; в псевдокоде) подразумевает:&lt;br /&gt;
&amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt; |T_{m,m-1}^{(k)}| \leq \varepsilon\,|T_{m,m}^{(k)}| \quad\quad &amp;lt;/math&amp;gt; , где &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt; \varepsilon &amp;lt;/math&amp;gt; - заданная точность&amp;lt;br&amp;gt;&lt;br /&gt;
Также вместо сдвига Релэя, обозначенного в алгоритме через &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;\mu^{(k)}&amp;lt;/math&amp;gt;, часто на практике используется сдвиг по Уилкинсону, который даёт гарантированную сходимость внедиагональных элементов матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt; T^{(k)} &amp;lt;/math&amp;gt;, формируемой на каждом шаге, к нулю, при этом жертвуя монотонностью их убывания.&amp;lt;ref&amp;gt;Голуб Дж., Ван Лоун Ч. - Матричные вычисления//М.: Мир. - 1999 (c. 378, вторая половина страницы)&amp;lt;/ref&amp;gt;&amp;lt;ref&amp;gt;Парлетт Б. Симметричная проблема собственных значений. Численные методы.,: Мир, 1983. с. 169&amp;lt;/ref&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Подробнее с различными сдвигами и соответствующими оценками скоростей и количествами операций можно ознакомиться по указанной ссылке:&amp;lt;ref&amp;gt;Парлетт Б. Симметричная проблема собственных значений. Численные методы.,: Мир, 1983. с. 179-182&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;Для совершения QR-декомпозиции на каждом шаге может использоваться любой из алгоритмов по ссылке.&amp;lt;ref&amp;gt;https://en.wikipedia.org/wiki/QR_decomposition&amp;lt;/ref&amp;gt; Подробные описания этих алгоритмов также доступны на данном ресурсе algowiki-project.&amp;lt;br&amp;gt;&lt;br /&gt;
Так как мы оперируем не обычной матрицей и даже не Хессенберговой, а симметричной и трёхдиагональной, то скорость таких алгоритмов значительно возрастёт. Например, согласно данному ресурсу &amp;lt;ref&amp;gt;http://algorithm.narod.ru/ln/eigen/ETridiag.html&amp;lt;/ref&amp;gt;, для QL-алгоритма с неявными сдвигами:&amp;lt;br&amp;gt;&lt;br /&gt;
Для трёхдиагональной матрицы объем арифметических действий составляет &amp;lt;math&amp;gt; O(n)&amp;lt;/math&amp;gt; на одну итерацию вместо &amp;lt;math&amp;gt; O(n^3)&amp;lt;/math&amp;gt; для матрицы общего вида, а число итераций для нахождения первых собственных значений примерно равно 4 - 5. Но на этих итерациях также уменьшаются внедиагональные элементы правого нижнего угла. И, таким образом, дальнейшие собственные значения ищутся значительно быстрее. Среднее число итераций на каждое собственное значение обычно составляет 1.3 - 1.6.&amp;lt;br&amp;gt; &lt;br /&gt;
Аналогично QL, QR-разложение трёхдиагольной матрицы также требует &amp;lt;math&amp;gt; O(n)&amp;lt;/math&amp;gt; флопов&amp;lt;ref&amp;gt;Голуб Дж., Ван Лоун Ч. - Матричные вычисления//М.: Мир. - 1999 (c. 378, начало раздела 8.2.2)&amp;lt;/ref&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Подводя итог, во второй части алгоритма Ланцоша можно выделить следующие макрооперации:&lt;br /&gt;
* умножение матрицы на вещественное число;&lt;br /&gt;
* перемножение матриц;&lt;br /&gt;
* умножение и сравнение вещественных чисел;&lt;br /&gt;
* + набор других макроопераций в зависимости от выбора метода, с помощью которого будет совершаться сама QR или QL-декомпозиция (выше продемонстрированы, уже, как минимум, 3 разных способа).&lt;br /&gt;
Так же, важно заметить, что набор макропераций может быть несколько другим, если выбрать какой-либо иной современный метод поиска собственных чисел трёхдиагональной матрицы, не использующий QR и QL разложения(факторизацию). Два таких метода были упомянуты в пункте 1.2.&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
С целью полностью не дублировать раздел 1.2 данной статьи, где представлен наглядный и доступный для понимания псевдокод алгоритма, постараемся лишь коротко просуммировать и обобщить весь перечень последовательных действий в рассматриваемом алгоритме.&lt;br /&gt;
&lt;br /&gt;
В качестве входных данных имеем: вещественная симметричная матрица &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; размера &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;n\times n&amp;lt;/math&amp;gt;, известный вещественный вектор &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;b&amp;lt;/math&amp;gt; длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; и число &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;n&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Далее:&lt;br /&gt;
* Инициализируем вещественную константу &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;\beta_0&amp;lt;/math&amp;gt; и векторы &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;q_0&amp;lt;/math&amp;gt; и &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;q_1&amp;lt;/math&amp;gt;&lt;br /&gt;
* Итерационно для всех &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j=1,...,k&amp;lt;/math&amp;gt;:&lt;br /&gt;
** Вычисляем вспомогательный вектор &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt;, используя умножение матрицы на вектор&lt;br /&gt;
** Вычисляем, используя скалярное произведение векторов, значение &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;\alpha_j&amp;lt;/math&amp;gt; - элемент на главной диагонали трёхдиагональной матрицы &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&amp;lt;/math&amp;gt;&lt;br /&gt;
** Вычисляем по формуле новое значение и перезаписываем вектор &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt;&lt;br /&gt;
** Вычисляем значение &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;\beta_j&amp;lt;/math&amp;gt; - элементы непосредственно над и под главной диагональю той же матрицы &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&amp;lt;/math&amp;gt;&lt;br /&gt;
** Вычисляем, зная вектор &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt;,  очередной столбец матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;Q&amp;lt;/math&amp;gt;, он же вектор Ланцоша : &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;\,\,q_{j+1}&amp;lt;/math&amp;gt;&lt;br /&gt;
** Теперь, когда матрица &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&amp;lt;/math&amp;gt; сформирована на очередном шаге, находим её собственные значения и вектора любым доступным способом, о чём было подробно сказано в пункте 1.2&lt;br /&gt;
** Переходим на следующую итерацию: &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j&amp;lt;/math&amp;gt;++&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
Оценим количество операций и сложность последовательного алгоритма, изложенного в предыдущем разделе.&lt;br /&gt;
*Для вычисления вектора &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt; умножается матрица размера &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;n\times n&amp;lt;/math&amp;gt; на вектор длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt;, и потребуется &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n^2&amp;lt;/math&amp;gt; операций умножения и &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n^2&amp;lt;/math&amp;gt; операций сложения.&lt;br /&gt;
*Умножение векторов &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;q^T_j&amp;lt;/math&amp;gt; и &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt; длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; потребует &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; операций умножения и &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; операций сложения.&lt;br /&gt;
*При вычислении нового значения вектора &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt; поэлементное сложение двух векторов длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; требует &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; операций сложения.&lt;br /&gt;
*Умножение вектора длины &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; на вещественное число требует &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; операций умножения.&lt;br /&gt;
*Нахождение квадратичной нормы вектора &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt;  длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; требует &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; умножений и &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; сложений и ещё 1 операцию извлечения квадратного корня.&lt;br /&gt;
*Заключительное нахождение собственных значений и собственных векторов трёхдиагональной матрицы &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;T_j&amp;lt;/math&amp;gt; размера &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j\times j&amp;lt;/math&amp;gt; с помощью QR-алгоритма потребует в худшем случае &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(j^3)&amp;lt;/math&amp;gt; операций.&amp;lt;ref&amp;gt;http://num-anal.srcc.msu.ru/lib_na/int_ae/int_ae6.htm (пункт 6.2, &amp;quot;Скорость сходимости при этом всегда не хуже квадратичной и почти всегда лучше кубической.&amp;quot;)&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Посчитаем теперь суммарное количество простейших операций на одной итерации алгоритма (без учёта записей в память):&lt;br /&gt;
*&amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n^2+5\,n&amp;lt;/math&amp;gt; операций умножения/деления&lt;br /&gt;
*&amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n^2+4\,n&amp;lt;/math&amp;gt; операций сложения/вычитания&lt;br /&gt;
*1 операция извлечения квадратного корня&amp;lt;br&amp;gt;&lt;br /&gt;
Отдельно после всех итераций при &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j=k&amp;lt;/math&amp;gt; :&lt;br /&gt;
*&amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(k^3)&amp;lt;/math&amp;gt; операций для поиска собственных значений и собственных векторов трёхдиагональной матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_k&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Итого можно утверждать следующее:&lt;br /&gt;
&lt;br /&gt;
Последовательная сложность одной итерации рассматриваемого алгоритма:  &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(n ^ 2) &amp;lt;/math&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Суммарная сложность алгоритма (&amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;/math&amp;gt; итераций): &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(k\,n ^ 2) + O(k ^ 3)&amp;lt;/math&amp;gt; &amp;lt;ref&amp;gt;Здесь мы полагаем, что мы не вычисляем собственные значения и векторы матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_j&amp;lt;/math&amp;gt; на каждом промежуточном шаге, а лишь единожды затрачиваем &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;O(k ^ 3)&amp;lt;/math&amp;gt; действий в конце для нахождения &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;/math&amp;gt; собственных значений и векторов матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_k&amp;lt;/math&amp;gt;&amp;lt;/ref&amp;gt; &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
На практике же обычно рассматривается число &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;&amp;lt;n&amp;lt;/math&amp;gt;, поэтому второе слагаемое можно опустить.&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
На рис. 1 продемонстрирован граф одной итерации (при каком-либо произвольном значении итератора &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j&amp;lt;/math&amp;gt;) описанного алгоритма без отображения входных и выходных данных. Наглядно продемонстрированы связи между всеми действиями, и с помощью деления на &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; потоков показано, какие операции возможно выполнять параллельно на каждом шаге с целью оптимизации и экономии машинного времени. В результате, после параллельно выполненных операций &#039;&#039;&#039;Division&#039;&#039;&#039; на заключительном ярусе, на выходе имеем значение следующего вектора Ланцоша &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;q_{j+1}&amp;lt;/math&amp;gt;, после чего следует переход на следующую итерацию, и процесс повторяется.&lt;br /&gt;
&lt;br /&gt;
[[Файл:Levin_graph.png|600px|thumb|center|Рис. 1  Структура одной итерации алгоритма]] &amp;lt;br&amp;gt;&lt;br /&gt;
Обозначения на рисунке: &amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Simp&#039;&#039;&#039; (от англ. simple) - операции сложения и умножения вещественных чисел при вычислении произведения матрицы на вектор;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Vec mult&#039;&#039;&#039; (от англ. vectors multiplication) - операция скалярного умножения двух векторов;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Vec subtr&#039;&#039;&#039; (от англ. vectors subtraction, из-за использованных в операции вычитаний векторов) - операция умножения вектора на число (выполняется дважды) и формирование нового значения &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;z_{new}&amp;lt;/math&amp;gt; по формуле: &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;z_{new} = z - \alpha_j q_j - \beta_{j-1}q_{j-1} \;&amp;lt;/math&amp;gt;;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;||\cdot||&amp;lt;/math&amp;gt; - операция вычисления нормы вектора;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Division&#039;&#039;&#039; - операция деления вектора на вещественное число  &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;\beta_j&amp;lt;/math&amp;gt; &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Важно отметить, что упомянутые выше операции также легко поддаются оптимизации. Например, попарные умножения вещественных координат векторов при вычислении скалярного произведения также легко выполняются параллельно на &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; потоках, а затем можно применить суммирование методом сдваивания, о котором сказано в следующем разделе. Умножение или деление вектора на вещественное число являющееся, по определению, умножением или делением всех его координат на это число тоже может быть выполнено эффективнее, если мы используем &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; потоков, а не выполняем эти действия последовательно.&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
Параллельные операции возможны только внутри итераций, так как рассматриваемый алгоритм является итерационным, и сами итерации строго последовательны.&amp;lt;br&amp;gt;&lt;br /&gt;
Рассмотрим в этом разделе подробнее, какой выигрыш мы можем получить при распараллеливании операций внутри одной итерации согласно графу из предыдущего раздела.&lt;br /&gt;
&lt;br /&gt;
Умножение вещественной симметричной матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; размера &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;n\times n&amp;lt;/math&amp;gt; на вектор &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;b&amp;lt;/math&amp;gt; длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; требует последовательного выполнения &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; ярусов умножений и сложений. Сложение элементов вектора длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; на каждом шаге перемножения можно оптимизировать и выполнить за &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;\log_2 n&amp;lt;/math&amp;gt; действий, если применять метод сдваивания.&lt;br /&gt;
&lt;br /&gt;
Дальнейшие операции выполняются последовательно, а вычисление значений векторов происходит за один ярус операций сложения или умножения.&lt;br /&gt;
&lt;br /&gt;
Ресурс параллелизма алгоритма вычисления собственных значений построенной трёхдиагональной матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_k&amp;lt;/math&amp;gt; размера &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k\times k&amp;lt;/math&amp;gt; зависит от выбранного алгоритма (об этих алгоритмах подробнее было сказано в разделах 1.2 и 1.4). Будет очень затратно с точки зрения объёма материала пытаться рассмотреть пусть даже часть этих методов в этой статье, а так же тонкости их распараллеливания. Предлагаем читателям при желании самим ознакомиться с этими алгоритмами на данном ресурсе или прибегнув к иным источникам.&lt;br /&gt;
&lt;br /&gt;
При классификации по высоте ЯПФ, таким образом, алгоритм Ланцоша без переортогонализации относится к алгоритмам с &#039;&#039;логарифмической сложностью&#039;&#039;, и его сложность равна &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(\log_2 n)&amp;lt;/math&amp;gt; с важным замечанием, что это сложность только одной итерации, а максимум в алгоритме может быть выполнено последовательно &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;/math&amp;gt; таких однотипных итераций, если не будет осуществлён ранний выход из цикла. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Несмотря на то, что на графе в предыдущем разделе для лучшей визуализации и понимания было изображено &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; потоков (никаких допущений мы не делали и нарушений с точки зрения логики и математики нет, можно изобразить большее число потоков, просто часть времени некоторые из них могут бездействовать и не использоваться), на самом деле правильным и разумным будет реализовать начальное параллельное выполнение &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n^2&amp;lt;/math&amp;gt; операций умножения всех вещественных элементов матрицы &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;A&amp;lt;/math&amp;gt; на соответствующие элементы вектора &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;q_j&amp;lt;/math&amp;gt;, после чего применять тот же самый упомянутый метод сдваивания. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Поэтому при классификации по ширине ЯПФ его сложность будет &#039;&#039;квадратичной&#039;&#039; и равна &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(n^2)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
&#039;&#039;&#039;Входные данные алгоритма:&#039;&#039;&#039; вещественная симметричная &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; размера &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;n\times n&amp;lt;/math&amp;gt;, вещественный вектор &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;b&amp;lt;/math&amp;gt; длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt;, и одно целое число &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;k&amp;lt;/math&amp;gt;, означающее количество итераций.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём входных данных:&#039;&#039;&#039; &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;n^2 +n + 1 &amp;lt;/math&amp;gt;. Если учесть, что матрица симметричная и достаточно для её однозначного определения задать элементы на главной диагонали и элементы над или под ней, то можно сократить объём входных данных с целью экономии памяти до: &amp;lt;math&amp;gt;\ \frac{n^2-n}{2}+n+n+1 =\frac{n^2+3n}{2} + 1&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные алгоритма:&#039;&#039;&#039; вектор собственных значений &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;\Theta^k&amp;lt;/math&amp;gt; длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;/math&amp;gt;, матрица &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;S^k&amp;lt;/math&amp;gt; из соответствующих собственных векторов размера &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n\times k&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём выходных данных:&#039;&#039;&#039; &amp;lt;math&amp;gt;k\;(n + 1)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
В данном разделе перечислены без какой-либо хронологии или связи друг с другом наиболее важные и разнообразные свойства алгоритма, на которые стоит и полезно обратить внимание, а также которые выгодно отличают его от схожих алгоритмов, решающих ту же задачу.&amp;lt;br&amp;gt;&lt;br /&gt;
1) Отношение последовательной сложности алгоритма к параллельной,с учётом &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;/math&amp;gt; итераций, равно &amp;lt;math&amp;gt;\;\;\frac{kn^2}{k \log_2{n}}=\frac{n^2}{\log_2{n}}&amp;lt;/math&amp;gt;;&amp;lt;br&amp;gt;&lt;br /&gt;
2) Вычислительная мощность алгоритма, как отношение числа операций к суммарному объему входных и выходных данных, равна &amp;lt;math style=&amp;quot;vertical-align:-70%&amp;gt;\;\;\frac{k\,n^2}{0.5\,n^2+1.5\,n+k\,n+k+1}&amp;lt;/math&amp;gt; и &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;\approx 2\,k&amp;lt;/math&amp;gt;, так как на практике верно отношение &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;&amp;lt;n&amp;lt;/math&amp;gt; ;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
3) Для собственных значений формируемых матриц &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_j&amp;lt;/math&amp;gt; верно отношение (следствие теоремы Коши о перемежаемости): &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;\lambda_i(T_{k+1})\geq \lambda_i(T_{k})\geq \lambda_{i+1}(T_{k+1})\geq \lambda_{i+1}(T_{k})&amp;lt;/math&amp;gt; ;&amp;lt;ref&amp;gt;James W. Demmel - Вычислительная линейная алгебра. Теория и приложения //Мир. - 2001 (c. 383)&amp;lt;/ref&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
4) Крайние (наибольшие и наименьшие) собственные значения матриц &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_j&amp;lt;/math&amp;gt; сходятся к крайним собственным значениям матрицы &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;A&amp;lt;/math&amp;gt; первыми (это часто происходит уже на ранних шагах при &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j\approx 2\,\sqrt{n}&amp;lt;/math&amp;gt;&amp;lt;ref&amp;gt;http://num-anal.srcc.msu.ru/lib_na/int_ae/int_ae6.htm (пункт 6.5)&amp;lt;/ref&amp;gt;), а собственные значения в середине спектра - последними;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
5) Из-за ограниченной точности постепенно теряется ортогональность вектора Ланцоша &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;q_j&amp;lt;/math&amp;gt; к предыдущим векторам Ланцоша, поэтому необходимо примерно каждые 10-15 итераций проводить дорогостоящую операцию реортогонализации, но это уже будет иной алгоритм с очень малым различием в одной операции и в программном коде, реализующем его, соответственно; &amp;lt;ref&amp;gt;Sam Handler - The Lanczos Algorithm For Large-Scale Eigenvalue Problems (08.01.07), slide №8&amp;lt;/ref&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
6) Эффективность и быстрота выполнения алгоритма очень сильно зависит от скорости памяти (диска). Согласно тесту только &#039;&#039;6%&#039;&#039; времени работы программы приходится на вычисления, остальное время затрачивается на ожидание отклика диска;&amp;lt;ref&amp;gt;Sam Handler - The Lanczos Algorithm For Large-Scale Eigenvalue Problems (08.01.07), slide №10&amp;lt;/ref&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
7) Метод Ланцоша удобен тем, что не требует хранения исходной матрицы полным массивом: метод использует исходную матрицу только в операциях умножения матрицы на вектор, что позволяет эффективно использовать разреженность матрицы или регулярность структуры матрицы. Поэтому метод Ланцоша может быть использован для матриц таких больших порядков, когда методы вращений и отражений не могут быть применены.&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;
Для исследования масштабируемости рассматриваемого алгоритма Ланцоша без переортогонализации автором была реализована программа на языке С++ с использованием технологии MPI. &amp;lt;ref&amp;gt;https://goo.gl/dGfzOD  или альтернативная ссылка с прикреплённым кодом: https://goo.gl/lFziv0 , по просьбе на почту я (автор статьи) готов предоставить желающим доступ к проекту с этим кодом на ресурсе Bitbucket&amp;lt;/ref&amp;gt; Дальнейшее исследование было проведено на суперкомпьютере &amp;quot;Ломоносов&amp;quot; Суперкомпьютерного комплекса МГУ. &amp;lt;br&amp;gt; Важно отметить, что реализованная программа выполняет только первую часть алгоритма - формирование матрицы &amp;lt;math &amp;gt;T_j&amp;lt;/math&amp;gt;. Вторая часть алгоритма (задача поиска собственных значений матрицы &amp;lt;math &amp;gt;T_j&amp;lt;/math&amp;gt;) может быть решена несколькими методами, каждый из которых обладает своей эффективностью распараллеливании и характерными свойствами. Подробно этот вопрос уже обсуждался в статье раннее, поэтому не будем ещё раз заострять на этом внимание и останавливаться.&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Сборка осуществлялась со следующими параметрами:&lt;br /&gt;
* Компилятор intel/15.0.090 &lt;br /&gt;
* Openmpi/1.8.4-icc&lt;br /&gt;
В серии проведённых расчётов рассматривались следующие числовые значения параметров:&lt;br /&gt;
* Размер &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;n&amp;lt;/math&amp;gt; задачи и, соответственно, матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt;, задействованной в операции умножения на вектор: [2000 : 30000] с шагом 1000&lt;br /&gt;
* Число процессоров: 1, 2, 4, 16, 32, 48, 64, 96, 128&lt;br /&gt;
* Число итераций в алгоритме: &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k=350&amp;lt;/math&amp;gt;&lt;br /&gt;
Число &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; взято таким вопреки информации в начале статьи, где говорится, что значение &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; редко превышает &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;10^2&amp;lt;/math&amp;gt; (хоть мы и имеем право брать его любым по нашему усмотрению). Это сделано исключительно для лучшей визуализации пиков на графиках в данном разделе и наглядности получаемых результатов, так как при меньших на порядок значениях &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; времена выполнения программ были слишком малы даже при минимальных числах процессоров и максимальных размерах &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;n&amp;lt;/math&amp;gt; задачи.&lt;br /&gt;
&lt;br /&gt;
== Динамические характеристики и эффективность реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Выводы для классов архитектур ==&lt;br /&gt;
По заданию, во второй части требовалось описать только разделы 2.4 и 2.7, прошу не спрашивать с меня все разделы 2.1-2.6. Надеюсь на понимание, мне физически не хватает времени на это задание + 2 других в течение семестра, делаю всё, что в моих силах :)&lt;br /&gt;
&lt;br /&gt;
== Существующие реализации алгоритма ==&lt;br /&gt;
Несмотря на то, что алгоритм является далеко не самым популярным, алгоритмом, про который нельзя сказать, что он всегда «на слуху», на сегодняшний день существует множество реализаций на различных популярных языках.&amp;lt;br&amp;gt;&lt;br /&gt;
Перечислим далее некоторые из них, указывая язык программирования, лежащий в их основе, и некоторые важные характеристики, которые обсуждались в статье ранее:&lt;br /&gt;
*&#039;&#039;Code on netlib.org by Jane Cullum and Ralph Willoughby&#039;&#039; (&#039;&#039;&#039;Fortran 77&#039;&#039;&#039;; без реортогонализации векторов; без реализации распараллеливания)&amp;lt;ref&amp;gt;http://www.netlib.org/lanczos/leval&amp;lt;/ref&amp;gt;&lt;br /&gt;
*&#039;&#039;Lanczos algorithm on freesourcecode.net&#039;&#039; (&#039;&#039;&#039;Matlab&#039;&#039;&#039;; присутствует реортогонализация векторов; без реализации распараллеливания)&amp;lt;ref&amp;gt;http://freesourcecode.net/matlabprojects/61741/lanczos-algorithm--in-matlab&amp;lt;/ref&amp;gt;&lt;br /&gt;
*&#039;&#039;Lanczos for eigenvalues in Numerical Linear Algebra, Spring 2007&#039;&#039; (&#039;&#039;&#039;Matlab&#039;&#039;&#039;; частичная или полная реортогонализация - доступны оба варианта; без реализации распараллеливания)&amp;lt;ref&amp;gt;Ссылки на файлы lanso.m и lanfu.m можно найти на https://www.nada.kth.se/~ruhe/2D5219/labs2007.html&amp;lt;/ref&amp;gt;&lt;br /&gt;
*&#039;&#039;Planso&#039;&#039; (название происходит от parallel Lanso.f) &#039;&#039;code by Kesheng Wu and Horst D. Simon&#039;&#039; (&#039;&#039;&#039;Fortran 77&#039;&#039;&#039;; частичная реортогонализация векторов; использование MPI для коммуникаций)&amp;lt;ref&amp;gt;https://github.com/jiahao/planso.jl/tree/master/external/PLAN/plan К сожалению, ссылка в описании пакета на github, ведущая на сайт National Energy Research Scientific Computing Center (NERSC), с более подробной информацией о данной программе больше не активна и выдаёт результат &#039;&#039;Page not found&#039;&#039;&amp;lt;/ref&amp;gt; &lt;br /&gt;
* &#039;&#039;Lanczos.cpp in the Vienna Computing Library&#039;&#039;  (&#039;&#039;&#039;C++&#039;&#039;&#039;, частичная реортогонализация, без реализации распараллеливания) &amp;lt;ref&amp;gt;http://viennacl.sourceforge.net/doc/lanczos_8cpp_source.html&amp;lt;/ref&amp;gt;&lt;br /&gt;
* &#039;&#039;Parallel Eigen Values code using C++ AMP on microsoft msdn blog&#039;&#039; (&#039;&#039;&#039;C++&#039;&#039;&#039;; ? ; распараллеливание есть и реализовано через C++ AMP) &amp;lt;ref&amp;gt;https://blogs.msdn.microsoft.com/nativeconcurrency/2013/12/20/eigen-values/ Подробнее о C++ Accelerated Massive Parallelism можно почитать здесь: https://msdn.microsoft.com/ru-ru/library/hh265137(v=vs.140).aspx или здесь: http://professorweb.ru/my/csharp/optimization/level4/4_6.php &amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;br /&gt;
[[en:Description of algorithm properties and structure]]&lt;/div&gt;</summary>
		<author><name>AleksLevin</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:AleksLevin/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%9B%D0%B0%D0%BD%D1%86%D0%BE%D1%88%D0%B0_%D0%B2%D1%8B%D1%87%D0%B8%D1%81%D0%BB%D0%B5%D0%BD%D0%B8%D1%8F_%D1%81%D0%BE%D0%B1%D1%81%D1%82%D0%B2%D0%B5%D0%BD%D0%BD%D1%8B%D1%85_%D0%B7%D0%BD%D0%B0%D1%87%D0%B5%D0%BD%D0%B8%D0%B9_%D1%81%D0%B8%D0%BC%D0%BC%D0%B5%D1%82%D1%80%D0%B8%D1%87%D0%BD%D0%BE%D0%B9_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86%D1%8B_%D0%B4%D0%BB%D1%8F_%D1%82%D0%BE%D1%87%D0%BD%D0%BE%D0%B9_%D0%B0%D1%80%D0%B8%D1%84%D0%BC%D0%B5%D1%82%D0%B8%D0%BA%D0%B8_(%D0%B1%D0%B5%D0%B7_%D0%BF%D0%B5%D1%80%D0%B5%D0%BE%D1%80%D1%82%D0%BE%D0%B3%D0%BE%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D0%B8)&amp;diff=20221</id>
		<title>Участник:AleksLevin/Алгоритм Ланцоша вычисления собственных значений симметричной матрицы для точной арифметики (без переортогонализации)</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:AleksLevin/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%9B%D0%B0%D0%BD%D1%86%D0%BE%D1%88%D0%B0_%D0%B2%D1%8B%D1%87%D0%B8%D1%81%D0%BB%D0%B5%D0%BD%D0%B8%D1%8F_%D1%81%D0%BE%D0%B1%D1%81%D1%82%D0%B2%D0%B5%D0%BD%D0%BD%D1%8B%D1%85_%D0%B7%D0%BD%D0%B0%D1%87%D0%B5%D0%BD%D0%B8%D0%B9_%D1%81%D0%B8%D0%BC%D0%BC%D0%B5%D1%82%D1%80%D0%B8%D1%87%D0%BD%D0%BE%D0%B9_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86%D1%8B_%D0%B4%D0%BB%D1%8F_%D1%82%D0%BE%D1%87%D0%BD%D0%BE%D0%B9_%D0%B0%D1%80%D0%B8%D1%84%D0%BC%D0%B5%D1%82%D0%B8%D0%BA%D0%B8_(%D0%B1%D0%B5%D0%B7_%D0%BF%D0%B5%D1%80%D0%B5%D0%BE%D1%80%D1%82%D0%BE%D0%B3%D0%BE%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D0%B8)&amp;diff=20221"/>
		<updated>2016-12-07T00:29:57Z</updated>

		<summary type="html">&lt;p&gt;AleksLevin: /* Масштабируемость алгоритма и его реализации */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Основные авторы описания: Левин А.Д.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{algorithm&lt;br /&gt;
| name              = Алгоритм Ланцоша для точной арифметики (без переортогонализации)&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(k\,n^2)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(k\log_2 n)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;\frac{n^2+3n}{2} + 1&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;k\;(n + 1)&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритмов =&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Данный алгоритм появился в 1950 г. и носит имя венгерского физика и математика Корнелия Ланцоша (венг. Lánczos Kornél). Алгоритм Ланцоша относится к итерационным методам вычисления собственных значений для матриц столь больших порядков &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt; n&amp;lt;/math&amp;gt;, что к ним нельзя применить прямые методы из-за ограничений по времени и памяти.&lt;br /&gt;
&lt;br /&gt;
Сам Ланцош указывал, что его метод предназначен для отыскания нескольких собственных векторов симметричных матриц, хотя к методу сразу было обращено внимание, как к способу приведения всей матрицы к трёхдиагональному виду. Двадцатью годами позже канадский математик Крис Пэж показал, что, несмотря на чувствительность к округлениям, алгоритм Ланцоша - эффективное средство вычисления некоторых &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; собственных чисел и соответствующих им собственных векторов. &amp;lt;ref&amp;gt;Парлетт Б. - Симметричная проблема собственных значений. Численные методы //М.: Мир. - 1983. (c. 276)&amp;lt;/ref&amp;gt;&lt;br /&gt;
Обычно число &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; берут в два раза больше, чем количество собственных значений матрицы, которые поставлена цель найти, и оно имеет порядок не более &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;10^2&amp;lt;/math&amp;gt;.&amp;lt;ref&amp;gt;Susan W. Bostic - Lanczos Eigensolution Method for High-Perfomance Computers, page 7&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Алгоритм Ланцоша для вычисления собственных значений симметричной матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; соединяет в себе метод Ланцоша для построения последовательности подпространств Крылова и ортонормированных векторов Ланцоша и процедуру Рэлея-Ритца получения оптимальных приближений собственных значений и соответствующих собственных векторов исходной матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt;.&amp;lt;ref&amp;gt;James W. Demmel - Вычислительная линейная алгебра. Теория и приложения //Мир. - 2001 (c. 381)&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
В данной статье рассматривается вариант алгоритма Ланцоша, в котором опущено влияние ошибок округления на вычислительный процесс, хотя на практике этому посвящается отдельное внимание и существуют различные методы решения данной проблемы, такие как частичная или полная переортогонализация. Этим модифицированным методам посвящены отдельные статьи на данном ресурсе.&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
Обозначения и формулы, используемые в данном разделе, взяты из литературы, указанной по ссылке.&amp;lt;ref&amp;gt;James W. Demmel - Вычислительная линейная алгебра. Теория и приложения //Мир. - 2001 (c. 313, &#039;&#039;&amp;lt;math&amp;gt; \S &amp;lt;/math&amp;gt; 6.6 Методы Крыловского подпространства&#039;&#039;)&amp;lt;/ref&amp;gt; &lt;br /&gt;
&lt;br /&gt;
Алгоритм Ланцоша для вычисления &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; собственных значений и собственных векторов вещественной симметричной матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A=A^T&amp;lt;/math&amp;gt; в точной арифметике: &amp;lt;ref&amp;gt;James W. Demmel - Вычислительная линейная алгебра. Теория и приложения //Мир. - 2001 (c. 381)&amp;lt;/ref&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{align}&lt;br /&gt;
q_1 = &amp;amp; \,\frac{b}{\|b\|_2},\; \beta_0 = 0,\; q_0 = 0\\&lt;br /&gt;
\mathbf{for} \; &amp;amp; j = 1 \; to \; k \,\; \mathbf{do} \\&lt;br /&gt;
&amp;amp; z = A\,q_j\\&lt;br /&gt;
&amp;amp; \alpha_j = q^T_j z\\&lt;br /&gt;
&amp;amp; z = z - \alpha_j q_j - \beta_{j-1}q_{j-1}\\&lt;br /&gt;
&amp;amp; \beta_j = \|z\|_2\\&lt;br /&gt;
&amp;amp; \mathbf{If} \; (\beta_j == 0) \; \mathbf{then}\; stop\; the\; algorithm \\ &lt;br /&gt;
&amp;amp; \;  q_{j+1} = \frac{z}{\beta_j} \\&lt;br /&gt;
&amp;amp; compute\; eigenvalues\; and \;eigenvectors\;of \;matrix \;\;T_j= Q^T_j A Q\;\;and\;estimate \;the\; errors\\&lt;br /&gt;
\mathbf{end} \; &amp;amp; \mathbf{for}&lt;br /&gt;
\end{align}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
В продемонстрированном выше алгоритме &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;b&amp;lt;/math&amp;gt; - заданный вещественный вектор. Также полагается известным алгоритм вычисления произведения матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; на вектор &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;x&amp;lt;/math&amp;gt;. &lt;br /&gt;
Введём матрицу Крылова, определяемую следующим соотношением: &amp;lt;math&amp;gt;K_j = [b,Ab,A^2b,...,A^{j-1}b]&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Далее, на практике, матрица &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;K&amp;lt;/math&amp;gt; заменяется матрицей &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;Q&amp;lt;/math&amp;gt;, такой, что при любом числе &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; линейные оболочки первых &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; столбцов в &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;K&amp;lt;/math&amp;gt; и &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;Q&amp;lt;/math&amp;gt; являются одним и тем же подпространством.&amp;lt;ref&amp;gt;James W. Demmel - Вычислительная линейная алгебра. Теория и приложения //Мир. - 2001 (c. 315)&amp;lt;/ref&amp;gt; &lt;br /&gt;
Тогда матрица &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;Q&amp;lt;/math&amp;gt;, в отличие от матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;K&amp;lt;/math&amp;gt;, хорошо обусловлена и легко обратима. В результате получаем матрицу &amp;lt;math&amp;gt;Q_j = [q_1, q_2, \dots, q_j]&amp;lt;/math&amp;gt; размерности &amp;lt;math&amp;gt;n\times j&amp;lt;/math&amp;gt;, столбцы которой ортогональны, являются базисом подпространства Крылова и называются векторами Ланцоша.&lt;br /&gt;
&lt;br /&gt;
В алгоритме Ланцоша вычислению подлежит столько первых столбцов в матрице &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;Q_j&amp;lt;/math&amp;gt;, сколько необходимо для получения требуемого приближения к решению &amp;lt;math&amp;gt;A\,x\,=b\,\,(A\,x=\lambda \, x)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Получение нулевого &amp;lt;math&amp;gt;\beta_j&amp;lt;/math&amp;gt; в итерационном процессе - событие, желательное в том смысле, что оно свидетельствует о том, что найдено некоторое подпространство, являющееся в точности инвариантным, а все собственные значения матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;T_j&amp;lt;/math&amp;gt; являются собственными значениями матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt;. На практике же нулевое и близкие к нулю значения получаются редко.&amp;lt;ref&amp;gt;Голуб Дж., Ван Лоун Ч. - Матричные вычисления//М.: Мир. - 1999 (c. 429)&amp;lt;/ref&amp;gt; &lt;br /&gt;
&lt;br /&gt;
Затем на каждом шаге цикла формируется симметричная трёхдиагональная матрица &amp;lt;math&amp;gt;T_j = Q^T_j A Q&amp;lt;/math&amp;gt;, к которой применяется процесс Рэлея-Ритца для поиска её собственных значений (на практике для поиска этих собственных значений можно использовать любой из специальных методов в параграфе книги по ссылке).&amp;lt;ref&amp;gt;Голуб Дж., Ван Лоун Ч. - Матричные вычисления//М.: Мир. - 1999 (&amp;lt;math&amp;gt;\S&amp;lt;/math&amp;gt; 8.4)&amp;lt;/ref&amp;gt;  &lt;br /&gt;
Эти собственные значения, они же числа Ритца, и полагаются приближёнными собственными значениями исходной матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt;.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Существует множество методов для отыскания собственных значений вещественной симметричной трехдиагональной матрицы. Большинство из них требует &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt; операций &amp;lt;ref&amp;gt;Парлетт Б. Симметричная проблема собственных значений. Численные методы.,: Мир, 1983. с. 179-182&amp;lt;/ref&amp;gt;, но существуют и быстрые алгоритмы, требующие лишь &amp;lt;math&amp;gt;O(n\ln n)&amp;lt;/math&amp;gt; операций.&amp;lt;ref&amp;gt;https://en.wikipedia.org/wiki/Tridiagonal_matrix#Eigenvalues  Раздел eigenvalues&amp;lt;/ref&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Одним из возможных способов отыскать собственные значения симметричной трехдиагональной матрицы - прямое вычисление корней характеристического полинома &amp;lt;math&amp;gt;p_n(\lambda)&amp;lt;/math&amp;gt; через метод деления пополам, где формируется последовательность Штурма и локализуются собственные числа, являющиеся корнями характеристического полинома. Нахождение всех &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; собственных значений матрицы этим способом требует &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;2n^2t&amp;lt;/math&amp;gt; умножений и вычитаний, где &amp;lt;math&amp;gt;t&amp;lt;/math&amp;gt; - число сделанных шагов с применением метода деления пополам.&amp;lt;ref&amp;gt;Уилкинсон Дж. X. Алгебраическая проблема собственныx значений. Изд-во &amp;quot;Наука&amp;quot;, 1970. - глава 5, с. 272-278&amp;lt;/ref&amp;gt; Соответствующие собственные вектора могут быть найдены посредством обратных итераций за &amp;lt;math&amp;gt; O(n) &amp;lt;/math&amp;gt; флопов. &amp;lt;ref&amp;gt;Голуб Дж., Ван Лоун Ч. - Матричные вычисления//М.: Мир. - 1999 (c. 394-395)&amp;lt;/ref&amp;gt; &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;На практике, если требуется только небольшая часть от всей совокупности собственных векторов и значений, и матрица имеет Хессенбергову или трёхдиагональную форму, очень эффективными будут методы факторизации, как, например, QR-алгоритм или QL-алгоритм со сдвигами (c целью ускорить алгоритм и сделать порядок сходимости квадратичным) или же без них.&amp;lt;ref&amp;gt;http://algorithm.narod.ru/ln/eigen/ETridiag.html&amp;lt;/ref&amp;gt; &amp;lt;br&amp;gt;&lt;br /&gt;
Весьма молодые и не менее актуальные конкуренты QR и QL алгоритмов, применяющиеся для поиска собственных значений:&lt;br /&gt;
*Методы divide-and-conquer (разделяй и властвуй), появившиеся в 1980-ых годах &amp;lt;ref&amp;gt;https://goo.gl/dapvbn ссылку пришлось сократить с помощью Google url shortener, так как символы подчеркивания портили её и не давали перейти по 1 клику&amp;lt;/ref&amp;gt;&lt;br /&gt;
*Relatively robust representation методы, появившиеся в 1990-ых и позволяющие найти собственные числа симметричной матрицы порядка &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;n&amp;lt;/math&amp;gt; за &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt; операций&lt;br /&gt;
&lt;br /&gt;
Если требуется вычислить собственные векторы, то необходимо хранить вычисляемые векторы Ланцоша. Если работа при этом производится только с оперативной памятью, то при большом порядке исходной матрицы (а именно для таких матриц и предназначен метод Ланцоша) число шагов  &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;j&amp;lt;/math&amp;gt;, которые могут быть выполнены до того момента, как оперативная память будет исчерпана, будет очень незначительно, а следовательно, искомые собственные пары могут не успеть сойтись с требуемой точностью. В этом случае метод Ланцоша можно использовать итерационным образом: после выполнения заданного числа шагов процесс прерывается и, если еще не все требуемые пары Ритца сошлись с требуемой точностью, то формируется новый начальный вектор &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;q_1&amp;lt;/math&amp;gt;, являющийся линейной комбинацией векторов Ритца, еще не сошедшихся с заданной точностью, и процесс начинается заново.&amp;lt;ref&amp;gt;http://num-anal.srcc.msu.ru/lib_na/int_ae/int_ae6.htm (пункт 6.5)&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
Вычислительное ядро рассматриваемого алгоритма (наиболее ресурсно-затратная часть алгоритма) -  формирование на каждом шаге цикла промежуточного вектора &amp;lt;math&amp;gt;z&amp;lt;/math&amp;gt;, вычисляемого по формуле: &amp;lt;math&amp;gt;z = A\,q_j&amp;lt;/math&amp;gt;. Данная операция, по сравнению с другими операциями алгоритма, затратна и требовательна, как с точки зрения количества производимых операций, так и с точки зрения объема оперируемых данных. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Например, умножение матрицы размера &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;n\times n&amp;lt;/math&amp;gt; на вектор длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; требует: &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;n^2+(n-1)n = 2n^2-n&amp;lt;/math&amp;gt; операций умножения и сложения. В свою очередь аналогичная операция умножения матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;(n+1)\times (n+1)&amp;lt;/math&amp;gt; на вектор длины &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;(n+1)&amp;lt;/math&amp;gt; требует: &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;2n^2+3n+1&amp;lt;/math&amp;gt;  операций умножения и сложения. То есть повышение размерности задачи всего на 1 увеличивает число необходимых действий в этом шаге алгоритма на: &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;4n+1&amp;lt;/math&amp;gt;. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Так же, стоит помнить, что, согласно разделу 1.2, данную операцию умножения матрицы на вектор необходимо выполнить &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;k&amp;lt;/math&amp;gt; раз. Нетрудно понять, насколько возрастает и колоссален масштаб операций, если в задачах, где критична точность, размерности &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; могут иметь порядок &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;10^5&amp;lt;/math&amp;gt; или даже более.&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
Как уже было упомянуто в данной статье в описании алгоритма, рассматриваемый алгоритм состоит из двух последовательно выполненных алгоритмов: метод Ланцоша для построения последовательности подпространств Крылова и ортонормированных векторов Ланцоша и процедура Рэлея-Ритца получения оптимальных приближений собственных значений и соответствующих собственных векторов исходной матрицы.&lt;br /&gt;
&lt;br /&gt;
В первой части алгоритма, где итерационно строятся Крыловское подпространство и трёхдиагональная матрица &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&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 style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; разреженная. Именно она подлежит оптимизации с использованием техник распараллеливания, поскольку она является вычислительным ядром алгоритма, а весь упомянутый процесс построения матрицы &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&amp;lt;/math&amp;gt; выполняется последовательно.&lt;br /&gt;
&lt;br /&gt;
Рассмотрим вторую часть алгоритма - поиск собственных значений сформированной матрицы &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&amp;lt;/math&amp;gt;.&amp;lt;br&amp;gt;&lt;br /&gt;
Далее, наглядно, в виде псевдокода, представлен, упомянутый в разделе 1.2, QR-алгоритм (аналогично можно рассмотреть и QL-алгоритм) со сдвигами Релэя, который весьма популярен на практике.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{align}&lt;br /&gt;
\mathbf{Input}: \;&amp;amp;tridiagonal\;\;matrix \;T\;with\;\;n\times n\;\;size\\&lt;br /&gt;
T^{(0)}&amp;amp;:=T\\&lt;br /&gt;
\mathbf{for}&amp;amp; \;\;m=n,...,2 \;\; \mathbf{do}\\&lt;br /&gt;
&amp;amp;k=0\\&lt;br /&gt;
&amp;amp; \mathbf{repeat}\\&lt;br /&gt;
&amp;amp; \quad \;\; k=k+1\\&lt;br /&gt;
&amp;amp; \quad \;\; \mu^{(k)}=T_{m,m}^{(k-1)}\\&lt;br /&gt;
&amp;amp; \quad \;\; Q^{(k)}R^{(k)}=T^{(k-1)}-\mu^{(k)}I\;\;using\;\;QR\;decomposition\\&lt;br /&gt;
&amp;amp; \quad \;\; T^{(k)}=R^{(k)}Q^{(k)}+\mu^{(k)}I\\&lt;br /&gt;
&amp;amp; \mathbf{until} \;\;\; |T_{m,m-1}^{(k)}| \;is\;\;small\;\;enough\\&lt;br /&gt;
&amp;amp; Save  \;\;T_{m,m}^{(k)} \;\;as\;\; converged\;\;eigenvalue\;of\;T\\ &lt;br /&gt;
&amp;amp; Remove \;\boldsymbol{n}\,th\;row\;and\;\boldsymbol{n}\,th\;column\;\;from \;T \\&lt;br /&gt;
&amp;amp; and\;take\;this\;new\;cropped\;matrix\;as\;new\;T^{(0)}\;with\;\;(n-1)\times (n-1)\;\;size\\&lt;br /&gt;
 \mathbf{end}&amp;amp;\; \mathbf{for}&lt;br /&gt;
\end{align}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Малость наддиагональных и поддиагональных элементов матрицы (фраза &#039;&#039;&amp;quot;small enough&amp;quot;&#039;&#039; в псевдокоде) подразумевает:&lt;br /&gt;
&amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt; |T_{m,m-1}^{(k)}| \leq \varepsilon\,|T_{m,m}^{(k)}| \quad\quad &amp;lt;/math&amp;gt; , где &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt; \varepsilon &amp;lt;/math&amp;gt; - заданная точность&amp;lt;br&amp;gt;&lt;br /&gt;
Также вместо сдвига Релэя, обозначенного в алгоритме через &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;\mu^{(k)}&amp;lt;/math&amp;gt;, часто на практике используется сдвиг по Уилкинсону, который даёт гарантированную сходимость внедиагональных элементов матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt; T^{(k)} &amp;lt;/math&amp;gt;, формируемой на каждом шаге, к нулю, при этом жертвуя монотонностью их убывания.&amp;lt;ref&amp;gt;Голуб Дж., Ван Лоун Ч. - Матричные вычисления//М.: Мир. - 1999 (c. 378, вторая половина страницы)&amp;lt;/ref&amp;gt;&amp;lt;ref&amp;gt;Парлетт Б. Симметричная проблема собственных значений. Численные методы.,: Мир, 1983. с. 169&amp;lt;/ref&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Подробнее с различными сдвигами и соответствующими оценками скоростей и количествами операций можно ознакомиться по указанной ссылке:&amp;lt;ref&amp;gt;Парлетт Б. Симметричная проблема собственных значений. Численные методы.,: Мир, 1983. с. 179-182&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;Для совершения QR-декомпозиции на каждом шаге может использоваться любой из алгоритмов по ссылке.&amp;lt;ref&amp;gt;https://en.wikipedia.org/wiki/QR_decomposition&amp;lt;/ref&amp;gt; Подробные описания этих алгоритмов также доступны на данном ресурсе algowiki-project.&amp;lt;br&amp;gt;&lt;br /&gt;
Так как мы оперируем не обычной матрицей и даже не Хессенберговой, а симметричной и трёхдиагональной, то скорость таких алгоритмов значительно возрастёт. Например, согласно данному ресурсу &amp;lt;ref&amp;gt;http://algorithm.narod.ru/ln/eigen/ETridiag.html&amp;lt;/ref&amp;gt;, для QL-алгоритма с неявными сдвигами:&amp;lt;br&amp;gt;&lt;br /&gt;
Для трёхдиагональной матрицы объем арифметических действий составляет &amp;lt;math&amp;gt; O(n)&amp;lt;/math&amp;gt; на одну итерацию вместо &amp;lt;math&amp;gt; O(n^3)&amp;lt;/math&amp;gt; для матрицы общего вида, а число итераций для нахождения первых собственных значений примерно равно 4 - 5. Но на этих итерациях также уменьшаются внедиагональные элементы правого нижнего угла. И, таким образом, дальнейшие собственные значения ищутся значительно быстрее. Среднее число итераций на каждое собственное значение обычно составляет 1.3 - 1.6.&amp;lt;br&amp;gt; &lt;br /&gt;
Аналогично QL, QR-разложение трёхдиагольной матрицы также требует &amp;lt;math&amp;gt; O(n)&amp;lt;/math&amp;gt; флопов&amp;lt;ref&amp;gt;Голуб Дж., Ван Лоун Ч. - Матричные вычисления//М.: Мир. - 1999 (c. 378, начало раздела 8.2.2)&amp;lt;/ref&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Подводя итог, во второй части алгоритма Ланцоша можно выделить следующие макрооперации:&lt;br /&gt;
* умножение матрицы на вещественное число;&lt;br /&gt;
* перемножение матриц;&lt;br /&gt;
* умножение и сравнение вещественных чисел;&lt;br /&gt;
* + набор других макроопераций в зависимости от выбора метода, с помощью которого будет совершаться сама QR или QL-декомпозиция (выше продемонстрированы, уже, как минимум, 3 разных способа).&lt;br /&gt;
Так же, важно заметить, что набор макропераций может быть несколько другим, если выбрать какой-либо иной современный метод поиска собственных чисел трёхдиагональной матрицы, не использующий QR и QL разложения(факторизацию). Два таких метода были упомянуты в пункте 1.2.&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
С целью полностью не дублировать раздел 1.2 данной статьи, где представлен наглядный и доступный для понимания псевдокод алгоритма, постараемся лишь коротко просуммировать и обобщить весь перечень последовательных действий в рассматриваемом алгоритме.&lt;br /&gt;
&lt;br /&gt;
В качестве входных данных имеем: вещественная симметричная матрица &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; размера &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;n\times n&amp;lt;/math&amp;gt;, известный вещественный вектор &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;b&amp;lt;/math&amp;gt; длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; и число &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;n&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Далее:&lt;br /&gt;
* Инициализируем вещественную константу &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;\beta_0&amp;lt;/math&amp;gt; и векторы &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;q_0&amp;lt;/math&amp;gt; и &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;q_1&amp;lt;/math&amp;gt;&lt;br /&gt;
* Итерационно для всех &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j=1,...,k&amp;lt;/math&amp;gt;:&lt;br /&gt;
** Вычисляем вспомогательный вектор &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt;, используя умножение матрицы на вектор&lt;br /&gt;
** Вычисляем, используя скалярное произведение векторов, значение &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;\alpha_j&amp;lt;/math&amp;gt; - элемент на главной диагонали трёхдиагональной матрицы &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&amp;lt;/math&amp;gt;&lt;br /&gt;
** Вычисляем по формуле новое значение и перезаписываем вектор &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt;&lt;br /&gt;
** Вычисляем значение &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;\beta_j&amp;lt;/math&amp;gt; - элементы непосредственно над и под главной диагональю той же матрицы &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&amp;lt;/math&amp;gt;&lt;br /&gt;
** Вычисляем, зная вектор &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt;,  очередной столбец матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;Q&amp;lt;/math&amp;gt;, он же вектор Ланцоша : &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;\,\,q_{j+1}&amp;lt;/math&amp;gt;&lt;br /&gt;
** Теперь, когда матрица &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&amp;lt;/math&amp;gt; сформирована на очередном шаге, находим её собственные значения и вектора любым доступным способом, о чём было подробно сказано в пункте 1.2&lt;br /&gt;
** Переходим на следующую итерацию: &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j&amp;lt;/math&amp;gt;++&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
Оценим количество операций и сложность последовательного алгоритма, изложенного в предыдущем разделе.&lt;br /&gt;
*Для вычисления вектора &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt; умножается матрица размера &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;n\times n&amp;lt;/math&amp;gt; на вектор длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt;, и потребуется &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n^2&amp;lt;/math&amp;gt; операций умножения и &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n^2&amp;lt;/math&amp;gt; операций сложения.&lt;br /&gt;
*Умножение векторов &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;q^T_j&amp;lt;/math&amp;gt; и &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt; длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; потребует &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; операций умножения и &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; операций сложения.&lt;br /&gt;
*При вычислении нового значения вектора &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt; поэлементное сложение двух векторов длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; требует &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; операций сложения.&lt;br /&gt;
*Умножение вектора длины &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; на вещественное число требует &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; операций умножения.&lt;br /&gt;
*Нахождение квадратичной нормы вектора &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt;  длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; требует &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; умножений и &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; сложений и ещё 1 операцию извлечения квадратного корня.&lt;br /&gt;
*Заключительное нахождение собственных значений и собственных векторов трёхдиагональной матрицы &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;T_j&amp;lt;/math&amp;gt; размера &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j\times j&amp;lt;/math&amp;gt; с помощью QR-алгоритма потребует в худшем случае &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(j^3)&amp;lt;/math&amp;gt; операций.&amp;lt;ref&amp;gt;http://num-anal.srcc.msu.ru/lib_na/int_ae/int_ae6.htm (пункт 6.2, &amp;quot;Скорость сходимости при этом всегда не хуже квадратичной и почти всегда лучше кубической.&amp;quot;)&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Посчитаем теперь суммарное количество простейших операций на одной итерации алгоритма (без учёта записей в память):&lt;br /&gt;
*&amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n^2+5\,n&amp;lt;/math&amp;gt; операций умножения/деления&lt;br /&gt;
*&amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n^2+4\,n&amp;lt;/math&amp;gt; операций сложения/вычитания&lt;br /&gt;
*1 операция извлечения квадратного корня&amp;lt;br&amp;gt;&lt;br /&gt;
Отдельно после всех итераций при &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j=k&amp;lt;/math&amp;gt; :&lt;br /&gt;
*&amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(k^3)&amp;lt;/math&amp;gt; операций для поиска собственных значений и собственных векторов трёхдиагональной матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_k&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Итого можно утверждать следующее:&lt;br /&gt;
&lt;br /&gt;
Последовательная сложность одной итерации рассматриваемого алгоритма:  &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(n ^ 2) &amp;lt;/math&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Суммарная сложность алгоритма (&amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;/math&amp;gt; итераций): &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(k\,n ^ 2) + O(k ^ 3)&amp;lt;/math&amp;gt; &amp;lt;ref&amp;gt;Здесь мы полагаем, что мы не вычисляем собственные значения и векторы матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_j&amp;lt;/math&amp;gt; на каждом промежуточном шаге, а лишь единожды затрачиваем &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;O(k ^ 3)&amp;lt;/math&amp;gt; действий в конце для нахождения &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;/math&amp;gt; собственных значений и векторов матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_k&amp;lt;/math&amp;gt;&amp;lt;/ref&amp;gt; &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
На практике же обычно рассматривается число &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;&amp;lt;n&amp;lt;/math&amp;gt;, поэтому второе слагаемое можно опустить.&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
На рис. 1 продемонстрирован граф одной итерации (при каком-либо произвольном значении итератора &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j&amp;lt;/math&amp;gt;) описанного алгоритма без отображения входных и выходных данных. Наглядно продемонстрированы связи между всеми действиями, и с помощью деления на &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; потоков показано, какие операции возможно выполнять параллельно на каждом шаге с целью оптимизации и экономии машинного времени. В результате, после параллельно выполненных операций &#039;&#039;&#039;Division&#039;&#039;&#039; на заключительном ярусе, на выходе имеем значение следующего вектора Ланцоша &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;q_{j+1}&amp;lt;/math&amp;gt;, после чего следует переход на следующую итерацию, и процесс повторяется.&lt;br /&gt;
&lt;br /&gt;
[[Файл:Levin_graph.png|600px|thumb|center|Рис. 1  Структура одной итерации алгоритма]] &amp;lt;br&amp;gt;&lt;br /&gt;
Обозначения на рисунке: &amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Simp&#039;&#039;&#039; (от англ. simple) - операции сложения и умножения вещественных чисел при вычислении произведения матрицы на вектор;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Vec mult&#039;&#039;&#039; (от англ. vectors multiplication) - операция скалярного умножения двух векторов;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Vec subtr&#039;&#039;&#039; (от англ. vectors subtraction, из-за использованных в операции вычитаний векторов) - операция умножения вектора на число (выполняется дважды) и формирование нового значения &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;z_{new}&amp;lt;/math&amp;gt; по формуле: &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;z_{new} = z - \alpha_j q_j - \beta_{j-1}q_{j-1} \;&amp;lt;/math&amp;gt;;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;||\cdot||&amp;lt;/math&amp;gt; - операция вычисления нормы вектора;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Division&#039;&#039;&#039; - операция деления вектора на вещественное число  &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;\beta_j&amp;lt;/math&amp;gt; &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Важно отметить, что упомянутые выше операции также легко поддаются оптимизации. Например, попарные умножения вещественных координат векторов при вычислении скалярного произведения также легко выполняются параллельно на &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; потоках, а затем можно применить суммирование методом сдваивания, о котором сказано в следующем разделе. Умножение или деление вектора на вещественное число являющееся, по определению, умножением или делением всех его координат на это число тоже может быть выполнено эффективнее, если мы используем &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; потоков, а не выполняем эти действия последовательно.&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
Параллельные операции возможны только внутри итераций, так как рассматриваемый алгоритм является итерационным, и сами итерации строго последовательны.&amp;lt;br&amp;gt;&lt;br /&gt;
Рассмотрим в этом разделе подробнее, какой выигрыш мы можем получить при распараллеливании операций внутри одной итерации согласно графу из предыдущего раздела.&lt;br /&gt;
&lt;br /&gt;
Умножение вещественной симметричной матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; размера &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;n\times n&amp;lt;/math&amp;gt; на вектор &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;b&amp;lt;/math&amp;gt; длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; требует последовательного выполнения &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; ярусов умножений и сложений. Сложение элементов вектора длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; на каждом шаге перемножения можно оптимизировать и выполнить за &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;\log_2 n&amp;lt;/math&amp;gt; действий, если применять метод сдваивания.&lt;br /&gt;
&lt;br /&gt;
Дальнейшие операции выполняются последовательно, а вычисление значений векторов происходит за один ярус операций сложения или умножения.&lt;br /&gt;
&lt;br /&gt;
Ресурс параллелизма алгоритма вычисления собственных значений построенной трёхдиагональной матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_k&amp;lt;/math&amp;gt; размера &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k\times k&amp;lt;/math&amp;gt; зависит от выбранного алгоритма (об этих алгоритмах подробнее было сказано в разделах 1.2 и 1.4). Будет очень затратно с точки зрения объёма материала пытаться рассмотреть пусть даже часть этих методов в этой статье, а так же тонкости их распараллеливания. Предлагаем читателям при желании самим ознакомиться с этими алгоритмами на данном ресурсе или прибегнув к иным источникам.&lt;br /&gt;
&lt;br /&gt;
При классификации по высоте ЯПФ, таким образом, алгоритм Ланцоша без переортогонализации относится к алгоритмам с &#039;&#039;логарифмической сложностью&#039;&#039;, и его сложность равна &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(\log_2 n)&amp;lt;/math&amp;gt; с важным замечанием, что это сложность только одной итерации, а максимум в алгоритме может быть выполнено последовательно &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;/math&amp;gt; таких однотипных итераций, если не будет осуществлён ранний выход из цикла. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Несмотря на то, что на графе в предыдущем разделе для лучшей визуализации и понимания было изображено &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; потоков (никаких допущений мы не делали и нарушений с точки зрения логики и математики нет, можно изобразить большее число потоков, просто часть времени некоторые из них могут бездействовать и не использоваться), на самом деле правильным и разумным будет реализовать начальное параллельное выполнение &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n^2&amp;lt;/math&amp;gt; операций умножения всех вещественных элементов матрицы &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;A&amp;lt;/math&amp;gt; на соответствующие элементы вектора &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;q_j&amp;lt;/math&amp;gt;, после чего применять тот же самый упомянутый метод сдваивания. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Поэтому при классификации по ширине ЯПФ его сложность будет &#039;&#039;квадратичной&#039;&#039; и равна &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(n^2)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
&#039;&#039;&#039;Входные данные алгоритма:&#039;&#039;&#039; вещественная симметричная &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; размера &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;n\times n&amp;lt;/math&amp;gt;, вещественный вектор &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;b&amp;lt;/math&amp;gt; длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt;, и одно целое число &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;k&amp;lt;/math&amp;gt;, означающее количество итераций.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём входных данных:&#039;&#039;&#039; &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;n^2 +n + 1 &amp;lt;/math&amp;gt;. Если учесть, что матрица симметричная и достаточно для её однозначного определения задать элементы на главной диагонали и элементы над или под ней, то можно сократить объём входных данных с целью экономии памяти до: &amp;lt;math&amp;gt;\ \frac{n^2-n}{2}+n+n+1 =\frac{n^2+3n}{2} + 1&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные алгоритма:&#039;&#039;&#039; вектор собственных значений &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;\Theta^k&amp;lt;/math&amp;gt; длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;/math&amp;gt;, матрица &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;S^k&amp;lt;/math&amp;gt; из соответствующих собственных векторов размера &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n\times k&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём выходных данных:&#039;&#039;&#039; &amp;lt;math&amp;gt;k\;(n + 1)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
В данном разделе перечислены без какой-либо хронологии или связи друг с другом наиболее важные и разнообразные свойства алгоритма, на которые стоит и полезно обратить внимание, а также которые выгодно отличают его от схожих алгоритмов, решающих ту же задачу.&amp;lt;br&amp;gt;&lt;br /&gt;
1) Отношение последовательной сложности алгоритма к параллельной,с учётом &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;/math&amp;gt; итераций, равно &amp;lt;math&amp;gt;\;\;\frac{kn^2}{k \log_2{n}}=\frac{n^2}{\log_2{n}}&amp;lt;/math&amp;gt;;&amp;lt;br&amp;gt;&lt;br /&gt;
2) Вычислительная мощность алгоритма, как отношение числа операций к суммарному объему входных и выходных данных, равна &amp;lt;math style=&amp;quot;vertical-align:-70%&amp;gt;\;\;\frac{k\,n^2}{0.5\,n^2+1.5\,n+k\,n+k+1}&amp;lt;/math&amp;gt; и &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;\approx 2\,k&amp;lt;/math&amp;gt;, так как на практике верно отношение &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;&amp;lt;n&amp;lt;/math&amp;gt; ;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
3) Для собственных значений формируемых матриц &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_j&amp;lt;/math&amp;gt; верно отношение (следствие теоремы Коши о перемежаемости): &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;\lambda_i(T_{k+1})\geq \lambda_i(T_{k})\geq \lambda_{i+1}(T_{k+1})\geq \lambda_{i+1}(T_{k})&amp;lt;/math&amp;gt; ;&amp;lt;ref&amp;gt;James W. Demmel - Вычислительная линейная алгебра. Теория и приложения //Мир. - 2001 (c. 383)&amp;lt;/ref&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
4) Крайние (наибольшие и наименьшие) собственные значения матриц &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_j&amp;lt;/math&amp;gt; сходятся к крайним собственным значениям матрицы &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;A&amp;lt;/math&amp;gt; первыми (это часто происходит уже на ранних шагах при &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j\approx 2\,\sqrt{n}&amp;lt;/math&amp;gt;&amp;lt;ref&amp;gt;http://num-anal.srcc.msu.ru/lib_na/int_ae/int_ae6.htm (пункт 6.5)&amp;lt;/ref&amp;gt;), а собственные значения в середине спектра - последними;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
5) Из-за ограниченной точности постепенно теряется ортогональность вектора Ланцоша &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;q_j&amp;lt;/math&amp;gt; к предыдущим векторам Ланцоша, поэтому необходимо примерно каждые 10-15 итераций проводить дорогостоящую операцию реортогонализации, но это уже будет иной алгоритм с очень малым различием в одной операции и в программном коде, реализующем его, соответственно; &amp;lt;ref&amp;gt;Sam Handler - The Lanczos Algorithm For Large-Scale Eigenvalue Problems (08.01.07), slide №8&amp;lt;/ref&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
6) Эффективность и быстрота выполнения алгоритма очень сильно зависит от скорости памяти (диска). Согласно тесту только &#039;&#039;6%&#039;&#039; времени работы программы приходится на вычисления, остальное время затрачивается на ожидание отклика диска;&amp;lt;ref&amp;gt;Sam Handler - The Lanczos Algorithm For Large-Scale Eigenvalue Problems (08.01.07), slide №10&amp;lt;/ref&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
7) Метод Ланцоша удобен тем, что не требует хранения исходной матрицы полным массивом: метод использует исходную матрицу только в операциях умножения матрицы на вектор, что позволяет эффективно использовать разреженность матрицы или регулярность структуры матрицы. Поэтому метод Ланцоша может быть использован для матриц таких больших порядков, когда методы вращений и отражений не могут быть применены.&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;
Для исследования масштабируемости рассматриваемого алгоритма Ланцоша без переортогонализации автором была реализована программа на языке С++ с использованием технологии MPI. &amp;lt;ref&amp;gt;https://goo.gl/dGfzOD  или альтернативная ссылка с прикреплённым кодом: https://goo.gl/lFziv0 , по просьбе на почту, я (автор статьи) готов предоставить желающим доступ к проекту с этим кодом на Bitbucket&amp;lt;/ref&amp;gt; Дальнейшее исследование было проведено на суперкомпьютере &amp;quot;Ломоносов&amp;quot; Суперкомпьютерного комплекса МГУ. &amp;lt;br&amp;gt; Важно отметить, что реализованная программа выполняет только первую часть алгоритма - формирование матрицы &amp;lt;math &amp;gt;T_j&amp;lt;/math&amp;gt;. Вторая часть алгоритма (задача поиска собственных значений матрицы &amp;lt;math &amp;gt;T_j&amp;lt;/math&amp;gt;) может быть решена несколькими методами, каждый из которых обладает своей эффективностью распараллеливании и характерными свойствами. Подробно этот вопрос уже обсуждался в статье раннее, поэтому не будем ещё раз заострять на этом внимание и останавливаться.&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Сборка осуществлялась со следующими параметрами:&lt;br /&gt;
* Компилятор intel/15.0.090 &lt;br /&gt;
* Openmpi/1.8.4-icc&lt;br /&gt;
В серии проведённых расчётов рассматривались следующие числовые значения параметров:&lt;br /&gt;
* Размер &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;n&amp;lt;/math&amp;gt; задачи и, соответственно, матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt;, задействованной в операции умножения на вектор: [2000 : 30000] с шагом 1000&lt;br /&gt;
* Число процессоров: 1, 2, 4, 16, 32, 48, 64, 96, 128&lt;br /&gt;
* Число итераций в алгоритме: &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k=350&amp;lt;/math&amp;gt;&lt;br /&gt;
Число &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; взято таким вопреки информации в начале статьи, где говорится, что значение &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; редко превышает &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;10^2&amp;lt;/math&amp;gt; (хоть мы и имеем право брать его любым по нашему усмотрению). Это сделано исключительно для лучшей визуализации пиков на графиках в данном разделе и наглядности получаемых результатов, так как при меньших на порядок значениях &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; времена выполнения программ были слишком малы даже при минимальных числах процессоров и максимальных размерах &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;n&amp;lt;/math&amp;gt; задачи.&lt;br /&gt;
&lt;br /&gt;
== Динамические характеристики и эффективность реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Выводы для классов архитектур ==&lt;br /&gt;
По заданию, во второй части требовалось описать только разделы 2.4 и 2.7, прошу не спрашивать с меня все разделы 2.1-2.6. Надеюсь на понимание, мне физически не хватает времени на это задание + 2 других в течение семестра, делаю всё, что в моих силах :)&lt;br /&gt;
&lt;br /&gt;
== Существующие реализации алгоритма ==&lt;br /&gt;
Несмотря на то, что алгоритм является далеко не самым популярным, алгоритмом, про который нельзя сказать, что он всегда «на слуху», на сегодняшний день существует множество реализаций на различных популярных языках.&amp;lt;br&amp;gt;&lt;br /&gt;
Перечислим далее некоторые из них, указывая язык программирования, лежащий в их основе, и некоторые важные характеристики, которые обсуждались в статье ранее:&lt;br /&gt;
*&#039;&#039;Code on netlib.org by Jane Cullum and Ralph Willoughby&#039;&#039; (&#039;&#039;&#039;Fortran 77&#039;&#039;&#039;; без реортогонализации векторов; без реализации распараллеливания)&amp;lt;ref&amp;gt;http://www.netlib.org/lanczos/leval&amp;lt;/ref&amp;gt;&lt;br /&gt;
*&#039;&#039;Lanczos algorithm on freesourcecode.net&#039;&#039; (&#039;&#039;&#039;Matlab&#039;&#039;&#039;; присутствует реортогонализация векторов; без реализации распараллеливания)&amp;lt;ref&amp;gt;http://freesourcecode.net/matlabprojects/61741/lanczos-algorithm--in-matlab&amp;lt;/ref&amp;gt;&lt;br /&gt;
*&#039;&#039;Lanczos for eigenvalues in Numerical Linear Algebra, Spring 2007&#039;&#039; (&#039;&#039;&#039;Matlab&#039;&#039;&#039;; частичная или полная реортогонализация - доступны оба варианта; без реализации распараллеливания)&amp;lt;ref&amp;gt;Ссылки на файлы lanso.m и lanfu.m можно найти на https://www.nada.kth.se/~ruhe/2D5219/labs2007.html&amp;lt;/ref&amp;gt;&lt;br /&gt;
*&#039;&#039;Planso&#039;&#039; (название происходит от parallel Lanso.f) &#039;&#039;code by Kesheng Wu and Horst D. Simon&#039;&#039; (&#039;&#039;&#039;Fortran 77&#039;&#039;&#039;; частичная реортогонализация векторов; использование MPI для коммуникаций)&amp;lt;ref&amp;gt;https://github.com/jiahao/planso.jl/tree/master/external/PLAN/plan К сожалению, ссылка в описании пакета на github, ведущая на сайт National Energy Research Scientific Computing Center (NERSC), с более подробной информацией о данной программе больше не активна и выдаёт результат &#039;&#039;Page not found&#039;&#039;&amp;lt;/ref&amp;gt; &lt;br /&gt;
* &#039;&#039;Lanczos.cpp in the Vienna Computing Library&#039;&#039;  (&#039;&#039;&#039;C++&#039;&#039;&#039;, частичная реортогонализация, без реализации распараллеливания) &amp;lt;ref&amp;gt;http://viennacl.sourceforge.net/doc/lanczos_8cpp_source.html&amp;lt;/ref&amp;gt;&lt;br /&gt;
* &#039;&#039;Parallel Eigen Values code using C++ AMP on microsoft msdn blog&#039;&#039; (&#039;&#039;&#039;C++&#039;&#039;&#039;; ? ; распараллеливание есть и реализовано через C++ AMP) &amp;lt;ref&amp;gt;https://blogs.msdn.microsoft.com/nativeconcurrency/2013/12/20/eigen-values/ Подробнее о C++ Accelerated Massive Parallelism можно почитать здесь: https://msdn.microsoft.com/ru-ru/library/hh265137(v=vs.140).aspx или здесь: http://professorweb.ru/my/csharp/optimization/level4/4_6.php &amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;br /&gt;
[[en:Description of algorithm properties and structure]]&lt;/div&gt;</summary>
		<author><name>AleksLevin</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:AleksLevin/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%9B%D0%B0%D0%BD%D1%86%D0%BE%D1%88%D0%B0_%D0%B2%D1%8B%D1%87%D0%B8%D1%81%D0%BB%D0%B5%D0%BD%D0%B8%D1%8F_%D1%81%D0%BE%D0%B1%D1%81%D1%82%D0%B2%D0%B5%D0%BD%D0%BD%D1%8B%D1%85_%D0%B7%D0%BD%D0%B0%D1%87%D0%B5%D0%BD%D0%B8%D0%B9_%D1%81%D0%B8%D0%BC%D0%BC%D0%B5%D1%82%D1%80%D0%B8%D1%87%D0%BD%D0%BE%D0%B9_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86%D1%8B_%D0%B4%D0%BB%D1%8F_%D1%82%D0%BE%D1%87%D0%BD%D0%BE%D0%B9_%D0%B0%D1%80%D0%B8%D1%84%D0%BC%D0%B5%D1%82%D0%B8%D0%BA%D0%B8_(%D0%B1%D0%B5%D0%B7_%D0%BF%D0%B5%D1%80%D0%B5%D0%BE%D1%80%D1%82%D0%BE%D0%B3%D0%BE%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D0%B8)&amp;diff=20220</id>
		<title>Участник:AleksLevin/Алгоритм Ланцоша вычисления собственных значений симметричной матрицы для точной арифметики (без переортогонализации)</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:AleksLevin/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%9B%D0%B0%D0%BD%D1%86%D0%BE%D1%88%D0%B0_%D0%B2%D1%8B%D1%87%D0%B8%D1%81%D0%BB%D0%B5%D0%BD%D0%B8%D1%8F_%D1%81%D0%BE%D0%B1%D1%81%D1%82%D0%B2%D0%B5%D0%BD%D0%BD%D1%8B%D1%85_%D0%B7%D0%BD%D0%B0%D1%87%D0%B5%D0%BD%D0%B8%D0%B9_%D1%81%D0%B8%D0%BC%D0%BC%D0%B5%D1%82%D1%80%D0%B8%D1%87%D0%BD%D0%BE%D0%B9_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86%D1%8B_%D0%B4%D0%BB%D1%8F_%D1%82%D0%BE%D1%87%D0%BD%D0%BE%D0%B9_%D0%B0%D1%80%D0%B8%D1%84%D0%BC%D0%B5%D1%82%D0%B8%D0%BA%D0%B8_(%D0%B1%D0%B5%D0%B7_%D0%BF%D0%B5%D1%80%D0%B5%D0%BE%D1%80%D1%82%D0%BE%D0%B3%D0%BE%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D0%B8)&amp;diff=20220"/>
		<updated>2016-12-07T00:23:57Z</updated>

		<summary type="html">&lt;p&gt;AleksLevin: /* Масштабируемость алгоритма и его реализации */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Основные авторы описания: Левин А.Д.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{algorithm&lt;br /&gt;
| name              = Алгоритм Ланцоша для точной арифметики (без переортогонализации)&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(k\,n^2)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(k\log_2 n)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;\frac{n^2+3n}{2} + 1&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;k\;(n + 1)&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритмов =&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Данный алгоритм появился в 1950 г. и носит имя венгерского физика и математика Корнелия Ланцоша (венг. Lánczos Kornél). Алгоритм Ланцоша относится к итерационным методам вычисления собственных значений для матриц столь больших порядков &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt; n&amp;lt;/math&amp;gt;, что к ним нельзя применить прямые методы из-за ограничений по времени и памяти.&lt;br /&gt;
&lt;br /&gt;
Сам Ланцош указывал, что его метод предназначен для отыскания нескольких собственных векторов симметричных матриц, хотя к методу сразу было обращено внимание, как к способу приведения всей матрицы к трёхдиагональному виду. Двадцатью годами позже канадский математик Крис Пэж показал, что, несмотря на чувствительность к округлениям, алгоритм Ланцоша - эффективное средство вычисления некоторых &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; собственных чисел и соответствующих им собственных векторов. &amp;lt;ref&amp;gt;Парлетт Б. - Симметричная проблема собственных значений. Численные методы //М.: Мир. - 1983. (c. 276)&amp;lt;/ref&amp;gt;&lt;br /&gt;
Обычно число &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; берут в два раза больше, чем количество собственных значений матрицы, которые поставлена цель найти, и оно имеет порядок не более &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;10^2&amp;lt;/math&amp;gt;.&amp;lt;ref&amp;gt;Susan W. Bostic - Lanczos Eigensolution Method for High-Perfomance Computers, page 7&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Алгоритм Ланцоша для вычисления собственных значений симметричной матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; соединяет в себе метод Ланцоша для построения последовательности подпространств Крылова и ортонормированных векторов Ланцоша и процедуру Рэлея-Ритца получения оптимальных приближений собственных значений и соответствующих собственных векторов исходной матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt;.&amp;lt;ref&amp;gt;James W. Demmel - Вычислительная линейная алгебра. Теория и приложения //Мир. - 2001 (c. 381)&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
В данной статье рассматривается вариант алгоритма Ланцоша, в котором опущено влияние ошибок округления на вычислительный процесс, хотя на практике этому посвящается отдельное внимание и существуют различные методы решения данной проблемы, такие как частичная или полная переортогонализация. Этим модифицированным методам посвящены отдельные статьи на данном ресурсе.&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
Обозначения и формулы, используемые в данном разделе, взяты из литературы, указанной по ссылке.&amp;lt;ref&amp;gt;James W. Demmel - Вычислительная линейная алгебра. Теория и приложения //Мир. - 2001 (c. 313, &#039;&#039;&amp;lt;math&amp;gt; \S &amp;lt;/math&amp;gt; 6.6 Методы Крыловского подпространства&#039;&#039;)&amp;lt;/ref&amp;gt; &lt;br /&gt;
&lt;br /&gt;
Алгоритм Ланцоша для вычисления &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; собственных значений и собственных векторов вещественной симметричной матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A=A^T&amp;lt;/math&amp;gt; в точной арифметике: &amp;lt;ref&amp;gt;James W. Demmel - Вычислительная линейная алгебра. Теория и приложения //Мир. - 2001 (c. 381)&amp;lt;/ref&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{align}&lt;br /&gt;
q_1 = &amp;amp; \,\frac{b}{\|b\|_2},\; \beta_0 = 0,\; q_0 = 0\\&lt;br /&gt;
\mathbf{for} \; &amp;amp; j = 1 \; to \; k \,\; \mathbf{do} \\&lt;br /&gt;
&amp;amp; z = A\,q_j\\&lt;br /&gt;
&amp;amp; \alpha_j = q^T_j z\\&lt;br /&gt;
&amp;amp; z = z - \alpha_j q_j - \beta_{j-1}q_{j-1}\\&lt;br /&gt;
&amp;amp; \beta_j = \|z\|_2\\&lt;br /&gt;
&amp;amp; \mathbf{If} \; (\beta_j == 0) \; \mathbf{then}\; stop\; the\; algorithm \\ &lt;br /&gt;
&amp;amp; \;  q_{j+1} = \frac{z}{\beta_j} \\&lt;br /&gt;
&amp;amp; compute\; eigenvalues\; and \;eigenvectors\;of \;matrix \;\;T_j= Q^T_j A Q\;\;and\;estimate \;the\; errors\\&lt;br /&gt;
\mathbf{end} \; &amp;amp; \mathbf{for}&lt;br /&gt;
\end{align}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
В продемонстрированном выше алгоритме &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;b&amp;lt;/math&amp;gt; - заданный вещественный вектор. Также полагается известным алгоритм вычисления произведения матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; на вектор &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;x&amp;lt;/math&amp;gt;. &lt;br /&gt;
Введём матрицу Крылова, определяемую следующим соотношением: &amp;lt;math&amp;gt;K_j = [b,Ab,A^2b,...,A^{j-1}b]&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Далее, на практике, матрица &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;K&amp;lt;/math&amp;gt; заменяется матрицей &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;Q&amp;lt;/math&amp;gt;, такой, что при любом числе &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; линейные оболочки первых &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; столбцов в &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;K&amp;lt;/math&amp;gt; и &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;Q&amp;lt;/math&amp;gt; являются одним и тем же подпространством.&amp;lt;ref&amp;gt;James W. Demmel - Вычислительная линейная алгебра. Теория и приложения //Мир. - 2001 (c. 315)&amp;lt;/ref&amp;gt; &lt;br /&gt;
Тогда матрица &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;Q&amp;lt;/math&amp;gt;, в отличие от матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;K&amp;lt;/math&amp;gt;, хорошо обусловлена и легко обратима. В результате получаем матрицу &amp;lt;math&amp;gt;Q_j = [q_1, q_2, \dots, q_j]&amp;lt;/math&amp;gt; размерности &amp;lt;math&amp;gt;n\times j&amp;lt;/math&amp;gt;, столбцы которой ортогональны, являются базисом подпространства Крылова и называются векторами Ланцоша.&lt;br /&gt;
&lt;br /&gt;
В алгоритме Ланцоша вычислению подлежит столько первых столбцов в матрице &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;Q_j&amp;lt;/math&amp;gt;, сколько необходимо для получения требуемого приближения к решению &amp;lt;math&amp;gt;A\,x\,=b\,\,(A\,x=\lambda \, x)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Получение нулевого &amp;lt;math&amp;gt;\beta_j&amp;lt;/math&amp;gt; в итерационном процессе - событие, желательное в том смысле, что оно свидетельствует о том, что найдено некоторое подпространство, являющееся в точности инвариантным, а все собственные значения матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;T_j&amp;lt;/math&amp;gt; являются собственными значениями матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt;. На практике же нулевое и близкие к нулю значения получаются редко.&amp;lt;ref&amp;gt;Голуб Дж., Ван Лоун Ч. - Матричные вычисления//М.: Мир. - 1999 (c. 429)&amp;lt;/ref&amp;gt; &lt;br /&gt;
&lt;br /&gt;
Затем на каждом шаге цикла формируется симметричная трёхдиагональная матрица &amp;lt;math&amp;gt;T_j = Q^T_j A Q&amp;lt;/math&amp;gt;, к которой применяется процесс Рэлея-Ритца для поиска её собственных значений (на практике для поиска этих собственных значений можно использовать любой из специальных методов в параграфе книги по ссылке).&amp;lt;ref&amp;gt;Голуб Дж., Ван Лоун Ч. - Матричные вычисления//М.: Мир. - 1999 (&amp;lt;math&amp;gt;\S&amp;lt;/math&amp;gt; 8.4)&amp;lt;/ref&amp;gt;  &lt;br /&gt;
Эти собственные значения, они же числа Ритца, и полагаются приближёнными собственными значениями исходной матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt;.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Существует множество методов для отыскания собственных значений вещественной симметричной трехдиагональной матрицы. Большинство из них требует &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt; операций &amp;lt;ref&amp;gt;Парлетт Б. Симметричная проблема собственных значений. Численные методы.,: Мир, 1983. с. 179-182&amp;lt;/ref&amp;gt;, но существуют и быстрые алгоритмы, требующие лишь &amp;lt;math&amp;gt;O(n\ln n)&amp;lt;/math&amp;gt; операций.&amp;lt;ref&amp;gt;https://en.wikipedia.org/wiki/Tridiagonal_matrix#Eigenvalues  Раздел eigenvalues&amp;lt;/ref&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Одним из возможных способов отыскать собственные значения симметричной трехдиагональной матрицы - прямое вычисление корней характеристического полинома &amp;lt;math&amp;gt;p_n(\lambda)&amp;lt;/math&amp;gt; через метод деления пополам, где формируется последовательность Штурма и локализуются собственные числа, являющиеся корнями характеристического полинома. Нахождение всех &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; собственных значений матрицы этим способом требует &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;2n^2t&amp;lt;/math&amp;gt; умножений и вычитаний, где &amp;lt;math&amp;gt;t&amp;lt;/math&amp;gt; - число сделанных шагов с применением метода деления пополам.&amp;lt;ref&amp;gt;Уилкинсон Дж. X. Алгебраическая проблема собственныx значений. Изд-во &amp;quot;Наука&amp;quot;, 1970. - глава 5, с. 272-278&amp;lt;/ref&amp;gt; Соответствующие собственные вектора могут быть найдены посредством обратных итераций за &amp;lt;math&amp;gt; O(n) &amp;lt;/math&amp;gt; флопов. &amp;lt;ref&amp;gt;Голуб Дж., Ван Лоун Ч. - Матричные вычисления//М.: Мир. - 1999 (c. 394-395)&amp;lt;/ref&amp;gt; &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;На практике, если требуется только небольшая часть от всей совокупности собственных векторов и значений, и матрица имеет Хессенбергову или трёхдиагональную форму, очень эффективными будут методы факторизации, как, например, QR-алгоритм или QL-алгоритм со сдвигами (c целью ускорить алгоритм и сделать порядок сходимости квадратичным) или же без них.&amp;lt;ref&amp;gt;http://algorithm.narod.ru/ln/eigen/ETridiag.html&amp;lt;/ref&amp;gt; &amp;lt;br&amp;gt;&lt;br /&gt;
Весьма молодые и не менее актуальные конкуренты QR и QL алгоритмов, применяющиеся для поиска собственных значений:&lt;br /&gt;
*Методы divide-and-conquer (разделяй и властвуй), появившиеся в 1980-ых годах &amp;lt;ref&amp;gt;https://goo.gl/dapvbn ссылку пришлось сократить с помощью Google url shortener, так как символы подчеркивания портили её и не давали перейти по 1 клику&amp;lt;/ref&amp;gt;&lt;br /&gt;
*Relatively robust representation методы, появившиеся в 1990-ых и позволяющие найти собственные числа симметричной матрицы порядка &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;n&amp;lt;/math&amp;gt; за &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt; операций&lt;br /&gt;
&lt;br /&gt;
Если требуется вычислить собственные векторы, то необходимо хранить вычисляемые векторы Ланцоша. Если работа при этом производится только с оперативной памятью, то при большом порядке исходной матрицы (а именно для таких матриц и предназначен метод Ланцоша) число шагов  &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;j&amp;lt;/math&amp;gt;, которые могут быть выполнены до того момента, как оперативная память будет исчерпана, будет очень незначительно, а следовательно, искомые собственные пары могут не успеть сойтись с требуемой точностью. В этом случае метод Ланцоша можно использовать итерационным образом: после выполнения заданного числа шагов процесс прерывается и, если еще не все требуемые пары Ритца сошлись с требуемой точностью, то формируется новый начальный вектор &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;q_1&amp;lt;/math&amp;gt;, являющийся линейной комбинацией векторов Ритца, еще не сошедшихся с заданной точностью, и процесс начинается заново.&amp;lt;ref&amp;gt;http://num-anal.srcc.msu.ru/lib_na/int_ae/int_ae6.htm (пункт 6.5)&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
Вычислительное ядро рассматриваемого алгоритма (наиболее ресурсно-затратная часть алгоритма) -  формирование на каждом шаге цикла промежуточного вектора &amp;lt;math&amp;gt;z&amp;lt;/math&amp;gt;, вычисляемого по формуле: &amp;lt;math&amp;gt;z = A\,q_j&amp;lt;/math&amp;gt;. Данная операция, по сравнению с другими операциями алгоритма, затратна и требовательна, как с точки зрения количества производимых операций, так и с точки зрения объема оперируемых данных. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Например, умножение матрицы размера &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;n\times n&amp;lt;/math&amp;gt; на вектор длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; требует: &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;n^2+(n-1)n = 2n^2-n&amp;lt;/math&amp;gt; операций умножения и сложения. В свою очередь аналогичная операция умножения матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;(n+1)\times (n+1)&amp;lt;/math&amp;gt; на вектор длины &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;(n+1)&amp;lt;/math&amp;gt; требует: &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;2n^2+3n+1&amp;lt;/math&amp;gt;  операций умножения и сложения. То есть повышение размерности задачи всего на 1 увеличивает число необходимых действий в этом шаге алгоритма на: &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;4n+1&amp;lt;/math&amp;gt;. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Так же, стоит помнить, что, согласно разделу 1.2, данную операцию умножения матрицы на вектор необходимо выполнить &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;k&amp;lt;/math&amp;gt; раз. Нетрудно понять, насколько возрастает и колоссален масштаб операций, если в задачах, где критична точность, размерности &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; могут иметь порядок &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;10^5&amp;lt;/math&amp;gt; или даже более.&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
Как уже было упомянуто в данной статье в описании алгоритма, рассматриваемый алгоритм состоит из двух последовательно выполненных алгоритмов: метод Ланцоша для построения последовательности подпространств Крылова и ортонормированных векторов Ланцоша и процедура Рэлея-Ритца получения оптимальных приближений собственных значений и соответствующих собственных векторов исходной матрицы.&lt;br /&gt;
&lt;br /&gt;
В первой части алгоритма, где итерационно строятся Крыловское подпространство и трёхдиагональная матрица &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&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 style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; разреженная. Именно она подлежит оптимизации с использованием техник распараллеливания, поскольку она является вычислительным ядром алгоритма, а весь упомянутый процесс построения матрицы &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&amp;lt;/math&amp;gt; выполняется последовательно.&lt;br /&gt;
&lt;br /&gt;
Рассмотрим вторую часть алгоритма - поиск собственных значений сформированной матрицы &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&amp;lt;/math&amp;gt;.&amp;lt;br&amp;gt;&lt;br /&gt;
Далее, наглядно, в виде псевдокода, представлен, упомянутый в разделе 1.2, QR-алгоритм (аналогично можно рассмотреть и QL-алгоритм) со сдвигами Релэя, который весьма популярен на практике.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{align}&lt;br /&gt;
\mathbf{Input}: \;&amp;amp;tridiagonal\;\;matrix \;T\;with\;\;n\times n\;\;size\\&lt;br /&gt;
T^{(0)}&amp;amp;:=T\\&lt;br /&gt;
\mathbf{for}&amp;amp; \;\;m=n,...,2 \;\; \mathbf{do}\\&lt;br /&gt;
&amp;amp;k=0\\&lt;br /&gt;
&amp;amp; \mathbf{repeat}\\&lt;br /&gt;
&amp;amp; \quad \;\; k=k+1\\&lt;br /&gt;
&amp;amp; \quad \;\; \mu^{(k)}=T_{m,m}^{(k-1)}\\&lt;br /&gt;
&amp;amp; \quad \;\; Q^{(k)}R^{(k)}=T^{(k-1)}-\mu^{(k)}I\;\;using\;\;QR\;decomposition\\&lt;br /&gt;
&amp;amp; \quad \;\; T^{(k)}=R^{(k)}Q^{(k)}+\mu^{(k)}I\\&lt;br /&gt;
&amp;amp; \mathbf{until} \;\;\; |T_{m,m-1}^{(k)}| \;is\;\;small\;\;enough\\&lt;br /&gt;
&amp;amp; Save  \;\;T_{m,m}^{(k)} \;\;as\;\; converged\;\;eigenvalue\;of\;T\\ &lt;br /&gt;
&amp;amp; Remove \;\boldsymbol{n}\,th\;row\;and\;\boldsymbol{n}\,th\;column\;\;from \;T \\&lt;br /&gt;
&amp;amp; and\;take\;this\;new\;cropped\;matrix\;as\;new\;T^{(0)}\;with\;\;(n-1)\times (n-1)\;\;size\\&lt;br /&gt;
 \mathbf{end}&amp;amp;\; \mathbf{for}&lt;br /&gt;
\end{align}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Малость наддиагональных и поддиагональных элементов матрицы (фраза &#039;&#039;&amp;quot;small enough&amp;quot;&#039;&#039; в псевдокоде) подразумевает:&lt;br /&gt;
&amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt; |T_{m,m-1}^{(k)}| \leq \varepsilon\,|T_{m,m}^{(k)}| \quad\quad &amp;lt;/math&amp;gt; , где &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt; \varepsilon &amp;lt;/math&amp;gt; - заданная точность&amp;lt;br&amp;gt;&lt;br /&gt;
Также вместо сдвига Релэя, обозначенного в алгоритме через &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;\mu^{(k)}&amp;lt;/math&amp;gt;, часто на практике используется сдвиг по Уилкинсону, который даёт гарантированную сходимость внедиагональных элементов матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt; T^{(k)} &amp;lt;/math&amp;gt;, формируемой на каждом шаге, к нулю, при этом жертвуя монотонностью их убывания.&amp;lt;ref&amp;gt;Голуб Дж., Ван Лоун Ч. - Матричные вычисления//М.: Мир. - 1999 (c. 378, вторая половина страницы)&amp;lt;/ref&amp;gt;&amp;lt;ref&amp;gt;Парлетт Б. Симметричная проблема собственных значений. Численные методы.,: Мир, 1983. с. 169&amp;lt;/ref&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Подробнее с различными сдвигами и соответствующими оценками скоростей и количествами операций можно ознакомиться по указанной ссылке:&amp;lt;ref&amp;gt;Парлетт Б. Симметричная проблема собственных значений. Численные методы.,: Мир, 1983. с. 179-182&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;Для совершения QR-декомпозиции на каждом шаге может использоваться любой из алгоритмов по ссылке.&amp;lt;ref&amp;gt;https://en.wikipedia.org/wiki/QR_decomposition&amp;lt;/ref&amp;gt; Подробные описания этих алгоритмов также доступны на данном ресурсе algowiki-project.&amp;lt;br&amp;gt;&lt;br /&gt;
Так как мы оперируем не обычной матрицей и даже не Хессенберговой, а симметричной и трёхдиагональной, то скорость таких алгоритмов значительно возрастёт. Например, согласно данному ресурсу &amp;lt;ref&amp;gt;http://algorithm.narod.ru/ln/eigen/ETridiag.html&amp;lt;/ref&amp;gt;, для QL-алгоритма с неявными сдвигами:&amp;lt;br&amp;gt;&lt;br /&gt;
Для трёхдиагональной матрицы объем арифметических действий составляет &amp;lt;math&amp;gt; O(n)&amp;lt;/math&amp;gt; на одну итерацию вместо &amp;lt;math&amp;gt; O(n^3)&amp;lt;/math&amp;gt; для матрицы общего вида, а число итераций для нахождения первых собственных значений примерно равно 4 - 5. Но на этих итерациях также уменьшаются внедиагональные элементы правого нижнего угла. И, таким образом, дальнейшие собственные значения ищутся значительно быстрее. Среднее число итераций на каждое собственное значение обычно составляет 1.3 - 1.6.&amp;lt;br&amp;gt; &lt;br /&gt;
Аналогично QL, QR-разложение трёхдиагольной матрицы также требует &amp;lt;math&amp;gt; O(n)&amp;lt;/math&amp;gt; флопов&amp;lt;ref&amp;gt;Голуб Дж., Ван Лоун Ч. - Матричные вычисления//М.: Мир. - 1999 (c. 378, начало раздела 8.2.2)&amp;lt;/ref&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Подводя итог, во второй части алгоритма Ланцоша можно выделить следующие макрооперации:&lt;br /&gt;
* умножение матрицы на вещественное число;&lt;br /&gt;
* перемножение матриц;&lt;br /&gt;
* умножение и сравнение вещественных чисел;&lt;br /&gt;
* + набор других макроопераций в зависимости от выбора метода, с помощью которого будет совершаться сама QR или QL-декомпозиция (выше продемонстрированы, уже, как минимум, 3 разных способа).&lt;br /&gt;
Так же, важно заметить, что набор макропераций может быть несколько другим, если выбрать какой-либо иной современный метод поиска собственных чисел трёхдиагональной матрицы, не использующий QR и QL разложения(факторизацию). Два таких метода были упомянуты в пункте 1.2.&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
С целью полностью не дублировать раздел 1.2 данной статьи, где представлен наглядный и доступный для понимания псевдокод алгоритма, постараемся лишь коротко просуммировать и обобщить весь перечень последовательных действий в рассматриваемом алгоритме.&lt;br /&gt;
&lt;br /&gt;
В качестве входных данных имеем: вещественная симметричная матрица &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; размера &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;n\times n&amp;lt;/math&amp;gt;, известный вещественный вектор &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;b&amp;lt;/math&amp;gt; длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; и число &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;n&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Далее:&lt;br /&gt;
* Инициализируем вещественную константу &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;\beta_0&amp;lt;/math&amp;gt; и векторы &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;q_0&amp;lt;/math&amp;gt; и &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;q_1&amp;lt;/math&amp;gt;&lt;br /&gt;
* Итерационно для всех &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j=1,...,k&amp;lt;/math&amp;gt;:&lt;br /&gt;
** Вычисляем вспомогательный вектор &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt;, используя умножение матрицы на вектор&lt;br /&gt;
** Вычисляем, используя скалярное произведение векторов, значение &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;\alpha_j&amp;lt;/math&amp;gt; - элемент на главной диагонали трёхдиагональной матрицы &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&amp;lt;/math&amp;gt;&lt;br /&gt;
** Вычисляем по формуле новое значение и перезаписываем вектор &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt;&lt;br /&gt;
** Вычисляем значение &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;\beta_j&amp;lt;/math&amp;gt; - элементы непосредственно над и под главной диагональю той же матрицы &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&amp;lt;/math&amp;gt;&lt;br /&gt;
** Вычисляем, зная вектор &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt;,  очередной столбец матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;Q&amp;lt;/math&amp;gt;, он же вектор Ланцоша : &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;\,\,q_{j+1}&amp;lt;/math&amp;gt;&lt;br /&gt;
** Теперь, когда матрица &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&amp;lt;/math&amp;gt; сформирована на очередном шаге, находим её собственные значения и вектора любым доступным способом, о чём было подробно сказано в пункте 1.2&lt;br /&gt;
** Переходим на следующую итерацию: &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j&amp;lt;/math&amp;gt;++&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
Оценим количество операций и сложность последовательного алгоритма, изложенного в предыдущем разделе.&lt;br /&gt;
*Для вычисления вектора &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt; умножается матрица размера &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;n\times n&amp;lt;/math&amp;gt; на вектор длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt;, и потребуется &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n^2&amp;lt;/math&amp;gt; операций умножения и &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n^2&amp;lt;/math&amp;gt; операций сложения.&lt;br /&gt;
*Умножение векторов &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;q^T_j&amp;lt;/math&amp;gt; и &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt; длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; потребует &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; операций умножения и &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; операций сложения.&lt;br /&gt;
*При вычислении нового значения вектора &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt; поэлементное сложение двух векторов длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; требует &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; операций сложения.&lt;br /&gt;
*Умножение вектора длины &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; на вещественное число требует &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; операций умножения.&lt;br /&gt;
*Нахождение квадратичной нормы вектора &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt;  длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; требует &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; умножений и &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; сложений и ещё 1 операцию извлечения квадратного корня.&lt;br /&gt;
*Заключительное нахождение собственных значений и собственных векторов трёхдиагональной матрицы &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;T_j&amp;lt;/math&amp;gt; размера &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j\times j&amp;lt;/math&amp;gt; с помощью QR-алгоритма потребует в худшем случае &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(j^3)&amp;lt;/math&amp;gt; операций.&amp;lt;ref&amp;gt;http://num-anal.srcc.msu.ru/lib_na/int_ae/int_ae6.htm (пункт 6.2, &amp;quot;Скорость сходимости при этом всегда не хуже квадратичной и почти всегда лучше кубической.&amp;quot;)&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Посчитаем теперь суммарное количество простейших операций на одной итерации алгоритма (без учёта записей в память):&lt;br /&gt;
*&amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n^2+5\,n&amp;lt;/math&amp;gt; операций умножения/деления&lt;br /&gt;
*&amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n^2+4\,n&amp;lt;/math&amp;gt; операций сложения/вычитания&lt;br /&gt;
*1 операция извлечения квадратного корня&amp;lt;br&amp;gt;&lt;br /&gt;
Отдельно после всех итераций при &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j=k&amp;lt;/math&amp;gt; :&lt;br /&gt;
*&amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(k^3)&amp;lt;/math&amp;gt; операций для поиска собственных значений и собственных векторов трёхдиагональной матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_k&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Итого можно утверждать следующее:&lt;br /&gt;
&lt;br /&gt;
Последовательная сложность одной итерации рассматриваемого алгоритма:  &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(n ^ 2) &amp;lt;/math&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Суммарная сложность алгоритма (&amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;/math&amp;gt; итераций): &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(k\,n ^ 2) + O(k ^ 3)&amp;lt;/math&amp;gt; &amp;lt;ref&amp;gt;Здесь мы полагаем, что мы не вычисляем собственные значения и векторы матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_j&amp;lt;/math&amp;gt; на каждом промежуточном шаге, а лишь единожды затрачиваем &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;O(k ^ 3)&amp;lt;/math&amp;gt; действий в конце для нахождения &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;/math&amp;gt; собственных значений и векторов матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_k&amp;lt;/math&amp;gt;&amp;lt;/ref&amp;gt; &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
На практике же обычно рассматривается число &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;&amp;lt;n&amp;lt;/math&amp;gt;, поэтому второе слагаемое можно опустить.&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
На рис. 1 продемонстрирован граф одной итерации (при каком-либо произвольном значении итератора &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j&amp;lt;/math&amp;gt;) описанного алгоритма без отображения входных и выходных данных. Наглядно продемонстрированы связи между всеми действиями, и с помощью деления на &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; потоков показано, какие операции возможно выполнять параллельно на каждом шаге с целью оптимизации и экономии машинного времени. В результате, после параллельно выполненных операций &#039;&#039;&#039;Division&#039;&#039;&#039; на заключительном ярусе, на выходе имеем значение следующего вектора Ланцоша &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;q_{j+1}&amp;lt;/math&amp;gt;, после чего следует переход на следующую итерацию, и процесс повторяется.&lt;br /&gt;
&lt;br /&gt;
[[Файл:Levin_graph.png|600px|thumb|center|Рис. 1  Структура одной итерации алгоритма]] &amp;lt;br&amp;gt;&lt;br /&gt;
Обозначения на рисунке: &amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Simp&#039;&#039;&#039; (от англ. simple) - операции сложения и умножения вещественных чисел при вычислении произведения матрицы на вектор;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Vec mult&#039;&#039;&#039; (от англ. vectors multiplication) - операция скалярного умножения двух векторов;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Vec subtr&#039;&#039;&#039; (от англ. vectors subtraction, из-за использованных в операции вычитаний векторов) - операция умножения вектора на число (выполняется дважды) и формирование нового значения &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;z_{new}&amp;lt;/math&amp;gt; по формуле: &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;z_{new} = z - \alpha_j q_j - \beta_{j-1}q_{j-1} \;&amp;lt;/math&amp;gt;;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;||\cdot||&amp;lt;/math&amp;gt; - операция вычисления нормы вектора;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Division&#039;&#039;&#039; - операция деления вектора на вещественное число  &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;\beta_j&amp;lt;/math&amp;gt; &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Важно отметить, что упомянутые выше операции также легко поддаются оптимизации. Например, попарные умножения вещественных координат векторов при вычислении скалярного произведения также легко выполняются параллельно на &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; потоках, а затем можно применить суммирование методом сдваивания, о котором сказано в следующем разделе. Умножение или деление вектора на вещественное число являющееся, по определению, умножением или делением всех его координат на это число тоже может быть выполнено эффективнее, если мы используем &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; потоков, а не выполняем эти действия последовательно.&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
Параллельные операции возможны только внутри итераций, так как рассматриваемый алгоритм является итерационным, и сами итерации строго последовательны.&amp;lt;br&amp;gt;&lt;br /&gt;
Рассмотрим в этом разделе подробнее, какой выигрыш мы можем получить при распараллеливании операций внутри одной итерации согласно графу из предыдущего раздела.&lt;br /&gt;
&lt;br /&gt;
Умножение вещественной симметричной матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; размера &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;n\times n&amp;lt;/math&amp;gt; на вектор &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;b&amp;lt;/math&amp;gt; длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; требует последовательного выполнения &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; ярусов умножений и сложений. Сложение элементов вектора длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; на каждом шаге перемножения можно оптимизировать и выполнить за &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;\log_2 n&amp;lt;/math&amp;gt; действий, если применять метод сдваивания.&lt;br /&gt;
&lt;br /&gt;
Дальнейшие операции выполняются последовательно, а вычисление значений векторов происходит за один ярус операций сложения или умножения.&lt;br /&gt;
&lt;br /&gt;
Ресурс параллелизма алгоритма вычисления собственных значений построенной трёхдиагональной матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_k&amp;lt;/math&amp;gt; размера &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k\times k&amp;lt;/math&amp;gt; зависит от выбранного алгоритма (об этих алгоритмах подробнее было сказано в разделах 1.2 и 1.4). Будет очень затратно с точки зрения объёма материала пытаться рассмотреть пусть даже часть этих методов в этой статье, а так же тонкости их распараллеливания. Предлагаем читателям при желании самим ознакомиться с этими алгоритмами на данном ресурсе или прибегнув к иным источникам.&lt;br /&gt;
&lt;br /&gt;
При классификации по высоте ЯПФ, таким образом, алгоритм Ланцоша без переортогонализации относится к алгоритмам с &#039;&#039;логарифмической сложностью&#039;&#039;, и его сложность равна &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(\log_2 n)&amp;lt;/math&amp;gt; с важным замечанием, что это сложность только одной итерации, а максимум в алгоритме может быть выполнено последовательно &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;/math&amp;gt; таких однотипных итераций, если не будет осуществлён ранний выход из цикла. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Несмотря на то, что на графе в предыдущем разделе для лучшей визуализации и понимания было изображено &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; потоков (никаких допущений мы не делали и нарушений с точки зрения логики и математики нет, можно изобразить большее число потоков, просто часть времени некоторые из них могут бездействовать и не использоваться), на самом деле правильным и разумным будет реализовать начальное параллельное выполнение &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n^2&amp;lt;/math&amp;gt; операций умножения всех вещественных элементов матрицы &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;A&amp;lt;/math&amp;gt; на соответствующие элементы вектора &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;q_j&amp;lt;/math&amp;gt;, после чего применять тот же самый упомянутый метод сдваивания. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Поэтому при классификации по ширине ЯПФ его сложность будет &#039;&#039;квадратичной&#039;&#039; и равна &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(n^2)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
&#039;&#039;&#039;Входные данные алгоритма:&#039;&#039;&#039; вещественная симметричная &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; размера &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;n\times n&amp;lt;/math&amp;gt;, вещественный вектор &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;b&amp;lt;/math&amp;gt; длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt;, и одно целое число &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;k&amp;lt;/math&amp;gt;, означающее количество итераций.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём входных данных:&#039;&#039;&#039; &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;n^2 +n + 1 &amp;lt;/math&amp;gt;. Если учесть, что матрица симметричная и достаточно для её однозначного определения задать элементы на главной диагонали и элементы над или под ней, то можно сократить объём входных данных с целью экономии памяти до: &amp;lt;math&amp;gt;\ \frac{n^2-n}{2}+n+n+1 =\frac{n^2+3n}{2} + 1&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные алгоритма:&#039;&#039;&#039; вектор собственных значений &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;\Theta^k&amp;lt;/math&amp;gt; длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;/math&amp;gt;, матрица &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;S^k&amp;lt;/math&amp;gt; из соответствующих собственных векторов размера &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n\times k&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём выходных данных:&#039;&#039;&#039; &amp;lt;math&amp;gt;k\;(n + 1)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
В данном разделе перечислены без какой-либо хронологии или связи друг с другом наиболее важные и разнообразные свойства алгоритма, на которые стоит и полезно обратить внимание, а также которые выгодно отличают его от схожих алгоритмов, решающих ту же задачу.&amp;lt;br&amp;gt;&lt;br /&gt;
1) Отношение последовательной сложности алгоритма к параллельной,с учётом &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;/math&amp;gt; итераций, равно &amp;lt;math&amp;gt;\;\;\frac{kn^2}{k \log_2{n}}=\frac{n^2}{\log_2{n}}&amp;lt;/math&amp;gt;;&amp;lt;br&amp;gt;&lt;br /&gt;
2) Вычислительная мощность алгоритма, как отношение числа операций к суммарному объему входных и выходных данных, равна &amp;lt;math style=&amp;quot;vertical-align:-70%&amp;gt;\;\;\frac{k\,n^2}{0.5\,n^2+1.5\,n+k\,n+k+1}&amp;lt;/math&amp;gt; и &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;\approx 2\,k&amp;lt;/math&amp;gt;, так как на практике верно отношение &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;&amp;lt;n&amp;lt;/math&amp;gt; ;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
3) Для собственных значений формируемых матриц &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_j&amp;lt;/math&amp;gt; верно отношение (следствие теоремы Коши о перемежаемости): &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;\lambda_i(T_{k+1})\geq \lambda_i(T_{k})\geq \lambda_{i+1}(T_{k+1})\geq \lambda_{i+1}(T_{k})&amp;lt;/math&amp;gt; ;&amp;lt;ref&amp;gt;James W. Demmel - Вычислительная линейная алгебра. Теория и приложения //Мир. - 2001 (c. 383)&amp;lt;/ref&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
4) Крайние (наибольшие и наименьшие) собственные значения матриц &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_j&amp;lt;/math&amp;gt; сходятся к крайним собственным значениям матрицы &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;A&amp;lt;/math&amp;gt; первыми (это часто происходит уже на ранних шагах при &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j\approx 2\,\sqrt{n}&amp;lt;/math&amp;gt;&amp;lt;ref&amp;gt;http://num-anal.srcc.msu.ru/lib_na/int_ae/int_ae6.htm (пункт 6.5)&amp;lt;/ref&amp;gt;), а собственные значения в середине спектра - последними;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
5) Из-за ограниченной точности постепенно теряется ортогональность вектора Ланцоша &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;q_j&amp;lt;/math&amp;gt; к предыдущим векторам Ланцоша, поэтому необходимо примерно каждые 10-15 итераций проводить дорогостоящую операцию реортогонализации, но это уже будет иной алгоритм с очень малым различием в одной операции и в программном коде, реализующем его, соответственно; &amp;lt;ref&amp;gt;Sam Handler - The Lanczos Algorithm For Large-Scale Eigenvalue Problems (08.01.07), slide №8&amp;lt;/ref&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
6) Эффективность и быстрота выполнения алгоритма очень сильно зависит от скорости памяти (диска). Согласно тесту только &#039;&#039;6%&#039;&#039; времени работы программы приходится на вычисления, остальное время затрачивается на ожидание отклика диска;&amp;lt;ref&amp;gt;Sam Handler - The Lanczos Algorithm For Large-Scale Eigenvalue Problems (08.01.07), slide №10&amp;lt;/ref&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
7) Метод Ланцоша удобен тем, что не требует хранения исходной матрицы полным массивом: метод использует исходную матрицу только в операциях умножения матрицы на вектор, что позволяет эффективно использовать разреженность матрицы или регулярность структуры матрицы. Поэтому метод Ланцоша может быть использован для матриц таких больших порядков, когда методы вращений и отражений не могут быть применены.&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;
Для исследования масштабируемости рассматриваемого алгоритма Ланцоша без переортогонализации автором была реализована программа на языке С++ с использованием технологии MPI. &amp;lt;ref&amp;gt;http://chopapp.com/#rvsztfxc или вторая ссылка с прикреплённым кодом: http://pasted.co/13b3244c , по просьбе на почту я (автор статьи) готов предоставить доступ к проекту с этим кодом на Bitbucket&amp;lt;/ref&amp;gt; Дальнейшее исследование было проведено на суперкомпьютере &amp;quot;Ломоносов&amp;quot; Суперкомпьютерного комплекса МГУ. &amp;lt;br&amp;gt; Важно отметить, что реализованная программа выполняет только первую часть алгоритма - формирование матрицы &amp;lt;math &amp;gt;T_j&amp;lt;/math&amp;gt;. Вторая часть алгоритма (задача поиска собственных значений матрицы &amp;lt;math &amp;gt;T_j&amp;lt;/math&amp;gt;) может быть решена несколькими методами, каждый из которых обладает своей эффективностью распараллеливании и характерными свойствами. Подробно этот вопрос уже обсуждался в статье раннее, поэтому не будем ещё раз заострять на этом внимание и останавливаться.&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Сборка осуществлялась со следующими параметрами:&lt;br /&gt;
* Компилятор intel/15.0.090 &lt;br /&gt;
* Openmpi/1.8.4-icc&lt;br /&gt;
В серии проведённых расчётов рассматривались следующие числовые значения параметров:&lt;br /&gt;
* Размер &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;n&amp;lt;/math&amp;gt; задачи и, соответственно, матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt;, задействованной в операции умножения на вектор: [2000 : 30000] с шагом 1000&lt;br /&gt;
* Число процессоров: 1, 2, 4, 16, 32, 48, 64, 96, 128&lt;br /&gt;
* Число итераций в алгоритме: &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k=350&amp;lt;/math&amp;gt;&lt;br /&gt;
Число &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; взято таким вопреки информации в начале статьи, где говорится, что значение &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; редко превышает &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;10^2&amp;lt;/math&amp;gt; (хоть мы и имеем право брать его любым по нашему усмотрению). Это сделано исключительно для лучшей визуализации пиков на графиках в данном разделе и наглядности получаемых результатов, так как при меньших на порядок значениях &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; времена выполнения программ были слишком малы даже при минимальных числах процессоров и максимальных размерах &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;n&amp;lt;/math&amp;gt; задачи.&lt;br /&gt;
&lt;br /&gt;
== Динамические характеристики и эффективность реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Выводы для классов архитектур ==&lt;br /&gt;
По заданию, во второй части требовалось описать только разделы 2.4 и 2.7, прошу не спрашивать с меня все разделы 2.1-2.6. Надеюсь на понимание, мне физически не хватает времени на это задание + 2 других в течение семестра, делаю всё, что в моих силах :)&lt;br /&gt;
&lt;br /&gt;
== Существующие реализации алгоритма ==&lt;br /&gt;
Несмотря на то, что алгоритм является далеко не самым популярным, алгоритмом, про который нельзя сказать, что он всегда «на слуху», на сегодняшний день существует множество реализаций на различных популярных языках.&amp;lt;br&amp;gt;&lt;br /&gt;
Перечислим далее некоторые из них, указывая язык программирования, лежащий в их основе, и некоторые важные характеристики, которые обсуждались в статье ранее:&lt;br /&gt;
*&#039;&#039;Code on netlib.org by Jane Cullum and Ralph Willoughby&#039;&#039; (&#039;&#039;&#039;Fortran 77&#039;&#039;&#039;; без реортогонализации векторов; без реализации распараллеливания)&amp;lt;ref&amp;gt;http://www.netlib.org/lanczos/leval&amp;lt;/ref&amp;gt;&lt;br /&gt;
*&#039;&#039;Lanczos algorithm on freesourcecode.net&#039;&#039; (&#039;&#039;&#039;Matlab&#039;&#039;&#039;; присутствует реортогонализация векторов; без реализации распараллеливания)&amp;lt;ref&amp;gt;http://freesourcecode.net/matlabprojects/61741/lanczos-algorithm--in-matlab&amp;lt;/ref&amp;gt;&lt;br /&gt;
*&#039;&#039;Lanczos for eigenvalues in Numerical Linear Algebra, Spring 2007&#039;&#039; (&#039;&#039;&#039;Matlab&#039;&#039;&#039;; частичная или полная реортогонализация - доступны оба варианта; без реализации распараллеливания)&amp;lt;ref&amp;gt;Ссылки на файлы lanso.m и lanfu.m можно найти на https://www.nada.kth.se/~ruhe/2D5219/labs2007.html&amp;lt;/ref&amp;gt;&lt;br /&gt;
*&#039;&#039;Planso&#039;&#039; (название происходит от parallel Lanso.f) &#039;&#039;code by Kesheng Wu and Horst D. Simon&#039;&#039; (&#039;&#039;&#039;Fortran 77&#039;&#039;&#039;; частичная реортогонализация векторов; использование MPI для коммуникаций)&amp;lt;ref&amp;gt;https://github.com/jiahao/planso.jl/tree/master/external/PLAN/plan К сожалению, ссылка в описании пакета на github, ведущая на сайт National Energy Research Scientific Computing Center (NERSC), с более подробной информацией о данной программе больше не активна и выдаёт результат &#039;&#039;Page not found&#039;&#039;&amp;lt;/ref&amp;gt; &lt;br /&gt;
* &#039;&#039;Lanczos.cpp in the Vienna Computing Library&#039;&#039;  (&#039;&#039;&#039;C++&#039;&#039;&#039;, частичная реортогонализация, без реализации распараллеливания) &amp;lt;ref&amp;gt;http://viennacl.sourceforge.net/doc/lanczos_8cpp_source.html&amp;lt;/ref&amp;gt;&lt;br /&gt;
* &#039;&#039;Parallel Eigen Values code using C++ AMP on microsoft msdn blog&#039;&#039; (&#039;&#039;&#039;C++&#039;&#039;&#039;; ? ; распараллеливание есть и реализовано через C++ AMP) &amp;lt;ref&amp;gt;https://blogs.msdn.microsoft.com/nativeconcurrency/2013/12/20/eigen-values/ Подробнее о C++ Accelerated Massive Parallelism можно почитать здесь: https://msdn.microsoft.com/ru-ru/library/hh265137(v=vs.140).aspx или здесь: http://professorweb.ru/my/csharp/optimization/level4/4_6.php &amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;br /&gt;
[[en:Description of algorithm properties and structure]]&lt;/div&gt;</summary>
		<author><name>AleksLevin</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:AleksLevin/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%9B%D0%B0%D0%BD%D1%86%D0%BE%D1%88%D0%B0_%D0%B2%D1%8B%D1%87%D0%B8%D1%81%D0%BB%D0%B5%D0%BD%D0%B8%D1%8F_%D1%81%D0%BE%D0%B1%D1%81%D1%82%D0%B2%D0%B5%D0%BD%D0%BD%D1%8B%D1%85_%D0%B7%D0%BD%D0%B0%D1%87%D0%B5%D0%BD%D0%B8%D0%B9_%D1%81%D0%B8%D0%BC%D0%BC%D0%B5%D1%82%D1%80%D0%B8%D1%87%D0%BD%D0%BE%D0%B9_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86%D1%8B_%D0%B4%D0%BB%D1%8F_%D1%82%D0%BE%D1%87%D0%BD%D0%BE%D0%B9_%D0%B0%D1%80%D0%B8%D1%84%D0%BC%D0%B5%D1%82%D0%B8%D0%BA%D0%B8_(%D0%B1%D0%B5%D0%B7_%D0%BF%D0%B5%D1%80%D0%B5%D0%BE%D1%80%D1%82%D0%BE%D0%B3%D0%BE%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D0%B8)&amp;diff=20219</id>
		<title>Участник:AleksLevin/Алгоритм Ланцоша вычисления собственных значений симметричной матрицы для точной арифметики (без переортогонализации)</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:AleksLevin/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%9B%D0%B0%D0%BD%D1%86%D0%BE%D1%88%D0%B0_%D0%B2%D1%8B%D1%87%D0%B8%D1%81%D0%BB%D0%B5%D0%BD%D0%B8%D1%8F_%D1%81%D0%BE%D0%B1%D1%81%D1%82%D0%B2%D0%B5%D0%BD%D0%BD%D1%8B%D1%85_%D0%B7%D0%BD%D0%B0%D1%87%D0%B5%D0%BD%D0%B8%D0%B9_%D1%81%D0%B8%D0%BC%D0%BC%D0%B5%D1%82%D1%80%D0%B8%D1%87%D0%BD%D0%BE%D0%B9_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86%D1%8B_%D0%B4%D0%BB%D1%8F_%D1%82%D0%BE%D1%87%D0%BD%D0%BE%D0%B9_%D0%B0%D1%80%D0%B8%D1%84%D0%BC%D0%B5%D1%82%D0%B8%D0%BA%D0%B8_(%D0%B1%D0%B5%D0%B7_%D0%BF%D0%B5%D1%80%D0%B5%D0%BE%D1%80%D1%82%D0%BE%D0%B3%D0%BE%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D0%B8)&amp;diff=20219"/>
		<updated>2016-12-07T00:23:15Z</updated>

		<summary type="html">&lt;p&gt;AleksLevin: /* Масштабируемость алгоритма и его реализации */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Основные авторы описания: Левин А.Д.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{algorithm&lt;br /&gt;
| name              = Алгоритм Ланцоша для точной арифметики (без переортогонализации)&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(k\,n^2)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(k\log_2 n)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;\frac{n^2+3n}{2} + 1&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;k\;(n + 1)&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритмов =&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Данный алгоритм появился в 1950 г. и носит имя венгерского физика и математика Корнелия Ланцоша (венг. Lánczos Kornél). Алгоритм Ланцоша относится к итерационным методам вычисления собственных значений для матриц столь больших порядков &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt; n&amp;lt;/math&amp;gt;, что к ним нельзя применить прямые методы из-за ограничений по времени и памяти.&lt;br /&gt;
&lt;br /&gt;
Сам Ланцош указывал, что его метод предназначен для отыскания нескольких собственных векторов симметричных матриц, хотя к методу сразу было обращено внимание, как к способу приведения всей матрицы к трёхдиагональному виду. Двадцатью годами позже канадский математик Крис Пэж показал, что, несмотря на чувствительность к округлениям, алгоритм Ланцоша - эффективное средство вычисления некоторых &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; собственных чисел и соответствующих им собственных векторов. &amp;lt;ref&amp;gt;Парлетт Б. - Симметричная проблема собственных значений. Численные методы //М.: Мир. - 1983. (c. 276)&amp;lt;/ref&amp;gt;&lt;br /&gt;
Обычно число &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; берут в два раза больше, чем количество собственных значений матрицы, которые поставлена цель найти, и оно имеет порядок не более &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;10^2&amp;lt;/math&amp;gt;.&amp;lt;ref&amp;gt;Susan W. Bostic - Lanczos Eigensolution Method for High-Perfomance Computers, page 7&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Алгоритм Ланцоша для вычисления собственных значений симметричной матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; соединяет в себе метод Ланцоша для построения последовательности подпространств Крылова и ортонормированных векторов Ланцоша и процедуру Рэлея-Ритца получения оптимальных приближений собственных значений и соответствующих собственных векторов исходной матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt;.&amp;lt;ref&amp;gt;James W. Demmel - Вычислительная линейная алгебра. Теория и приложения //Мир. - 2001 (c. 381)&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
В данной статье рассматривается вариант алгоритма Ланцоша, в котором опущено влияние ошибок округления на вычислительный процесс, хотя на практике этому посвящается отдельное внимание и существуют различные методы решения данной проблемы, такие как частичная или полная переортогонализация. Этим модифицированным методам посвящены отдельные статьи на данном ресурсе.&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
Обозначения и формулы, используемые в данном разделе, взяты из литературы, указанной по ссылке.&amp;lt;ref&amp;gt;James W. Demmel - Вычислительная линейная алгебра. Теория и приложения //Мир. - 2001 (c. 313, &#039;&#039;&amp;lt;math&amp;gt; \S &amp;lt;/math&amp;gt; 6.6 Методы Крыловского подпространства&#039;&#039;)&amp;lt;/ref&amp;gt; &lt;br /&gt;
&lt;br /&gt;
Алгоритм Ланцоша для вычисления &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; собственных значений и собственных векторов вещественной симметричной матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A=A^T&amp;lt;/math&amp;gt; в точной арифметике: &amp;lt;ref&amp;gt;James W. Demmel - Вычислительная линейная алгебра. Теория и приложения //Мир. - 2001 (c. 381)&amp;lt;/ref&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{align}&lt;br /&gt;
q_1 = &amp;amp; \,\frac{b}{\|b\|_2},\; \beta_0 = 0,\; q_0 = 0\\&lt;br /&gt;
\mathbf{for} \; &amp;amp; j = 1 \; to \; k \,\; \mathbf{do} \\&lt;br /&gt;
&amp;amp; z = A\,q_j\\&lt;br /&gt;
&amp;amp; \alpha_j = q^T_j z\\&lt;br /&gt;
&amp;amp; z = z - \alpha_j q_j - \beta_{j-1}q_{j-1}\\&lt;br /&gt;
&amp;amp; \beta_j = \|z\|_2\\&lt;br /&gt;
&amp;amp; \mathbf{If} \; (\beta_j == 0) \; \mathbf{then}\; stop\; the\; algorithm \\ &lt;br /&gt;
&amp;amp; \;  q_{j+1} = \frac{z}{\beta_j} \\&lt;br /&gt;
&amp;amp; compute\; eigenvalues\; and \;eigenvectors\;of \;matrix \;\;T_j= Q^T_j A Q\;\;and\;estimate \;the\; errors\\&lt;br /&gt;
\mathbf{end} \; &amp;amp; \mathbf{for}&lt;br /&gt;
\end{align}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
В продемонстрированном выше алгоритме &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;b&amp;lt;/math&amp;gt; - заданный вещественный вектор. Также полагается известным алгоритм вычисления произведения матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; на вектор &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;x&amp;lt;/math&amp;gt;. &lt;br /&gt;
Введём матрицу Крылова, определяемую следующим соотношением: &amp;lt;math&amp;gt;K_j = [b,Ab,A^2b,...,A^{j-1}b]&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Далее, на практике, матрица &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;K&amp;lt;/math&amp;gt; заменяется матрицей &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;Q&amp;lt;/math&amp;gt;, такой, что при любом числе &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; линейные оболочки первых &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; столбцов в &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;K&amp;lt;/math&amp;gt; и &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;Q&amp;lt;/math&amp;gt; являются одним и тем же подпространством.&amp;lt;ref&amp;gt;James W. Demmel - Вычислительная линейная алгебра. Теория и приложения //Мир. - 2001 (c. 315)&amp;lt;/ref&amp;gt; &lt;br /&gt;
Тогда матрица &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;Q&amp;lt;/math&amp;gt;, в отличие от матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;K&amp;lt;/math&amp;gt;, хорошо обусловлена и легко обратима. В результате получаем матрицу &amp;lt;math&amp;gt;Q_j = [q_1, q_2, \dots, q_j]&amp;lt;/math&amp;gt; размерности &amp;lt;math&amp;gt;n\times j&amp;lt;/math&amp;gt;, столбцы которой ортогональны, являются базисом подпространства Крылова и называются векторами Ланцоша.&lt;br /&gt;
&lt;br /&gt;
В алгоритме Ланцоша вычислению подлежит столько первых столбцов в матрице &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;Q_j&amp;lt;/math&amp;gt;, сколько необходимо для получения требуемого приближения к решению &amp;lt;math&amp;gt;A\,x\,=b\,\,(A\,x=\lambda \, x)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Получение нулевого &amp;lt;math&amp;gt;\beta_j&amp;lt;/math&amp;gt; в итерационном процессе - событие, желательное в том смысле, что оно свидетельствует о том, что найдено некоторое подпространство, являющееся в точности инвариантным, а все собственные значения матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;T_j&amp;lt;/math&amp;gt; являются собственными значениями матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt;. На практике же нулевое и близкие к нулю значения получаются редко.&amp;lt;ref&amp;gt;Голуб Дж., Ван Лоун Ч. - Матричные вычисления//М.: Мир. - 1999 (c. 429)&amp;lt;/ref&amp;gt; &lt;br /&gt;
&lt;br /&gt;
Затем на каждом шаге цикла формируется симметричная трёхдиагональная матрица &amp;lt;math&amp;gt;T_j = Q^T_j A Q&amp;lt;/math&amp;gt;, к которой применяется процесс Рэлея-Ритца для поиска её собственных значений (на практике для поиска этих собственных значений можно использовать любой из специальных методов в параграфе книги по ссылке).&amp;lt;ref&amp;gt;Голуб Дж., Ван Лоун Ч. - Матричные вычисления//М.: Мир. - 1999 (&amp;lt;math&amp;gt;\S&amp;lt;/math&amp;gt; 8.4)&amp;lt;/ref&amp;gt;  &lt;br /&gt;
Эти собственные значения, они же числа Ритца, и полагаются приближёнными собственными значениями исходной матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt;.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Существует множество методов для отыскания собственных значений вещественной симметричной трехдиагональной матрицы. Большинство из них требует &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt; операций &amp;lt;ref&amp;gt;Парлетт Б. Симметричная проблема собственных значений. Численные методы.,: Мир, 1983. с. 179-182&amp;lt;/ref&amp;gt;, но существуют и быстрые алгоритмы, требующие лишь &amp;lt;math&amp;gt;O(n\ln n)&amp;lt;/math&amp;gt; операций.&amp;lt;ref&amp;gt;https://en.wikipedia.org/wiki/Tridiagonal_matrix#Eigenvalues  Раздел eigenvalues&amp;lt;/ref&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Одним из возможных способов отыскать собственные значения симметричной трехдиагональной матрицы - прямое вычисление корней характеристического полинома &amp;lt;math&amp;gt;p_n(\lambda)&amp;lt;/math&amp;gt; через метод деления пополам, где формируется последовательность Штурма и локализуются собственные числа, являющиеся корнями характеристического полинома. Нахождение всех &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; собственных значений матрицы этим способом требует &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;2n^2t&amp;lt;/math&amp;gt; умножений и вычитаний, где &amp;lt;math&amp;gt;t&amp;lt;/math&amp;gt; - число сделанных шагов с применением метода деления пополам.&amp;lt;ref&amp;gt;Уилкинсон Дж. X. Алгебраическая проблема собственныx значений. Изд-во &amp;quot;Наука&amp;quot;, 1970. - глава 5, с. 272-278&amp;lt;/ref&amp;gt; Соответствующие собственные вектора могут быть найдены посредством обратных итераций за &amp;lt;math&amp;gt; O(n) &amp;lt;/math&amp;gt; флопов. &amp;lt;ref&amp;gt;Голуб Дж., Ван Лоун Ч. - Матричные вычисления//М.: Мир. - 1999 (c. 394-395)&amp;lt;/ref&amp;gt; &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;На практике, если требуется только небольшая часть от всей совокупности собственных векторов и значений, и матрица имеет Хессенбергову или трёхдиагональную форму, очень эффективными будут методы факторизации, как, например, QR-алгоритм или QL-алгоритм со сдвигами (c целью ускорить алгоритм и сделать порядок сходимости квадратичным) или же без них.&amp;lt;ref&amp;gt;http://algorithm.narod.ru/ln/eigen/ETridiag.html&amp;lt;/ref&amp;gt; &amp;lt;br&amp;gt;&lt;br /&gt;
Весьма молодые и не менее актуальные конкуренты QR и QL алгоритмов, применяющиеся для поиска собственных значений:&lt;br /&gt;
*Методы divide-and-conquer (разделяй и властвуй), появившиеся в 1980-ых годах &amp;lt;ref&amp;gt;https://goo.gl/dapvbn ссылку пришлось сократить с помощью Google url shortener, так как символы подчеркивания портили её и не давали перейти по 1 клику&amp;lt;/ref&amp;gt;&lt;br /&gt;
*Relatively robust representation методы, появившиеся в 1990-ых и позволяющие найти собственные числа симметричной матрицы порядка &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;n&amp;lt;/math&amp;gt; за &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt; операций&lt;br /&gt;
&lt;br /&gt;
Если требуется вычислить собственные векторы, то необходимо хранить вычисляемые векторы Ланцоша. Если работа при этом производится только с оперативной памятью, то при большом порядке исходной матрицы (а именно для таких матриц и предназначен метод Ланцоша) число шагов  &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;j&amp;lt;/math&amp;gt;, которые могут быть выполнены до того момента, как оперативная память будет исчерпана, будет очень незначительно, а следовательно, искомые собственные пары могут не успеть сойтись с требуемой точностью. В этом случае метод Ланцоша можно использовать итерационным образом: после выполнения заданного числа шагов процесс прерывается и, если еще не все требуемые пары Ритца сошлись с требуемой точностью, то формируется новый начальный вектор &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;q_1&amp;lt;/math&amp;gt;, являющийся линейной комбинацией векторов Ритца, еще не сошедшихся с заданной точностью, и процесс начинается заново.&amp;lt;ref&amp;gt;http://num-anal.srcc.msu.ru/lib_na/int_ae/int_ae6.htm (пункт 6.5)&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
Вычислительное ядро рассматриваемого алгоритма (наиболее ресурсно-затратная часть алгоритма) -  формирование на каждом шаге цикла промежуточного вектора &amp;lt;math&amp;gt;z&amp;lt;/math&amp;gt;, вычисляемого по формуле: &amp;lt;math&amp;gt;z = A\,q_j&amp;lt;/math&amp;gt;. Данная операция, по сравнению с другими операциями алгоритма, затратна и требовательна, как с точки зрения количества производимых операций, так и с точки зрения объема оперируемых данных. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Например, умножение матрицы размера &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;n\times n&amp;lt;/math&amp;gt; на вектор длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; требует: &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;n^2+(n-1)n = 2n^2-n&amp;lt;/math&amp;gt; операций умножения и сложения. В свою очередь аналогичная операция умножения матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;(n+1)\times (n+1)&amp;lt;/math&amp;gt; на вектор длины &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;(n+1)&amp;lt;/math&amp;gt; требует: &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;2n^2+3n+1&amp;lt;/math&amp;gt;  операций умножения и сложения. То есть повышение размерности задачи всего на 1 увеличивает число необходимых действий в этом шаге алгоритма на: &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;4n+1&amp;lt;/math&amp;gt;. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Так же, стоит помнить, что, согласно разделу 1.2, данную операцию умножения матрицы на вектор необходимо выполнить &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;k&amp;lt;/math&amp;gt; раз. Нетрудно понять, насколько возрастает и колоссален масштаб операций, если в задачах, где критична точность, размерности &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; могут иметь порядок &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;10^5&amp;lt;/math&amp;gt; или даже более.&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
Как уже было упомянуто в данной статье в описании алгоритма, рассматриваемый алгоритм состоит из двух последовательно выполненных алгоритмов: метод Ланцоша для построения последовательности подпространств Крылова и ортонормированных векторов Ланцоша и процедура Рэлея-Ритца получения оптимальных приближений собственных значений и соответствующих собственных векторов исходной матрицы.&lt;br /&gt;
&lt;br /&gt;
В первой части алгоритма, где итерационно строятся Крыловское подпространство и трёхдиагональная матрица &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&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 style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; разреженная. Именно она подлежит оптимизации с использованием техник распараллеливания, поскольку она является вычислительным ядром алгоритма, а весь упомянутый процесс построения матрицы &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&amp;lt;/math&amp;gt; выполняется последовательно.&lt;br /&gt;
&lt;br /&gt;
Рассмотрим вторую часть алгоритма - поиск собственных значений сформированной матрицы &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&amp;lt;/math&amp;gt;.&amp;lt;br&amp;gt;&lt;br /&gt;
Далее, наглядно, в виде псевдокода, представлен, упомянутый в разделе 1.2, QR-алгоритм (аналогично можно рассмотреть и QL-алгоритм) со сдвигами Релэя, который весьма популярен на практике.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{align}&lt;br /&gt;
\mathbf{Input}: \;&amp;amp;tridiagonal\;\;matrix \;T\;with\;\;n\times n\;\;size\\&lt;br /&gt;
T^{(0)}&amp;amp;:=T\\&lt;br /&gt;
\mathbf{for}&amp;amp; \;\;m=n,...,2 \;\; \mathbf{do}\\&lt;br /&gt;
&amp;amp;k=0\\&lt;br /&gt;
&amp;amp; \mathbf{repeat}\\&lt;br /&gt;
&amp;amp; \quad \;\; k=k+1\\&lt;br /&gt;
&amp;amp; \quad \;\; \mu^{(k)}=T_{m,m}^{(k-1)}\\&lt;br /&gt;
&amp;amp; \quad \;\; Q^{(k)}R^{(k)}=T^{(k-1)}-\mu^{(k)}I\;\;using\;\;QR\;decomposition\\&lt;br /&gt;
&amp;amp; \quad \;\; T^{(k)}=R^{(k)}Q^{(k)}+\mu^{(k)}I\\&lt;br /&gt;
&amp;amp; \mathbf{until} \;\;\; |T_{m,m-1}^{(k)}| \;is\;\;small\;\;enough\\&lt;br /&gt;
&amp;amp; Save  \;\;T_{m,m}^{(k)} \;\;as\;\; converged\;\;eigenvalue\;of\;T\\ &lt;br /&gt;
&amp;amp; Remove \;\boldsymbol{n}\,th\;row\;and\;\boldsymbol{n}\,th\;column\;\;from \;T \\&lt;br /&gt;
&amp;amp; and\;take\;this\;new\;cropped\;matrix\;as\;new\;T^{(0)}\;with\;\;(n-1)\times (n-1)\;\;size\\&lt;br /&gt;
 \mathbf{end}&amp;amp;\; \mathbf{for}&lt;br /&gt;
\end{align}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Малость наддиагональных и поддиагональных элементов матрицы (фраза &#039;&#039;&amp;quot;small enough&amp;quot;&#039;&#039; в псевдокоде) подразумевает:&lt;br /&gt;
&amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt; |T_{m,m-1}^{(k)}| \leq \varepsilon\,|T_{m,m}^{(k)}| \quad\quad &amp;lt;/math&amp;gt; , где &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt; \varepsilon &amp;lt;/math&amp;gt; - заданная точность&amp;lt;br&amp;gt;&lt;br /&gt;
Также вместо сдвига Релэя, обозначенного в алгоритме через &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;\mu^{(k)}&amp;lt;/math&amp;gt;, часто на практике используется сдвиг по Уилкинсону, который даёт гарантированную сходимость внедиагональных элементов матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt; T^{(k)} &amp;lt;/math&amp;gt;, формируемой на каждом шаге, к нулю, при этом жертвуя монотонностью их убывания.&amp;lt;ref&amp;gt;Голуб Дж., Ван Лоун Ч. - Матричные вычисления//М.: Мир. - 1999 (c. 378, вторая половина страницы)&amp;lt;/ref&amp;gt;&amp;lt;ref&amp;gt;Парлетт Б. Симметричная проблема собственных значений. Численные методы.,: Мир, 1983. с. 169&amp;lt;/ref&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Подробнее с различными сдвигами и соответствующими оценками скоростей и количествами операций можно ознакомиться по указанной ссылке:&amp;lt;ref&amp;gt;Парлетт Б. Симметричная проблема собственных значений. Численные методы.,: Мир, 1983. с. 179-182&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;Для совершения QR-декомпозиции на каждом шаге может использоваться любой из алгоритмов по ссылке.&amp;lt;ref&amp;gt;https://en.wikipedia.org/wiki/QR_decomposition&amp;lt;/ref&amp;gt; Подробные описания этих алгоритмов также доступны на данном ресурсе algowiki-project.&amp;lt;br&amp;gt;&lt;br /&gt;
Так как мы оперируем не обычной матрицей и даже не Хессенберговой, а симметричной и трёхдиагональной, то скорость таких алгоритмов значительно возрастёт. Например, согласно данному ресурсу &amp;lt;ref&amp;gt;http://algorithm.narod.ru/ln/eigen/ETridiag.html&amp;lt;/ref&amp;gt;, для QL-алгоритма с неявными сдвигами:&amp;lt;br&amp;gt;&lt;br /&gt;
Для трёхдиагональной матрицы объем арифметических действий составляет &amp;lt;math&amp;gt; O(n)&amp;lt;/math&amp;gt; на одну итерацию вместо &amp;lt;math&amp;gt; O(n^3)&amp;lt;/math&amp;gt; для матрицы общего вида, а число итераций для нахождения первых собственных значений примерно равно 4 - 5. Но на этих итерациях также уменьшаются внедиагональные элементы правого нижнего угла. И, таким образом, дальнейшие собственные значения ищутся значительно быстрее. Среднее число итераций на каждое собственное значение обычно составляет 1.3 - 1.6.&amp;lt;br&amp;gt; &lt;br /&gt;
Аналогично QL, QR-разложение трёхдиагольной матрицы также требует &amp;lt;math&amp;gt; O(n)&amp;lt;/math&amp;gt; флопов&amp;lt;ref&amp;gt;Голуб Дж., Ван Лоун Ч. - Матричные вычисления//М.: Мир. - 1999 (c. 378, начало раздела 8.2.2)&amp;lt;/ref&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Подводя итог, во второй части алгоритма Ланцоша можно выделить следующие макрооперации:&lt;br /&gt;
* умножение матрицы на вещественное число;&lt;br /&gt;
* перемножение матриц;&lt;br /&gt;
* умножение и сравнение вещественных чисел;&lt;br /&gt;
* + набор других макроопераций в зависимости от выбора метода, с помощью которого будет совершаться сама QR или QL-декомпозиция (выше продемонстрированы, уже, как минимум, 3 разных способа).&lt;br /&gt;
Так же, важно заметить, что набор макропераций может быть несколько другим, если выбрать какой-либо иной современный метод поиска собственных чисел трёхдиагональной матрицы, не использующий QR и QL разложения(факторизацию). Два таких метода были упомянуты в пункте 1.2.&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
С целью полностью не дублировать раздел 1.2 данной статьи, где представлен наглядный и доступный для понимания псевдокод алгоритма, постараемся лишь коротко просуммировать и обобщить весь перечень последовательных действий в рассматриваемом алгоритме.&lt;br /&gt;
&lt;br /&gt;
В качестве входных данных имеем: вещественная симметричная матрица &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; размера &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;n\times n&amp;lt;/math&amp;gt;, известный вещественный вектор &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;b&amp;lt;/math&amp;gt; длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; и число &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;n&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Далее:&lt;br /&gt;
* Инициализируем вещественную константу &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;\beta_0&amp;lt;/math&amp;gt; и векторы &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;q_0&amp;lt;/math&amp;gt; и &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;q_1&amp;lt;/math&amp;gt;&lt;br /&gt;
* Итерационно для всех &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j=1,...,k&amp;lt;/math&amp;gt;:&lt;br /&gt;
** Вычисляем вспомогательный вектор &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt;, используя умножение матрицы на вектор&lt;br /&gt;
** Вычисляем, используя скалярное произведение векторов, значение &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;\alpha_j&amp;lt;/math&amp;gt; - элемент на главной диагонали трёхдиагональной матрицы &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&amp;lt;/math&amp;gt;&lt;br /&gt;
** Вычисляем по формуле новое значение и перезаписываем вектор &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt;&lt;br /&gt;
** Вычисляем значение &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;\beta_j&amp;lt;/math&amp;gt; - элементы непосредственно над и под главной диагональю той же матрицы &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&amp;lt;/math&amp;gt;&lt;br /&gt;
** Вычисляем, зная вектор &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt;,  очередной столбец матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;Q&amp;lt;/math&amp;gt;, он же вектор Ланцоша : &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;\,\,q_{j+1}&amp;lt;/math&amp;gt;&lt;br /&gt;
** Теперь, когда матрица &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&amp;lt;/math&amp;gt; сформирована на очередном шаге, находим её собственные значения и вектора любым доступным способом, о чём было подробно сказано в пункте 1.2&lt;br /&gt;
** Переходим на следующую итерацию: &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j&amp;lt;/math&amp;gt;++&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
Оценим количество операций и сложность последовательного алгоритма, изложенного в предыдущем разделе.&lt;br /&gt;
*Для вычисления вектора &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt; умножается матрица размера &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;n\times n&amp;lt;/math&amp;gt; на вектор длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt;, и потребуется &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n^2&amp;lt;/math&amp;gt; операций умножения и &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n^2&amp;lt;/math&amp;gt; операций сложения.&lt;br /&gt;
*Умножение векторов &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;q^T_j&amp;lt;/math&amp;gt; и &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt; длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; потребует &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; операций умножения и &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; операций сложения.&lt;br /&gt;
*При вычислении нового значения вектора &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt; поэлементное сложение двух векторов длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; требует &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; операций сложения.&lt;br /&gt;
*Умножение вектора длины &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; на вещественное число требует &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; операций умножения.&lt;br /&gt;
*Нахождение квадратичной нормы вектора &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt;  длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; требует &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; умножений и &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; сложений и ещё 1 операцию извлечения квадратного корня.&lt;br /&gt;
*Заключительное нахождение собственных значений и собственных векторов трёхдиагональной матрицы &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;T_j&amp;lt;/math&amp;gt; размера &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j\times j&amp;lt;/math&amp;gt; с помощью QR-алгоритма потребует в худшем случае &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(j^3)&amp;lt;/math&amp;gt; операций.&amp;lt;ref&amp;gt;http://num-anal.srcc.msu.ru/lib_na/int_ae/int_ae6.htm (пункт 6.2, &amp;quot;Скорость сходимости при этом всегда не хуже квадратичной и почти всегда лучше кубической.&amp;quot;)&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Посчитаем теперь суммарное количество простейших операций на одной итерации алгоритма (без учёта записей в память):&lt;br /&gt;
*&amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n^2+5\,n&amp;lt;/math&amp;gt; операций умножения/деления&lt;br /&gt;
*&amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n^2+4\,n&amp;lt;/math&amp;gt; операций сложения/вычитания&lt;br /&gt;
*1 операция извлечения квадратного корня&amp;lt;br&amp;gt;&lt;br /&gt;
Отдельно после всех итераций при &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j=k&amp;lt;/math&amp;gt; :&lt;br /&gt;
*&amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(k^3)&amp;lt;/math&amp;gt; операций для поиска собственных значений и собственных векторов трёхдиагональной матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_k&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Итого можно утверждать следующее:&lt;br /&gt;
&lt;br /&gt;
Последовательная сложность одной итерации рассматриваемого алгоритма:  &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(n ^ 2) &amp;lt;/math&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Суммарная сложность алгоритма (&amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;/math&amp;gt; итераций): &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(k\,n ^ 2) + O(k ^ 3)&amp;lt;/math&amp;gt; &amp;lt;ref&amp;gt;Здесь мы полагаем, что мы не вычисляем собственные значения и векторы матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_j&amp;lt;/math&amp;gt; на каждом промежуточном шаге, а лишь единожды затрачиваем &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;O(k ^ 3)&amp;lt;/math&amp;gt; действий в конце для нахождения &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;/math&amp;gt; собственных значений и векторов матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_k&amp;lt;/math&amp;gt;&amp;lt;/ref&amp;gt; &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
На практике же обычно рассматривается число &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;&amp;lt;n&amp;lt;/math&amp;gt;, поэтому второе слагаемое можно опустить.&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
На рис. 1 продемонстрирован граф одной итерации (при каком-либо произвольном значении итератора &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j&amp;lt;/math&amp;gt;) описанного алгоритма без отображения входных и выходных данных. Наглядно продемонстрированы связи между всеми действиями, и с помощью деления на &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; потоков показано, какие операции возможно выполнять параллельно на каждом шаге с целью оптимизации и экономии машинного времени. В результате, после параллельно выполненных операций &#039;&#039;&#039;Division&#039;&#039;&#039; на заключительном ярусе, на выходе имеем значение следующего вектора Ланцоша &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;q_{j+1}&amp;lt;/math&amp;gt;, после чего следует переход на следующую итерацию, и процесс повторяется.&lt;br /&gt;
&lt;br /&gt;
[[Файл:Levin_graph.png|600px|thumb|center|Рис. 1  Структура одной итерации алгоритма]] &amp;lt;br&amp;gt;&lt;br /&gt;
Обозначения на рисунке: &amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Simp&#039;&#039;&#039; (от англ. simple) - операции сложения и умножения вещественных чисел при вычислении произведения матрицы на вектор;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Vec mult&#039;&#039;&#039; (от англ. vectors multiplication) - операция скалярного умножения двух векторов;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Vec subtr&#039;&#039;&#039; (от англ. vectors subtraction, из-за использованных в операции вычитаний векторов) - операция умножения вектора на число (выполняется дважды) и формирование нового значения &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;z_{new}&amp;lt;/math&amp;gt; по формуле: &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;z_{new} = z - \alpha_j q_j - \beta_{j-1}q_{j-1} \;&amp;lt;/math&amp;gt;;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;||\cdot||&amp;lt;/math&amp;gt; - операция вычисления нормы вектора;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Division&#039;&#039;&#039; - операция деления вектора на вещественное число  &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;\beta_j&amp;lt;/math&amp;gt; &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Важно отметить, что упомянутые выше операции также легко поддаются оптимизации. Например, попарные умножения вещественных координат векторов при вычислении скалярного произведения также легко выполняются параллельно на &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; потоках, а затем можно применить суммирование методом сдваивания, о котором сказано в следующем разделе. Умножение или деление вектора на вещественное число являющееся, по определению, умножением или делением всех его координат на это число тоже может быть выполнено эффективнее, если мы используем &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; потоков, а не выполняем эти действия последовательно.&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
Параллельные операции возможны только внутри итераций, так как рассматриваемый алгоритм является итерационным, и сами итерации строго последовательны.&amp;lt;br&amp;gt;&lt;br /&gt;
Рассмотрим в этом разделе подробнее, какой выигрыш мы можем получить при распараллеливании операций внутри одной итерации согласно графу из предыдущего раздела.&lt;br /&gt;
&lt;br /&gt;
Умножение вещественной симметричной матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; размера &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;n\times n&amp;lt;/math&amp;gt; на вектор &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;b&amp;lt;/math&amp;gt; длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; требует последовательного выполнения &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; ярусов умножений и сложений. Сложение элементов вектора длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; на каждом шаге перемножения можно оптимизировать и выполнить за &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;\log_2 n&amp;lt;/math&amp;gt; действий, если применять метод сдваивания.&lt;br /&gt;
&lt;br /&gt;
Дальнейшие операции выполняются последовательно, а вычисление значений векторов происходит за один ярус операций сложения или умножения.&lt;br /&gt;
&lt;br /&gt;
Ресурс параллелизма алгоритма вычисления собственных значений построенной трёхдиагональной матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_k&amp;lt;/math&amp;gt; размера &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k\times k&amp;lt;/math&amp;gt; зависит от выбранного алгоритма (об этих алгоритмах подробнее было сказано в разделах 1.2 и 1.4). Будет очень затратно с точки зрения объёма материала пытаться рассмотреть пусть даже часть этих методов в этой статье, а так же тонкости их распараллеливания. Предлагаем читателям при желании самим ознакомиться с этими алгоритмами на данном ресурсе или прибегнув к иным источникам.&lt;br /&gt;
&lt;br /&gt;
При классификации по высоте ЯПФ, таким образом, алгоритм Ланцоша без переортогонализации относится к алгоритмам с &#039;&#039;логарифмической сложностью&#039;&#039;, и его сложность равна &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(\log_2 n)&amp;lt;/math&amp;gt; с важным замечанием, что это сложность только одной итерации, а максимум в алгоритме может быть выполнено последовательно &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;/math&amp;gt; таких однотипных итераций, если не будет осуществлён ранний выход из цикла. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Несмотря на то, что на графе в предыдущем разделе для лучшей визуализации и понимания было изображено &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; потоков (никаких допущений мы не делали и нарушений с точки зрения логики и математики нет, можно изобразить большее число потоков, просто часть времени некоторые из них могут бездействовать и не использоваться), на самом деле правильным и разумным будет реализовать начальное параллельное выполнение &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n^2&amp;lt;/math&amp;gt; операций умножения всех вещественных элементов матрицы &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;A&amp;lt;/math&amp;gt; на соответствующие элементы вектора &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;q_j&amp;lt;/math&amp;gt;, после чего применять тот же самый упомянутый метод сдваивания. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Поэтому при классификации по ширине ЯПФ его сложность будет &#039;&#039;квадратичной&#039;&#039; и равна &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(n^2)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
&#039;&#039;&#039;Входные данные алгоритма:&#039;&#039;&#039; вещественная симметричная &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; размера &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;n\times n&amp;lt;/math&amp;gt;, вещественный вектор &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;b&amp;lt;/math&amp;gt; длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt;, и одно целое число &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;k&amp;lt;/math&amp;gt;, означающее количество итераций.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём входных данных:&#039;&#039;&#039; &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;n^2 +n + 1 &amp;lt;/math&amp;gt;. Если учесть, что матрица симметричная и достаточно для её однозначного определения задать элементы на главной диагонали и элементы над или под ней, то можно сократить объём входных данных с целью экономии памяти до: &amp;lt;math&amp;gt;\ \frac{n^2-n}{2}+n+n+1 =\frac{n^2+3n}{2} + 1&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные алгоритма:&#039;&#039;&#039; вектор собственных значений &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;\Theta^k&amp;lt;/math&amp;gt; длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;/math&amp;gt;, матрица &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;S^k&amp;lt;/math&amp;gt; из соответствующих собственных векторов размера &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n\times k&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём выходных данных:&#039;&#039;&#039; &amp;lt;math&amp;gt;k\;(n + 1)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
В данном разделе перечислены без какой-либо хронологии или связи друг с другом наиболее важные и разнообразные свойства алгоритма, на которые стоит и полезно обратить внимание, а также которые выгодно отличают его от схожих алгоритмов, решающих ту же задачу.&amp;lt;br&amp;gt;&lt;br /&gt;
1) Отношение последовательной сложности алгоритма к параллельной,с учётом &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;/math&amp;gt; итераций, равно &amp;lt;math&amp;gt;\;\;\frac{kn^2}{k \log_2{n}}=\frac{n^2}{\log_2{n}}&amp;lt;/math&amp;gt;;&amp;lt;br&amp;gt;&lt;br /&gt;
2) Вычислительная мощность алгоритма, как отношение числа операций к суммарному объему входных и выходных данных, равна &amp;lt;math style=&amp;quot;vertical-align:-70%&amp;gt;\;\;\frac{k\,n^2}{0.5\,n^2+1.5\,n+k\,n+k+1}&amp;lt;/math&amp;gt; и &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;\approx 2\,k&amp;lt;/math&amp;gt;, так как на практике верно отношение &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;&amp;lt;n&amp;lt;/math&amp;gt; ;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
3) Для собственных значений формируемых матриц &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_j&amp;lt;/math&amp;gt; верно отношение (следствие теоремы Коши о перемежаемости): &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;\lambda_i(T_{k+1})\geq \lambda_i(T_{k})\geq \lambda_{i+1}(T_{k+1})\geq \lambda_{i+1}(T_{k})&amp;lt;/math&amp;gt; ;&amp;lt;ref&amp;gt;James W. Demmel - Вычислительная линейная алгебра. Теория и приложения //Мир. - 2001 (c. 383)&amp;lt;/ref&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
4) Крайние (наибольшие и наименьшие) собственные значения матриц &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_j&amp;lt;/math&amp;gt; сходятся к крайним собственным значениям матрицы &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;A&amp;lt;/math&amp;gt; первыми (это часто происходит уже на ранних шагах при &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j\approx 2\,\sqrt{n}&amp;lt;/math&amp;gt;&amp;lt;ref&amp;gt;http://num-anal.srcc.msu.ru/lib_na/int_ae/int_ae6.htm (пункт 6.5)&amp;lt;/ref&amp;gt;), а собственные значения в середине спектра - последними;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
5) Из-за ограниченной точности постепенно теряется ортогональность вектора Ланцоша &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;q_j&amp;lt;/math&amp;gt; к предыдущим векторам Ланцоша, поэтому необходимо примерно каждые 10-15 итераций проводить дорогостоящую операцию реортогонализации, но это уже будет иной алгоритм с очень малым различием в одной операции и в программном коде, реализующем его, соответственно; &amp;lt;ref&amp;gt;Sam Handler - The Lanczos Algorithm For Large-Scale Eigenvalue Problems (08.01.07), slide №8&amp;lt;/ref&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
6) Эффективность и быстрота выполнения алгоритма очень сильно зависит от скорости памяти (диска). Согласно тесту только &#039;&#039;6%&#039;&#039; времени работы программы приходится на вычисления, остальное время затрачивается на ожидание отклика диска;&amp;lt;ref&amp;gt;Sam Handler - The Lanczos Algorithm For Large-Scale Eigenvalue Problems (08.01.07), slide №10&amp;lt;/ref&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
7) Метод Ланцоша удобен тем, что не требует хранения исходной матрицы полным массивом: метод использует исходную матрицу только в операциях умножения матрицы на вектор, что позволяет эффективно использовать разреженность матрицы или регулярность структуры матрицы. Поэтому метод Ланцоша может быть использован для матриц таких больших порядков, когда методы вращений и отражений не могут быть применены.&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;
Для исследования масштабируемости рассматриваемого алгоритма Ланцоша без переортогонализации автором была реализована программа на языке С++ с использованием технологии MPI. &amp;lt;ref&amp;gt;http://chopapp.com/#rvsztfxc или вторая ссылка с прикреплённым кодом: http://pasted.co/13b3244c , по просьбе на почту я (автор статьи) готов предоставить доступ к проекту с этим кодом на Bitbucket&amp;lt;/ref&amp;gt; Дальнейшее исследование было проведено на суперкомпьютере &amp;quot;Ломоносов&amp;quot; Суперкомпьютерного комплекса МГУ. &amp;lt;br&amp;gt; Важно отметить, что реализованная программа выполняет только первую часть алгоритма - формирование матрицы &amp;lt;math &amp;gt;T_j&amp;lt;/math&amp;gt;. Вторая часть алгоритма (задача поиска собственных значений матрицы &amp;lt;math &amp;gt;T_j&amp;lt;/math&amp;gt;) может быть решена несколькими методами, каждый из которых обладает своей эффективностью распараллеливании и характерными свойствами. Подробно этот вопрос уже обсуждался в статье раннее, поэтому не будем ещё раз заострять на этом внимание и останавливаться.&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Сборка осуществлялась со следующими параметрами:&lt;br /&gt;
* Компилятор intel/15.0.090 &lt;br /&gt;
* Openmpi/1.8.4-icc&lt;br /&gt;
В серии проведённых расчётов рассматривались следующие числовые значения параметров:&lt;br /&gt;
* Размер &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;n&amp;lt;/math&amp;gt; задачи и, соответственно, матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt;, задействованной в операции умножения на вектор: [2000 : 30000] с шагом 1000&lt;br /&gt;
* Число процессоров: 1, 2, 4, 16, 32, 48, 64, 96, 128&lt;br /&gt;
* Число итераций в алгоритме: &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k=350&amp;lt;/math&amp;gt;&lt;br /&gt;
Число &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; взято таким вопреки информации в начале статьи, где говорится, что значение &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; редко превышает &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;10^2&amp;lt;/math&amp;gt; (хоть мы и имеем право брать его любым по нашему усмотрению). Это сделано исключительно для лучшей визуализации пиков на графиках в данном разделе и наглядности получаемых результатов, так как при меньших на порядок значениях &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; времена выполнения программ были слишком малы даже при минимальных числах процессоров и максимальных размерах исходной задачи.&lt;br /&gt;
&lt;br /&gt;
== Динамические характеристики и эффективность реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Выводы для классов архитектур ==&lt;br /&gt;
По заданию, во второй части требовалось описать только разделы 2.4 и 2.7, прошу не спрашивать с меня все разделы 2.1-2.6. Надеюсь на понимание, мне физически не хватает времени на это задание + 2 других в течение семестра, делаю всё, что в моих силах :)&lt;br /&gt;
&lt;br /&gt;
== Существующие реализации алгоритма ==&lt;br /&gt;
Несмотря на то, что алгоритм является далеко не самым популярным, алгоритмом, про который нельзя сказать, что он всегда «на слуху», на сегодняшний день существует множество реализаций на различных популярных языках.&amp;lt;br&amp;gt;&lt;br /&gt;
Перечислим далее некоторые из них, указывая язык программирования, лежащий в их основе, и некоторые важные характеристики, которые обсуждались в статье ранее:&lt;br /&gt;
*&#039;&#039;Code on netlib.org by Jane Cullum and Ralph Willoughby&#039;&#039; (&#039;&#039;&#039;Fortran 77&#039;&#039;&#039;; без реортогонализации векторов; без реализации распараллеливания)&amp;lt;ref&amp;gt;http://www.netlib.org/lanczos/leval&amp;lt;/ref&amp;gt;&lt;br /&gt;
*&#039;&#039;Lanczos algorithm on freesourcecode.net&#039;&#039; (&#039;&#039;&#039;Matlab&#039;&#039;&#039;; присутствует реортогонализация векторов; без реализации распараллеливания)&amp;lt;ref&amp;gt;http://freesourcecode.net/matlabprojects/61741/lanczos-algorithm--in-matlab&amp;lt;/ref&amp;gt;&lt;br /&gt;
*&#039;&#039;Lanczos for eigenvalues in Numerical Linear Algebra, Spring 2007&#039;&#039; (&#039;&#039;&#039;Matlab&#039;&#039;&#039;; частичная или полная реортогонализация - доступны оба варианта; без реализации распараллеливания)&amp;lt;ref&amp;gt;Ссылки на файлы lanso.m и lanfu.m можно найти на https://www.nada.kth.se/~ruhe/2D5219/labs2007.html&amp;lt;/ref&amp;gt;&lt;br /&gt;
*&#039;&#039;Planso&#039;&#039; (название происходит от parallel Lanso.f) &#039;&#039;code by Kesheng Wu and Horst D. Simon&#039;&#039; (&#039;&#039;&#039;Fortran 77&#039;&#039;&#039;; частичная реортогонализация векторов; использование MPI для коммуникаций)&amp;lt;ref&amp;gt;https://github.com/jiahao/planso.jl/tree/master/external/PLAN/plan К сожалению, ссылка в описании пакета на github, ведущая на сайт National Energy Research Scientific Computing Center (NERSC), с более подробной информацией о данной программе больше не активна и выдаёт результат &#039;&#039;Page not found&#039;&#039;&amp;lt;/ref&amp;gt; &lt;br /&gt;
* &#039;&#039;Lanczos.cpp in the Vienna Computing Library&#039;&#039;  (&#039;&#039;&#039;C++&#039;&#039;&#039;, частичная реортогонализация, без реализации распараллеливания) &amp;lt;ref&amp;gt;http://viennacl.sourceforge.net/doc/lanczos_8cpp_source.html&amp;lt;/ref&amp;gt;&lt;br /&gt;
* &#039;&#039;Parallel Eigen Values code using C++ AMP on microsoft msdn blog&#039;&#039; (&#039;&#039;&#039;C++&#039;&#039;&#039;; ? ; распараллеливание есть и реализовано через C++ AMP) &amp;lt;ref&amp;gt;https://blogs.msdn.microsoft.com/nativeconcurrency/2013/12/20/eigen-values/ Подробнее о C++ Accelerated Massive Parallelism можно почитать здесь: https://msdn.microsoft.com/ru-ru/library/hh265137(v=vs.140).aspx или здесь: http://professorweb.ru/my/csharp/optimization/level4/4_6.php &amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;br /&gt;
[[en:Description of algorithm properties and structure]]&lt;/div&gt;</summary>
		<author><name>AleksLevin</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:AleksLevin/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%9B%D0%B0%D0%BD%D1%86%D0%BE%D1%88%D0%B0_%D0%B2%D1%8B%D1%87%D0%B8%D1%81%D0%BB%D0%B5%D0%BD%D0%B8%D1%8F_%D1%81%D0%BE%D0%B1%D1%81%D1%82%D0%B2%D0%B5%D0%BD%D0%BD%D1%8B%D1%85_%D0%B7%D0%BD%D0%B0%D1%87%D0%B5%D0%BD%D0%B8%D0%B9_%D1%81%D0%B8%D0%BC%D0%BC%D0%B5%D1%82%D1%80%D0%B8%D1%87%D0%BD%D0%BE%D0%B9_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86%D1%8B_%D0%B4%D0%BB%D1%8F_%D1%82%D0%BE%D1%87%D0%BD%D0%BE%D0%B9_%D0%B0%D1%80%D0%B8%D1%84%D0%BC%D0%B5%D1%82%D0%B8%D0%BA%D0%B8_(%D0%B1%D0%B5%D0%B7_%D0%BF%D0%B5%D1%80%D0%B5%D0%BE%D1%80%D1%82%D0%BE%D0%B3%D0%BE%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D0%B8)&amp;diff=20218</id>
		<title>Участник:AleksLevin/Алгоритм Ланцоша вычисления собственных значений симметричной матрицы для точной арифметики (без переортогонализации)</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:AleksLevin/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%9B%D0%B0%D0%BD%D1%86%D0%BE%D1%88%D0%B0_%D0%B2%D1%8B%D1%87%D0%B8%D1%81%D0%BB%D0%B5%D0%BD%D0%B8%D1%8F_%D1%81%D0%BE%D0%B1%D1%81%D1%82%D0%B2%D0%B5%D0%BD%D0%BD%D1%8B%D1%85_%D0%B7%D0%BD%D0%B0%D1%87%D0%B5%D0%BD%D0%B8%D0%B9_%D1%81%D0%B8%D0%BC%D0%BC%D0%B5%D1%82%D1%80%D0%B8%D1%87%D0%BD%D0%BE%D0%B9_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86%D1%8B_%D0%B4%D0%BB%D1%8F_%D1%82%D0%BE%D1%87%D0%BD%D0%BE%D0%B9_%D0%B0%D1%80%D0%B8%D1%84%D0%BC%D0%B5%D1%82%D0%B8%D0%BA%D0%B8_(%D0%B1%D0%B5%D0%B7_%D0%BF%D0%B5%D1%80%D0%B5%D0%BE%D1%80%D1%82%D0%BE%D0%B3%D0%BE%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D0%B8)&amp;diff=20218"/>
		<updated>2016-12-07T00:22:50Z</updated>

		<summary type="html">&lt;p&gt;AleksLevin: /* Масштабируемость алгоритма и его реализации */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Основные авторы описания: Левин А.Д.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{algorithm&lt;br /&gt;
| name              = Алгоритм Ланцоша для точной арифметики (без переортогонализации)&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(k\,n^2)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(k\log_2 n)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;\frac{n^2+3n}{2} + 1&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;k\;(n + 1)&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритмов =&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Данный алгоритм появился в 1950 г. и носит имя венгерского физика и математика Корнелия Ланцоша (венг. Lánczos Kornél). Алгоритм Ланцоша относится к итерационным методам вычисления собственных значений для матриц столь больших порядков &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt; n&amp;lt;/math&amp;gt;, что к ним нельзя применить прямые методы из-за ограничений по времени и памяти.&lt;br /&gt;
&lt;br /&gt;
Сам Ланцош указывал, что его метод предназначен для отыскания нескольких собственных векторов симметричных матриц, хотя к методу сразу было обращено внимание, как к способу приведения всей матрицы к трёхдиагональному виду. Двадцатью годами позже канадский математик Крис Пэж показал, что, несмотря на чувствительность к округлениям, алгоритм Ланцоша - эффективное средство вычисления некоторых &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; собственных чисел и соответствующих им собственных векторов. &amp;lt;ref&amp;gt;Парлетт Б. - Симметричная проблема собственных значений. Численные методы //М.: Мир. - 1983. (c. 276)&amp;lt;/ref&amp;gt;&lt;br /&gt;
Обычно число &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; берут в два раза больше, чем количество собственных значений матрицы, которые поставлена цель найти, и оно имеет порядок не более &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;10^2&amp;lt;/math&amp;gt;.&amp;lt;ref&amp;gt;Susan W. Bostic - Lanczos Eigensolution Method for High-Perfomance Computers, page 7&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Алгоритм Ланцоша для вычисления собственных значений симметричной матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; соединяет в себе метод Ланцоша для построения последовательности подпространств Крылова и ортонормированных векторов Ланцоша и процедуру Рэлея-Ритца получения оптимальных приближений собственных значений и соответствующих собственных векторов исходной матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt;.&amp;lt;ref&amp;gt;James W. Demmel - Вычислительная линейная алгебра. Теория и приложения //Мир. - 2001 (c. 381)&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
В данной статье рассматривается вариант алгоритма Ланцоша, в котором опущено влияние ошибок округления на вычислительный процесс, хотя на практике этому посвящается отдельное внимание и существуют различные методы решения данной проблемы, такие как частичная или полная переортогонализация. Этим модифицированным методам посвящены отдельные статьи на данном ресурсе.&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
Обозначения и формулы, используемые в данном разделе, взяты из литературы, указанной по ссылке.&amp;lt;ref&amp;gt;James W. Demmel - Вычислительная линейная алгебра. Теория и приложения //Мир. - 2001 (c. 313, &#039;&#039;&amp;lt;math&amp;gt; \S &amp;lt;/math&amp;gt; 6.6 Методы Крыловского подпространства&#039;&#039;)&amp;lt;/ref&amp;gt; &lt;br /&gt;
&lt;br /&gt;
Алгоритм Ланцоша для вычисления &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; собственных значений и собственных векторов вещественной симметричной матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A=A^T&amp;lt;/math&amp;gt; в точной арифметике: &amp;lt;ref&amp;gt;James W. Demmel - Вычислительная линейная алгебра. Теория и приложения //Мир. - 2001 (c. 381)&amp;lt;/ref&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{align}&lt;br /&gt;
q_1 = &amp;amp; \,\frac{b}{\|b\|_2},\; \beta_0 = 0,\; q_0 = 0\\&lt;br /&gt;
\mathbf{for} \; &amp;amp; j = 1 \; to \; k \,\; \mathbf{do} \\&lt;br /&gt;
&amp;amp; z = A\,q_j\\&lt;br /&gt;
&amp;amp; \alpha_j = q^T_j z\\&lt;br /&gt;
&amp;amp; z = z - \alpha_j q_j - \beta_{j-1}q_{j-1}\\&lt;br /&gt;
&amp;amp; \beta_j = \|z\|_2\\&lt;br /&gt;
&amp;amp; \mathbf{If} \; (\beta_j == 0) \; \mathbf{then}\; stop\; the\; algorithm \\ &lt;br /&gt;
&amp;amp; \;  q_{j+1} = \frac{z}{\beta_j} \\&lt;br /&gt;
&amp;amp; compute\; eigenvalues\; and \;eigenvectors\;of \;matrix \;\;T_j= Q^T_j A Q\;\;and\;estimate \;the\; errors\\&lt;br /&gt;
\mathbf{end} \; &amp;amp; \mathbf{for}&lt;br /&gt;
\end{align}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
В продемонстрированном выше алгоритме &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;b&amp;lt;/math&amp;gt; - заданный вещественный вектор. Также полагается известным алгоритм вычисления произведения матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; на вектор &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;x&amp;lt;/math&amp;gt;. &lt;br /&gt;
Введём матрицу Крылова, определяемую следующим соотношением: &amp;lt;math&amp;gt;K_j = [b,Ab,A^2b,...,A^{j-1}b]&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Далее, на практике, матрица &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;K&amp;lt;/math&amp;gt; заменяется матрицей &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;Q&amp;lt;/math&amp;gt;, такой, что при любом числе &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; линейные оболочки первых &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; столбцов в &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;K&amp;lt;/math&amp;gt; и &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;Q&amp;lt;/math&amp;gt; являются одним и тем же подпространством.&amp;lt;ref&amp;gt;James W. Demmel - Вычислительная линейная алгебра. Теория и приложения //Мир. - 2001 (c. 315)&amp;lt;/ref&amp;gt; &lt;br /&gt;
Тогда матрица &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;Q&amp;lt;/math&amp;gt;, в отличие от матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;K&amp;lt;/math&amp;gt;, хорошо обусловлена и легко обратима. В результате получаем матрицу &amp;lt;math&amp;gt;Q_j = [q_1, q_2, \dots, q_j]&amp;lt;/math&amp;gt; размерности &amp;lt;math&amp;gt;n\times j&amp;lt;/math&amp;gt;, столбцы которой ортогональны, являются базисом подпространства Крылова и называются векторами Ланцоша.&lt;br /&gt;
&lt;br /&gt;
В алгоритме Ланцоша вычислению подлежит столько первых столбцов в матрице &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;Q_j&amp;lt;/math&amp;gt;, сколько необходимо для получения требуемого приближения к решению &amp;lt;math&amp;gt;A\,x\,=b\,\,(A\,x=\lambda \, x)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Получение нулевого &amp;lt;math&amp;gt;\beta_j&amp;lt;/math&amp;gt; в итерационном процессе - событие, желательное в том смысле, что оно свидетельствует о том, что найдено некоторое подпространство, являющееся в точности инвариантным, а все собственные значения матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;T_j&amp;lt;/math&amp;gt; являются собственными значениями матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt;. На практике же нулевое и близкие к нулю значения получаются редко.&amp;lt;ref&amp;gt;Голуб Дж., Ван Лоун Ч. - Матричные вычисления//М.: Мир. - 1999 (c. 429)&amp;lt;/ref&amp;gt; &lt;br /&gt;
&lt;br /&gt;
Затем на каждом шаге цикла формируется симметричная трёхдиагональная матрица &amp;lt;math&amp;gt;T_j = Q^T_j A Q&amp;lt;/math&amp;gt;, к которой применяется процесс Рэлея-Ритца для поиска её собственных значений (на практике для поиска этих собственных значений можно использовать любой из специальных методов в параграфе книги по ссылке).&amp;lt;ref&amp;gt;Голуб Дж., Ван Лоун Ч. - Матричные вычисления//М.: Мир. - 1999 (&amp;lt;math&amp;gt;\S&amp;lt;/math&amp;gt; 8.4)&amp;lt;/ref&amp;gt;  &lt;br /&gt;
Эти собственные значения, они же числа Ритца, и полагаются приближёнными собственными значениями исходной матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt;.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Существует множество методов для отыскания собственных значений вещественной симметричной трехдиагональной матрицы. Большинство из них требует &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt; операций &amp;lt;ref&amp;gt;Парлетт Б. Симметричная проблема собственных значений. Численные методы.,: Мир, 1983. с. 179-182&amp;lt;/ref&amp;gt;, но существуют и быстрые алгоритмы, требующие лишь &amp;lt;math&amp;gt;O(n\ln n)&amp;lt;/math&amp;gt; операций.&amp;lt;ref&amp;gt;https://en.wikipedia.org/wiki/Tridiagonal_matrix#Eigenvalues  Раздел eigenvalues&amp;lt;/ref&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Одним из возможных способов отыскать собственные значения симметричной трехдиагональной матрицы - прямое вычисление корней характеристического полинома &amp;lt;math&amp;gt;p_n(\lambda)&amp;lt;/math&amp;gt; через метод деления пополам, где формируется последовательность Штурма и локализуются собственные числа, являющиеся корнями характеристического полинома. Нахождение всех &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; собственных значений матрицы этим способом требует &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;2n^2t&amp;lt;/math&amp;gt; умножений и вычитаний, где &amp;lt;math&amp;gt;t&amp;lt;/math&amp;gt; - число сделанных шагов с применением метода деления пополам.&amp;lt;ref&amp;gt;Уилкинсон Дж. X. Алгебраическая проблема собственныx значений. Изд-во &amp;quot;Наука&amp;quot;, 1970. - глава 5, с. 272-278&amp;lt;/ref&amp;gt; Соответствующие собственные вектора могут быть найдены посредством обратных итераций за &amp;lt;math&amp;gt; O(n) &amp;lt;/math&amp;gt; флопов. &amp;lt;ref&amp;gt;Голуб Дж., Ван Лоун Ч. - Матричные вычисления//М.: Мир. - 1999 (c. 394-395)&amp;lt;/ref&amp;gt; &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;На практике, если требуется только небольшая часть от всей совокупности собственных векторов и значений, и матрица имеет Хессенбергову или трёхдиагональную форму, очень эффективными будут методы факторизации, как, например, QR-алгоритм или QL-алгоритм со сдвигами (c целью ускорить алгоритм и сделать порядок сходимости квадратичным) или же без них.&amp;lt;ref&amp;gt;http://algorithm.narod.ru/ln/eigen/ETridiag.html&amp;lt;/ref&amp;gt; &amp;lt;br&amp;gt;&lt;br /&gt;
Весьма молодые и не менее актуальные конкуренты QR и QL алгоритмов, применяющиеся для поиска собственных значений:&lt;br /&gt;
*Методы divide-and-conquer (разделяй и властвуй), появившиеся в 1980-ых годах &amp;lt;ref&amp;gt;https://goo.gl/dapvbn ссылку пришлось сократить с помощью Google url shortener, так как символы подчеркивания портили её и не давали перейти по 1 клику&amp;lt;/ref&amp;gt;&lt;br /&gt;
*Relatively robust representation методы, появившиеся в 1990-ых и позволяющие найти собственные числа симметричной матрицы порядка &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;n&amp;lt;/math&amp;gt; за &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt; операций&lt;br /&gt;
&lt;br /&gt;
Если требуется вычислить собственные векторы, то необходимо хранить вычисляемые векторы Ланцоша. Если работа при этом производится только с оперативной памятью, то при большом порядке исходной матрицы (а именно для таких матриц и предназначен метод Ланцоша) число шагов  &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;j&amp;lt;/math&amp;gt;, которые могут быть выполнены до того момента, как оперативная память будет исчерпана, будет очень незначительно, а следовательно, искомые собственные пары могут не успеть сойтись с требуемой точностью. В этом случае метод Ланцоша можно использовать итерационным образом: после выполнения заданного числа шагов процесс прерывается и, если еще не все требуемые пары Ритца сошлись с требуемой точностью, то формируется новый начальный вектор &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;q_1&amp;lt;/math&amp;gt;, являющийся линейной комбинацией векторов Ритца, еще не сошедшихся с заданной точностью, и процесс начинается заново.&amp;lt;ref&amp;gt;http://num-anal.srcc.msu.ru/lib_na/int_ae/int_ae6.htm (пункт 6.5)&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
Вычислительное ядро рассматриваемого алгоритма (наиболее ресурсно-затратная часть алгоритма) -  формирование на каждом шаге цикла промежуточного вектора &amp;lt;math&amp;gt;z&amp;lt;/math&amp;gt;, вычисляемого по формуле: &amp;lt;math&amp;gt;z = A\,q_j&amp;lt;/math&amp;gt;. Данная операция, по сравнению с другими операциями алгоритма, затратна и требовательна, как с точки зрения количества производимых операций, так и с точки зрения объема оперируемых данных. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Например, умножение матрицы размера &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;n\times n&amp;lt;/math&amp;gt; на вектор длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; требует: &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;n^2+(n-1)n = 2n^2-n&amp;lt;/math&amp;gt; операций умножения и сложения. В свою очередь аналогичная операция умножения матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;(n+1)\times (n+1)&amp;lt;/math&amp;gt; на вектор длины &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;(n+1)&amp;lt;/math&amp;gt; требует: &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;2n^2+3n+1&amp;lt;/math&amp;gt;  операций умножения и сложения. То есть повышение размерности задачи всего на 1 увеличивает число необходимых действий в этом шаге алгоритма на: &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;4n+1&amp;lt;/math&amp;gt;. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Так же, стоит помнить, что, согласно разделу 1.2, данную операцию умножения матрицы на вектор необходимо выполнить &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;k&amp;lt;/math&amp;gt; раз. Нетрудно понять, насколько возрастает и колоссален масштаб операций, если в задачах, где критична точность, размерности &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; могут иметь порядок &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;10^5&amp;lt;/math&amp;gt; или даже более.&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
Как уже было упомянуто в данной статье в описании алгоритма, рассматриваемый алгоритм состоит из двух последовательно выполненных алгоритмов: метод Ланцоша для построения последовательности подпространств Крылова и ортонормированных векторов Ланцоша и процедура Рэлея-Ритца получения оптимальных приближений собственных значений и соответствующих собственных векторов исходной матрицы.&lt;br /&gt;
&lt;br /&gt;
В первой части алгоритма, где итерационно строятся Крыловское подпространство и трёхдиагональная матрица &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&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 style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; разреженная. Именно она подлежит оптимизации с использованием техник распараллеливания, поскольку она является вычислительным ядром алгоритма, а весь упомянутый процесс построения матрицы &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&amp;lt;/math&amp;gt; выполняется последовательно.&lt;br /&gt;
&lt;br /&gt;
Рассмотрим вторую часть алгоритма - поиск собственных значений сформированной матрицы &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&amp;lt;/math&amp;gt;.&amp;lt;br&amp;gt;&lt;br /&gt;
Далее, наглядно, в виде псевдокода, представлен, упомянутый в разделе 1.2, QR-алгоритм (аналогично можно рассмотреть и QL-алгоритм) со сдвигами Релэя, который весьма популярен на практике.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{align}&lt;br /&gt;
\mathbf{Input}: \;&amp;amp;tridiagonal\;\;matrix \;T\;with\;\;n\times n\;\;size\\&lt;br /&gt;
T^{(0)}&amp;amp;:=T\\&lt;br /&gt;
\mathbf{for}&amp;amp; \;\;m=n,...,2 \;\; \mathbf{do}\\&lt;br /&gt;
&amp;amp;k=0\\&lt;br /&gt;
&amp;amp; \mathbf{repeat}\\&lt;br /&gt;
&amp;amp; \quad \;\; k=k+1\\&lt;br /&gt;
&amp;amp; \quad \;\; \mu^{(k)}=T_{m,m}^{(k-1)}\\&lt;br /&gt;
&amp;amp; \quad \;\; Q^{(k)}R^{(k)}=T^{(k-1)}-\mu^{(k)}I\;\;using\;\;QR\;decomposition\\&lt;br /&gt;
&amp;amp; \quad \;\; T^{(k)}=R^{(k)}Q^{(k)}+\mu^{(k)}I\\&lt;br /&gt;
&amp;amp; \mathbf{until} \;\;\; |T_{m,m-1}^{(k)}| \;is\;\;small\;\;enough\\&lt;br /&gt;
&amp;amp; Save  \;\;T_{m,m}^{(k)} \;\;as\;\; converged\;\;eigenvalue\;of\;T\\ &lt;br /&gt;
&amp;amp; Remove \;\boldsymbol{n}\,th\;row\;and\;\boldsymbol{n}\,th\;column\;\;from \;T \\&lt;br /&gt;
&amp;amp; and\;take\;this\;new\;cropped\;matrix\;as\;new\;T^{(0)}\;with\;\;(n-1)\times (n-1)\;\;size\\&lt;br /&gt;
 \mathbf{end}&amp;amp;\; \mathbf{for}&lt;br /&gt;
\end{align}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Малость наддиагональных и поддиагональных элементов матрицы (фраза &#039;&#039;&amp;quot;small enough&amp;quot;&#039;&#039; в псевдокоде) подразумевает:&lt;br /&gt;
&amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt; |T_{m,m-1}^{(k)}| \leq \varepsilon\,|T_{m,m}^{(k)}| \quad\quad &amp;lt;/math&amp;gt; , где &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt; \varepsilon &amp;lt;/math&amp;gt; - заданная точность&amp;lt;br&amp;gt;&lt;br /&gt;
Также вместо сдвига Релэя, обозначенного в алгоритме через &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;\mu^{(k)}&amp;lt;/math&amp;gt;, часто на практике используется сдвиг по Уилкинсону, который даёт гарантированную сходимость внедиагональных элементов матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt; T^{(k)} &amp;lt;/math&amp;gt;, формируемой на каждом шаге, к нулю, при этом жертвуя монотонностью их убывания.&amp;lt;ref&amp;gt;Голуб Дж., Ван Лоун Ч. - Матричные вычисления//М.: Мир. - 1999 (c. 378, вторая половина страницы)&amp;lt;/ref&amp;gt;&amp;lt;ref&amp;gt;Парлетт Б. Симметричная проблема собственных значений. Численные методы.,: Мир, 1983. с. 169&amp;lt;/ref&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Подробнее с различными сдвигами и соответствующими оценками скоростей и количествами операций можно ознакомиться по указанной ссылке:&amp;lt;ref&amp;gt;Парлетт Б. Симметричная проблема собственных значений. Численные методы.,: Мир, 1983. с. 179-182&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;Для совершения QR-декомпозиции на каждом шаге может использоваться любой из алгоритмов по ссылке.&amp;lt;ref&amp;gt;https://en.wikipedia.org/wiki/QR_decomposition&amp;lt;/ref&amp;gt; Подробные описания этих алгоритмов также доступны на данном ресурсе algowiki-project.&amp;lt;br&amp;gt;&lt;br /&gt;
Так как мы оперируем не обычной матрицей и даже не Хессенберговой, а симметричной и трёхдиагональной, то скорость таких алгоритмов значительно возрастёт. Например, согласно данному ресурсу &amp;lt;ref&amp;gt;http://algorithm.narod.ru/ln/eigen/ETridiag.html&amp;lt;/ref&amp;gt;, для QL-алгоритма с неявными сдвигами:&amp;lt;br&amp;gt;&lt;br /&gt;
Для трёхдиагональной матрицы объем арифметических действий составляет &amp;lt;math&amp;gt; O(n)&amp;lt;/math&amp;gt; на одну итерацию вместо &amp;lt;math&amp;gt; O(n^3)&amp;lt;/math&amp;gt; для матрицы общего вида, а число итераций для нахождения первых собственных значений примерно равно 4 - 5. Но на этих итерациях также уменьшаются внедиагональные элементы правого нижнего угла. И, таким образом, дальнейшие собственные значения ищутся значительно быстрее. Среднее число итераций на каждое собственное значение обычно составляет 1.3 - 1.6.&amp;lt;br&amp;gt; &lt;br /&gt;
Аналогично QL, QR-разложение трёхдиагольной матрицы также требует &amp;lt;math&amp;gt; O(n)&amp;lt;/math&amp;gt; флопов&amp;lt;ref&amp;gt;Голуб Дж., Ван Лоун Ч. - Матричные вычисления//М.: Мир. - 1999 (c. 378, начало раздела 8.2.2)&amp;lt;/ref&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Подводя итог, во второй части алгоритма Ланцоша можно выделить следующие макрооперации:&lt;br /&gt;
* умножение матрицы на вещественное число;&lt;br /&gt;
* перемножение матриц;&lt;br /&gt;
* умножение и сравнение вещественных чисел;&lt;br /&gt;
* + набор других макроопераций в зависимости от выбора метода, с помощью которого будет совершаться сама QR или QL-декомпозиция (выше продемонстрированы, уже, как минимум, 3 разных способа).&lt;br /&gt;
Так же, важно заметить, что набор макропераций может быть несколько другим, если выбрать какой-либо иной современный метод поиска собственных чисел трёхдиагональной матрицы, не использующий QR и QL разложения(факторизацию). Два таких метода были упомянуты в пункте 1.2.&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
С целью полностью не дублировать раздел 1.2 данной статьи, где представлен наглядный и доступный для понимания псевдокод алгоритма, постараемся лишь коротко просуммировать и обобщить весь перечень последовательных действий в рассматриваемом алгоритме.&lt;br /&gt;
&lt;br /&gt;
В качестве входных данных имеем: вещественная симметричная матрица &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; размера &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;n\times n&amp;lt;/math&amp;gt;, известный вещественный вектор &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;b&amp;lt;/math&amp;gt; длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; и число &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;n&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Далее:&lt;br /&gt;
* Инициализируем вещественную константу &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;\beta_0&amp;lt;/math&amp;gt; и векторы &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;q_0&amp;lt;/math&amp;gt; и &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;q_1&amp;lt;/math&amp;gt;&lt;br /&gt;
* Итерационно для всех &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j=1,...,k&amp;lt;/math&amp;gt;:&lt;br /&gt;
** Вычисляем вспомогательный вектор &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt;, используя умножение матрицы на вектор&lt;br /&gt;
** Вычисляем, используя скалярное произведение векторов, значение &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;\alpha_j&amp;lt;/math&amp;gt; - элемент на главной диагонали трёхдиагональной матрицы &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&amp;lt;/math&amp;gt;&lt;br /&gt;
** Вычисляем по формуле новое значение и перезаписываем вектор &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt;&lt;br /&gt;
** Вычисляем значение &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;\beta_j&amp;lt;/math&amp;gt; - элементы непосредственно над и под главной диагональю той же матрицы &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&amp;lt;/math&amp;gt;&lt;br /&gt;
** Вычисляем, зная вектор &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt;,  очередной столбец матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;Q&amp;lt;/math&amp;gt;, он же вектор Ланцоша : &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;\,\,q_{j+1}&amp;lt;/math&amp;gt;&lt;br /&gt;
** Теперь, когда матрица &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&amp;lt;/math&amp;gt; сформирована на очередном шаге, находим её собственные значения и вектора любым доступным способом, о чём было подробно сказано в пункте 1.2&lt;br /&gt;
** Переходим на следующую итерацию: &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j&amp;lt;/math&amp;gt;++&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
Оценим количество операций и сложность последовательного алгоритма, изложенного в предыдущем разделе.&lt;br /&gt;
*Для вычисления вектора &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt; умножается матрица размера &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;n\times n&amp;lt;/math&amp;gt; на вектор длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt;, и потребуется &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n^2&amp;lt;/math&amp;gt; операций умножения и &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n^2&amp;lt;/math&amp;gt; операций сложения.&lt;br /&gt;
*Умножение векторов &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;q^T_j&amp;lt;/math&amp;gt; и &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt; длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; потребует &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; операций умножения и &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; операций сложения.&lt;br /&gt;
*При вычислении нового значения вектора &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt; поэлементное сложение двух векторов длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; требует &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; операций сложения.&lt;br /&gt;
*Умножение вектора длины &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; на вещественное число требует &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; операций умножения.&lt;br /&gt;
*Нахождение квадратичной нормы вектора &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt;  длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; требует &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; умножений и &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; сложений и ещё 1 операцию извлечения квадратного корня.&lt;br /&gt;
*Заключительное нахождение собственных значений и собственных векторов трёхдиагональной матрицы &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;T_j&amp;lt;/math&amp;gt; размера &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j\times j&amp;lt;/math&amp;gt; с помощью QR-алгоритма потребует в худшем случае &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(j^3)&amp;lt;/math&amp;gt; операций.&amp;lt;ref&amp;gt;http://num-anal.srcc.msu.ru/lib_na/int_ae/int_ae6.htm (пункт 6.2, &amp;quot;Скорость сходимости при этом всегда не хуже квадратичной и почти всегда лучше кубической.&amp;quot;)&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Посчитаем теперь суммарное количество простейших операций на одной итерации алгоритма (без учёта записей в память):&lt;br /&gt;
*&amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n^2+5\,n&amp;lt;/math&amp;gt; операций умножения/деления&lt;br /&gt;
*&amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n^2+4\,n&amp;lt;/math&amp;gt; операций сложения/вычитания&lt;br /&gt;
*1 операция извлечения квадратного корня&amp;lt;br&amp;gt;&lt;br /&gt;
Отдельно после всех итераций при &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j=k&amp;lt;/math&amp;gt; :&lt;br /&gt;
*&amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(k^3)&amp;lt;/math&amp;gt; операций для поиска собственных значений и собственных векторов трёхдиагональной матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_k&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Итого можно утверждать следующее:&lt;br /&gt;
&lt;br /&gt;
Последовательная сложность одной итерации рассматриваемого алгоритма:  &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(n ^ 2) &amp;lt;/math&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Суммарная сложность алгоритма (&amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;/math&amp;gt; итераций): &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(k\,n ^ 2) + O(k ^ 3)&amp;lt;/math&amp;gt; &amp;lt;ref&amp;gt;Здесь мы полагаем, что мы не вычисляем собственные значения и векторы матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_j&amp;lt;/math&amp;gt; на каждом промежуточном шаге, а лишь единожды затрачиваем &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;O(k ^ 3)&amp;lt;/math&amp;gt; действий в конце для нахождения &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;/math&amp;gt; собственных значений и векторов матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_k&amp;lt;/math&amp;gt;&amp;lt;/ref&amp;gt; &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
На практике же обычно рассматривается число &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;&amp;lt;n&amp;lt;/math&amp;gt;, поэтому второе слагаемое можно опустить.&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
На рис. 1 продемонстрирован граф одной итерации (при каком-либо произвольном значении итератора &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j&amp;lt;/math&amp;gt;) описанного алгоритма без отображения входных и выходных данных. Наглядно продемонстрированы связи между всеми действиями, и с помощью деления на &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; потоков показано, какие операции возможно выполнять параллельно на каждом шаге с целью оптимизации и экономии машинного времени. В результате, после параллельно выполненных операций &#039;&#039;&#039;Division&#039;&#039;&#039; на заключительном ярусе, на выходе имеем значение следующего вектора Ланцоша &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;q_{j+1}&amp;lt;/math&amp;gt;, после чего следует переход на следующую итерацию, и процесс повторяется.&lt;br /&gt;
&lt;br /&gt;
[[Файл:Levin_graph.png|600px|thumb|center|Рис. 1  Структура одной итерации алгоритма]] &amp;lt;br&amp;gt;&lt;br /&gt;
Обозначения на рисунке: &amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Simp&#039;&#039;&#039; (от англ. simple) - операции сложения и умножения вещественных чисел при вычислении произведения матрицы на вектор;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Vec mult&#039;&#039;&#039; (от англ. vectors multiplication) - операция скалярного умножения двух векторов;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Vec subtr&#039;&#039;&#039; (от англ. vectors subtraction, из-за использованных в операции вычитаний векторов) - операция умножения вектора на число (выполняется дважды) и формирование нового значения &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;z_{new}&amp;lt;/math&amp;gt; по формуле: &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;z_{new} = z - \alpha_j q_j - \beta_{j-1}q_{j-1} \;&amp;lt;/math&amp;gt;;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;||\cdot||&amp;lt;/math&amp;gt; - операция вычисления нормы вектора;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Division&#039;&#039;&#039; - операция деления вектора на вещественное число  &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;\beta_j&amp;lt;/math&amp;gt; &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Важно отметить, что упомянутые выше операции также легко поддаются оптимизации. Например, попарные умножения вещественных координат векторов при вычислении скалярного произведения также легко выполняются параллельно на &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; потоках, а затем можно применить суммирование методом сдваивания, о котором сказано в следующем разделе. Умножение или деление вектора на вещественное число являющееся, по определению, умножением или делением всех его координат на это число тоже может быть выполнено эффективнее, если мы используем &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; потоков, а не выполняем эти действия последовательно.&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
Параллельные операции возможны только внутри итераций, так как рассматриваемый алгоритм является итерационным, и сами итерации строго последовательны.&amp;lt;br&amp;gt;&lt;br /&gt;
Рассмотрим в этом разделе подробнее, какой выигрыш мы можем получить при распараллеливании операций внутри одной итерации согласно графу из предыдущего раздела.&lt;br /&gt;
&lt;br /&gt;
Умножение вещественной симметричной матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; размера &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;n\times n&amp;lt;/math&amp;gt; на вектор &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;b&amp;lt;/math&amp;gt; длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; требует последовательного выполнения &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; ярусов умножений и сложений. Сложение элементов вектора длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; на каждом шаге перемножения можно оптимизировать и выполнить за &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;\log_2 n&amp;lt;/math&amp;gt; действий, если применять метод сдваивания.&lt;br /&gt;
&lt;br /&gt;
Дальнейшие операции выполняются последовательно, а вычисление значений векторов происходит за один ярус операций сложения или умножения.&lt;br /&gt;
&lt;br /&gt;
Ресурс параллелизма алгоритма вычисления собственных значений построенной трёхдиагональной матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_k&amp;lt;/math&amp;gt; размера &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k\times k&amp;lt;/math&amp;gt; зависит от выбранного алгоритма (об этих алгоритмах подробнее было сказано в разделах 1.2 и 1.4). Будет очень затратно с точки зрения объёма материала пытаться рассмотреть пусть даже часть этих методов в этой статье, а так же тонкости их распараллеливания. Предлагаем читателям при желании самим ознакомиться с этими алгоритмами на данном ресурсе или прибегнув к иным источникам.&lt;br /&gt;
&lt;br /&gt;
При классификации по высоте ЯПФ, таким образом, алгоритм Ланцоша без переортогонализации относится к алгоритмам с &#039;&#039;логарифмической сложностью&#039;&#039;, и его сложность равна &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(\log_2 n)&amp;lt;/math&amp;gt; с важным замечанием, что это сложность только одной итерации, а максимум в алгоритме может быть выполнено последовательно &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;/math&amp;gt; таких однотипных итераций, если не будет осуществлён ранний выход из цикла. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Несмотря на то, что на графе в предыдущем разделе для лучшей визуализации и понимания было изображено &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; потоков (никаких допущений мы не делали и нарушений с точки зрения логики и математики нет, можно изобразить большее число потоков, просто часть времени некоторые из них могут бездействовать и не использоваться), на самом деле правильным и разумным будет реализовать начальное параллельное выполнение &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n^2&amp;lt;/math&amp;gt; операций умножения всех вещественных элементов матрицы &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;A&amp;lt;/math&amp;gt; на соответствующие элементы вектора &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;q_j&amp;lt;/math&amp;gt;, после чего применять тот же самый упомянутый метод сдваивания. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Поэтому при классификации по ширине ЯПФ его сложность будет &#039;&#039;квадратичной&#039;&#039; и равна &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(n^2)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
&#039;&#039;&#039;Входные данные алгоритма:&#039;&#039;&#039; вещественная симметричная &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; размера &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;n\times n&amp;lt;/math&amp;gt;, вещественный вектор &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;b&amp;lt;/math&amp;gt; длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt;, и одно целое число &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;k&amp;lt;/math&amp;gt;, означающее количество итераций.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём входных данных:&#039;&#039;&#039; &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;n^2 +n + 1 &amp;lt;/math&amp;gt;. Если учесть, что матрица симметричная и достаточно для её однозначного определения задать элементы на главной диагонали и элементы над или под ней, то можно сократить объём входных данных с целью экономии памяти до: &amp;lt;math&amp;gt;\ \frac{n^2-n}{2}+n+n+1 =\frac{n^2+3n}{2} + 1&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные алгоритма:&#039;&#039;&#039; вектор собственных значений &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;\Theta^k&amp;lt;/math&amp;gt; длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;/math&amp;gt;, матрица &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;S^k&amp;lt;/math&amp;gt; из соответствующих собственных векторов размера &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n\times k&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём выходных данных:&#039;&#039;&#039; &amp;lt;math&amp;gt;k\;(n + 1)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
В данном разделе перечислены без какой-либо хронологии или связи друг с другом наиболее важные и разнообразные свойства алгоритма, на которые стоит и полезно обратить внимание, а также которые выгодно отличают его от схожих алгоритмов, решающих ту же задачу.&amp;lt;br&amp;gt;&lt;br /&gt;
1) Отношение последовательной сложности алгоритма к параллельной,с учётом &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;/math&amp;gt; итераций, равно &amp;lt;math&amp;gt;\;\;\frac{kn^2}{k \log_2{n}}=\frac{n^2}{\log_2{n}}&amp;lt;/math&amp;gt;;&amp;lt;br&amp;gt;&lt;br /&gt;
2) Вычислительная мощность алгоритма, как отношение числа операций к суммарному объему входных и выходных данных, равна &amp;lt;math style=&amp;quot;vertical-align:-70%&amp;gt;\;\;\frac{k\,n^2}{0.5\,n^2+1.5\,n+k\,n+k+1}&amp;lt;/math&amp;gt; и &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;\approx 2\,k&amp;lt;/math&amp;gt;, так как на практике верно отношение &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;&amp;lt;n&amp;lt;/math&amp;gt; ;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
3) Для собственных значений формируемых матриц &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_j&amp;lt;/math&amp;gt; верно отношение (следствие теоремы Коши о перемежаемости): &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;\lambda_i(T_{k+1})\geq \lambda_i(T_{k})\geq \lambda_{i+1}(T_{k+1})\geq \lambda_{i+1}(T_{k})&amp;lt;/math&amp;gt; ;&amp;lt;ref&amp;gt;James W. Demmel - Вычислительная линейная алгебра. Теория и приложения //Мир. - 2001 (c. 383)&amp;lt;/ref&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
4) Крайние (наибольшие и наименьшие) собственные значения матриц &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_j&amp;lt;/math&amp;gt; сходятся к крайним собственным значениям матрицы &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;A&amp;lt;/math&amp;gt; первыми (это часто происходит уже на ранних шагах при &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j\approx 2\,\sqrt{n}&amp;lt;/math&amp;gt;&amp;lt;ref&amp;gt;http://num-anal.srcc.msu.ru/lib_na/int_ae/int_ae6.htm (пункт 6.5)&amp;lt;/ref&amp;gt;), а собственные значения в середине спектра - последними;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
5) Из-за ограниченной точности постепенно теряется ортогональность вектора Ланцоша &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;q_j&amp;lt;/math&amp;gt; к предыдущим векторам Ланцоша, поэтому необходимо примерно каждые 10-15 итераций проводить дорогостоящую операцию реортогонализации, но это уже будет иной алгоритм с очень малым различием в одной операции и в программном коде, реализующем его, соответственно; &amp;lt;ref&amp;gt;Sam Handler - The Lanczos Algorithm For Large-Scale Eigenvalue Problems (08.01.07), slide №8&amp;lt;/ref&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
6) Эффективность и быстрота выполнения алгоритма очень сильно зависит от скорости памяти (диска). Согласно тесту только &#039;&#039;6%&#039;&#039; времени работы программы приходится на вычисления, остальное время затрачивается на ожидание отклика диска;&amp;lt;ref&amp;gt;Sam Handler - The Lanczos Algorithm For Large-Scale Eigenvalue Problems (08.01.07), slide №10&amp;lt;/ref&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
7) Метод Ланцоша удобен тем, что не требует хранения исходной матрицы полным массивом: метод использует исходную матрицу только в операциях умножения матрицы на вектор, что позволяет эффективно использовать разреженность матрицы или регулярность структуры матрицы. Поэтому метод Ланцоша может быть использован для матриц таких больших порядков, когда методы вращений и отражений не могут быть применены.&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;
Для исследования масштабируемости рассматриваемого алгоритма Ланцоша без переортогонализации автором была реализована программа на языке С++ с использованием технологии MPI. &amp;lt;ref&amp;gt;http://chopapp.com/#rvsztfxc или вторая ссылка с прикреплённым кодом: http://pasted.co/13b3244c , по просьбе на почту я (автор статьи) готов предоставить доступ к проекту с этим кодом на Bitbucket&amp;lt;/ref&amp;gt; Дальнейшее исследование выполнялось на суперкомпьютере &amp;quot;Ломоносов&amp;quot; Суперкомпьютерного комплекса МГУ. &amp;lt;br&amp;gt; Важно отметить, что реализованная программа выполняет только первую часть алгоритма - формирование матрицы &amp;lt;math &amp;gt;T_j&amp;lt;/math&amp;gt;. Вторая часть алгоритма (задача поиска собственных значений матрицы &amp;lt;math &amp;gt;T_j&amp;lt;/math&amp;gt;) может быть решена несколькими методами, каждый из которых обладает своей эффективностью распараллеливании и характерными свойствами. Подробно этот вопрос уже обсуждался в статье раннее, поэтому не будем ещё раз заострять на этом внимание и останавливаться.&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Сборка осуществлялась со следующими параметрами:&lt;br /&gt;
* Компилятор intel/15.0.090 &lt;br /&gt;
* Openmpi/1.8.4-icc&lt;br /&gt;
В серии проведённых расчётов рассматривались следующие числовые значения параметров:&lt;br /&gt;
* Размер &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;n&amp;lt;/math&amp;gt; задачи и, соответственно, матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt;, задействованной в операции умножения на вектор: [2000 : 30000] с шагом 1000&lt;br /&gt;
* Число процессоров: 1, 2, 4, 16, 32, 48, 64, 96, 128&lt;br /&gt;
* Число итераций в алгоритме: &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k=350&amp;lt;/math&amp;gt;&lt;br /&gt;
Число &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; взято таким вопреки информации в начале статьи, где говорится, что значение &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; редко превышает &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;10^2&amp;lt;/math&amp;gt; (хоть мы и имеем право брать его любым по нашему усмотрению). Это сделано исключительно для лучшей визуализации пиков на графиках в данном разделе и наглядности получаемых результатов, так как при меньших на порядок значениях &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; времена выполнения программ были слишком малы даже при минимальных числах процессоров и максимальных размерах исходной задачи.&lt;br /&gt;
&lt;br /&gt;
== Динамические характеристики и эффективность реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Выводы для классов архитектур ==&lt;br /&gt;
По заданию, во второй части требовалось описать только разделы 2.4 и 2.7, прошу не спрашивать с меня все разделы 2.1-2.6. Надеюсь на понимание, мне физически не хватает времени на это задание + 2 других в течение семестра, делаю всё, что в моих силах :)&lt;br /&gt;
&lt;br /&gt;
== Существующие реализации алгоритма ==&lt;br /&gt;
Несмотря на то, что алгоритм является далеко не самым популярным, алгоритмом, про который нельзя сказать, что он всегда «на слуху», на сегодняшний день существует множество реализаций на различных популярных языках.&amp;lt;br&amp;gt;&lt;br /&gt;
Перечислим далее некоторые из них, указывая язык программирования, лежащий в их основе, и некоторые важные характеристики, которые обсуждались в статье ранее:&lt;br /&gt;
*&#039;&#039;Code on netlib.org by Jane Cullum and Ralph Willoughby&#039;&#039; (&#039;&#039;&#039;Fortran 77&#039;&#039;&#039;; без реортогонализации векторов; без реализации распараллеливания)&amp;lt;ref&amp;gt;http://www.netlib.org/lanczos/leval&amp;lt;/ref&amp;gt;&lt;br /&gt;
*&#039;&#039;Lanczos algorithm on freesourcecode.net&#039;&#039; (&#039;&#039;&#039;Matlab&#039;&#039;&#039;; присутствует реортогонализация векторов; без реализации распараллеливания)&amp;lt;ref&amp;gt;http://freesourcecode.net/matlabprojects/61741/lanczos-algorithm--in-matlab&amp;lt;/ref&amp;gt;&lt;br /&gt;
*&#039;&#039;Lanczos for eigenvalues in Numerical Linear Algebra, Spring 2007&#039;&#039; (&#039;&#039;&#039;Matlab&#039;&#039;&#039;; частичная или полная реортогонализация - доступны оба варианта; без реализации распараллеливания)&amp;lt;ref&amp;gt;Ссылки на файлы lanso.m и lanfu.m можно найти на https://www.nada.kth.se/~ruhe/2D5219/labs2007.html&amp;lt;/ref&amp;gt;&lt;br /&gt;
*&#039;&#039;Planso&#039;&#039; (название происходит от parallel Lanso.f) &#039;&#039;code by Kesheng Wu and Horst D. Simon&#039;&#039; (&#039;&#039;&#039;Fortran 77&#039;&#039;&#039;; частичная реортогонализация векторов; использование MPI для коммуникаций)&amp;lt;ref&amp;gt;https://github.com/jiahao/planso.jl/tree/master/external/PLAN/plan К сожалению, ссылка в описании пакета на github, ведущая на сайт National Energy Research Scientific Computing Center (NERSC), с более подробной информацией о данной программе больше не активна и выдаёт результат &#039;&#039;Page not found&#039;&#039;&amp;lt;/ref&amp;gt; &lt;br /&gt;
* &#039;&#039;Lanczos.cpp in the Vienna Computing Library&#039;&#039;  (&#039;&#039;&#039;C++&#039;&#039;&#039;, частичная реортогонализация, без реализации распараллеливания) &amp;lt;ref&amp;gt;http://viennacl.sourceforge.net/doc/lanczos_8cpp_source.html&amp;lt;/ref&amp;gt;&lt;br /&gt;
* &#039;&#039;Parallel Eigen Values code using C++ AMP on microsoft msdn blog&#039;&#039; (&#039;&#039;&#039;C++&#039;&#039;&#039;; ? ; распараллеливание есть и реализовано через C++ AMP) &amp;lt;ref&amp;gt;https://blogs.msdn.microsoft.com/nativeconcurrency/2013/12/20/eigen-values/ Подробнее о C++ Accelerated Massive Parallelism можно почитать здесь: https://msdn.microsoft.com/ru-ru/library/hh265137(v=vs.140).aspx или здесь: http://professorweb.ru/my/csharp/optimization/level4/4_6.php &amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;br /&gt;
[[en:Description of algorithm properties and structure]]&lt;/div&gt;</summary>
		<author><name>AleksLevin</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:AleksLevin/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%9B%D0%B0%D0%BD%D1%86%D0%BE%D1%88%D0%B0_%D0%B2%D1%8B%D1%87%D0%B8%D1%81%D0%BB%D0%B5%D0%BD%D0%B8%D1%8F_%D1%81%D0%BE%D0%B1%D1%81%D1%82%D0%B2%D0%B5%D0%BD%D0%BD%D1%8B%D1%85_%D0%B7%D0%BD%D0%B0%D1%87%D0%B5%D0%BD%D0%B8%D0%B9_%D1%81%D0%B8%D0%BC%D0%BC%D0%B5%D1%82%D1%80%D0%B8%D1%87%D0%BD%D0%BE%D0%B9_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86%D1%8B_%D0%B4%D0%BB%D1%8F_%D1%82%D0%BE%D1%87%D0%BD%D0%BE%D0%B9_%D0%B0%D1%80%D0%B8%D1%84%D0%BC%D0%B5%D1%82%D0%B8%D0%BA%D0%B8_(%D0%B1%D0%B5%D0%B7_%D0%BF%D0%B5%D1%80%D0%B5%D0%BE%D1%80%D1%82%D0%BE%D0%B3%D0%BE%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D0%B8)&amp;diff=20217</id>
		<title>Участник:AleksLevin/Алгоритм Ланцоша вычисления собственных значений симметричной матрицы для точной арифметики (без переортогонализации)</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:AleksLevin/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%9B%D0%B0%D0%BD%D1%86%D0%BE%D1%88%D0%B0_%D0%B2%D1%8B%D1%87%D0%B8%D1%81%D0%BB%D0%B5%D0%BD%D0%B8%D1%8F_%D1%81%D0%BE%D0%B1%D1%81%D1%82%D0%B2%D0%B5%D0%BD%D0%BD%D1%8B%D1%85_%D0%B7%D0%BD%D0%B0%D1%87%D0%B5%D0%BD%D0%B8%D0%B9_%D1%81%D0%B8%D0%BC%D0%BC%D0%B5%D1%82%D1%80%D0%B8%D1%87%D0%BD%D0%BE%D0%B9_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86%D1%8B_%D0%B4%D0%BB%D1%8F_%D1%82%D0%BE%D1%87%D0%BD%D0%BE%D0%B9_%D0%B0%D1%80%D0%B8%D1%84%D0%BC%D0%B5%D1%82%D0%B8%D0%BA%D0%B8_(%D0%B1%D0%B5%D0%B7_%D0%BF%D0%B5%D1%80%D0%B5%D0%BE%D1%80%D1%82%D0%BE%D0%B3%D0%BE%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D0%B8)&amp;diff=20217"/>
		<updated>2016-12-07T00:20:35Z</updated>

		<summary type="html">&lt;p&gt;AleksLevin: /* Масштабируемость алгоритма и его реализации */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Основные авторы описания: Левин А.Д.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{algorithm&lt;br /&gt;
| name              = Алгоритм Ланцоша для точной арифметики (без переортогонализации)&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(k\,n^2)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(k\log_2 n)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;\frac{n^2+3n}{2} + 1&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;k\;(n + 1)&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритмов =&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Данный алгоритм появился в 1950 г. и носит имя венгерского физика и математика Корнелия Ланцоша (венг. Lánczos Kornél). Алгоритм Ланцоша относится к итерационным методам вычисления собственных значений для матриц столь больших порядков &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt; n&amp;lt;/math&amp;gt;, что к ним нельзя применить прямые методы из-за ограничений по времени и памяти.&lt;br /&gt;
&lt;br /&gt;
Сам Ланцош указывал, что его метод предназначен для отыскания нескольких собственных векторов симметричных матриц, хотя к методу сразу было обращено внимание, как к способу приведения всей матрицы к трёхдиагональному виду. Двадцатью годами позже канадский математик Крис Пэж показал, что, несмотря на чувствительность к округлениям, алгоритм Ланцоша - эффективное средство вычисления некоторых &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; собственных чисел и соответствующих им собственных векторов. &amp;lt;ref&amp;gt;Парлетт Б. - Симметричная проблема собственных значений. Численные методы //М.: Мир. - 1983. (c. 276)&amp;lt;/ref&amp;gt;&lt;br /&gt;
Обычно число &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; берут в два раза больше, чем количество собственных значений матрицы, которые поставлена цель найти, и оно имеет порядок не более &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;10^2&amp;lt;/math&amp;gt;.&amp;lt;ref&amp;gt;Susan W. Bostic - Lanczos Eigensolution Method for High-Perfomance Computers, page 7&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Алгоритм Ланцоша для вычисления собственных значений симметричной матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; соединяет в себе метод Ланцоша для построения последовательности подпространств Крылова и ортонормированных векторов Ланцоша и процедуру Рэлея-Ритца получения оптимальных приближений собственных значений и соответствующих собственных векторов исходной матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt;.&amp;lt;ref&amp;gt;James W. Demmel - Вычислительная линейная алгебра. Теория и приложения //Мир. - 2001 (c. 381)&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
В данной статье рассматривается вариант алгоритма Ланцоша, в котором опущено влияние ошибок округления на вычислительный процесс, хотя на практике этому посвящается отдельное внимание и существуют различные методы решения данной проблемы, такие как частичная или полная переортогонализация. Этим модифицированным методам посвящены отдельные статьи на данном ресурсе.&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
Обозначения и формулы, используемые в данном разделе, взяты из литературы, указанной по ссылке.&amp;lt;ref&amp;gt;James W. Demmel - Вычислительная линейная алгебра. Теория и приложения //Мир. - 2001 (c. 313, &#039;&#039;&amp;lt;math&amp;gt; \S &amp;lt;/math&amp;gt; 6.6 Методы Крыловского подпространства&#039;&#039;)&amp;lt;/ref&amp;gt; &lt;br /&gt;
&lt;br /&gt;
Алгоритм Ланцоша для вычисления &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; собственных значений и собственных векторов вещественной симметричной матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A=A^T&amp;lt;/math&amp;gt; в точной арифметике: &amp;lt;ref&amp;gt;James W. Demmel - Вычислительная линейная алгебра. Теория и приложения //Мир. - 2001 (c. 381)&amp;lt;/ref&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{align}&lt;br /&gt;
q_1 = &amp;amp; \,\frac{b}{\|b\|_2},\; \beta_0 = 0,\; q_0 = 0\\&lt;br /&gt;
\mathbf{for} \; &amp;amp; j = 1 \; to \; k \,\; \mathbf{do} \\&lt;br /&gt;
&amp;amp; z = A\,q_j\\&lt;br /&gt;
&amp;amp; \alpha_j = q^T_j z\\&lt;br /&gt;
&amp;amp; z = z - \alpha_j q_j - \beta_{j-1}q_{j-1}\\&lt;br /&gt;
&amp;amp; \beta_j = \|z\|_2\\&lt;br /&gt;
&amp;amp; \mathbf{If} \; (\beta_j == 0) \; \mathbf{then}\; stop\; the\; algorithm \\ &lt;br /&gt;
&amp;amp; \;  q_{j+1} = \frac{z}{\beta_j} \\&lt;br /&gt;
&amp;amp; compute\; eigenvalues\; and \;eigenvectors\;of \;matrix \;\;T_j= Q^T_j A Q\;\;and\;estimate \;the\; errors\\&lt;br /&gt;
\mathbf{end} \; &amp;amp; \mathbf{for}&lt;br /&gt;
\end{align}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
В продемонстрированном выше алгоритме &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;b&amp;lt;/math&amp;gt; - заданный вещественный вектор. Также полагается известным алгоритм вычисления произведения матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; на вектор &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;x&amp;lt;/math&amp;gt;. &lt;br /&gt;
Введём матрицу Крылова, определяемую следующим соотношением: &amp;lt;math&amp;gt;K_j = [b,Ab,A^2b,...,A^{j-1}b]&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Далее, на практике, матрица &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;K&amp;lt;/math&amp;gt; заменяется матрицей &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;Q&amp;lt;/math&amp;gt;, такой, что при любом числе &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; линейные оболочки первых &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; столбцов в &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;K&amp;lt;/math&amp;gt; и &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;Q&amp;lt;/math&amp;gt; являются одним и тем же подпространством.&amp;lt;ref&amp;gt;James W. Demmel - Вычислительная линейная алгебра. Теория и приложения //Мир. - 2001 (c. 315)&amp;lt;/ref&amp;gt; &lt;br /&gt;
Тогда матрица &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;Q&amp;lt;/math&amp;gt;, в отличие от матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;K&amp;lt;/math&amp;gt;, хорошо обусловлена и легко обратима. В результате получаем матрицу &amp;lt;math&amp;gt;Q_j = [q_1, q_2, \dots, q_j]&amp;lt;/math&amp;gt; размерности &amp;lt;math&amp;gt;n\times j&amp;lt;/math&amp;gt;, столбцы которой ортогональны, являются базисом подпространства Крылова и называются векторами Ланцоша.&lt;br /&gt;
&lt;br /&gt;
В алгоритме Ланцоша вычислению подлежит столько первых столбцов в матрице &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;Q_j&amp;lt;/math&amp;gt;, сколько необходимо для получения требуемого приближения к решению &amp;lt;math&amp;gt;A\,x\,=b\,\,(A\,x=\lambda \, x)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Получение нулевого &amp;lt;math&amp;gt;\beta_j&amp;lt;/math&amp;gt; в итерационном процессе - событие, желательное в том смысле, что оно свидетельствует о том, что найдено некоторое подпространство, являющееся в точности инвариантным, а все собственные значения матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;T_j&amp;lt;/math&amp;gt; являются собственными значениями матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt;. На практике же нулевое и близкие к нулю значения получаются редко.&amp;lt;ref&amp;gt;Голуб Дж., Ван Лоун Ч. - Матричные вычисления//М.: Мир. - 1999 (c. 429)&amp;lt;/ref&amp;gt; &lt;br /&gt;
&lt;br /&gt;
Затем на каждом шаге цикла формируется симметричная трёхдиагональная матрица &amp;lt;math&amp;gt;T_j = Q^T_j A Q&amp;lt;/math&amp;gt;, к которой применяется процесс Рэлея-Ритца для поиска её собственных значений (на практике для поиска этих собственных значений можно использовать любой из специальных методов в параграфе книги по ссылке).&amp;lt;ref&amp;gt;Голуб Дж., Ван Лоун Ч. - Матричные вычисления//М.: Мир. - 1999 (&amp;lt;math&amp;gt;\S&amp;lt;/math&amp;gt; 8.4)&amp;lt;/ref&amp;gt;  &lt;br /&gt;
Эти собственные значения, они же числа Ритца, и полагаются приближёнными собственными значениями исходной матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt;.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Существует множество методов для отыскания собственных значений вещественной симметричной трехдиагональной матрицы. Большинство из них требует &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt; операций &amp;lt;ref&amp;gt;Парлетт Б. Симметричная проблема собственных значений. Численные методы.,: Мир, 1983. с. 179-182&amp;lt;/ref&amp;gt;, но существуют и быстрые алгоритмы, требующие лишь &amp;lt;math&amp;gt;O(n\ln n)&amp;lt;/math&amp;gt; операций.&amp;lt;ref&amp;gt;https://en.wikipedia.org/wiki/Tridiagonal_matrix#Eigenvalues  Раздел eigenvalues&amp;lt;/ref&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Одним из возможных способов отыскать собственные значения симметричной трехдиагональной матрицы - прямое вычисление корней характеристического полинома &amp;lt;math&amp;gt;p_n(\lambda)&amp;lt;/math&amp;gt; через метод деления пополам, где формируется последовательность Штурма и локализуются собственные числа, являющиеся корнями характеристического полинома. Нахождение всех &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; собственных значений матрицы этим способом требует &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;2n^2t&amp;lt;/math&amp;gt; умножений и вычитаний, где &amp;lt;math&amp;gt;t&amp;lt;/math&amp;gt; - число сделанных шагов с применением метода деления пополам.&amp;lt;ref&amp;gt;Уилкинсон Дж. X. Алгебраическая проблема собственныx значений. Изд-во &amp;quot;Наука&amp;quot;, 1970. - глава 5, с. 272-278&amp;lt;/ref&amp;gt; Соответствующие собственные вектора могут быть найдены посредством обратных итераций за &amp;lt;math&amp;gt; O(n) &amp;lt;/math&amp;gt; флопов. &amp;lt;ref&amp;gt;Голуб Дж., Ван Лоун Ч. - Матричные вычисления//М.: Мир. - 1999 (c. 394-395)&amp;lt;/ref&amp;gt; &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;На практике, если требуется только небольшая часть от всей совокупности собственных векторов и значений, и матрица имеет Хессенбергову или трёхдиагональную форму, очень эффективными будут методы факторизации, как, например, QR-алгоритм или QL-алгоритм со сдвигами (c целью ускорить алгоритм и сделать порядок сходимости квадратичным) или же без них.&amp;lt;ref&amp;gt;http://algorithm.narod.ru/ln/eigen/ETridiag.html&amp;lt;/ref&amp;gt; &amp;lt;br&amp;gt;&lt;br /&gt;
Весьма молодые и не менее актуальные конкуренты QR и QL алгоритмов, применяющиеся для поиска собственных значений:&lt;br /&gt;
*Методы divide-and-conquer (разделяй и властвуй), появившиеся в 1980-ых годах &amp;lt;ref&amp;gt;https://goo.gl/dapvbn ссылку пришлось сократить с помощью Google url shortener, так как символы подчеркивания портили её и не давали перейти по 1 клику&amp;lt;/ref&amp;gt;&lt;br /&gt;
*Relatively robust representation методы, появившиеся в 1990-ых и позволяющие найти собственные числа симметричной матрицы порядка &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;n&amp;lt;/math&amp;gt; за &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt; операций&lt;br /&gt;
&lt;br /&gt;
Если требуется вычислить собственные векторы, то необходимо хранить вычисляемые векторы Ланцоша. Если работа при этом производится только с оперативной памятью, то при большом порядке исходной матрицы (а именно для таких матриц и предназначен метод Ланцоша) число шагов  &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;j&amp;lt;/math&amp;gt;, которые могут быть выполнены до того момента, как оперативная память будет исчерпана, будет очень незначительно, а следовательно, искомые собственные пары могут не успеть сойтись с требуемой точностью. В этом случае метод Ланцоша можно использовать итерационным образом: после выполнения заданного числа шагов процесс прерывается и, если еще не все требуемые пары Ритца сошлись с требуемой точностью, то формируется новый начальный вектор &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;q_1&amp;lt;/math&amp;gt;, являющийся линейной комбинацией векторов Ритца, еще не сошедшихся с заданной точностью, и процесс начинается заново.&amp;lt;ref&amp;gt;http://num-anal.srcc.msu.ru/lib_na/int_ae/int_ae6.htm (пункт 6.5)&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
Вычислительное ядро рассматриваемого алгоритма (наиболее ресурсно-затратная часть алгоритма) -  формирование на каждом шаге цикла промежуточного вектора &amp;lt;math&amp;gt;z&amp;lt;/math&amp;gt;, вычисляемого по формуле: &amp;lt;math&amp;gt;z = A\,q_j&amp;lt;/math&amp;gt;. Данная операция, по сравнению с другими операциями алгоритма, затратна и требовательна, как с точки зрения количества производимых операций, так и с точки зрения объема оперируемых данных. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Например, умножение матрицы размера &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;n\times n&amp;lt;/math&amp;gt; на вектор длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; требует: &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;n^2+(n-1)n = 2n^2-n&amp;lt;/math&amp;gt; операций умножения и сложения. В свою очередь аналогичная операция умножения матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;(n+1)\times (n+1)&amp;lt;/math&amp;gt; на вектор длины &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;(n+1)&amp;lt;/math&amp;gt; требует: &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;2n^2+3n+1&amp;lt;/math&amp;gt;  операций умножения и сложения. То есть повышение размерности задачи всего на 1 увеличивает число необходимых действий в этом шаге алгоритма на: &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;4n+1&amp;lt;/math&amp;gt;. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Так же, стоит помнить, что, согласно разделу 1.2, данную операцию умножения матрицы на вектор необходимо выполнить &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;k&amp;lt;/math&amp;gt; раз. Нетрудно понять, насколько возрастает и колоссален масштаб операций, если в задачах, где критична точность, размерности &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; могут иметь порядок &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;10^5&amp;lt;/math&amp;gt; или даже более.&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
Как уже было упомянуто в данной статье в описании алгоритма, рассматриваемый алгоритм состоит из двух последовательно выполненных алгоритмов: метод Ланцоша для построения последовательности подпространств Крылова и ортонормированных векторов Ланцоша и процедура Рэлея-Ритца получения оптимальных приближений собственных значений и соответствующих собственных векторов исходной матрицы.&lt;br /&gt;
&lt;br /&gt;
В первой части алгоритма, где итерационно строятся Крыловское подпространство и трёхдиагональная матрица &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&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 style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; разреженная. Именно она подлежит оптимизации с использованием техник распараллеливания, поскольку она является вычислительным ядром алгоритма, а весь упомянутый процесс построения матрицы &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&amp;lt;/math&amp;gt; выполняется последовательно.&lt;br /&gt;
&lt;br /&gt;
Рассмотрим вторую часть алгоритма - поиск собственных значений сформированной матрицы &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&amp;lt;/math&amp;gt;.&amp;lt;br&amp;gt;&lt;br /&gt;
Далее, наглядно, в виде псевдокода, представлен, упомянутый в разделе 1.2, QR-алгоритм (аналогично можно рассмотреть и QL-алгоритм) со сдвигами Релэя, который весьма популярен на практике.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{align}&lt;br /&gt;
\mathbf{Input}: \;&amp;amp;tridiagonal\;\;matrix \;T\;with\;\;n\times n\;\;size\\&lt;br /&gt;
T^{(0)}&amp;amp;:=T\\&lt;br /&gt;
\mathbf{for}&amp;amp; \;\;m=n,...,2 \;\; \mathbf{do}\\&lt;br /&gt;
&amp;amp;k=0\\&lt;br /&gt;
&amp;amp; \mathbf{repeat}\\&lt;br /&gt;
&amp;amp; \quad \;\; k=k+1\\&lt;br /&gt;
&amp;amp; \quad \;\; \mu^{(k)}=T_{m,m}^{(k-1)}\\&lt;br /&gt;
&amp;amp; \quad \;\; Q^{(k)}R^{(k)}=T^{(k-1)}-\mu^{(k)}I\;\;using\;\;QR\;decomposition\\&lt;br /&gt;
&amp;amp; \quad \;\; T^{(k)}=R^{(k)}Q^{(k)}+\mu^{(k)}I\\&lt;br /&gt;
&amp;amp; \mathbf{until} \;\;\; |T_{m,m-1}^{(k)}| \;is\;\;small\;\;enough\\&lt;br /&gt;
&amp;amp; Save  \;\;T_{m,m}^{(k)} \;\;as\;\; converged\;\;eigenvalue\;of\;T\\ &lt;br /&gt;
&amp;amp; Remove \;\boldsymbol{n}\,th\;row\;and\;\boldsymbol{n}\,th\;column\;\;from \;T \\&lt;br /&gt;
&amp;amp; and\;take\;this\;new\;cropped\;matrix\;as\;new\;T^{(0)}\;with\;\;(n-1)\times (n-1)\;\;size\\&lt;br /&gt;
 \mathbf{end}&amp;amp;\; \mathbf{for}&lt;br /&gt;
\end{align}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Малость наддиагональных и поддиагональных элементов матрицы (фраза &#039;&#039;&amp;quot;small enough&amp;quot;&#039;&#039; в псевдокоде) подразумевает:&lt;br /&gt;
&amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt; |T_{m,m-1}^{(k)}| \leq \varepsilon\,|T_{m,m}^{(k)}| \quad\quad &amp;lt;/math&amp;gt; , где &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt; \varepsilon &amp;lt;/math&amp;gt; - заданная точность&amp;lt;br&amp;gt;&lt;br /&gt;
Также вместо сдвига Релэя, обозначенного в алгоритме через &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;\mu^{(k)}&amp;lt;/math&amp;gt;, часто на практике используется сдвиг по Уилкинсону, который даёт гарантированную сходимость внедиагональных элементов матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt; T^{(k)} &amp;lt;/math&amp;gt;, формируемой на каждом шаге, к нулю, при этом жертвуя монотонностью их убывания.&amp;lt;ref&amp;gt;Голуб Дж., Ван Лоун Ч. - Матричные вычисления//М.: Мир. - 1999 (c. 378, вторая половина страницы)&amp;lt;/ref&amp;gt;&amp;lt;ref&amp;gt;Парлетт Б. Симметричная проблема собственных значений. Численные методы.,: Мир, 1983. с. 169&amp;lt;/ref&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Подробнее с различными сдвигами и соответствующими оценками скоростей и количествами операций можно ознакомиться по указанной ссылке:&amp;lt;ref&amp;gt;Парлетт Б. Симметричная проблема собственных значений. Численные методы.,: Мир, 1983. с. 179-182&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;Для совершения QR-декомпозиции на каждом шаге может использоваться любой из алгоритмов по ссылке.&amp;lt;ref&amp;gt;https://en.wikipedia.org/wiki/QR_decomposition&amp;lt;/ref&amp;gt; Подробные описания этих алгоритмов также доступны на данном ресурсе algowiki-project.&amp;lt;br&amp;gt;&lt;br /&gt;
Так как мы оперируем не обычной матрицей и даже не Хессенберговой, а симметричной и трёхдиагональной, то скорость таких алгоритмов значительно возрастёт. Например, согласно данному ресурсу &amp;lt;ref&amp;gt;http://algorithm.narod.ru/ln/eigen/ETridiag.html&amp;lt;/ref&amp;gt;, для QL-алгоритма с неявными сдвигами:&amp;lt;br&amp;gt;&lt;br /&gt;
Для трёхдиагональной матрицы объем арифметических действий составляет &amp;lt;math&amp;gt; O(n)&amp;lt;/math&amp;gt; на одну итерацию вместо &amp;lt;math&amp;gt; O(n^3)&amp;lt;/math&amp;gt; для матрицы общего вида, а число итераций для нахождения первых собственных значений примерно равно 4 - 5. Но на этих итерациях также уменьшаются внедиагональные элементы правого нижнего угла. И, таким образом, дальнейшие собственные значения ищутся значительно быстрее. Среднее число итераций на каждое собственное значение обычно составляет 1.3 - 1.6.&amp;lt;br&amp;gt; &lt;br /&gt;
Аналогично QL, QR-разложение трёхдиагольной матрицы также требует &amp;lt;math&amp;gt; O(n)&amp;lt;/math&amp;gt; флопов&amp;lt;ref&amp;gt;Голуб Дж., Ван Лоун Ч. - Матричные вычисления//М.: Мир. - 1999 (c. 378, начало раздела 8.2.2)&amp;lt;/ref&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Подводя итог, во второй части алгоритма Ланцоша можно выделить следующие макрооперации:&lt;br /&gt;
* умножение матрицы на вещественное число;&lt;br /&gt;
* перемножение матриц;&lt;br /&gt;
* умножение и сравнение вещественных чисел;&lt;br /&gt;
* + набор других макроопераций в зависимости от выбора метода, с помощью которого будет совершаться сама QR или QL-декомпозиция (выше продемонстрированы, уже, как минимум, 3 разных способа).&lt;br /&gt;
Так же, важно заметить, что набор макропераций может быть несколько другим, если выбрать какой-либо иной современный метод поиска собственных чисел трёхдиагональной матрицы, не использующий QR и QL разложения(факторизацию). Два таких метода были упомянуты в пункте 1.2.&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
С целью полностью не дублировать раздел 1.2 данной статьи, где представлен наглядный и доступный для понимания псевдокод алгоритма, постараемся лишь коротко просуммировать и обобщить весь перечень последовательных действий в рассматриваемом алгоритме.&lt;br /&gt;
&lt;br /&gt;
В качестве входных данных имеем: вещественная симметричная матрица &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; размера &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;n\times n&amp;lt;/math&amp;gt;, известный вещественный вектор &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;b&amp;lt;/math&amp;gt; длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; и число &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;n&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Далее:&lt;br /&gt;
* Инициализируем вещественную константу &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;\beta_0&amp;lt;/math&amp;gt; и векторы &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;q_0&amp;lt;/math&amp;gt; и &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;q_1&amp;lt;/math&amp;gt;&lt;br /&gt;
* Итерационно для всех &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j=1,...,k&amp;lt;/math&amp;gt;:&lt;br /&gt;
** Вычисляем вспомогательный вектор &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt;, используя умножение матрицы на вектор&lt;br /&gt;
** Вычисляем, используя скалярное произведение векторов, значение &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;\alpha_j&amp;lt;/math&amp;gt; - элемент на главной диагонали трёхдиагональной матрицы &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&amp;lt;/math&amp;gt;&lt;br /&gt;
** Вычисляем по формуле новое значение и перезаписываем вектор &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt;&lt;br /&gt;
** Вычисляем значение &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;\beta_j&amp;lt;/math&amp;gt; - элементы непосредственно над и под главной диагональю той же матрицы &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&amp;lt;/math&amp;gt;&lt;br /&gt;
** Вычисляем, зная вектор &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt;,  очередной столбец матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;Q&amp;lt;/math&amp;gt;, он же вектор Ланцоша : &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;\,\,q_{j+1}&amp;lt;/math&amp;gt;&lt;br /&gt;
** Теперь, когда матрица &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&amp;lt;/math&amp;gt; сформирована на очередном шаге, находим её собственные значения и вектора любым доступным способом, о чём было подробно сказано в пункте 1.2&lt;br /&gt;
** Переходим на следующую итерацию: &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j&amp;lt;/math&amp;gt;++&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
Оценим количество операций и сложность последовательного алгоритма, изложенного в предыдущем разделе.&lt;br /&gt;
*Для вычисления вектора &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt; умножается матрица размера &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;n\times n&amp;lt;/math&amp;gt; на вектор длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt;, и потребуется &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n^2&amp;lt;/math&amp;gt; операций умножения и &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n^2&amp;lt;/math&amp;gt; операций сложения.&lt;br /&gt;
*Умножение векторов &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;q^T_j&amp;lt;/math&amp;gt; и &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt; длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; потребует &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; операций умножения и &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; операций сложения.&lt;br /&gt;
*При вычислении нового значения вектора &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt; поэлементное сложение двух векторов длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; требует &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; операций сложения.&lt;br /&gt;
*Умножение вектора длины &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; на вещественное число требует &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; операций умножения.&lt;br /&gt;
*Нахождение квадратичной нормы вектора &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt;  длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; требует &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; умножений и &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; сложений и ещё 1 операцию извлечения квадратного корня.&lt;br /&gt;
*Заключительное нахождение собственных значений и собственных векторов трёхдиагональной матрицы &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;T_j&amp;lt;/math&amp;gt; размера &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j\times j&amp;lt;/math&amp;gt; с помощью QR-алгоритма потребует в худшем случае &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(j^3)&amp;lt;/math&amp;gt; операций.&amp;lt;ref&amp;gt;http://num-anal.srcc.msu.ru/lib_na/int_ae/int_ae6.htm (пункт 6.2, &amp;quot;Скорость сходимости при этом всегда не хуже квадратичной и почти всегда лучше кубической.&amp;quot;)&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Посчитаем теперь суммарное количество простейших операций на одной итерации алгоритма (без учёта записей в память):&lt;br /&gt;
*&amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n^2+5\,n&amp;lt;/math&amp;gt; операций умножения/деления&lt;br /&gt;
*&amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n^2+4\,n&amp;lt;/math&amp;gt; операций сложения/вычитания&lt;br /&gt;
*1 операция извлечения квадратного корня&amp;lt;br&amp;gt;&lt;br /&gt;
Отдельно после всех итераций при &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j=k&amp;lt;/math&amp;gt; :&lt;br /&gt;
*&amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(k^3)&amp;lt;/math&amp;gt; операций для поиска собственных значений и собственных векторов трёхдиагональной матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_k&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Итого можно утверждать следующее:&lt;br /&gt;
&lt;br /&gt;
Последовательная сложность одной итерации рассматриваемого алгоритма:  &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(n ^ 2) &amp;lt;/math&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Суммарная сложность алгоритма (&amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;/math&amp;gt; итераций): &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(k\,n ^ 2) + O(k ^ 3)&amp;lt;/math&amp;gt; &amp;lt;ref&amp;gt;Здесь мы полагаем, что мы не вычисляем собственные значения и векторы матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_j&amp;lt;/math&amp;gt; на каждом промежуточном шаге, а лишь единожды затрачиваем &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;O(k ^ 3)&amp;lt;/math&amp;gt; действий в конце для нахождения &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;/math&amp;gt; собственных значений и векторов матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_k&amp;lt;/math&amp;gt;&amp;lt;/ref&amp;gt; &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
На практике же обычно рассматривается число &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;&amp;lt;n&amp;lt;/math&amp;gt;, поэтому второе слагаемое можно опустить.&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
На рис. 1 продемонстрирован граф одной итерации (при каком-либо произвольном значении итератора &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j&amp;lt;/math&amp;gt;) описанного алгоритма без отображения входных и выходных данных. Наглядно продемонстрированы связи между всеми действиями, и с помощью деления на &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; потоков показано, какие операции возможно выполнять параллельно на каждом шаге с целью оптимизации и экономии машинного времени. В результате, после параллельно выполненных операций &#039;&#039;&#039;Division&#039;&#039;&#039; на заключительном ярусе, на выходе имеем значение следующего вектора Ланцоша &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;q_{j+1}&amp;lt;/math&amp;gt;, после чего следует переход на следующую итерацию, и процесс повторяется.&lt;br /&gt;
&lt;br /&gt;
[[Файл:Levin_graph.png|600px|thumb|center|Рис. 1  Структура одной итерации алгоритма]] &amp;lt;br&amp;gt;&lt;br /&gt;
Обозначения на рисунке: &amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Simp&#039;&#039;&#039; (от англ. simple) - операции сложения и умножения вещественных чисел при вычислении произведения матрицы на вектор;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Vec mult&#039;&#039;&#039; (от англ. vectors multiplication) - операция скалярного умножения двух векторов;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Vec subtr&#039;&#039;&#039; (от англ. vectors subtraction, из-за использованных в операции вычитаний векторов) - операция умножения вектора на число (выполняется дважды) и формирование нового значения &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;z_{new}&amp;lt;/math&amp;gt; по формуле: &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;z_{new} = z - \alpha_j q_j - \beta_{j-1}q_{j-1} \;&amp;lt;/math&amp;gt;;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;||\cdot||&amp;lt;/math&amp;gt; - операция вычисления нормы вектора;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Division&#039;&#039;&#039; - операция деления вектора на вещественное число  &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;\beta_j&amp;lt;/math&amp;gt; &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Важно отметить, что упомянутые выше операции также легко поддаются оптимизации. Например, попарные умножения вещественных координат векторов при вычислении скалярного произведения также легко выполняются параллельно на &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; потоках, а затем можно применить суммирование методом сдваивания, о котором сказано в следующем разделе. Умножение или деление вектора на вещественное число являющееся, по определению, умножением или делением всех его координат на это число тоже может быть выполнено эффективнее, если мы используем &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; потоков, а не выполняем эти действия последовательно.&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
Параллельные операции возможны только внутри итераций, так как рассматриваемый алгоритм является итерационным, и сами итерации строго последовательны.&amp;lt;br&amp;gt;&lt;br /&gt;
Рассмотрим в этом разделе подробнее, какой выигрыш мы можем получить при распараллеливании операций внутри одной итерации согласно графу из предыдущего раздела.&lt;br /&gt;
&lt;br /&gt;
Умножение вещественной симметричной матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; размера &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;n\times n&amp;lt;/math&amp;gt; на вектор &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;b&amp;lt;/math&amp;gt; длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; требует последовательного выполнения &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; ярусов умножений и сложений. Сложение элементов вектора длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; на каждом шаге перемножения можно оптимизировать и выполнить за &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;\log_2 n&amp;lt;/math&amp;gt; действий, если применять метод сдваивания.&lt;br /&gt;
&lt;br /&gt;
Дальнейшие операции выполняются последовательно, а вычисление значений векторов происходит за один ярус операций сложения или умножения.&lt;br /&gt;
&lt;br /&gt;
Ресурс параллелизма алгоритма вычисления собственных значений построенной трёхдиагональной матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_k&amp;lt;/math&amp;gt; размера &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k\times k&amp;lt;/math&amp;gt; зависит от выбранного алгоритма (об этих алгоритмах подробнее было сказано в разделах 1.2 и 1.4). Будет очень затратно с точки зрения объёма материала пытаться рассмотреть пусть даже часть этих методов в этой статье, а так же тонкости их распараллеливания. Предлагаем читателям при желании самим ознакомиться с этими алгоритмами на данном ресурсе или прибегнув к иным источникам.&lt;br /&gt;
&lt;br /&gt;
При классификации по высоте ЯПФ, таким образом, алгоритм Ланцоша без переортогонализации относится к алгоритмам с &#039;&#039;логарифмической сложностью&#039;&#039;, и его сложность равна &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(\log_2 n)&amp;lt;/math&amp;gt; с важным замечанием, что это сложность только одной итерации, а максимум в алгоритме может быть выполнено последовательно &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;/math&amp;gt; таких однотипных итераций, если не будет осуществлён ранний выход из цикла. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Несмотря на то, что на графе в предыдущем разделе для лучшей визуализации и понимания было изображено &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; потоков (никаких допущений мы не делали и нарушений с точки зрения логики и математики нет, можно изобразить большее число потоков, просто часть времени некоторые из них могут бездействовать и не использоваться), на самом деле правильным и разумным будет реализовать начальное параллельное выполнение &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n^2&amp;lt;/math&amp;gt; операций умножения всех вещественных элементов матрицы &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;A&amp;lt;/math&amp;gt; на соответствующие элементы вектора &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;q_j&amp;lt;/math&amp;gt;, после чего применять тот же самый упомянутый метод сдваивания. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Поэтому при классификации по ширине ЯПФ его сложность будет &#039;&#039;квадратичной&#039;&#039; и равна &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(n^2)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
&#039;&#039;&#039;Входные данные алгоритма:&#039;&#039;&#039; вещественная симметричная &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; размера &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;n\times n&amp;lt;/math&amp;gt;, вещественный вектор &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;b&amp;lt;/math&amp;gt; длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt;, и одно целое число &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;k&amp;lt;/math&amp;gt;, означающее количество итераций.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём входных данных:&#039;&#039;&#039; &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;n^2 +n + 1 &amp;lt;/math&amp;gt;. Если учесть, что матрица симметричная и достаточно для её однозначного определения задать элементы на главной диагонали и элементы над или под ней, то можно сократить объём входных данных с целью экономии памяти до: &amp;lt;math&amp;gt;\ \frac{n^2-n}{2}+n+n+1 =\frac{n^2+3n}{2} + 1&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные алгоритма:&#039;&#039;&#039; вектор собственных значений &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;\Theta^k&amp;lt;/math&amp;gt; длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;/math&amp;gt;, матрица &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;S^k&amp;lt;/math&amp;gt; из соответствующих собственных векторов размера &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n\times k&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём выходных данных:&#039;&#039;&#039; &amp;lt;math&amp;gt;k\;(n + 1)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
В данном разделе перечислены без какой-либо хронологии или связи друг с другом наиболее важные и разнообразные свойства алгоритма, на которые стоит и полезно обратить внимание, а также которые выгодно отличают его от схожих алгоритмов, решающих ту же задачу.&amp;lt;br&amp;gt;&lt;br /&gt;
1) Отношение последовательной сложности алгоритма к параллельной,с учётом &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;/math&amp;gt; итераций, равно &amp;lt;math&amp;gt;\;\;\frac{kn^2}{k \log_2{n}}=\frac{n^2}{\log_2{n}}&amp;lt;/math&amp;gt;;&amp;lt;br&amp;gt;&lt;br /&gt;
2) Вычислительная мощность алгоритма, как отношение числа операций к суммарному объему входных и выходных данных, равна &amp;lt;math style=&amp;quot;vertical-align:-70%&amp;gt;\;\;\frac{k\,n^2}{0.5\,n^2+1.5\,n+k\,n+k+1}&amp;lt;/math&amp;gt; и &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;\approx 2\,k&amp;lt;/math&amp;gt;, так как на практике верно отношение &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;&amp;lt;n&amp;lt;/math&amp;gt; ;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
3) Для собственных значений формируемых матриц &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_j&amp;lt;/math&amp;gt; верно отношение (следствие теоремы Коши о перемежаемости): &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;\lambda_i(T_{k+1})\geq \lambda_i(T_{k})\geq \lambda_{i+1}(T_{k+1})\geq \lambda_{i+1}(T_{k})&amp;lt;/math&amp;gt; ;&amp;lt;ref&amp;gt;James W. Demmel - Вычислительная линейная алгебра. Теория и приложения //Мир. - 2001 (c. 383)&amp;lt;/ref&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
4) Крайние (наибольшие и наименьшие) собственные значения матриц &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_j&amp;lt;/math&amp;gt; сходятся к крайним собственным значениям матрицы &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;A&amp;lt;/math&amp;gt; первыми (это часто происходит уже на ранних шагах при &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j\approx 2\,\sqrt{n}&amp;lt;/math&amp;gt;&amp;lt;ref&amp;gt;http://num-anal.srcc.msu.ru/lib_na/int_ae/int_ae6.htm (пункт 6.5)&amp;lt;/ref&amp;gt;), а собственные значения в середине спектра - последними;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
5) Из-за ограниченной точности постепенно теряется ортогональность вектора Ланцоша &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;q_j&amp;lt;/math&amp;gt; к предыдущим векторам Ланцоша, поэтому необходимо примерно каждые 10-15 итераций проводить дорогостоящую операцию реортогонализации, но это уже будет иной алгоритм с очень малым различием в одной операции и в программном коде, реализующем его, соответственно; &amp;lt;ref&amp;gt;Sam Handler - The Lanczos Algorithm For Large-Scale Eigenvalue Problems (08.01.07), slide №8&amp;lt;/ref&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
6) Эффективность и быстрота выполнения алгоритма очень сильно зависит от скорости памяти (диска). Согласно тесту только &#039;&#039;6%&#039;&#039; времени работы программы приходится на вычисления, остальное время затрачивается на ожидание отклика диска;&amp;lt;ref&amp;gt;Sam Handler - The Lanczos Algorithm For Large-Scale Eigenvalue Problems (08.01.07), slide №10&amp;lt;/ref&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
7) Метод Ланцоша удобен тем, что не требует хранения исходной матрицы полным массивом: метод использует исходную матрицу только в операциях умножения матрицы на вектор, что позволяет эффективно использовать разреженность матрицы или регулярность структуры матрицы. Поэтому метод Ланцоша может быть использован для матриц таких больших порядков, когда методы вращений и отражений не могут быть применены.&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;
Для исследования масштабируемости рассматриваемого алгоритма Ланцоша без переортогонализации автором была реализована программа на языке С++ с использованием технологии MPI &amp;lt;ref&amp;gt;http://chopapp.com/#rvsztfxc или вторая ссылка с прикреплённым кодом: http://pasted.co/13b3244c , по просьбе на почту готов предоставить доступ к проекту на Bitbucket&amp;lt;/ref&amp;gt;. Дальнейшее исследование выполнялось на суперкомпьютере &amp;quot;Ломоносов&amp;quot; Суперкомпьютерного комплекса МГУ. &amp;lt;br&amp;gt; Важно отметить, что реализованная программа выполняет только первую часть алгоритма - формирование матрицы &amp;lt;math &amp;gt;T_j&amp;lt;/math&amp;gt;. Вторая часть алгоритма (задача поиска собственных значений матрицы &amp;lt;math &amp;gt;T_j&amp;lt;/math&amp;gt;) может быть решена несколькими методами, каждый из которых обладает своей эффективностью распараллеливании и характерными свойствами. Подробно этот вопрос уже обсуждался в статье раннее, поэтому не будем ещё раз заострять на этом внимание и останавливаться.&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Сборка осуществлялась со следующими параметрами:&lt;br /&gt;
* Компилятор intel/15.0.090 &lt;br /&gt;
* Openmpi/1.8.4-icc&lt;br /&gt;
В серии проведённых расчётов рассматривались следующие числовые значения параметров:&lt;br /&gt;
* Размер &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;n&amp;lt;/math&amp;gt; задачи и, соответственно, матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt;, задействованной в операции умножения на вектор: [2000 : 30000] с шагом 1000&lt;br /&gt;
* Число процессоров: 1, 2, 4, 16, 32, 48, 64, 96, 128&lt;br /&gt;
* Число итераций в алгоритме: &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k=350&amp;lt;/math&amp;gt;&lt;br /&gt;
Число &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; взято таким вопреки информации в начале статьи, где говорится, что значение &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; редко превышает &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;10^2&amp;lt;/math&amp;gt; (хоть мы и имеем право брать его любым по нашему усмотрению). Это сделано исключительно для лучшей визуализации пиков на графиках в данном разделе и наглядности получаемых результатов, так как при меньших на порядок значениях &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; времена выполнения программ были слишком малы даже при минимальных числах процессоров и максимальных размерах исходной задачи.&lt;br /&gt;
&lt;br /&gt;
== Динамические характеристики и эффективность реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Выводы для классов архитектур ==&lt;br /&gt;
По заданию, во второй части требовалось описать только разделы 2.4 и 2.7, прошу не спрашивать с меня все разделы 2.1-2.6. Надеюсь на понимание, мне физически не хватает времени на это задание + 2 других в течение семестра, делаю всё, что в моих силах :)&lt;br /&gt;
&lt;br /&gt;
== Существующие реализации алгоритма ==&lt;br /&gt;
Несмотря на то, что алгоритм является далеко не самым популярным, алгоритмом, про который нельзя сказать, что он всегда «на слуху», на сегодняшний день существует множество реализаций на различных популярных языках.&amp;lt;br&amp;gt;&lt;br /&gt;
Перечислим далее некоторые из них, указывая язык программирования, лежащий в их основе, и некоторые важные характеристики, которые обсуждались в статье ранее:&lt;br /&gt;
*&#039;&#039;Code on netlib.org by Jane Cullum and Ralph Willoughby&#039;&#039; (&#039;&#039;&#039;Fortran 77&#039;&#039;&#039;; без реортогонализации векторов; без реализации распараллеливания)&amp;lt;ref&amp;gt;http://www.netlib.org/lanczos/leval&amp;lt;/ref&amp;gt;&lt;br /&gt;
*&#039;&#039;Lanczos algorithm on freesourcecode.net&#039;&#039; (&#039;&#039;&#039;Matlab&#039;&#039;&#039;; присутствует реортогонализация векторов; без реализации распараллеливания)&amp;lt;ref&amp;gt;http://freesourcecode.net/matlabprojects/61741/lanczos-algorithm--in-matlab&amp;lt;/ref&amp;gt;&lt;br /&gt;
*&#039;&#039;Lanczos for eigenvalues in Numerical Linear Algebra, Spring 2007&#039;&#039; (&#039;&#039;&#039;Matlab&#039;&#039;&#039;; частичная или полная реортогонализация - доступны оба варианта; без реализации распараллеливания)&amp;lt;ref&amp;gt;Ссылки на файлы lanso.m и lanfu.m можно найти на https://www.nada.kth.se/~ruhe/2D5219/labs2007.html&amp;lt;/ref&amp;gt;&lt;br /&gt;
*&#039;&#039;Planso&#039;&#039; (название происходит от parallel Lanso.f) &#039;&#039;code by Kesheng Wu and Horst D. Simon&#039;&#039; (&#039;&#039;&#039;Fortran 77&#039;&#039;&#039;; частичная реортогонализация векторов; использование MPI для коммуникаций)&amp;lt;ref&amp;gt;https://github.com/jiahao/planso.jl/tree/master/external/PLAN/plan К сожалению, ссылка в описании пакета на github, ведущая на сайт National Energy Research Scientific Computing Center (NERSC), с более подробной информацией о данной программе больше не активна и выдаёт результат &#039;&#039;Page not found&#039;&#039;&amp;lt;/ref&amp;gt; &lt;br /&gt;
* &#039;&#039;Lanczos.cpp in the Vienna Computing Library&#039;&#039;  (&#039;&#039;&#039;C++&#039;&#039;&#039;, частичная реортогонализация, без реализации распараллеливания) &amp;lt;ref&amp;gt;http://viennacl.sourceforge.net/doc/lanczos_8cpp_source.html&amp;lt;/ref&amp;gt;&lt;br /&gt;
* &#039;&#039;Parallel Eigen Values code using C++ AMP on microsoft msdn blog&#039;&#039; (&#039;&#039;&#039;C++&#039;&#039;&#039;; ? ; распараллеливание есть и реализовано через C++ AMP) &amp;lt;ref&amp;gt;https://blogs.msdn.microsoft.com/nativeconcurrency/2013/12/20/eigen-values/ Подробнее о C++ Accelerated Massive Parallelism можно почитать здесь: https://msdn.microsoft.com/ru-ru/library/hh265137(v=vs.140).aspx или здесь: http://professorweb.ru/my/csharp/optimization/level4/4_6.php &amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;br /&gt;
[[en:Description of algorithm properties and structure]]&lt;/div&gt;</summary>
		<author><name>AleksLevin</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:AleksLevin/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%9B%D0%B0%D0%BD%D1%86%D0%BE%D1%88%D0%B0_%D0%B2%D1%8B%D1%87%D0%B8%D1%81%D0%BB%D0%B5%D0%BD%D0%B8%D1%8F_%D1%81%D0%BE%D0%B1%D1%81%D1%82%D0%B2%D0%B5%D0%BD%D0%BD%D1%8B%D1%85_%D0%B7%D0%BD%D0%B0%D1%87%D0%B5%D0%BD%D0%B8%D0%B9_%D1%81%D0%B8%D0%BC%D0%BC%D0%B5%D1%82%D1%80%D0%B8%D1%87%D0%BD%D0%BE%D0%B9_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86%D1%8B_%D0%B4%D0%BB%D1%8F_%D1%82%D0%BE%D1%87%D0%BD%D0%BE%D0%B9_%D0%B0%D1%80%D0%B8%D1%84%D0%BC%D0%B5%D1%82%D0%B8%D0%BA%D0%B8_(%D0%B1%D0%B5%D0%B7_%D0%BF%D0%B5%D1%80%D0%B5%D0%BE%D1%80%D1%82%D0%BE%D0%B3%D0%BE%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D0%B8)&amp;diff=20215</id>
		<title>Участник:AleksLevin/Алгоритм Ланцоша вычисления собственных значений симметричной матрицы для точной арифметики (без переортогонализации)</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:AleksLevin/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%9B%D0%B0%D0%BD%D1%86%D0%BE%D1%88%D0%B0_%D0%B2%D1%8B%D1%87%D0%B8%D1%81%D0%BB%D0%B5%D0%BD%D0%B8%D1%8F_%D1%81%D0%BE%D0%B1%D1%81%D1%82%D0%B2%D0%B5%D0%BD%D0%BD%D1%8B%D1%85_%D0%B7%D0%BD%D0%B0%D1%87%D0%B5%D0%BD%D0%B8%D0%B9_%D1%81%D0%B8%D0%BC%D0%BC%D0%B5%D1%82%D1%80%D0%B8%D1%87%D0%BD%D0%BE%D0%B9_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86%D1%8B_%D0%B4%D0%BB%D1%8F_%D1%82%D0%BE%D1%87%D0%BD%D0%BE%D0%B9_%D0%B0%D1%80%D0%B8%D1%84%D0%BC%D0%B5%D1%82%D0%B8%D0%BA%D0%B8_(%D0%B1%D0%B5%D0%B7_%D0%BF%D0%B5%D1%80%D0%B5%D0%BE%D1%80%D1%82%D0%BE%D0%B3%D0%BE%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D0%B8)&amp;diff=20215"/>
		<updated>2016-12-06T23:47:04Z</updated>

		<summary type="html">&lt;p&gt;AleksLevin: /* Информационный граф */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Основные авторы описания: Левин А.Д.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{algorithm&lt;br /&gt;
| name              = Алгоритм Ланцоша для точной арифметики (без переортогонализации)&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(k\,n^2)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(k\log_2 n)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;\frac{n^2+3n}{2} + 1&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;k\;(n + 1)&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритмов =&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Данный алгоритм появился в 1950 г. и носит имя венгерского физика и математика Корнелия Ланцоша (венг. Lánczos Kornél). Алгоритм Ланцоша относится к итерационным методам вычисления собственных значений для матриц столь больших порядков &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt; n&amp;lt;/math&amp;gt;, что к ним нельзя применить прямые методы из-за ограничений по времени и памяти.&lt;br /&gt;
&lt;br /&gt;
Сам Ланцош указывал, что его метод предназначен для отыскания нескольких собственных векторов симметричных матриц, хотя к методу сразу было обращено внимание, как к способу приведения всей матрицы к трёхдиагональному виду. Двадцатью годами позже канадский математик Крис Пэж показал, что, несмотря на чувствительность к округлениям, алгоритм Ланцоша - эффективное средство вычисления некоторых &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; собственных чисел и соответствующих им собственных векторов. &amp;lt;ref&amp;gt;Парлетт Б. - Симметричная проблема собственных значений. Численные методы //М.: Мир. - 1983. (c. 276)&amp;lt;/ref&amp;gt;&lt;br /&gt;
Обычно число &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; берут в два раза больше, чем количество собственных значений матрицы, которые поставлена цель найти, и оно имеет порядок не более &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;10^2&amp;lt;/math&amp;gt;.&amp;lt;ref&amp;gt;Susan W. Bostic - Lanczos Eigensolution Method for High-Perfomance Computers, page 7&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Алгоритм Ланцоша для вычисления собственных значений симметричной матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; соединяет в себе метод Ланцоша для построения последовательности подпространств Крылова и ортонормированных векторов Ланцоша и процедуру Рэлея-Ритца получения оптимальных приближений собственных значений и соответствующих собственных векторов исходной матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt;.&amp;lt;ref&amp;gt;James W. Demmel - Вычислительная линейная алгебра. Теория и приложения //Мир. - 2001 (c. 381)&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
В данной статье рассматривается вариант алгоритма Ланцоша, в котором опущено влияние ошибок округления на вычислительный процесс, хотя на практике этому посвящается отдельное внимание и существуют различные методы решения данной проблемы, такие как частичная или полная переортогонализация. Этим модифицированным методам посвящены отдельные статьи на данном ресурсе.&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
Обозначения и формулы, используемые в данном разделе, взяты из литературы, указанной по ссылке.&amp;lt;ref&amp;gt;James W. Demmel - Вычислительная линейная алгебра. Теория и приложения //Мир. - 2001 (c. 313, &#039;&#039;&amp;lt;math&amp;gt; \S &amp;lt;/math&amp;gt; 6.6 Методы Крыловского подпространства&#039;&#039;)&amp;lt;/ref&amp;gt; &lt;br /&gt;
&lt;br /&gt;
Алгоритм Ланцоша для вычисления &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; собственных значений и собственных векторов вещественной симметричной матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A=A^T&amp;lt;/math&amp;gt; в точной арифметике: &amp;lt;ref&amp;gt;James W. Demmel - Вычислительная линейная алгебра. Теория и приложения //Мир. - 2001 (c. 381)&amp;lt;/ref&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{align}&lt;br /&gt;
q_1 = &amp;amp; \,\frac{b}{\|b\|_2},\; \beta_0 = 0,\; q_0 = 0\\&lt;br /&gt;
\mathbf{for} \; &amp;amp; j = 1 \; to \; k \,\; \mathbf{do} \\&lt;br /&gt;
&amp;amp; z = A\,q_j\\&lt;br /&gt;
&amp;amp; \alpha_j = q^T_j z\\&lt;br /&gt;
&amp;amp; z = z - \alpha_j q_j - \beta_{j-1}q_{j-1}\\&lt;br /&gt;
&amp;amp; \beta_j = \|z\|_2\\&lt;br /&gt;
&amp;amp; \mathbf{If} \; (\beta_j == 0) \; \mathbf{then}\; stop\; the\; algorithm \\ &lt;br /&gt;
&amp;amp; \;  q_{j+1} = \frac{z}{\beta_j} \\&lt;br /&gt;
&amp;amp; compute\; eigenvalues\; and \;eigenvectors\;of \;matrix \;\;T_j= Q^T_j A Q\;\;and\;estimate \;the\; errors\\&lt;br /&gt;
\mathbf{end} \; &amp;amp; \mathbf{for}&lt;br /&gt;
\end{align}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
В продемонстрированном выше алгоритме &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;b&amp;lt;/math&amp;gt; - заданный вещественный вектор. Также полагается известным алгоритм вычисления произведения матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; на вектор &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;x&amp;lt;/math&amp;gt;. &lt;br /&gt;
Введём матрицу Крылова, определяемую следующим соотношением: &amp;lt;math&amp;gt;K_j = [b,Ab,A^2b,...,A^{j-1}b]&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Далее, на практике, матрица &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;K&amp;lt;/math&amp;gt; заменяется матрицей &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;Q&amp;lt;/math&amp;gt;, такой, что при любом числе &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; линейные оболочки первых &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; столбцов в &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;K&amp;lt;/math&amp;gt; и &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;Q&amp;lt;/math&amp;gt; являются одним и тем же подпространством.&amp;lt;ref&amp;gt;James W. Demmel - Вычислительная линейная алгебра. Теория и приложения //Мир. - 2001 (c. 315)&amp;lt;/ref&amp;gt; &lt;br /&gt;
Тогда матрица &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;Q&amp;lt;/math&amp;gt;, в отличие от матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;K&amp;lt;/math&amp;gt;, хорошо обусловлена и легко обратима. В результате получаем матрицу &amp;lt;math&amp;gt;Q_j = [q_1, q_2, \dots, q_j]&amp;lt;/math&amp;gt; размерности &amp;lt;math&amp;gt;n\times j&amp;lt;/math&amp;gt;, столбцы которой ортогональны, являются базисом подпространства Крылова и называются векторами Ланцоша.&lt;br /&gt;
&lt;br /&gt;
В алгоритме Ланцоша вычислению подлежит столько первых столбцов в матрице &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;Q_j&amp;lt;/math&amp;gt;, сколько необходимо для получения требуемого приближения к решению &amp;lt;math&amp;gt;A\,x\,=b\,\,(A\,x=\lambda \, x)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Получение нулевого &amp;lt;math&amp;gt;\beta_j&amp;lt;/math&amp;gt; в итерационном процессе - событие, желательное в том смысле, что оно свидетельствует о том, что найдено некоторое подпространство, являющееся в точности инвариантным, а все собственные значения матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;T_j&amp;lt;/math&amp;gt; являются собственными значениями матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt;. На практике же нулевое и близкие к нулю значения получаются редко.&amp;lt;ref&amp;gt;Голуб Дж., Ван Лоун Ч. - Матричные вычисления//М.: Мир. - 1999 (c. 429)&amp;lt;/ref&amp;gt; &lt;br /&gt;
&lt;br /&gt;
Затем на каждом шаге цикла формируется симметричная трёхдиагональная матрица &amp;lt;math&amp;gt;T_j = Q^T_j A Q&amp;lt;/math&amp;gt;, к которой применяется процесс Рэлея-Ритца для поиска её собственных значений (на практике для поиска этих собственных значений можно использовать любой из специальных методов в параграфе книги по ссылке).&amp;lt;ref&amp;gt;Голуб Дж., Ван Лоун Ч. - Матричные вычисления//М.: Мир. - 1999 (&amp;lt;math&amp;gt;\S&amp;lt;/math&amp;gt; 8.4)&amp;lt;/ref&amp;gt;  &lt;br /&gt;
Эти собственные значения, они же числа Ритца, и полагаются приближёнными собственными значениями исходной матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt;.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Существует множество методов для отыскания собственных значений вещественной симметричной трехдиагональной матрицы. Большинство из них требует &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt; операций &amp;lt;ref&amp;gt;Парлетт Б. Симметричная проблема собственных значений. Численные методы.,: Мир, 1983. с. 179-182&amp;lt;/ref&amp;gt;, но существуют и быстрые алгоритмы, требующие лишь &amp;lt;math&amp;gt;O(n\ln n)&amp;lt;/math&amp;gt; операций.&amp;lt;ref&amp;gt;https://en.wikipedia.org/wiki/Tridiagonal_matrix#Eigenvalues  Раздел eigenvalues&amp;lt;/ref&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Одним из возможных способов отыскать собственные значения симметричной трехдиагональной матрицы - прямое вычисление корней характеристического полинома &amp;lt;math&amp;gt;p_n(\lambda)&amp;lt;/math&amp;gt; через метод деления пополам, где формируется последовательность Штурма и локализуются собственные числа, являющиеся корнями характеристического полинома. Нахождение всех &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; собственных значений матрицы этим способом требует &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;2n^2t&amp;lt;/math&amp;gt; умножений и вычитаний, где &amp;lt;math&amp;gt;t&amp;lt;/math&amp;gt; - число сделанных шагов с применением метода деления пополам.&amp;lt;ref&amp;gt;Уилкинсон Дж. X. Алгебраическая проблема собственныx значений. Изд-во &amp;quot;Наука&amp;quot;, 1970. - глава 5, с. 272-278&amp;lt;/ref&amp;gt; Соответствующие собственные вектора могут быть найдены посредством обратных итераций за &amp;lt;math&amp;gt; O(n) &amp;lt;/math&amp;gt; флопов. &amp;lt;ref&amp;gt;Голуб Дж., Ван Лоун Ч. - Матричные вычисления//М.: Мир. - 1999 (c. 394-395)&amp;lt;/ref&amp;gt; &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;На практике, если требуется только небольшая часть от всей совокупности собственных векторов и значений, и матрица имеет Хессенбергову или трёхдиагональную форму, очень эффективными будут методы факторизации, как, например, QR-алгоритм или QL-алгоритм со сдвигами (c целью ускорить алгоритм и сделать порядок сходимости квадратичным) или же без них.&amp;lt;ref&amp;gt;http://algorithm.narod.ru/ln/eigen/ETridiag.html&amp;lt;/ref&amp;gt; &amp;lt;br&amp;gt;&lt;br /&gt;
Весьма молодые и не менее актуальные конкуренты QR и QL алгоритмов, применяющиеся для поиска собственных значений:&lt;br /&gt;
*Методы divide-and-conquer (разделяй и властвуй), появившиеся в 1980-ых годах &amp;lt;ref&amp;gt;https://goo.gl/dapvbn ссылку пришлось сократить с помощью Google url shortener, так как символы подчеркивания портили её и не давали перейти по 1 клику&amp;lt;/ref&amp;gt;&lt;br /&gt;
*Relatively robust representation методы, появившиеся в 1990-ых и позволяющие найти собственные числа симметричной матрицы порядка &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;n&amp;lt;/math&amp;gt; за &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt; операций&lt;br /&gt;
&lt;br /&gt;
Если требуется вычислить собственные векторы, то необходимо хранить вычисляемые векторы Ланцоша. Если работа при этом производится только с оперативной памятью, то при большом порядке исходной матрицы (а именно для таких матриц и предназначен метод Ланцоша) число шагов  &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;j&amp;lt;/math&amp;gt;, которые могут быть выполнены до того момента, как оперативная память будет исчерпана, будет очень незначительно, а следовательно, искомые собственные пары могут не успеть сойтись с требуемой точностью. В этом случае метод Ланцоша можно использовать итерационным образом: после выполнения заданного числа шагов процесс прерывается и, если еще не все требуемые пары Ритца сошлись с требуемой точностью, то формируется новый начальный вектор &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;q_1&amp;lt;/math&amp;gt;, являющийся линейной комбинацией векторов Ритца, еще не сошедшихся с заданной точностью, и процесс начинается заново.&amp;lt;ref&amp;gt;http://num-anal.srcc.msu.ru/lib_na/int_ae/int_ae6.htm (пункт 6.5)&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
Вычислительное ядро рассматриваемого алгоритма (наиболее ресурсно-затратная часть алгоритма) -  формирование на каждом шаге цикла промежуточного вектора &amp;lt;math&amp;gt;z&amp;lt;/math&amp;gt;, вычисляемого по формуле: &amp;lt;math&amp;gt;z = A\,q_j&amp;lt;/math&amp;gt;. Данная операция, по сравнению с другими операциями алгоритма, затратна и требовательна, как с точки зрения количества производимых операций, так и с точки зрения объема оперируемых данных. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Например, умножение матрицы размера &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;n\times n&amp;lt;/math&amp;gt; на вектор длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; требует: &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;n^2+(n-1)n = 2n^2-n&amp;lt;/math&amp;gt; операций умножения и сложения. В свою очередь аналогичная операция умножения матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;(n+1)\times (n+1)&amp;lt;/math&amp;gt; на вектор длины &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;(n+1)&amp;lt;/math&amp;gt; требует: &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;2n^2+3n+1&amp;lt;/math&amp;gt;  операций умножения и сложения. То есть повышение размерности задачи всего на 1 увеличивает число необходимых действий в этом шаге алгоритма на: &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;4n+1&amp;lt;/math&amp;gt;. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Так же, стоит помнить, что, согласно разделу 1.2, данную операцию умножения матрицы на вектор необходимо выполнить &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;k&amp;lt;/math&amp;gt; раз. Нетрудно понять, насколько возрастает и колоссален масштаб операций, если в задачах, где критична точность, размерности &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; могут иметь порядок &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;10^5&amp;lt;/math&amp;gt; или даже более.&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
Как уже было упомянуто в данной статье в описании алгоритма, рассматриваемый алгоритм состоит из двух последовательно выполненных алгоритмов: метод Ланцоша для построения последовательности подпространств Крылова и ортонормированных векторов Ланцоша и процедура Рэлея-Ритца получения оптимальных приближений собственных значений и соответствующих собственных векторов исходной матрицы.&lt;br /&gt;
&lt;br /&gt;
В первой части алгоритма, где итерационно строятся Крыловское подпространство и трёхдиагональная матрица &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&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 style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; разреженная. Именно она подлежит оптимизации с использованием техник распараллеливания, поскольку она является вычислительным ядром алгоритма, а весь упомянутый процесс построения матрицы &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&amp;lt;/math&amp;gt; выполняется последовательно.&lt;br /&gt;
&lt;br /&gt;
Рассмотрим вторую часть алгоритма - поиск собственных значений сформированной матрицы &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&amp;lt;/math&amp;gt;.&amp;lt;br&amp;gt;&lt;br /&gt;
Далее, наглядно, в виде псевдокода, представлен, упомянутый в разделе 1.2, QR-алгоритм (аналогично можно рассмотреть и QL-алгоритм) со сдвигами Релэя, который весьма популярен на практике.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{align}&lt;br /&gt;
\mathbf{Input}: \;&amp;amp;tridiagonal\;\;matrix \;T\;with\;\;n\times n\;\;size\\&lt;br /&gt;
T^{(0)}&amp;amp;:=T\\&lt;br /&gt;
\mathbf{for}&amp;amp; \;\;m=n,...,2 \;\; \mathbf{do}\\&lt;br /&gt;
&amp;amp;k=0\\&lt;br /&gt;
&amp;amp; \mathbf{repeat}\\&lt;br /&gt;
&amp;amp; \quad \;\; k=k+1\\&lt;br /&gt;
&amp;amp; \quad \;\; \mu^{(k)}=T_{m,m}^{(k-1)}\\&lt;br /&gt;
&amp;amp; \quad \;\; Q^{(k)}R^{(k)}=T^{(k-1)}-\mu^{(k)}I\;\;using\;\;QR\;decomposition\\&lt;br /&gt;
&amp;amp; \quad \;\; T^{(k)}=R^{(k)}Q^{(k)}+\mu^{(k)}I\\&lt;br /&gt;
&amp;amp; \mathbf{until} \;\;\; |T_{m,m-1}^{(k)}| \;is\;\;small\;\;enough\\&lt;br /&gt;
&amp;amp; Save  \;\;T_{m,m}^{(k)} \;\;as\;\; converged\;\;eigenvalue\;of\;T\\ &lt;br /&gt;
&amp;amp; Remove \;\boldsymbol{n}\,th\;row\;and\;\boldsymbol{n}\,th\;column\;\;from \;T \\&lt;br /&gt;
&amp;amp; and\;take\;this\;new\;cropped\;matrix\;as\;new\;T^{(0)}\;with\;\;(n-1)\times (n-1)\;\;size\\&lt;br /&gt;
 \mathbf{end}&amp;amp;\; \mathbf{for}&lt;br /&gt;
\end{align}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Малость наддиагональных и поддиагональных элементов матрицы (фраза &#039;&#039;&amp;quot;small enough&amp;quot;&#039;&#039; в псевдокоде) подразумевает:&lt;br /&gt;
&amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt; |T_{m,m-1}^{(k)}| \leq \varepsilon\,|T_{m,m}^{(k)}| \quad\quad &amp;lt;/math&amp;gt; , где &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt; \varepsilon &amp;lt;/math&amp;gt; - заданная точность&amp;lt;br&amp;gt;&lt;br /&gt;
Также вместо сдвига Релэя, обозначенного в алгоритме через &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;\mu^{(k)}&amp;lt;/math&amp;gt;, часто на практике используется сдвиг по Уилкинсону, который даёт гарантированную сходимость внедиагональных элементов матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt; T^{(k)} &amp;lt;/math&amp;gt;, формируемой на каждом шаге, к нулю, при этом жертвуя монотонностью их убывания.&amp;lt;ref&amp;gt;Голуб Дж., Ван Лоун Ч. - Матричные вычисления//М.: Мир. - 1999 (c. 378, вторая половина страницы)&amp;lt;/ref&amp;gt;&amp;lt;ref&amp;gt;Парлетт Б. Симметричная проблема собственных значений. Численные методы.,: Мир, 1983. с. 169&amp;lt;/ref&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Подробнее с различными сдвигами и соответствующими оценками скоростей и количествами операций можно ознакомиться по указанной ссылке:&amp;lt;ref&amp;gt;Парлетт Б. Симметричная проблема собственных значений. Численные методы.,: Мир, 1983. с. 179-182&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;Для совершения QR-декомпозиции на каждом шаге может использоваться любой из алгоритмов по ссылке.&amp;lt;ref&amp;gt;https://en.wikipedia.org/wiki/QR_decomposition&amp;lt;/ref&amp;gt; Подробные описания этих алгоритмов также доступны на данном ресурсе algowiki-project.&amp;lt;br&amp;gt;&lt;br /&gt;
Так как мы оперируем не обычной матрицей и даже не Хессенберговой, а симметричной и трёхдиагональной, то скорость таких алгоритмов значительно возрастёт. Например, согласно данному ресурсу &amp;lt;ref&amp;gt;http://algorithm.narod.ru/ln/eigen/ETridiag.html&amp;lt;/ref&amp;gt;, для QL-алгоритма с неявными сдвигами:&amp;lt;br&amp;gt;&lt;br /&gt;
Для трёхдиагональной матрицы объем арифметических действий составляет &amp;lt;math&amp;gt; O(n)&amp;lt;/math&amp;gt; на одну итерацию вместо &amp;lt;math&amp;gt; O(n^3)&amp;lt;/math&amp;gt; для матрицы общего вида, а число итераций для нахождения первых собственных значений примерно равно 4 - 5. Но на этих итерациях также уменьшаются внедиагональные элементы правого нижнего угла. И, таким образом, дальнейшие собственные значения ищутся значительно быстрее. Среднее число итераций на каждое собственное значение обычно составляет 1.3 - 1.6.&amp;lt;br&amp;gt; &lt;br /&gt;
Аналогично QL, QR-разложение трёхдиагольной матрицы также требует &amp;lt;math&amp;gt; O(n)&amp;lt;/math&amp;gt; флопов&amp;lt;ref&amp;gt;Голуб Дж., Ван Лоун Ч. - Матричные вычисления//М.: Мир. - 1999 (c. 378, начало раздела 8.2.2)&amp;lt;/ref&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Подводя итог, во второй части алгоритма Ланцоша можно выделить следующие макрооперации:&lt;br /&gt;
* умножение матрицы на вещественное число;&lt;br /&gt;
* перемножение матриц;&lt;br /&gt;
* умножение и сравнение вещественных чисел;&lt;br /&gt;
* + набор других макроопераций в зависимости от выбора метода, с помощью которого будет совершаться сама QR или QL-декомпозиция (выше продемонстрированы, уже, как минимум, 3 разных способа).&lt;br /&gt;
Так же, важно заметить, что набор макропераций может быть несколько другим, если выбрать какой-либо иной современный метод поиска собственных чисел трёхдиагональной матрицы, не использующий QR и QL разложения(факторизацию). Два таких метода были упомянуты в пункте 1.2.&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
С целью полностью не дублировать раздел 1.2 данной статьи, где представлен наглядный и доступный для понимания псевдокод алгоритма, постараемся лишь коротко просуммировать и обобщить весь перечень последовательных действий в рассматриваемом алгоритме.&lt;br /&gt;
&lt;br /&gt;
В качестве входных данных имеем: вещественная симметричная матрица &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; размера &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;n\times n&amp;lt;/math&amp;gt;, известный вещественный вектор &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;b&amp;lt;/math&amp;gt; длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; и число &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;n&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Далее:&lt;br /&gt;
* Инициализируем вещественную константу &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;\beta_0&amp;lt;/math&amp;gt; и векторы &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;q_0&amp;lt;/math&amp;gt; и &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;q_1&amp;lt;/math&amp;gt;&lt;br /&gt;
* Итерационно для всех &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j=1,...,k&amp;lt;/math&amp;gt;:&lt;br /&gt;
** Вычисляем вспомогательный вектор &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt;, используя умножение матрицы на вектор&lt;br /&gt;
** Вычисляем, используя скалярное произведение векторов, значение &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;\alpha_j&amp;lt;/math&amp;gt; - элемент на главной диагонали трёхдиагональной матрицы &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&amp;lt;/math&amp;gt;&lt;br /&gt;
** Вычисляем по формуле новое значение и перезаписываем вектор &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt;&lt;br /&gt;
** Вычисляем значение &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;\beta_j&amp;lt;/math&amp;gt; - элементы непосредственно над и под главной диагональю той же матрицы &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&amp;lt;/math&amp;gt;&lt;br /&gt;
** Вычисляем, зная вектор &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt;,  очередной столбец матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;Q&amp;lt;/math&amp;gt;, он же вектор Ланцоша : &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;\,\,q_{j+1}&amp;lt;/math&amp;gt;&lt;br /&gt;
** Теперь, когда матрица &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&amp;lt;/math&amp;gt; сформирована на очередном шаге, находим её собственные значения и вектора любым доступным способом, о чём было подробно сказано в пункте 1.2&lt;br /&gt;
** Переходим на следующую итерацию: &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j&amp;lt;/math&amp;gt;++&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
Оценим количество операций и сложность последовательного алгоритма, изложенного в предыдущем разделе.&lt;br /&gt;
*Для вычисления вектора &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt; умножается матрица размера &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;n\times n&amp;lt;/math&amp;gt; на вектор длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt;, и потребуется &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n^2&amp;lt;/math&amp;gt; операций умножения и &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n^2&amp;lt;/math&amp;gt; операций сложения.&lt;br /&gt;
*Умножение векторов &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;q^T_j&amp;lt;/math&amp;gt; и &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt; длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; потребует &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; операций умножения и &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; операций сложения.&lt;br /&gt;
*При вычислении нового значения вектора &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt; поэлементное сложение двух векторов длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; требует &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; операций сложения.&lt;br /&gt;
*Умножение вектора длины &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; на вещественное число требует &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; операций умножения.&lt;br /&gt;
*Нахождение квадратичной нормы вектора &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt;  длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; требует &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; умножений и &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; сложений и ещё 1 операцию извлечения квадратного корня.&lt;br /&gt;
*Заключительное нахождение собственных значений и собственных векторов трёхдиагональной матрицы &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;T_j&amp;lt;/math&amp;gt; размера &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j\times j&amp;lt;/math&amp;gt; с помощью QR-алгоритма потребует в худшем случае &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(j^3)&amp;lt;/math&amp;gt; операций.&amp;lt;ref&amp;gt;http://num-anal.srcc.msu.ru/lib_na/int_ae/int_ae6.htm (пункт 6.2, &amp;quot;Скорость сходимости при этом всегда не хуже квадратичной и почти всегда лучше кубической.&amp;quot;)&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Посчитаем теперь суммарное количество простейших операций на одной итерации алгоритма (без учёта записей в память):&lt;br /&gt;
*&amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n^2+5\,n&amp;lt;/math&amp;gt; операций умножения/деления&lt;br /&gt;
*&amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n^2+4\,n&amp;lt;/math&amp;gt; операций сложения/вычитания&lt;br /&gt;
*1 операция извлечения квадратного корня&amp;lt;br&amp;gt;&lt;br /&gt;
Отдельно после всех итераций при &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j=k&amp;lt;/math&amp;gt; :&lt;br /&gt;
*&amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(k^3)&amp;lt;/math&amp;gt; операций для поиска собственных значений и собственных векторов трёхдиагональной матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_k&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Итого можно утверждать следующее:&lt;br /&gt;
&lt;br /&gt;
Последовательная сложность одной итерации рассматриваемого алгоритма:  &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(n ^ 2) &amp;lt;/math&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Суммарная сложность алгоритма (&amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;/math&amp;gt; итераций): &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(k\,n ^ 2) + O(k ^ 3)&amp;lt;/math&amp;gt; &amp;lt;ref&amp;gt;Здесь мы полагаем, что мы не вычисляем собственные значения и векторы матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_j&amp;lt;/math&amp;gt; на каждом промежуточном шаге, а лишь единожды затрачиваем &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;O(k ^ 3)&amp;lt;/math&amp;gt; действий в конце для нахождения &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;/math&amp;gt; собственных значений и векторов матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_k&amp;lt;/math&amp;gt;&amp;lt;/ref&amp;gt; &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
На практике же обычно рассматривается число &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;&amp;lt;n&amp;lt;/math&amp;gt;, поэтому второе слагаемое можно опустить.&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
На рис. 1 продемонстрирован граф одной итерации (при каком-либо произвольном значении итератора &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j&amp;lt;/math&amp;gt;) описанного алгоритма без отображения входных и выходных данных. Наглядно продемонстрированы связи между всеми действиями, и с помощью деления на &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; потоков показано, какие операции возможно выполнять параллельно на каждом шаге с целью оптимизации и экономии машинного времени. В результате, после параллельно выполненных операций &#039;&#039;&#039;Division&#039;&#039;&#039; на заключительном ярусе, на выходе имеем значение следующего вектора Ланцоша &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;q_{j+1}&amp;lt;/math&amp;gt;, после чего следует переход на следующую итерацию, и процесс повторяется.&lt;br /&gt;
&lt;br /&gt;
[[Файл:Levin_graph.png|600px|thumb|center|Рис. 1  Структура одной итерации алгоритма]] &amp;lt;br&amp;gt;&lt;br /&gt;
Обозначения на рисунке: &amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Simp&#039;&#039;&#039; (от англ. simple) - операции сложения и умножения вещественных чисел при вычислении произведения матрицы на вектор;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Vec mult&#039;&#039;&#039; (от англ. vectors multiplication) - операция скалярного умножения двух векторов;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Vec subtr&#039;&#039;&#039; (от англ. vectors subtraction, из-за использованных в операции вычитаний векторов) - операция умножения вектора на число (выполняется дважды) и формирование нового значения &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;z_{new}&amp;lt;/math&amp;gt; по формуле: &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;z_{new} = z - \alpha_j q_j - \beta_{j-1}q_{j-1} \;&amp;lt;/math&amp;gt;;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;||\cdot||&amp;lt;/math&amp;gt; - операция вычисления нормы вектора;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Division&#039;&#039;&#039; - операция деления вектора на вещественное число  &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;\beta_j&amp;lt;/math&amp;gt; &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Важно отметить, что упомянутые выше операции также легко поддаются оптимизации. Например, попарные умножения вещественных координат векторов при вычислении скалярного произведения также легко выполняются параллельно на &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; потоках, а затем можно применить суммирование методом сдваивания, о котором сказано в следующем разделе. Умножение или деление вектора на вещественное число являющееся, по определению, умножением или делением всех его координат на это число тоже может быть выполнено эффективнее, если мы используем &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; потоков, а не выполняем эти действия последовательно.&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
Параллельные операции возможны только внутри итераций, так как рассматриваемый алгоритм является итерационным, и сами итерации строго последовательны.&amp;lt;br&amp;gt;&lt;br /&gt;
Рассмотрим в этом разделе подробнее, какой выигрыш мы можем получить при распараллеливании операций внутри одной итерации согласно графу из предыдущего раздела.&lt;br /&gt;
&lt;br /&gt;
Умножение вещественной симметричной матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; размера &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;n\times n&amp;lt;/math&amp;gt; на вектор &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;b&amp;lt;/math&amp;gt; длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; требует последовательного выполнения &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; ярусов умножений и сложений. Сложение элементов вектора длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; на каждом шаге перемножения можно оптимизировать и выполнить за &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;\log_2 n&amp;lt;/math&amp;gt; действий, если применять метод сдваивания.&lt;br /&gt;
&lt;br /&gt;
Дальнейшие операции выполняются последовательно, а вычисление значений векторов происходит за один ярус операций сложения или умножения.&lt;br /&gt;
&lt;br /&gt;
Ресурс параллелизма алгоритма вычисления собственных значений построенной трёхдиагональной матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_k&amp;lt;/math&amp;gt; размера &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k\times k&amp;lt;/math&amp;gt; зависит от выбранного алгоритма (об этих алгоритмах подробнее было сказано в разделах 1.2 и 1.4). Будет очень затратно с точки зрения объёма материала пытаться рассмотреть пусть даже часть этих методов в этой статье, а так же тонкости их распараллеливания. Предлагаем читателям при желании самим ознакомиться с этими алгоритмами на данном ресурсе или прибегнув к иным источникам.&lt;br /&gt;
&lt;br /&gt;
При классификации по высоте ЯПФ, таким образом, алгоритм Ланцоша без переортогонализации относится к алгоритмам с &#039;&#039;логарифмической сложностью&#039;&#039;, и его сложность равна &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(\log_2 n)&amp;lt;/math&amp;gt; с важным замечанием, что это сложность только одной итерации, а максимум в алгоритме может быть выполнено последовательно &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;/math&amp;gt; таких однотипных итераций, если не будет осуществлён ранний выход из цикла. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Несмотря на то, что на графе в предыдущем разделе для лучшей визуализации и понимания было изображено &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; потоков (никаких допущений мы не делали и нарушений с точки зрения логики и математики нет, можно изобразить большее число потоков, просто часть времени некоторые из них могут бездействовать и не использоваться), на самом деле правильным и разумным будет реализовать начальное параллельное выполнение &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n^2&amp;lt;/math&amp;gt; операций умножения всех вещественных элементов матрицы &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;A&amp;lt;/math&amp;gt; на соответствующие элементы вектора &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;q_j&amp;lt;/math&amp;gt;, после чего применять тот же самый упомянутый метод сдваивания. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Поэтому при классификации по ширине ЯПФ его сложность будет &#039;&#039;квадратичной&#039;&#039; и равна &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(n^2)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
&#039;&#039;&#039;Входные данные алгоритма:&#039;&#039;&#039; вещественная симметричная &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; размера &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;n\times n&amp;lt;/math&amp;gt;, вещественный вектор &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;b&amp;lt;/math&amp;gt; длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt;, и одно целое число &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;k&amp;lt;/math&amp;gt;, означающее количество итераций.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём входных данных:&#039;&#039;&#039; &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;n^2 +n + 1 &amp;lt;/math&amp;gt;. Если учесть, что матрица симметричная и достаточно для её однозначного определения задать элементы на главной диагонали и элементы над или под ней, то можно сократить объём входных данных с целью экономии памяти до: &amp;lt;math&amp;gt;\ \frac{n^2-n}{2}+n+n+1 =\frac{n^2+3n}{2} + 1&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные алгоритма:&#039;&#039;&#039; вектор собственных значений &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;\Theta^k&amp;lt;/math&amp;gt; длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;/math&amp;gt;, матрица &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;S^k&amp;lt;/math&amp;gt; из соответствующих собственных векторов размера &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n\times k&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём выходных данных:&#039;&#039;&#039; &amp;lt;math&amp;gt;k\;(n + 1)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
В данном разделе перечислены без какой-либо хронологии или связи друг с другом наиболее важные и разнообразные свойства алгоритма, на которые стоит и полезно обратить внимание, а также которые выгодно отличают его от схожих алгоритмов, решающих ту же задачу.&amp;lt;br&amp;gt;&lt;br /&gt;
1) Отношение последовательной сложности алгоритма к параллельной,с учётом &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;/math&amp;gt; итераций, равно &amp;lt;math&amp;gt;\;\;\frac{kn^2}{k \log_2{n}}=\frac{n^2}{\log_2{n}}&amp;lt;/math&amp;gt;;&amp;lt;br&amp;gt;&lt;br /&gt;
2) Вычислительная мощность алгоритма, как отношение числа операций к суммарному объему входных и выходных данных, равна &amp;lt;math style=&amp;quot;vertical-align:-70%&amp;gt;\;\;\frac{k\,n^2}{0.5\,n^2+1.5\,n+k\,n+k+1}&amp;lt;/math&amp;gt; и &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;\approx 2\,k&amp;lt;/math&amp;gt;, так как на практике верно отношение &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;&amp;lt;n&amp;lt;/math&amp;gt; ;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
3) Для собственных значений формируемых матриц &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_j&amp;lt;/math&amp;gt; верно отношение (следствие теоремы Коши о перемежаемости): &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;\lambda_i(T_{k+1})\geq \lambda_i(T_{k})\geq \lambda_{i+1}(T_{k+1})\geq \lambda_{i+1}(T_{k})&amp;lt;/math&amp;gt; ;&amp;lt;ref&amp;gt;James W. Demmel - Вычислительная линейная алгебра. Теория и приложения //Мир. - 2001 (c. 383)&amp;lt;/ref&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
4) Крайние (наибольшие и наименьшие) собственные значения матриц &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_j&amp;lt;/math&amp;gt; сходятся к крайним собственным значениям матрицы &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;A&amp;lt;/math&amp;gt; первыми (это часто происходит уже на ранних шагах при &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j\approx 2\,\sqrt{n}&amp;lt;/math&amp;gt;&amp;lt;ref&amp;gt;http://num-anal.srcc.msu.ru/lib_na/int_ae/int_ae6.htm (пункт 6.5)&amp;lt;/ref&amp;gt;), а собственные значения в середине спектра - последними;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
5) Из-за ограниченной точности постепенно теряется ортогональность вектора Ланцоша &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;q_j&amp;lt;/math&amp;gt; к предыдущим векторам Ланцоша, поэтому необходимо примерно каждые 10-15 итераций проводить дорогостоящую операцию реортогонализации, но это уже будет иной алгоритм с очень малым различием в одной операции и в программном коде, реализующем его, соответственно; &amp;lt;ref&amp;gt;Sam Handler - The Lanczos Algorithm For Large-Scale Eigenvalue Problems (08.01.07), slide №8&amp;lt;/ref&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
6) Эффективность и быстрота выполнения алгоритма очень сильно зависит от скорости памяти (диска). Согласно тесту только &#039;&#039;6%&#039;&#039; времени работы программы приходится на вычисления, остальное время затрачивается на ожидание отклика диска;&amp;lt;ref&amp;gt;Sam Handler - The Lanczos Algorithm For Large-Scale Eigenvalue Problems (08.01.07), slide №10&amp;lt;/ref&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
7) Метод Ланцоша удобен тем, что не требует хранения исходной матрицы полным массивом: метод использует исходную матрицу только в операциях умножения матрицы на вектор, что позволяет эффективно использовать разреженность матрицы или регулярность структуры матрицы. Поэтому метод Ланцоша может быть использован для матриц таких больших порядков, когда методы вращений и отражений не могут быть применены.&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;
Для исследования масштабируемости рассматриваемого алгоритма Ланцоша без переортогонализации автором была реализована программа на языке С++ с использованием технологии MPI (&#039;&#039;&#039;не забыть вставить ссылку на код&#039;&#039;&#039;). Дальнейшее исследование выполнялось на суперкомпьютере &amp;quot;Ломоносов&amp;quot; Суперкомпьютерного комплекса МГУ. &amp;lt;br&amp;gt; Важно отметить, что реализованная программа выполняет только первую часть алгоритма - формирование матрицы &amp;lt;math &amp;gt;T_j&amp;lt;/math&amp;gt;. Вторая часть алгоритма (задача поиска собственных значений матрицы &amp;lt;math &amp;gt;T_j&amp;lt;/math&amp;gt;) может быть решена несколькими методами, каждый из которых обладает своей эффективностью распараллеливании и характерными свойствами. Подробно этот вопрос уже обсуждался в статье раннее, поэтому не будем ещё раз заострять на этом внимание и останавливаться.&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Сборка осуществлялась со следующими параметрами:&lt;br /&gt;
* Компилятор intel/15.0.090 &lt;br /&gt;
* Openmpi/1.8.4-icc&lt;br /&gt;
В серии проведённых расчётов рассматривались следующие числовые значения параметров:&lt;br /&gt;
* Размер &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;n&amp;lt;/math&amp;gt; задачи и, соответственно, матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt;, задействованной в операции умножения на вектор: [2000 : 30000] с шагом 1000&lt;br /&gt;
* Число процессоров: 1, 2, 4, 16, 32, 48, 64, 96, 128&lt;br /&gt;
* Число итераций в алгоритме: &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k=350&amp;lt;/math&amp;gt;&lt;br /&gt;
Число &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; взято таким вопреки информации в начале статьи, где говорится, что значение &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; редко превышает &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;10^2&amp;lt;/math&amp;gt; (хоть мы и имеем право брать его любым по нашему усмотрению). Это сделано исключительно для лучшей визуализации пиков на графиках в данном разделе и наглядности получаемых результатов, так как при меньших на порядок значениях &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; времена выполнения программ были слишком малы даже при минимальных числах процессоров и максимальных размерах исходной задачи.&lt;br /&gt;
&lt;br /&gt;
== Динамические характеристики и эффективность реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Выводы для классов архитектур ==&lt;br /&gt;
По заданию, во второй части требовалось описать только разделы 2.4 и 2.7, прошу не спрашивать с меня все разделы 2.1-2.6. Надеюсь на понимание, мне физически не хватает времени на это задание + 2 других в течение семестра, делаю всё, что в моих силах :)&lt;br /&gt;
&lt;br /&gt;
== Существующие реализации алгоритма ==&lt;br /&gt;
Несмотря на то, что алгоритм является далеко не самым популярным, алгоритмом, про который нельзя сказать, что он всегда «на слуху», на сегодняшний день существует множество реализаций на различных популярных языках.&amp;lt;br&amp;gt;&lt;br /&gt;
Перечислим далее некоторые из них, указывая язык программирования, лежащий в их основе, и некоторые важные характеристики, которые обсуждались в статье ранее:&lt;br /&gt;
*&#039;&#039;Code on netlib.org by Jane Cullum and Ralph Willoughby&#039;&#039; (&#039;&#039;&#039;Fortran 77&#039;&#039;&#039;; без реортогонализации векторов; без реализации распараллеливания)&amp;lt;ref&amp;gt;http://www.netlib.org/lanczos/leval&amp;lt;/ref&amp;gt;&lt;br /&gt;
*&#039;&#039;Lanczos algorithm on freesourcecode.net&#039;&#039; (&#039;&#039;&#039;Matlab&#039;&#039;&#039;; присутствует реортогонализация векторов; без реализации распараллеливания)&amp;lt;ref&amp;gt;http://freesourcecode.net/matlabprojects/61741/lanczos-algorithm--in-matlab&amp;lt;/ref&amp;gt;&lt;br /&gt;
*&#039;&#039;Lanczos for eigenvalues in Numerical Linear Algebra, Spring 2007&#039;&#039; (&#039;&#039;&#039;Matlab&#039;&#039;&#039;; частичная или полная реортогонализация - доступны оба варианта; без реализации распараллеливания)&amp;lt;ref&amp;gt;Ссылки на файлы lanso.m и lanfu.m можно найти на https://www.nada.kth.se/~ruhe/2D5219/labs2007.html&amp;lt;/ref&amp;gt;&lt;br /&gt;
*&#039;&#039;Planso&#039;&#039; (название происходит от parallel Lanso.f) &#039;&#039;code by Kesheng Wu and Horst D. Simon&#039;&#039; (&#039;&#039;&#039;Fortran 77&#039;&#039;&#039;; частичная реортогонализация векторов; использование MPI для коммуникаций)&amp;lt;ref&amp;gt;https://github.com/jiahao/planso.jl/tree/master/external/PLAN/plan К сожалению, ссылка в описании пакета на github, ведущая на сайт National Energy Research Scientific Computing Center (NERSC), с более подробной информацией о данной программе больше не активна и выдаёт результат &#039;&#039;Page not found&#039;&#039;&amp;lt;/ref&amp;gt; &lt;br /&gt;
* &#039;&#039;Lanczos.cpp in the Vienna Computing Library&#039;&#039;  (&#039;&#039;&#039;C++&#039;&#039;&#039;, частичная реортогонализация, без реализации распараллеливания) &amp;lt;ref&amp;gt;http://viennacl.sourceforge.net/doc/lanczos_8cpp_source.html&amp;lt;/ref&amp;gt;&lt;br /&gt;
* &#039;&#039;Parallel Eigen Values code using C++ AMP on microsoft msdn blog&#039;&#039; (&#039;&#039;&#039;C++&#039;&#039;&#039;; ? ; распараллеливание есть и реализовано через C++ AMP) &amp;lt;ref&amp;gt;https://blogs.msdn.microsoft.com/nativeconcurrency/2013/12/20/eigen-values/ Подробнее о C++ Accelerated Massive Parallelism можно почитать здесь: https://msdn.microsoft.com/ru-ru/library/hh265137(v=vs.140).aspx или здесь: http://professorweb.ru/my/csharp/optimization/level4/4_6.php &amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;br /&gt;
[[en:Description of algorithm properties and structure]]&lt;/div&gt;</summary>
		<author><name>AleksLevin</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:AleksLevin/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%9B%D0%B0%D0%BD%D1%86%D0%BE%D1%88%D0%B0_%D0%B2%D1%8B%D1%87%D0%B8%D1%81%D0%BB%D0%B5%D0%BD%D0%B8%D1%8F_%D1%81%D0%BE%D0%B1%D1%81%D1%82%D0%B2%D0%B5%D0%BD%D0%BD%D1%8B%D1%85_%D0%B7%D0%BD%D0%B0%D1%87%D0%B5%D0%BD%D0%B8%D0%B9_%D1%81%D0%B8%D0%BC%D0%BC%D0%B5%D1%82%D1%80%D0%B8%D1%87%D0%BD%D0%BE%D0%B9_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86%D1%8B_%D0%B4%D0%BB%D1%8F_%D1%82%D0%BE%D1%87%D0%BD%D0%BE%D0%B9_%D0%B0%D1%80%D0%B8%D1%84%D0%BC%D0%B5%D1%82%D0%B8%D0%BA%D0%B8_(%D0%B1%D0%B5%D0%B7_%D0%BF%D0%B5%D1%80%D0%B5%D0%BE%D1%80%D1%82%D0%BE%D0%B3%D0%BE%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D0%B8)&amp;diff=20213</id>
		<title>Участник:AleksLevin/Алгоритм Ланцоша вычисления собственных значений симметричной матрицы для точной арифметики (без переортогонализации)</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:AleksLevin/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%9B%D0%B0%D0%BD%D1%86%D0%BE%D1%88%D0%B0_%D0%B2%D1%8B%D1%87%D0%B8%D1%81%D0%BB%D0%B5%D0%BD%D0%B8%D1%8F_%D1%81%D0%BE%D0%B1%D1%81%D1%82%D0%B2%D0%B5%D0%BD%D0%BD%D1%8B%D1%85_%D0%B7%D0%BD%D0%B0%D1%87%D0%B5%D0%BD%D0%B8%D0%B9_%D1%81%D0%B8%D0%BC%D0%BC%D0%B5%D1%82%D1%80%D0%B8%D1%87%D0%BD%D0%BE%D0%B9_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86%D1%8B_%D0%B4%D0%BB%D1%8F_%D1%82%D0%BE%D1%87%D0%BD%D0%BE%D0%B9_%D0%B0%D1%80%D0%B8%D1%84%D0%BC%D0%B5%D1%82%D0%B8%D0%BA%D0%B8_(%D0%B1%D0%B5%D0%B7_%D0%BF%D0%B5%D1%80%D0%B5%D0%BE%D1%80%D1%82%D0%BE%D0%B3%D0%BE%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D0%B8)&amp;diff=20213"/>
		<updated>2016-12-06T23:45:41Z</updated>

		<summary type="html">&lt;p&gt;AleksLevin: /* Информационный граф */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Основные авторы описания: Левин А.Д.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{algorithm&lt;br /&gt;
| name              = Алгоритм Ланцоша для точной арифметики (без переортогонализации)&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(k\,n^2)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(k\log_2 n)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;\frac{n^2+3n}{2} + 1&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;k\;(n + 1)&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритмов =&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Данный алгоритм появился в 1950 г. и носит имя венгерского физика и математика Корнелия Ланцоша (венг. Lánczos Kornél). Алгоритм Ланцоша относится к итерационным методам вычисления собственных значений для матриц столь больших порядков &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt; n&amp;lt;/math&amp;gt;, что к ним нельзя применить прямые методы из-за ограничений по времени и памяти.&lt;br /&gt;
&lt;br /&gt;
Сам Ланцош указывал, что его метод предназначен для отыскания нескольких собственных векторов симметричных матриц, хотя к методу сразу было обращено внимание, как к способу приведения всей матрицы к трёхдиагональному виду. Двадцатью годами позже канадский математик Крис Пэж показал, что, несмотря на чувствительность к округлениям, алгоритм Ланцоша - эффективное средство вычисления некоторых &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; собственных чисел и соответствующих им собственных векторов. &amp;lt;ref&amp;gt;Парлетт Б. - Симметричная проблема собственных значений. Численные методы //М.: Мир. - 1983. (c. 276)&amp;lt;/ref&amp;gt;&lt;br /&gt;
Обычно число &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; берут в два раза больше, чем количество собственных значений матрицы, которые поставлена цель найти, и оно имеет порядок не более &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;10^2&amp;lt;/math&amp;gt;.&amp;lt;ref&amp;gt;Susan W. Bostic - Lanczos Eigensolution Method for High-Perfomance Computers, page 7&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Алгоритм Ланцоша для вычисления собственных значений симметричной матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; соединяет в себе метод Ланцоша для построения последовательности подпространств Крылова и ортонормированных векторов Ланцоша и процедуру Рэлея-Ритца получения оптимальных приближений собственных значений и соответствующих собственных векторов исходной матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt;.&amp;lt;ref&amp;gt;James W. Demmel - Вычислительная линейная алгебра. Теория и приложения //Мир. - 2001 (c. 381)&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
В данной статье рассматривается вариант алгоритма Ланцоша, в котором опущено влияние ошибок округления на вычислительный процесс, хотя на практике этому посвящается отдельное внимание и существуют различные методы решения данной проблемы, такие как частичная или полная переортогонализация. Этим модифицированным методам посвящены отдельные статьи на данном ресурсе.&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
Обозначения и формулы, используемые в данном разделе, взяты из литературы, указанной по ссылке.&amp;lt;ref&amp;gt;James W. Demmel - Вычислительная линейная алгебра. Теория и приложения //Мир. - 2001 (c. 313, &#039;&#039;&amp;lt;math&amp;gt; \S &amp;lt;/math&amp;gt; 6.6 Методы Крыловского подпространства&#039;&#039;)&amp;lt;/ref&amp;gt; &lt;br /&gt;
&lt;br /&gt;
Алгоритм Ланцоша для вычисления &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; собственных значений и собственных векторов вещественной симметричной матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A=A^T&amp;lt;/math&amp;gt; в точной арифметике: &amp;lt;ref&amp;gt;James W. Demmel - Вычислительная линейная алгебра. Теория и приложения //Мир. - 2001 (c. 381)&amp;lt;/ref&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{align}&lt;br /&gt;
q_1 = &amp;amp; \,\frac{b}{\|b\|_2},\; \beta_0 = 0,\; q_0 = 0\\&lt;br /&gt;
\mathbf{for} \; &amp;amp; j = 1 \; to \; k \,\; \mathbf{do} \\&lt;br /&gt;
&amp;amp; z = A\,q_j\\&lt;br /&gt;
&amp;amp; \alpha_j = q^T_j z\\&lt;br /&gt;
&amp;amp; z = z - \alpha_j q_j - \beta_{j-1}q_{j-1}\\&lt;br /&gt;
&amp;amp; \beta_j = \|z\|_2\\&lt;br /&gt;
&amp;amp; \mathbf{If} \; (\beta_j == 0) \; \mathbf{then}\; stop\; the\; algorithm \\ &lt;br /&gt;
&amp;amp; \;  q_{j+1} = \frac{z}{\beta_j} \\&lt;br /&gt;
&amp;amp; compute\; eigenvalues\; and \;eigenvectors\;of \;matrix \;\;T_j= Q^T_j A Q\;\;and\;estimate \;the\; errors\\&lt;br /&gt;
\mathbf{end} \; &amp;amp; \mathbf{for}&lt;br /&gt;
\end{align}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
В продемонстрированном выше алгоритме &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;b&amp;lt;/math&amp;gt; - заданный вещественный вектор. Также полагается известным алгоритм вычисления произведения матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; на вектор &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;x&amp;lt;/math&amp;gt;. &lt;br /&gt;
Введём матрицу Крылова, определяемую следующим соотношением: &amp;lt;math&amp;gt;K_j = [b,Ab,A^2b,...,A^{j-1}b]&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Далее, на практике, матрица &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;K&amp;lt;/math&amp;gt; заменяется матрицей &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;Q&amp;lt;/math&amp;gt;, такой, что при любом числе &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; линейные оболочки первых &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; столбцов в &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;K&amp;lt;/math&amp;gt; и &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;Q&amp;lt;/math&amp;gt; являются одним и тем же подпространством.&amp;lt;ref&amp;gt;James W. Demmel - Вычислительная линейная алгебра. Теория и приложения //Мир. - 2001 (c. 315)&amp;lt;/ref&amp;gt; &lt;br /&gt;
Тогда матрица &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;Q&amp;lt;/math&amp;gt;, в отличие от матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;K&amp;lt;/math&amp;gt;, хорошо обусловлена и легко обратима. В результате получаем матрицу &amp;lt;math&amp;gt;Q_j = [q_1, q_2, \dots, q_j]&amp;lt;/math&amp;gt; размерности &amp;lt;math&amp;gt;n\times j&amp;lt;/math&amp;gt;, столбцы которой ортогональны, являются базисом подпространства Крылова и называются векторами Ланцоша.&lt;br /&gt;
&lt;br /&gt;
В алгоритме Ланцоша вычислению подлежит столько первых столбцов в матрице &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;Q_j&amp;lt;/math&amp;gt;, сколько необходимо для получения требуемого приближения к решению &amp;lt;math&amp;gt;A\,x\,=b\,\,(A\,x=\lambda \, x)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Получение нулевого &amp;lt;math&amp;gt;\beta_j&amp;lt;/math&amp;gt; в итерационном процессе - событие, желательное в том смысле, что оно свидетельствует о том, что найдено некоторое подпространство, являющееся в точности инвариантным, а все собственные значения матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;T_j&amp;lt;/math&amp;gt; являются собственными значениями матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt;. На практике же нулевое и близкие к нулю значения получаются редко.&amp;lt;ref&amp;gt;Голуб Дж., Ван Лоун Ч. - Матричные вычисления//М.: Мир. - 1999 (c. 429)&amp;lt;/ref&amp;gt; &lt;br /&gt;
&lt;br /&gt;
Затем на каждом шаге цикла формируется симметричная трёхдиагональная матрица &amp;lt;math&amp;gt;T_j = Q^T_j A Q&amp;lt;/math&amp;gt;, к которой применяется процесс Рэлея-Ритца для поиска её собственных значений (на практике для поиска этих собственных значений можно использовать любой из специальных методов в параграфе книги по ссылке).&amp;lt;ref&amp;gt;Голуб Дж., Ван Лоун Ч. - Матричные вычисления//М.: Мир. - 1999 (&amp;lt;math&amp;gt;\S&amp;lt;/math&amp;gt; 8.4)&amp;lt;/ref&amp;gt;  &lt;br /&gt;
Эти собственные значения, они же числа Ритца, и полагаются приближёнными собственными значениями исходной матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt;.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Существует множество методов для отыскания собственных значений вещественной симметричной трехдиагональной матрицы. Большинство из них требует &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt; операций &amp;lt;ref&amp;gt;Парлетт Б. Симметричная проблема собственных значений. Численные методы.,: Мир, 1983. с. 179-182&amp;lt;/ref&amp;gt;, но существуют и быстрые алгоритмы, требующие лишь &amp;lt;math&amp;gt;O(n\ln n)&amp;lt;/math&amp;gt; операций.&amp;lt;ref&amp;gt;https://en.wikipedia.org/wiki/Tridiagonal_matrix#Eigenvalues  Раздел eigenvalues&amp;lt;/ref&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Одним из возможных способов отыскать собственные значения симметричной трехдиагональной матрицы - прямое вычисление корней характеристического полинома &amp;lt;math&amp;gt;p_n(\lambda)&amp;lt;/math&amp;gt; через метод деления пополам, где формируется последовательность Штурма и локализуются собственные числа, являющиеся корнями характеристического полинома. Нахождение всех &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; собственных значений матрицы этим способом требует &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;2n^2t&amp;lt;/math&amp;gt; умножений и вычитаний, где &amp;lt;math&amp;gt;t&amp;lt;/math&amp;gt; - число сделанных шагов с применением метода деления пополам.&amp;lt;ref&amp;gt;Уилкинсон Дж. X. Алгебраическая проблема собственныx значений. Изд-во &amp;quot;Наука&amp;quot;, 1970. - глава 5, с. 272-278&amp;lt;/ref&amp;gt; Соответствующие собственные вектора могут быть найдены посредством обратных итераций за &amp;lt;math&amp;gt; O(n) &amp;lt;/math&amp;gt; флопов. &amp;lt;ref&amp;gt;Голуб Дж., Ван Лоун Ч. - Матричные вычисления//М.: Мир. - 1999 (c. 394-395)&amp;lt;/ref&amp;gt; &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;На практике, если требуется только небольшая часть от всей совокупности собственных векторов и значений, и матрица имеет Хессенбергову или трёхдиагональную форму, очень эффективными будут методы факторизации, как, например, QR-алгоритм или QL-алгоритм со сдвигами (c целью ускорить алгоритм и сделать порядок сходимости квадратичным) или же без них.&amp;lt;ref&amp;gt;http://algorithm.narod.ru/ln/eigen/ETridiag.html&amp;lt;/ref&amp;gt; &amp;lt;br&amp;gt;&lt;br /&gt;
Весьма молодые и не менее актуальные конкуренты QR и QL алгоритмов, применяющиеся для поиска собственных значений:&lt;br /&gt;
*Методы divide-and-conquer (разделяй и властвуй), появившиеся в 1980-ых годах &amp;lt;ref&amp;gt;https://goo.gl/dapvbn ссылку пришлось сократить с помощью Google url shortener, так как символы подчеркивания портили её и не давали перейти по 1 клику&amp;lt;/ref&amp;gt;&lt;br /&gt;
*Relatively robust representation методы, появившиеся в 1990-ых и позволяющие найти собственные числа симметричной матрицы порядка &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;n&amp;lt;/math&amp;gt; за &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt; операций&lt;br /&gt;
&lt;br /&gt;
Если требуется вычислить собственные векторы, то необходимо хранить вычисляемые векторы Ланцоша. Если работа при этом производится только с оперативной памятью, то при большом порядке исходной матрицы (а именно для таких матриц и предназначен метод Ланцоша) число шагов  &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;j&amp;lt;/math&amp;gt;, которые могут быть выполнены до того момента, как оперативная память будет исчерпана, будет очень незначительно, а следовательно, искомые собственные пары могут не успеть сойтись с требуемой точностью. В этом случае метод Ланцоша можно использовать итерационным образом: после выполнения заданного числа шагов процесс прерывается и, если еще не все требуемые пары Ритца сошлись с требуемой точностью, то формируется новый начальный вектор &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;q_1&amp;lt;/math&amp;gt;, являющийся линейной комбинацией векторов Ритца, еще не сошедшихся с заданной точностью, и процесс начинается заново.&amp;lt;ref&amp;gt;http://num-anal.srcc.msu.ru/lib_na/int_ae/int_ae6.htm (пункт 6.5)&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
Вычислительное ядро рассматриваемого алгоритма (наиболее ресурсно-затратная часть алгоритма) -  формирование на каждом шаге цикла промежуточного вектора &amp;lt;math&amp;gt;z&amp;lt;/math&amp;gt;, вычисляемого по формуле: &amp;lt;math&amp;gt;z = A\,q_j&amp;lt;/math&amp;gt;. Данная операция, по сравнению с другими операциями алгоритма, затратна и требовательна, как с точки зрения количества производимых операций, так и с точки зрения объема оперируемых данных. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Например, умножение матрицы размера &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;n\times n&amp;lt;/math&amp;gt; на вектор длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; требует: &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;n^2+(n-1)n = 2n^2-n&amp;lt;/math&amp;gt; операций умножения и сложения. В свою очередь аналогичная операция умножения матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;(n+1)\times (n+1)&amp;lt;/math&amp;gt; на вектор длины &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;(n+1)&amp;lt;/math&amp;gt; требует: &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;2n^2+3n+1&amp;lt;/math&amp;gt;  операций умножения и сложения. То есть повышение размерности задачи всего на 1 увеличивает число необходимых действий в этом шаге алгоритма на: &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;4n+1&amp;lt;/math&amp;gt;. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Так же, стоит помнить, что, согласно разделу 1.2, данную операцию умножения матрицы на вектор необходимо выполнить &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;k&amp;lt;/math&amp;gt; раз. Нетрудно понять, насколько возрастает и колоссален масштаб операций, если в задачах, где критична точность, размерности &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; могут иметь порядок &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;10^5&amp;lt;/math&amp;gt; или даже более.&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
Как уже было упомянуто в данной статье в описании алгоритма, рассматриваемый алгоритм состоит из двух последовательно выполненных алгоритмов: метод Ланцоша для построения последовательности подпространств Крылова и ортонормированных векторов Ланцоша и процедура Рэлея-Ритца получения оптимальных приближений собственных значений и соответствующих собственных векторов исходной матрицы.&lt;br /&gt;
&lt;br /&gt;
В первой части алгоритма, где итерационно строятся Крыловское подпространство и трёхдиагональная матрица &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&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 style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; разреженная. Именно она подлежит оптимизации с использованием техник распараллеливания, поскольку она является вычислительным ядром алгоритма, а весь упомянутый процесс построения матрицы &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&amp;lt;/math&amp;gt; выполняется последовательно.&lt;br /&gt;
&lt;br /&gt;
Рассмотрим вторую часть алгоритма - поиск собственных значений сформированной матрицы &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&amp;lt;/math&amp;gt;.&amp;lt;br&amp;gt;&lt;br /&gt;
Далее, наглядно, в виде псевдокода, представлен, упомянутый в разделе 1.2, QR-алгоритм (аналогично можно рассмотреть и QL-алгоритм) со сдвигами Релэя, который весьма популярен на практике.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{align}&lt;br /&gt;
\mathbf{Input}: \;&amp;amp;tridiagonal\;\;matrix \;T\;with\;\;n\times n\;\;size\\&lt;br /&gt;
T^{(0)}&amp;amp;:=T\\&lt;br /&gt;
\mathbf{for}&amp;amp; \;\;m=n,...,2 \;\; \mathbf{do}\\&lt;br /&gt;
&amp;amp;k=0\\&lt;br /&gt;
&amp;amp; \mathbf{repeat}\\&lt;br /&gt;
&amp;amp; \quad \;\; k=k+1\\&lt;br /&gt;
&amp;amp; \quad \;\; \mu^{(k)}=T_{m,m}^{(k-1)}\\&lt;br /&gt;
&amp;amp; \quad \;\; Q^{(k)}R^{(k)}=T^{(k-1)}-\mu^{(k)}I\;\;using\;\;QR\;decomposition\\&lt;br /&gt;
&amp;amp; \quad \;\; T^{(k)}=R^{(k)}Q^{(k)}+\mu^{(k)}I\\&lt;br /&gt;
&amp;amp; \mathbf{until} \;\;\; |T_{m,m-1}^{(k)}| \;is\;\;small\;\;enough\\&lt;br /&gt;
&amp;amp; Save  \;\;T_{m,m}^{(k)} \;\;as\;\; converged\;\;eigenvalue\;of\;T\\ &lt;br /&gt;
&amp;amp; Remove \;\boldsymbol{n}\,th\;row\;and\;\boldsymbol{n}\,th\;column\;\;from \;T \\&lt;br /&gt;
&amp;amp; and\;take\;this\;new\;cropped\;matrix\;as\;new\;T^{(0)}\;with\;\;(n-1)\times (n-1)\;\;size\\&lt;br /&gt;
 \mathbf{end}&amp;amp;\; \mathbf{for}&lt;br /&gt;
\end{align}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Малость наддиагональных и поддиагональных элементов матрицы (фраза &#039;&#039;&amp;quot;small enough&amp;quot;&#039;&#039; в псевдокоде) подразумевает:&lt;br /&gt;
&amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt; |T_{m,m-1}^{(k)}| \leq \varepsilon\,|T_{m,m}^{(k)}| \quad\quad &amp;lt;/math&amp;gt; , где &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt; \varepsilon &amp;lt;/math&amp;gt; - заданная точность&amp;lt;br&amp;gt;&lt;br /&gt;
Также вместо сдвига Релэя, обозначенного в алгоритме через &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;\mu^{(k)}&amp;lt;/math&amp;gt;, часто на практике используется сдвиг по Уилкинсону, который даёт гарантированную сходимость внедиагональных элементов матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt; T^{(k)} &amp;lt;/math&amp;gt;, формируемой на каждом шаге, к нулю, при этом жертвуя монотонностью их убывания.&amp;lt;ref&amp;gt;Голуб Дж., Ван Лоун Ч. - Матричные вычисления//М.: Мир. - 1999 (c. 378, вторая половина страницы)&amp;lt;/ref&amp;gt;&amp;lt;ref&amp;gt;Парлетт Б. Симметричная проблема собственных значений. Численные методы.,: Мир, 1983. с. 169&amp;lt;/ref&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Подробнее с различными сдвигами и соответствующими оценками скоростей и количествами операций можно ознакомиться по указанной ссылке:&amp;lt;ref&amp;gt;Парлетт Б. Симметричная проблема собственных значений. Численные методы.,: Мир, 1983. с. 179-182&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;Для совершения QR-декомпозиции на каждом шаге может использоваться любой из алгоритмов по ссылке.&amp;lt;ref&amp;gt;https://en.wikipedia.org/wiki/QR_decomposition&amp;lt;/ref&amp;gt; Подробные описания этих алгоритмов также доступны на данном ресурсе algowiki-project.&amp;lt;br&amp;gt;&lt;br /&gt;
Так как мы оперируем не обычной матрицей и даже не Хессенберговой, а симметричной и трёхдиагональной, то скорость таких алгоритмов значительно возрастёт. Например, согласно данному ресурсу &amp;lt;ref&amp;gt;http://algorithm.narod.ru/ln/eigen/ETridiag.html&amp;lt;/ref&amp;gt;, для QL-алгоритма с неявными сдвигами:&amp;lt;br&amp;gt;&lt;br /&gt;
Для трёхдиагональной матрицы объем арифметических действий составляет &amp;lt;math&amp;gt; O(n)&amp;lt;/math&amp;gt; на одну итерацию вместо &amp;lt;math&amp;gt; O(n^3)&amp;lt;/math&amp;gt; для матрицы общего вида, а число итераций для нахождения первых собственных значений примерно равно 4 - 5. Но на этих итерациях также уменьшаются внедиагональные элементы правого нижнего угла. И, таким образом, дальнейшие собственные значения ищутся значительно быстрее. Среднее число итераций на каждое собственное значение обычно составляет 1.3 - 1.6.&amp;lt;br&amp;gt; &lt;br /&gt;
Аналогично QL, QR-разложение трёхдиагольной матрицы также требует &amp;lt;math&amp;gt; O(n)&amp;lt;/math&amp;gt; флопов&amp;lt;ref&amp;gt;Голуб Дж., Ван Лоун Ч. - Матричные вычисления//М.: Мир. - 1999 (c. 378, начало раздела 8.2.2)&amp;lt;/ref&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Подводя итог, во второй части алгоритма Ланцоша можно выделить следующие макрооперации:&lt;br /&gt;
* умножение матрицы на вещественное число;&lt;br /&gt;
* перемножение матриц;&lt;br /&gt;
* умножение и сравнение вещественных чисел;&lt;br /&gt;
* + набор других макроопераций в зависимости от выбора метода, с помощью которого будет совершаться сама QR или QL-декомпозиция (выше продемонстрированы, уже, как минимум, 3 разных способа).&lt;br /&gt;
Так же, важно заметить, что набор макропераций может быть несколько другим, если выбрать какой-либо иной современный метод поиска собственных чисел трёхдиагональной матрицы, не использующий QR и QL разложения(факторизацию). Два таких метода были упомянуты в пункте 1.2.&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
С целью полностью не дублировать раздел 1.2 данной статьи, где представлен наглядный и доступный для понимания псевдокод алгоритма, постараемся лишь коротко просуммировать и обобщить весь перечень последовательных действий в рассматриваемом алгоритме.&lt;br /&gt;
&lt;br /&gt;
В качестве входных данных имеем: вещественная симметричная матрица &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; размера &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;n\times n&amp;lt;/math&amp;gt;, известный вещественный вектор &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;b&amp;lt;/math&amp;gt; длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; и число &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;n&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Далее:&lt;br /&gt;
* Инициализируем вещественную константу &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;\beta_0&amp;lt;/math&amp;gt; и векторы &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;q_0&amp;lt;/math&amp;gt; и &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;q_1&amp;lt;/math&amp;gt;&lt;br /&gt;
* Итерационно для всех &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j=1,...,k&amp;lt;/math&amp;gt;:&lt;br /&gt;
** Вычисляем вспомогательный вектор &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt;, используя умножение матрицы на вектор&lt;br /&gt;
** Вычисляем, используя скалярное произведение векторов, значение &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;\alpha_j&amp;lt;/math&amp;gt; - элемент на главной диагонали трёхдиагональной матрицы &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&amp;lt;/math&amp;gt;&lt;br /&gt;
** Вычисляем по формуле новое значение и перезаписываем вектор &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt;&lt;br /&gt;
** Вычисляем значение &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;\beta_j&amp;lt;/math&amp;gt; - элементы непосредственно над и под главной диагональю той же матрицы &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&amp;lt;/math&amp;gt;&lt;br /&gt;
** Вычисляем, зная вектор &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt;,  очередной столбец матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;Q&amp;lt;/math&amp;gt;, он же вектор Ланцоша : &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;\,\,q_{j+1}&amp;lt;/math&amp;gt;&lt;br /&gt;
** Теперь, когда матрица &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&amp;lt;/math&amp;gt; сформирована на очередном шаге, находим её собственные значения и вектора любым доступным способом, о чём было подробно сказано в пункте 1.2&lt;br /&gt;
** Переходим на следующую итерацию: &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j&amp;lt;/math&amp;gt;++&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
Оценим количество операций и сложность последовательного алгоритма, изложенного в предыдущем разделе.&lt;br /&gt;
*Для вычисления вектора &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt; умножается матрица размера &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;n\times n&amp;lt;/math&amp;gt; на вектор длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt;, и потребуется &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n^2&amp;lt;/math&amp;gt; операций умножения и &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n^2&amp;lt;/math&amp;gt; операций сложения.&lt;br /&gt;
*Умножение векторов &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;q^T_j&amp;lt;/math&amp;gt; и &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt; длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; потребует &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; операций умножения и &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; операций сложения.&lt;br /&gt;
*При вычислении нового значения вектора &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt; поэлементное сложение двух векторов длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; требует &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; операций сложения.&lt;br /&gt;
*Умножение вектора длины &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; на вещественное число требует &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; операций умножения.&lt;br /&gt;
*Нахождение квадратичной нормы вектора &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt;  длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; требует &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; умножений и &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; сложений и ещё 1 операцию извлечения квадратного корня.&lt;br /&gt;
*Заключительное нахождение собственных значений и собственных векторов трёхдиагональной матрицы &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;T_j&amp;lt;/math&amp;gt; размера &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j\times j&amp;lt;/math&amp;gt; с помощью QR-алгоритма потребует в худшем случае &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(j^3)&amp;lt;/math&amp;gt; операций.&amp;lt;ref&amp;gt;http://num-anal.srcc.msu.ru/lib_na/int_ae/int_ae6.htm (пункт 6.2, &amp;quot;Скорость сходимости при этом всегда не хуже квадратичной и почти всегда лучше кубической.&amp;quot;)&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Посчитаем теперь суммарное количество простейших операций на одной итерации алгоритма (без учёта записей в память):&lt;br /&gt;
*&amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n^2+5\,n&amp;lt;/math&amp;gt; операций умножения/деления&lt;br /&gt;
*&amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n^2+4\,n&amp;lt;/math&amp;gt; операций сложения/вычитания&lt;br /&gt;
*1 операция извлечения квадратного корня&amp;lt;br&amp;gt;&lt;br /&gt;
Отдельно после всех итераций при &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j=k&amp;lt;/math&amp;gt; :&lt;br /&gt;
*&amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(k^3)&amp;lt;/math&amp;gt; операций для поиска собственных значений и собственных векторов трёхдиагональной матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_k&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Итого можно утверждать следующее:&lt;br /&gt;
&lt;br /&gt;
Последовательная сложность одной итерации рассматриваемого алгоритма:  &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(n ^ 2) &amp;lt;/math&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Суммарная сложность алгоритма (&amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;/math&amp;gt; итераций): &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(k\,n ^ 2) + O(k ^ 3)&amp;lt;/math&amp;gt; &amp;lt;ref&amp;gt;Здесь мы полагаем, что мы не вычисляем собственные значения и векторы матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_j&amp;lt;/math&amp;gt; на каждом промежуточном шаге, а лишь единожды затрачиваем &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;O(k ^ 3)&amp;lt;/math&amp;gt; действий в конце для нахождения &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;/math&amp;gt; собственных значений и векторов матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_k&amp;lt;/math&amp;gt;&amp;lt;/ref&amp;gt; &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
На практике же обычно рассматривается число &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;&amp;lt;n&amp;lt;/math&amp;gt;, поэтому второе слагаемое можно опустить.&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
На рис. 1 продемонстрирован граф одной итерации (при каком-либо произвольном значении итератора &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j&amp;lt;/math&amp;gt;) описанного алгоритма без отображения входных и выходных данных. Наглядно продемонстрированы связи между всеми действиями, и с помощью деления на &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; потоков показано, какие операции возможно выполнять параллельно на каждом шаге с целью оптимизации и экономии машинного времени. В результате, после параллельно выполненных операций &#039;&#039;&#039;Division&#039;&#039;&#039; на заключительном ярусе, на выходе имеем значение следующего вектора Ланцоша &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;q_{j+1}&amp;lt;/math&amp;gt;, после чего следует переход на следующую итерацию, и процесс повторяется.&lt;br /&gt;
&lt;br /&gt;
[[Файл:Levin_graph.png|600px|thumb|center|Рис. 1  Информационный граф одной итерации алгоритма]] &amp;lt;br&amp;gt;&lt;br /&gt;
Обозначения на рисунке: &amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Simp&#039;&#039;&#039; (от англ. simple) - операции сложения и умножения вещественных чисел при вычислении произведения матрицы на вектор;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Vec mult&#039;&#039;&#039; (от англ. vectors multiplication) - операция скалярного умножения двух векторов;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Vec subtr&#039;&#039;&#039; (от англ. vectors subtraction, из-за использованных в операции вычитаний векторов) - операция умножения вектора на число (выполняется дважды) и формирование нового значения &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;z_{new}&amp;lt;/math&amp;gt; по формуле: &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;z_{new} = z - \alpha_j q_j - \beta_{j-1}q_{j-1} \;&amp;lt;/math&amp;gt;;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;||\cdot||&amp;lt;/math&amp;gt; - операция вычисления нормы вектора;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Division&#039;&#039;&#039; - операция деления вектора на вещественное число  &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;\beta_j&amp;lt;/math&amp;gt; &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Важно отметить, что упомянутые выше операции также легко поддаются оптимизации. Например, попарные умножения вещественных координат векторов при вычислении скалярного произведения также легко выполняются параллельно на &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; потоках, а затем можно применить суммирование методом сдваивания, о котором сказано в следующем разделе. Умножение или деление вектора на вещественное число являющееся, по определению, умножением или делением всех его координат на это число тоже может быть выполнено эффективнее, если мы используем &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; потоков, а не выполняем эти действия последовательно.&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
Параллельные операции возможны только внутри итераций, так как рассматриваемый алгоритм является итерационным, и сами итерации строго последовательны.&amp;lt;br&amp;gt;&lt;br /&gt;
Рассмотрим в этом разделе подробнее, какой выигрыш мы можем получить при распараллеливании операций внутри одной итерации согласно графу из предыдущего раздела.&lt;br /&gt;
&lt;br /&gt;
Умножение вещественной симметричной матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; размера &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;n\times n&amp;lt;/math&amp;gt; на вектор &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;b&amp;lt;/math&amp;gt; длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; требует последовательного выполнения &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; ярусов умножений и сложений. Сложение элементов вектора длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; на каждом шаге перемножения можно оптимизировать и выполнить за &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;\log_2 n&amp;lt;/math&amp;gt; действий, если применять метод сдваивания.&lt;br /&gt;
&lt;br /&gt;
Дальнейшие операции выполняются последовательно, а вычисление значений векторов происходит за один ярус операций сложения или умножения.&lt;br /&gt;
&lt;br /&gt;
Ресурс параллелизма алгоритма вычисления собственных значений построенной трёхдиагональной матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_k&amp;lt;/math&amp;gt; размера &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k\times k&amp;lt;/math&amp;gt; зависит от выбранного алгоритма (об этих алгоритмах подробнее было сказано в разделах 1.2 и 1.4). Будет очень затратно с точки зрения объёма материала пытаться рассмотреть пусть даже часть этих методов в этой статье, а так же тонкости их распараллеливания. Предлагаем читателям при желании самим ознакомиться с этими алгоритмами на данном ресурсе или прибегнув к иным источникам.&lt;br /&gt;
&lt;br /&gt;
При классификации по высоте ЯПФ, таким образом, алгоритм Ланцоша без переортогонализации относится к алгоритмам с &#039;&#039;логарифмической сложностью&#039;&#039;, и его сложность равна &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(\log_2 n)&amp;lt;/math&amp;gt; с важным замечанием, что это сложность только одной итерации, а максимум в алгоритме может быть выполнено последовательно &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;/math&amp;gt; таких однотипных итераций, если не будет осуществлён ранний выход из цикла. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Несмотря на то, что на графе в предыдущем разделе для лучшей визуализации и понимания было изображено &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; потоков (никаких допущений мы не делали и нарушений с точки зрения логики и математики нет, можно изобразить большее число потоков, просто часть времени некоторые из них могут бездействовать и не использоваться), на самом деле правильным и разумным будет реализовать начальное параллельное выполнение &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n^2&amp;lt;/math&amp;gt; операций умножения всех вещественных элементов матрицы &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;A&amp;lt;/math&amp;gt; на соответствующие элементы вектора &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;q_j&amp;lt;/math&amp;gt;, после чего применять тот же самый упомянутый метод сдваивания. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Поэтому при классификации по ширине ЯПФ его сложность будет &#039;&#039;квадратичной&#039;&#039; и равна &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(n^2)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
&#039;&#039;&#039;Входные данные алгоритма:&#039;&#039;&#039; вещественная симметричная &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; размера &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;n\times n&amp;lt;/math&amp;gt;, вещественный вектор &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;b&amp;lt;/math&amp;gt; длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt;, и одно целое число &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;k&amp;lt;/math&amp;gt;, означающее количество итераций.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём входных данных:&#039;&#039;&#039; &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;n^2 +n + 1 &amp;lt;/math&amp;gt;. Если учесть, что матрица симметричная и достаточно для её однозначного определения задать элементы на главной диагонали и элементы над или под ней, то можно сократить объём входных данных с целью экономии памяти до: &amp;lt;math&amp;gt;\ \frac{n^2-n}{2}+n+n+1 =\frac{n^2+3n}{2} + 1&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные алгоритма:&#039;&#039;&#039; вектор собственных значений &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;\Theta^k&amp;lt;/math&amp;gt; длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;/math&amp;gt;, матрица &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;S^k&amp;lt;/math&amp;gt; из соответствующих собственных векторов размера &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n\times k&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём выходных данных:&#039;&#039;&#039; &amp;lt;math&amp;gt;k\;(n + 1)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
В данном разделе перечислены без какой-либо хронологии или связи друг с другом наиболее важные и разнообразные свойства алгоритма, на которые стоит и полезно обратить внимание, а также которые выгодно отличают его от схожих алгоритмов, решающих ту же задачу.&amp;lt;br&amp;gt;&lt;br /&gt;
1) Отношение последовательной сложности алгоритма к параллельной,с учётом &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;/math&amp;gt; итераций, равно &amp;lt;math&amp;gt;\;\;\frac{kn^2}{k \log_2{n}}=\frac{n^2}{\log_2{n}}&amp;lt;/math&amp;gt;;&amp;lt;br&amp;gt;&lt;br /&gt;
2) Вычислительная мощность алгоритма, как отношение числа операций к суммарному объему входных и выходных данных, равна &amp;lt;math style=&amp;quot;vertical-align:-70%&amp;gt;\;\;\frac{k\,n^2}{0.5\,n^2+1.5\,n+k\,n+k+1}&amp;lt;/math&amp;gt; и &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;\approx 2\,k&amp;lt;/math&amp;gt;, так как на практике верно отношение &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;&amp;lt;n&amp;lt;/math&amp;gt; ;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
3) Для собственных значений формируемых матриц &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_j&amp;lt;/math&amp;gt; верно отношение (следствие теоремы Коши о перемежаемости): &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;\lambda_i(T_{k+1})\geq \lambda_i(T_{k})\geq \lambda_{i+1}(T_{k+1})\geq \lambda_{i+1}(T_{k})&amp;lt;/math&amp;gt; ;&amp;lt;ref&amp;gt;James W. Demmel - Вычислительная линейная алгебра. Теория и приложения //Мир. - 2001 (c. 383)&amp;lt;/ref&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
4) Крайние (наибольшие и наименьшие) собственные значения матриц &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_j&amp;lt;/math&amp;gt; сходятся к крайним собственным значениям матрицы &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;A&amp;lt;/math&amp;gt; первыми (это часто происходит уже на ранних шагах при &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j\approx 2\,\sqrt{n}&amp;lt;/math&amp;gt;&amp;lt;ref&amp;gt;http://num-anal.srcc.msu.ru/lib_na/int_ae/int_ae6.htm (пункт 6.5)&amp;lt;/ref&amp;gt;), а собственные значения в середине спектра - последними;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
5) Из-за ограниченной точности постепенно теряется ортогональность вектора Ланцоша &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;q_j&amp;lt;/math&amp;gt; к предыдущим векторам Ланцоша, поэтому необходимо примерно каждые 10-15 итераций проводить дорогостоящую операцию реортогонализации, но это уже будет иной алгоритм с очень малым различием в одной операции и в программном коде, реализующем его, соответственно; &amp;lt;ref&amp;gt;Sam Handler - The Lanczos Algorithm For Large-Scale Eigenvalue Problems (08.01.07), slide №8&amp;lt;/ref&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
6) Эффективность и быстрота выполнения алгоритма очень сильно зависит от скорости памяти (диска). Согласно тесту только &#039;&#039;6%&#039;&#039; времени работы программы приходится на вычисления, остальное время затрачивается на ожидание отклика диска;&amp;lt;ref&amp;gt;Sam Handler - The Lanczos Algorithm For Large-Scale Eigenvalue Problems (08.01.07), slide №10&amp;lt;/ref&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
7) Метод Ланцоша удобен тем, что не требует хранения исходной матрицы полным массивом: метод использует исходную матрицу только в операциях умножения матрицы на вектор, что позволяет эффективно использовать разреженность матрицы или регулярность структуры матрицы. Поэтому метод Ланцоша может быть использован для матриц таких больших порядков, когда методы вращений и отражений не могут быть применены.&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;
Для исследования масштабируемости рассматриваемого алгоритма Ланцоша без переортогонализации автором была реализована программа на языке С++ с использованием технологии MPI (&#039;&#039;&#039;не забыть вставить ссылку на код&#039;&#039;&#039;). Дальнейшее исследование выполнялось на суперкомпьютере &amp;quot;Ломоносов&amp;quot; Суперкомпьютерного комплекса МГУ. &amp;lt;br&amp;gt; Важно отметить, что реализованная программа выполняет только первую часть алгоритма - формирование матрицы &amp;lt;math &amp;gt;T_j&amp;lt;/math&amp;gt;. Вторая часть алгоритма (задача поиска собственных значений матрицы &amp;lt;math &amp;gt;T_j&amp;lt;/math&amp;gt;) может быть решена несколькими методами, каждый из которых обладает своей эффективностью распараллеливании и характерными свойствами. Подробно этот вопрос уже обсуждался в статье раннее, поэтому не будем ещё раз заострять на этом внимание и останавливаться.&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Сборка осуществлялась со следующими параметрами:&lt;br /&gt;
* Компилятор intel/15.0.090 &lt;br /&gt;
* Openmpi/1.8.4-icc&lt;br /&gt;
В серии проведённых расчётов рассматривались следующие числовые значения параметров:&lt;br /&gt;
* Размер &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;n&amp;lt;/math&amp;gt; задачи и, соответственно, матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt;, задействованной в операции умножения на вектор: [2000 : 30000] с шагом 1000&lt;br /&gt;
* Число процессоров: 1, 2, 4, 16, 32, 48, 64, 96, 128&lt;br /&gt;
* Число итераций в алгоритме: &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k=350&amp;lt;/math&amp;gt;&lt;br /&gt;
Число &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; взято таким вопреки информации в начале статьи, где говорится, что значение &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; редко превышает &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;10^2&amp;lt;/math&amp;gt; (хоть мы и имеем право брать его любым по нашему усмотрению). Это сделано исключительно для лучшей визуализации пиков на графиках в данном разделе и наглядности получаемых результатов, так как при меньших на порядок значениях &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; времена выполнения программ были слишком малы даже при минимальных числах процессоров и максимальных размерах исходной задачи.&lt;br /&gt;
&lt;br /&gt;
== Динамические характеристики и эффективность реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Выводы для классов архитектур ==&lt;br /&gt;
По заданию, во второй части требовалось описать только разделы 2.4 и 2.7, прошу не спрашивать с меня все разделы 2.1-2.6. Надеюсь на понимание, мне физически не хватает времени на это задание + 2 других в течение семестра, делаю всё, что в моих силах :)&lt;br /&gt;
&lt;br /&gt;
== Существующие реализации алгоритма ==&lt;br /&gt;
Несмотря на то, что алгоритм является далеко не самым популярным, алгоритмом, про который нельзя сказать, что он всегда «на слуху», на сегодняшний день существует множество реализаций на различных популярных языках.&amp;lt;br&amp;gt;&lt;br /&gt;
Перечислим далее некоторые из них, указывая язык программирования, лежащий в их основе, и некоторые важные характеристики, которые обсуждались в статье ранее:&lt;br /&gt;
*&#039;&#039;Code on netlib.org by Jane Cullum and Ralph Willoughby&#039;&#039; (&#039;&#039;&#039;Fortran 77&#039;&#039;&#039;; без реортогонализации векторов; без реализации распараллеливания)&amp;lt;ref&amp;gt;http://www.netlib.org/lanczos/leval&amp;lt;/ref&amp;gt;&lt;br /&gt;
*&#039;&#039;Lanczos algorithm on freesourcecode.net&#039;&#039; (&#039;&#039;&#039;Matlab&#039;&#039;&#039;; присутствует реортогонализация векторов; без реализации распараллеливания)&amp;lt;ref&amp;gt;http://freesourcecode.net/matlabprojects/61741/lanczos-algorithm--in-matlab&amp;lt;/ref&amp;gt;&lt;br /&gt;
*&#039;&#039;Lanczos for eigenvalues in Numerical Linear Algebra, Spring 2007&#039;&#039; (&#039;&#039;&#039;Matlab&#039;&#039;&#039;; частичная или полная реортогонализация - доступны оба варианта; без реализации распараллеливания)&amp;lt;ref&amp;gt;Ссылки на файлы lanso.m и lanfu.m можно найти на https://www.nada.kth.se/~ruhe/2D5219/labs2007.html&amp;lt;/ref&amp;gt;&lt;br /&gt;
*&#039;&#039;Planso&#039;&#039; (название происходит от parallel Lanso.f) &#039;&#039;code by Kesheng Wu and Horst D. Simon&#039;&#039; (&#039;&#039;&#039;Fortran 77&#039;&#039;&#039;; частичная реортогонализация векторов; использование MPI для коммуникаций)&amp;lt;ref&amp;gt;https://github.com/jiahao/planso.jl/tree/master/external/PLAN/plan К сожалению, ссылка в описании пакета на github, ведущая на сайт National Energy Research Scientific Computing Center (NERSC), с более подробной информацией о данной программе больше не активна и выдаёт результат &#039;&#039;Page not found&#039;&#039;&amp;lt;/ref&amp;gt; &lt;br /&gt;
* &#039;&#039;Lanczos.cpp in the Vienna Computing Library&#039;&#039;  (&#039;&#039;&#039;C++&#039;&#039;&#039;, частичная реортогонализация, без реализации распараллеливания) &amp;lt;ref&amp;gt;http://viennacl.sourceforge.net/doc/lanczos_8cpp_source.html&amp;lt;/ref&amp;gt;&lt;br /&gt;
* &#039;&#039;Parallel Eigen Values code using C++ AMP on microsoft msdn blog&#039;&#039; (&#039;&#039;&#039;C++&#039;&#039;&#039;; ? ; распараллеливание есть и реализовано через C++ AMP) &amp;lt;ref&amp;gt;https://blogs.msdn.microsoft.com/nativeconcurrency/2013/12/20/eigen-values/ Подробнее о C++ Accelerated Massive Parallelism можно почитать здесь: https://msdn.microsoft.com/ru-ru/library/hh265137(v=vs.140).aspx или здесь: http://professorweb.ru/my/csharp/optimization/level4/4_6.php &amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;br /&gt;
[[en:Description of algorithm properties and structure]]&lt;/div&gt;</summary>
		<author><name>AleksLevin</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:AleksLevin/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%9B%D0%B0%D0%BD%D1%86%D0%BE%D1%88%D0%B0_%D0%B2%D1%8B%D1%87%D0%B8%D1%81%D0%BB%D0%B5%D0%BD%D0%B8%D1%8F_%D1%81%D0%BE%D0%B1%D1%81%D1%82%D0%B2%D0%B5%D0%BD%D0%BD%D1%8B%D1%85_%D0%B7%D0%BD%D0%B0%D1%87%D0%B5%D0%BD%D0%B8%D0%B9_%D1%81%D0%B8%D0%BC%D0%BC%D0%B5%D1%82%D1%80%D0%B8%D1%87%D0%BD%D0%BE%D0%B9_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86%D1%8B_%D0%B4%D0%BB%D1%8F_%D1%82%D0%BE%D1%87%D0%BD%D0%BE%D0%B9_%D0%B0%D1%80%D0%B8%D1%84%D0%BC%D0%B5%D1%82%D0%B8%D0%BA%D0%B8_(%D0%B1%D0%B5%D0%B7_%D0%BF%D0%B5%D1%80%D0%B5%D0%BE%D1%80%D1%82%D0%BE%D0%B3%D0%BE%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D0%B8)&amp;diff=20212</id>
		<title>Участник:AleksLevin/Алгоритм Ланцоша вычисления собственных значений симметричной матрицы для точной арифметики (без переортогонализации)</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:AleksLevin/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%9B%D0%B0%D0%BD%D1%86%D0%BE%D1%88%D0%B0_%D0%B2%D1%8B%D1%87%D0%B8%D1%81%D0%BB%D0%B5%D0%BD%D0%B8%D1%8F_%D1%81%D0%BE%D0%B1%D1%81%D1%82%D0%B2%D0%B5%D0%BD%D0%BD%D1%8B%D1%85_%D0%B7%D0%BD%D0%B0%D1%87%D0%B5%D0%BD%D0%B8%D0%B9_%D1%81%D0%B8%D0%BC%D0%BC%D0%B5%D1%82%D1%80%D0%B8%D1%87%D0%BD%D0%BE%D0%B9_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86%D1%8B_%D0%B4%D0%BB%D1%8F_%D1%82%D0%BE%D1%87%D0%BD%D0%BE%D0%B9_%D0%B0%D1%80%D0%B8%D1%84%D0%BC%D0%B5%D1%82%D0%B8%D0%BA%D0%B8_(%D0%B1%D0%B5%D0%B7_%D0%BF%D0%B5%D1%80%D0%B5%D0%BE%D1%80%D1%82%D0%BE%D0%B3%D0%BE%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D0%B8)&amp;diff=20212"/>
		<updated>2016-12-06T23:44:35Z</updated>

		<summary type="html">&lt;p&gt;AleksLevin: /* Масштабируемость алгоритма и его реализации */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Основные авторы описания: Левин А.Д.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{algorithm&lt;br /&gt;
| name              = Алгоритм Ланцоша для точной арифметики (без переортогонализации)&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(k\,n^2)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(k\log_2 n)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;\frac{n^2+3n}{2} + 1&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;k\;(n + 1)&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритмов =&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Данный алгоритм появился в 1950 г. и носит имя венгерского физика и математика Корнелия Ланцоша (венг. Lánczos Kornél). Алгоритм Ланцоша относится к итерационным методам вычисления собственных значений для матриц столь больших порядков &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt; n&amp;lt;/math&amp;gt;, что к ним нельзя применить прямые методы из-за ограничений по времени и памяти.&lt;br /&gt;
&lt;br /&gt;
Сам Ланцош указывал, что его метод предназначен для отыскания нескольких собственных векторов симметричных матриц, хотя к методу сразу было обращено внимание, как к способу приведения всей матрицы к трёхдиагональному виду. Двадцатью годами позже канадский математик Крис Пэж показал, что, несмотря на чувствительность к округлениям, алгоритм Ланцоша - эффективное средство вычисления некоторых &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; собственных чисел и соответствующих им собственных векторов. &amp;lt;ref&amp;gt;Парлетт Б. - Симметричная проблема собственных значений. Численные методы //М.: Мир. - 1983. (c. 276)&amp;lt;/ref&amp;gt;&lt;br /&gt;
Обычно число &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; берут в два раза больше, чем количество собственных значений матрицы, которые поставлена цель найти, и оно имеет порядок не более &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;10^2&amp;lt;/math&amp;gt;.&amp;lt;ref&amp;gt;Susan W. Bostic - Lanczos Eigensolution Method for High-Perfomance Computers, page 7&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Алгоритм Ланцоша для вычисления собственных значений симметричной матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; соединяет в себе метод Ланцоша для построения последовательности подпространств Крылова и ортонормированных векторов Ланцоша и процедуру Рэлея-Ритца получения оптимальных приближений собственных значений и соответствующих собственных векторов исходной матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt;.&amp;lt;ref&amp;gt;James W. Demmel - Вычислительная линейная алгебра. Теория и приложения //Мир. - 2001 (c. 381)&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
В данной статье рассматривается вариант алгоритма Ланцоша, в котором опущено влияние ошибок округления на вычислительный процесс, хотя на практике этому посвящается отдельное внимание и существуют различные методы решения данной проблемы, такие как частичная или полная переортогонализация. Этим модифицированным методам посвящены отдельные статьи на данном ресурсе.&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
Обозначения и формулы, используемые в данном разделе, взяты из литературы, указанной по ссылке.&amp;lt;ref&amp;gt;James W. Demmel - Вычислительная линейная алгебра. Теория и приложения //Мир. - 2001 (c. 313, &#039;&#039;&amp;lt;math&amp;gt; \S &amp;lt;/math&amp;gt; 6.6 Методы Крыловского подпространства&#039;&#039;)&amp;lt;/ref&amp;gt; &lt;br /&gt;
&lt;br /&gt;
Алгоритм Ланцоша для вычисления &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; собственных значений и собственных векторов вещественной симметричной матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A=A^T&amp;lt;/math&amp;gt; в точной арифметике: &amp;lt;ref&amp;gt;James W. Demmel - Вычислительная линейная алгебра. Теория и приложения //Мир. - 2001 (c. 381)&amp;lt;/ref&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{align}&lt;br /&gt;
q_1 = &amp;amp; \,\frac{b}{\|b\|_2},\; \beta_0 = 0,\; q_0 = 0\\&lt;br /&gt;
\mathbf{for} \; &amp;amp; j = 1 \; to \; k \,\; \mathbf{do} \\&lt;br /&gt;
&amp;amp; z = A\,q_j\\&lt;br /&gt;
&amp;amp; \alpha_j = q^T_j z\\&lt;br /&gt;
&amp;amp; z = z - \alpha_j q_j - \beta_{j-1}q_{j-1}\\&lt;br /&gt;
&amp;amp; \beta_j = \|z\|_2\\&lt;br /&gt;
&amp;amp; \mathbf{If} \; (\beta_j == 0) \; \mathbf{then}\; stop\; the\; algorithm \\ &lt;br /&gt;
&amp;amp; \;  q_{j+1} = \frac{z}{\beta_j} \\&lt;br /&gt;
&amp;amp; compute\; eigenvalues\; and \;eigenvectors\;of \;matrix \;\;T_j= Q^T_j A Q\;\;and\;estimate \;the\; errors\\&lt;br /&gt;
\mathbf{end} \; &amp;amp; \mathbf{for}&lt;br /&gt;
\end{align}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
В продемонстрированном выше алгоритме &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;b&amp;lt;/math&amp;gt; - заданный вещественный вектор. Также полагается известным алгоритм вычисления произведения матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; на вектор &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;x&amp;lt;/math&amp;gt;. &lt;br /&gt;
Введём матрицу Крылова, определяемую следующим соотношением: &amp;lt;math&amp;gt;K_j = [b,Ab,A^2b,...,A^{j-1}b]&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Далее, на практике, матрица &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;K&amp;lt;/math&amp;gt; заменяется матрицей &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;Q&amp;lt;/math&amp;gt;, такой, что при любом числе &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; линейные оболочки первых &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; столбцов в &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;K&amp;lt;/math&amp;gt; и &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;Q&amp;lt;/math&amp;gt; являются одним и тем же подпространством.&amp;lt;ref&amp;gt;James W. Demmel - Вычислительная линейная алгебра. Теория и приложения //Мир. - 2001 (c. 315)&amp;lt;/ref&amp;gt; &lt;br /&gt;
Тогда матрица &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;Q&amp;lt;/math&amp;gt;, в отличие от матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;K&amp;lt;/math&amp;gt;, хорошо обусловлена и легко обратима. В результате получаем матрицу &amp;lt;math&amp;gt;Q_j = [q_1, q_2, \dots, q_j]&amp;lt;/math&amp;gt; размерности &amp;lt;math&amp;gt;n\times j&amp;lt;/math&amp;gt;, столбцы которой ортогональны, являются базисом подпространства Крылова и называются векторами Ланцоша.&lt;br /&gt;
&lt;br /&gt;
В алгоритме Ланцоша вычислению подлежит столько первых столбцов в матрице &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;Q_j&amp;lt;/math&amp;gt;, сколько необходимо для получения требуемого приближения к решению &amp;lt;math&amp;gt;A\,x\,=b\,\,(A\,x=\lambda \, x)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Получение нулевого &amp;lt;math&amp;gt;\beta_j&amp;lt;/math&amp;gt; в итерационном процессе - событие, желательное в том смысле, что оно свидетельствует о том, что найдено некоторое подпространство, являющееся в точности инвариантным, а все собственные значения матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;T_j&amp;lt;/math&amp;gt; являются собственными значениями матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt;. На практике же нулевое и близкие к нулю значения получаются редко.&amp;lt;ref&amp;gt;Голуб Дж., Ван Лоун Ч. - Матричные вычисления//М.: Мир. - 1999 (c. 429)&amp;lt;/ref&amp;gt; &lt;br /&gt;
&lt;br /&gt;
Затем на каждом шаге цикла формируется симметричная трёхдиагональная матрица &amp;lt;math&amp;gt;T_j = Q^T_j A Q&amp;lt;/math&amp;gt;, к которой применяется процесс Рэлея-Ритца для поиска её собственных значений (на практике для поиска этих собственных значений можно использовать любой из специальных методов в параграфе книги по ссылке).&amp;lt;ref&amp;gt;Голуб Дж., Ван Лоун Ч. - Матричные вычисления//М.: Мир. - 1999 (&amp;lt;math&amp;gt;\S&amp;lt;/math&amp;gt; 8.4)&amp;lt;/ref&amp;gt;  &lt;br /&gt;
Эти собственные значения, они же числа Ритца, и полагаются приближёнными собственными значениями исходной матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt;.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Существует множество методов для отыскания собственных значений вещественной симметричной трехдиагональной матрицы. Большинство из них требует &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt; операций &amp;lt;ref&amp;gt;Парлетт Б. Симметричная проблема собственных значений. Численные методы.,: Мир, 1983. с. 179-182&amp;lt;/ref&amp;gt;, но существуют и быстрые алгоритмы, требующие лишь &amp;lt;math&amp;gt;O(n\ln n)&amp;lt;/math&amp;gt; операций.&amp;lt;ref&amp;gt;https://en.wikipedia.org/wiki/Tridiagonal_matrix#Eigenvalues  Раздел eigenvalues&amp;lt;/ref&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Одним из возможных способов отыскать собственные значения симметричной трехдиагональной матрицы - прямое вычисление корней характеристического полинома &amp;lt;math&amp;gt;p_n(\lambda)&amp;lt;/math&amp;gt; через метод деления пополам, где формируется последовательность Штурма и локализуются собственные числа, являющиеся корнями характеристического полинома. Нахождение всех &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; собственных значений матрицы этим способом требует &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;2n^2t&amp;lt;/math&amp;gt; умножений и вычитаний, где &amp;lt;math&amp;gt;t&amp;lt;/math&amp;gt; - число сделанных шагов с применением метода деления пополам.&amp;lt;ref&amp;gt;Уилкинсон Дж. X. Алгебраическая проблема собственныx значений. Изд-во &amp;quot;Наука&amp;quot;, 1970. - глава 5, с. 272-278&amp;lt;/ref&amp;gt; Соответствующие собственные вектора могут быть найдены посредством обратных итераций за &amp;lt;math&amp;gt; O(n) &amp;lt;/math&amp;gt; флопов. &amp;lt;ref&amp;gt;Голуб Дж., Ван Лоун Ч. - Матричные вычисления//М.: Мир. - 1999 (c. 394-395)&amp;lt;/ref&amp;gt; &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;На практике, если требуется только небольшая часть от всей совокупности собственных векторов и значений, и матрица имеет Хессенбергову или трёхдиагональную форму, очень эффективными будут методы факторизации, как, например, QR-алгоритм или QL-алгоритм со сдвигами (c целью ускорить алгоритм и сделать порядок сходимости квадратичным) или же без них.&amp;lt;ref&amp;gt;http://algorithm.narod.ru/ln/eigen/ETridiag.html&amp;lt;/ref&amp;gt; &amp;lt;br&amp;gt;&lt;br /&gt;
Весьма молодые и не менее актуальные конкуренты QR и QL алгоритмов, применяющиеся для поиска собственных значений:&lt;br /&gt;
*Методы divide-and-conquer (разделяй и властвуй), появившиеся в 1980-ых годах &amp;lt;ref&amp;gt;https://goo.gl/dapvbn ссылку пришлось сократить с помощью Google url shortener, так как символы подчеркивания портили её и не давали перейти по 1 клику&amp;lt;/ref&amp;gt;&lt;br /&gt;
*Relatively robust representation методы, появившиеся в 1990-ых и позволяющие найти собственные числа симметричной матрицы порядка &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;n&amp;lt;/math&amp;gt; за &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt; операций&lt;br /&gt;
&lt;br /&gt;
Если требуется вычислить собственные векторы, то необходимо хранить вычисляемые векторы Ланцоша. Если работа при этом производится только с оперативной памятью, то при большом порядке исходной матрицы (а именно для таких матриц и предназначен метод Ланцоша) число шагов  &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;j&amp;lt;/math&amp;gt;, которые могут быть выполнены до того момента, как оперативная память будет исчерпана, будет очень незначительно, а следовательно, искомые собственные пары могут не успеть сойтись с требуемой точностью. В этом случае метод Ланцоша можно использовать итерационным образом: после выполнения заданного числа шагов процесс прерывается и, если еще не все требуемые пары Ритца сошлись с требуемой точностью, то формируется новый начальный вектор &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;q_1&amp;lt;/math&amp;gt;, являющийся линейной комбинацией векторов Ритца, еще не сошедшихся с заданной точностью, и процесс начинается заново.&amp;lt;ref&amp;gt;http://num-anal.srcc.msu.ru/lib_na/int_ae/int_ae6.htm (пункт 6.5)&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
Вычислительное ядро рассматриваемого алгоритма (наиболее ресурсно-затратная часть алгоритма) -  формирование на каждом шаге цикла промежуточного вектора &amp;lt;math&amp;gt;z&amp;lt;/math&amp;gt;, вычисляемого по формуле: &amp;lt;math&amp;gt;z = A\,q_j&amp;lt;/math&amp;gt;. Данная операция, по сравнению с другими операциями алгоритма, затратна и требовательна, как с точки зрения количества производимых операций, так и с точки зрения объема оперируемых данных. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Например, умножение матрицы размера &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;n\times n&amp;lt;/math&amp;gt; на вектор длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; требует: &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;n^2+(n-1)n = 2n^2-n&amp;lt;/math&amp;gt; операций умножения и сложения. В свою очередь аналогичная операция умножения матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;(n+1)\times (n+1)&amp;lt;/math&amp;gt; на вектор длины &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;(n+1)&amp;lt;/math&amp;gt; требует: &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;2n^2+3n+1&amp;lt;/math&amp;gt;  операций умножения и сложения. То есть повышение размерности задачи всего на 1 увеличивает число необходимых действий в этом шаге алгоритма на: &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;4n+1&amp;lt;/math&amp;gt;. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Так же, стоит помнить, что, согласно разделу 1.2, данную операцию умножения матрицы на вектор необходимо выполнить &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;k&amp;lt;/math&amp;gt; раз. Нетрудно понять, насколько возрастает и колоссален масштаб операций, если в задачах, где критична точность, размерности &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; могут иметь порядок &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;10^5&amp;lt;/math&amp;gt; или даже более.&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
Как уже было упомянуто в данной статье в описании алгоритма, рассматриваемый алгоритм состоит из двух последовательно выполненных алгоритмов: метод Ланцоша для построения последовательности подпространств Крылова и ортонормированных векторов Ланцоша и процедура Рэлея-Ритца получения оптимальных приближений собственных значений и соответствующих собственных векторов исходной матрицы.&lt;br /&gt;
&lt;br /&gt;
В первой части алгоритма, где итерационно строятся Крыловское подпространство и трёхдиагональная матрица &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&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 style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; разреженная. Именно она подлежит оптимизации с использованием техник распараллеливания, поскольку она является вычислительным ядром алгоритма, а весь упомянутый процесс построения матрицы &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&amp;lt;/math&amp;gt; выполняется последовательно.&lt;br /&gt;
&lt;br /&gt;
Рассмотрим вторую часть алгоритма - поиск собственных значений сформированной матрицы &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&amp;lt;/math&amp;gt;.&amp;lt;br&amp;gt;&lt;br /&gt;
Далее, наглядно, в виде псевдокода, представлен, упомянутый в разделе 1.2, QR-алгоритм (аналогично можно рассмотреть и QL-алгоритм) со сдвигами Релэя, который весьма популярен на практике.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{align}&lt;br /&gt;
\mathbf{Input}: \;&amp;amp;tridiagonal\;\;matrix \;T\;with\;\;n\times n\;\;size\\&lt;br /&gt;
T^{(0)}&amp;amp;:=T\\&lt;br /&gt;
\mathbf{for}&amp;amp; \;\;m=n,...,2 \;\; \mathbf{do}\\&lt;br /&gt;
&amp;amp;k=0\\&lt;br /&gt;
&amp;amp; \mathbf{repeat}\\&lt;br /&gt;
&amp;amp; \quad \;\; k=k+1\\&lt;br /&gt;
&amp;amp; \quad \;\; \mu^{(k)}=T_{m,m}^{(k-1)}\\&lt;br /&gt;
&amp;amp; \quad \;\; Q^{(k)}R^{(k)}=T^{(k-1)}-\mu^{(k)}I\;\;using\;\;QR\;decomposition\\&lt;br /&gt;
&amp;amp; \quad \;\; T^{(k)}=R^{(k)}Q^{(k)}+\mu^{(k)}I\\&lt;br /&gt;
&amp;amp; \mathbf{until} \;\;\; |T_{m,m-1}^{(k)}| \;is\;\;small\;\;enough\\&lt;br /&gt;
&amp;amp; Save  \;\;T_{m,m}^{(k)} \;\;as\;\; converged\;\;eigenvalue\;of\;T\\ &lt;br /&gt;
&amp;amp; Remove \;\boldsymbol{n}\,th\;row\;and\;\boldsymbol{n}\,th\;column\;\;from \;T \\&lt;br /&gt;
&amp;amp; and\;take\;this\;new\;cropped\;matrix\;as\;new\;T^{(0)}\;with\;\;(n-1)\times (n-1)\;\;size\\&lt;br /&gt;
 \mathbf{end}&amp;amp;\; \mathbf{for}&lt;br /&gt;
\end{align}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Малость наддиагональных и поддиагональных элементов матрицы (фраза &#039;&#039;&amp;quot;small enough&amp;quot;&#039;&#039; в псевдокоде) подразумевает:&lt;br /&gt;
&amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt; |T_{m,m-1}^{(k)}| \leq \varepsilon\,|T_{m,m}^{(k)}| \quad\quad &amp;lt;/math&amp;gt; , где &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt; \varepsilon &amp;lt;/math&amp;gt; - заданная точность&amp;lt;br&amp;gt;&lt;br /&gt;
Также вместо сдвига Релэя, обозначенного в алгоритме через &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;\mu^{(k)}&amp;lt;/math&amp;gt;, часто на практике используется сдвиг по Уилкинсону, который даёт гарантированную сходимость внедиагональных элементов матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt; T^{(k)} &amp;lt;/math&amp;gt;, формируемой на каждом шаге, к нулю, при этом жертвуя монотонностью их убывания.&amp;lt;ref&amp;gt;Голуб Дж., Ван Лоун Ч. - Матричные вычисления//М.: Мир. - 1999 (c. 378, вторая половина страницы)&amp;lt;/ref&amp;gt;&amp;lt;ref&amp;gt;Парлетт Б. Симметричная проблема собственных значений. Численные методы.,: Мир, 1983. с. 169&amp;lt;/ref&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Подробнее с различными сдвигами и соответствующими оценками скоростей и количествами операций можно ознакомиться по указанной ссылке:&amp;lt;ref&amp;gt;Парлетт Б. Симметричная проблема собственных значений. Численные методы.,: Мир, 1983. с. 179-182&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;Для совершения QR-декомпозиции на каждом шаге может использоваться любой из алгоритмов по ссылке.&amp;lt;ref&amp;gt;https://en.wikipedia.org/wiki/QR_decomposition&amp;lt;/ref&amp;gt; Подробные описания этих алгоритмов также доступны на данном ресурсе algowiki-project.&amp;lt;br&amp;gt;&lt;br /&gt;
Так как мы оперируем не обычной матрицей и даже не Хессенберговой, а симметричной и трёхдиагональной, то скорость таких алгоритмов значительно возрастёт. Например, согласно данному ресурсу &amp;lt;ref&amp;gt;http://algorithm.narod.ru/ln/eigen/ETridiag.html&amp;lt;/ref&amp;gt;, для QL-алгоритма с неявными сдвигами:&amp;lt;br&amp;gt;&lt;br /&gt;
Для трёхдиагональной матрицы объем арифметических действий составляет &amp;lt;math&amp;gt; O(n)&amp;lt;/math&amp;gt; на одну итерацию вместо &amp;lt;math&amp;gt; O(n^3)&amp;lt;/math&amp;gt; для матрицы общего вида, а число итераций для нахождения первых собственных значений примерно равно 4 - 5. Но на этих итерациях также уменьшаются внедиагональные элементы правого нижнего угла. И, таким образом, дальнейшие собственные значения ищутся значительно быстрее. Среднее число итераций на каждое собственное значение обычно составляет 1.3 - 1.6.&amp;lt;br&amp;gt; &lt;br /&gt;
Аналогично QL, QR-разложение трёхдиагольной матрицы также требует &amp;lt;math&amp;gt; O(n)&amp;lt;/math&amp;gt; флопов&amp;lt;ref&amp;gt;Голуб Дж., Ван Лоун Ч. - Матричные вычисления//М.: Мир. - 1999 (c. 378, начало раздела 8.2.2)&amp;lt;/ref&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Подводя итог, во второй части алгоритма Ланцоша можно выделить следующие макрооперации:&lt;br /&gt;
* умножение матрицы на вещественное число;&lt;br /&gt;
* перемножение матриц;&lt;br /&gt;
* умножение и сравнение вещественных чисел;&lt;br /&gt;
* + набор других макроопераций в зависимости от выбора метода, с помощью которого будет совершаться сама QR или QL-декомпозиция (выше продемонстрированы, уже, как минимум, 3 разных способа).&lt;br /&gt;
Так же, важно заметить, что набор макропераций может быть несколько другим, если выбрать какой-либо иной современный метод поиска собственных чисел трёхдиагональной матрицы, не использующий QR и QL разложения(факторизацию). Два таких метода были упомянуты в пункте 1.2.&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
С целью полностью не дублировать раздел 1.2 данной статьи, где представлен наглядный и доступный для понимания псевдокод алгоритма, постараемся лишь коротко просуммировать и обобщить весь перечень последовательных действий в рассматриваемом алгоритме.&lt;br /&gt;
&lt;br /&gt;
В качестве входных данных имеем: вещественная симметричная матрица &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; размера &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;n\times n&amp;lt;/math&amp;gt;, известный вещественный вектор &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;b&amp;lt;/math&amp;gt; длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; и число &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;n&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Далее:&lt;br /&gt;
* Инициализируем вещественную константу &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;\beta_0&amp;lt;/math&amp;gt; и векторы &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;q_0&amp;lt;/math&amp;gt; и &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;q_1&amp;lt;/math&amp;gt;&lt;br /&gt;
* Итерационно для всех &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j=1,...,k&amp;lt;/math&amp;gt;:&lt;br /&gt;
** Вычисляем вспомогательный вектор &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt;, используя умножение матрицы на вектор&lt;br /&gt;
** Вычисляем, используя скалярное произведение векторов, значение &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;\alpha_j&amp;lt;/math&amp;gt; - элемент на главной диагонали трёхдиагональной матрицы &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&amp;lt;/math&amp;gt;&lt;br /&gt;
** Вычисляем по формуле новое значение и перезаписываем вектор &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt;&lt;br /&gt;
** Вычисляем значение &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;\beta_j&amp;lt;/math&amp;gt; - элементы непосредственно над и под главной диагональю той же матрицы &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&amp;lt;/math&amp;gt;&lt;br /&gt;
** Вычисляем, зная вектор &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt;,  очередной столбец матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;Q&amp;lt;/math&amp;gt;, он же вектор Ланцоша : &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;\,\,q_{j+1}&amp;lt;/math&amp;gt;&lt;br /&gt;
** Теперь, когда матрица &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&amp;lt;/math&amp;gt; сформирована на очередном шаге, находим её собственные значения и вектора любым доступным способом, о чём было подробно сказано в пункте 1.2&lt;br /&gt;
** Переходим на следующую итерацию: &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j&amp;lt;/math&amp;gt;++&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
Оценим количество операций и сложность последовательного алгоритма, изложенного в предыдущем разделе.&lt;br /&gt;
*Для вычисления вектора &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt; умножается матрица размера &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;n\times n&amp;lt;/math&amp;gt; на вектор длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt;, и потребуется &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n^2&amp;lt;/math&amp;gt; операций умножения и &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n^2&amp;lt;/math&amp;gt; операций сложения.&lt;br /&gt;
*Умножение векторов &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;q^T_j&amp;lt;/math&amp;gt; и &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt; длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; потребует &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; операций умножения и &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; операций сложения.&lt;br /&gt;
*При вычислении нового значения вектора &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt; поэлементное сложение двух векторов длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; требует &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; операций сложения.&lt;br /&gt;
*Умножение вектора длины &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; на вещественное число требует &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; операций умножения.&lt;br /&gt;
*Нахождение квадратичной нормы вектора &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt;  длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; требует &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; умножений и &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; сложений и ещё 1 операцию извлечения квадратного корня.&lt;br /&gt;
*Заключительное нахождение собственных значений и собственных векторов трёхдиагональной матрицы &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;T_j&amp;lt;/math&amp;gt; размера &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j\times j&amp;lt;/math&amp;gt; с помощью QR-алгоритма потребует в худшем случае &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(j^3)&amp;lt;/math&amp;gt; операций.&amp;lt;ref&amp;gt;http://num-anal.srcc.msu.ru/lib_na/int_ae/int_ae6.htm (пункт 6.2, &amp;quot;Скорость сходимости при этом всегда не хуже квадратичной и почти всегда лучше кубической.&amp;quot;)&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Посчитаем теперь суммарное количество простейших операций на одной итерации алгоритма (без учёта записей в память):&lt;br /&gt;
*&amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n^2+5\,n&amp;lt;/math&amp;gt; операций умножения/деления&lt;br /&gt;
*&amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n^2+4\,n&amp;lt;/math&amp;gt; операций сложения/вычитания&lt;br /&gt;
*1 операция извлечения квадратного корня&amp;lt;br&amp;gt;&lt;br /&gt;
Отдельно после всех итераций при &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j=k&amp;lt;/math&amp;gt; :&lt;br /&gt;
*&amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(k^3)&amp;lt;/math&amp;gt; операций для поиска собственных значений и собственных векторов трёхдиагональной матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_k&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Итого можно утверждать следующее:&lt;br /&gt;
&lt;br /&gt;
Последовательная сложность одной итерации рассматриваемого алгоритма:  &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(n ^ 2) &amp;lt;/math&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Суммарная сложность алгоритма (&amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;/math&amp;gt; итераций): &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(k\,n ^ 2) + O(k ^ 3)&amp;lt;/math&amp;gt; &amp;lt;ref&amp;gt;Здесь мы полагаем, что мы не вычисляем собственные значения и векторы матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_j&amp;lt;/math&amp;gt; на каждом промежуточном шаге, а лишь единожды затрачиваем &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;O(k ^ 3)&amp;lt;/math&amp;gt; действий в конце для нахождения &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;/math&amp;gt; собственных значений и векторов матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_k&amp;lt;/math&amp;gt;&amp;lt;/ref&amp;gt; &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
На практике же обычно рассматривается число &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;&amp;lt;n&amp;lt;/math&amp;gt;, поэтому второе слагаемое можно опустить.&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
На рис. 1 продемонстрирован граф одной итерации (при каком-либо произвольном значении итератора &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j&amp;lt;/math&amp;gt;) описанного алгоритма без отображения входных и выходных данных. Наглядно продемонстрированы связи между всеми действиями, и с помощью деления на &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; потоков показано, какие операции возможно выполнять параллельно на каждом шаге с целью оптимизации и экономии машинного времени. В результате, после параллельно выполненных операций &#039;&#039;&#039;Division&#039;&#039;&#039; на заключительном ярусе, на выходе имеем значение следующего вектора Ланцоша &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;q_{j+1}&amp;lt;/math&amp;gt;, после чего следует переход на следующую итерацию, и процесс повторяется.&lt;br /&gt;
&lt;br /&gt;
[[Файл:Levin_graph.png|600px|thumb|center|Рис. 1]] &amp;lt;br&amp;gt;&lt;br /&gt;
Обозначения на рисунке: &amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Simp&#039;&#039;&#039; (от англ. simple) - операции сложения и умножения вещественных чисел при вычислении произведения матрицы на вектор;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Vec mult&#039;&#039;&#039; (от англ. vectors multiplication) - операция скалярного умножения двух векторов;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Vec subtr&#039;&#039;&#039; (от англ. vectors subtraction, из-за использованных в операции вычитаний векторов) - операция умножения вектора на число (выполняется дважды) и формирование нового значения &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;z_{new}&amp;lt;/math&amp;gt; по формуле: &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;z_{new} = z - \alpha_j q_j - \beta_{j-1}q_{j-1} \;&amp;lt;/math&amp;gt;;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;||\cdot||&amp;lt;/math&amp;gt; - операция вычисления нормы вектора;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Division&#039;&#039;&#039; - операция деления вектора на вещественное число  &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;\beta_j&amp;lt;/math&amp;gt; &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Важно отметить, что упомянутые выше операции также легко поддаются оптимизации. Например, попарные умножения вещественных координат векторов при вычислении скалярного произведения также легко выполняются параллельно на &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; потоках, а затем можно применить суммирование методом сдваивания, о котором сказано в следующем разделе. Умножение или деление вектора на вещественное число являющееся, по определению, умножением или делением всех его координат на это число тоже может быть выполнено эффективнее, если мы используем &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; потоков, а не выполняем эти действия последовательно.&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
Параллельные операции возможны только внутри итераций, так как рассматриваемый алгоритм является итерационным, и сами итерации строго последовательны.&amp;lt;br&amp;gt;&lt;br /&gt;
Рассмотрим в этом разделе подробнее, какой выигрыш мы можем получить при распараллеливании операций внутри одной итерации согласно графу из предыдущего раздела.&lt;br /&gt;
&lt;br /&gt;
Умножение вещественной симметричной матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; размера &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;n\times n&amp;lt;/math&amp;gt; на вектор &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;b&amp;lt;/math&amp;gt; длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; требует последовательного выполнения &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; ярусов умножений и сложений. Сложение элементов вектора длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; на каждом шаге перемножения можно оптимизировать и выполнить за &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;\log_2 n&amp;lt;/math&amp;gt; действий, если применять метод сдваивания.&lt;br /&gt;
&lt;br /&gt;
Дальнейшие операции выполняются последовательно, а вычисление значений векторов происходит за один ярус операций сложения или умножения.&lt;br /&gt;
&lt;br /&gt;
Ресурс параллелизма алгоритма вычисления собственных значений построенной трёхдиагональной матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_k&amp;lt;/math&amp;gt; размера &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k\times k&amp;lt;/math&amp;gt; зависит от выбранного алгоритма (об этих алгоритмах подробнее было сказано в разделах 1.2 и 1.4). Будет очень затратно с точки зрения объёма материала пытаться рассмотреть пусть даже часть этих методов в этой статье, а так же тонкости их распараллеливания. Предлагаем читателям при желании самим ознакомиться с этими алгоритмами на данном ресурсе или прибегнув к иным источникам.&lt;br /&gt;
&lt;br /&gt;
При классификации по высоте ЯПФ, таким образом, алгоритм Ланцоша без переортогонализации относится к алгоритмам с &#039;&#039;логарифмической сложностью&#039;&#039;, и его сложность равна &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(\log_2 n)&amp;lt;/math&amp;gt; с важным замечанием, что это сложность только одной итерации, а максимум в алгоритме может быть выполнено последовательно &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;/math&amp;gt; таких однотипных итераций, если не будет осуществлён ранний выход из цикла. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Несмотря на то, что на графе в предыдущем разделе для лучшей визуализации и понимания было изображено &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; потоков (никаких допущений мы не делали и нарушений с точки зрения логики и математики нет, можно изобразить большее число потоков, просто часть времени некоторые из них могут бездействовать и не использоваться), на самом деле правильным и разумным будет реализовать начальное параллельное выполнение &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n^2&amp;lt;/math&amp;gt; операций умножения всех вещественных элементов матрицы &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;A&amp;lt;/math&amp;gt; на соответствующие элементы вектора &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;q_j&amp;lt;/math&amp;gt;, после чего применять тот же самый упомянутый метод сдваивания. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Поэтому при классификации по ширине ЯПФ его сложность будет &#039;&#039;квадратичной&#039;&#039; и равна &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(n^2)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
&#039;&#039;&#039;Входные данные алгоритма:&#039;&#039;&#039; вещественная симметричная &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; размера &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;n\times n&amp;lt;/math&amp;gt;, вещественный вектор &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;b&amp;lt;/math&amp;gt; длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt;, и одно целое число &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;k&amp;lt;/math&amp;gt;, означающее количество итераций.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём входных данных:&#039;&#039;&#039; &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;n^2 +n + 1 &amp;lt;/math&amp;gt;. Если учесть, что матрица симметричная и достаточно для её однозначного определения задать элементы на главной диагонали и элементы над или под ней, то можно сократить объём входных данных с целью экономии памяти до: &amp;lt;math&amp;gt;\ \frac{n^2-n}{2}+n+n+1 =\frac{n^2+3n}{2} + 1&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные алгоритма:&#039;&#039;&#039; вектор собственных значений &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;\Theta^k&amp;lt;/math&amp;gt; длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;/math&amp;gt;, матрица &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;S^k&amp;lt;/math&amp;gt; из соответствующих собственных векторов размера &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n\times k&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём выходных данных:&#039;&#039;&#039; &amp;lt;math&amp;gt;k\;(n + 1)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
В данном разделе перечислены без какой-либо хронологии или связи друг с другом наиболее важные и разнообразные свойства алгоритма, на которые стоит и полезно обратить внимание, а также которые выгодно отличают его от схожих алгоритмов, решающих ту же задачу.&amp;lt;br&amp;gt;&lt;br /&gt;
1) Отношение последовательной сложности алгоритма к параллельной,с учётом &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;/math&amp;gt; итераций, равно &amp;lt;math&amp;gt;\;\;\frac{kn^2}{k \log_2{n}}=\frac{n^2}{\log_2{n}}&amp;lt;/math&amp;gt;;&amp;lt;br&amp;gt;&lt;br /&gt;
2) Вычислительная мощность алгоритма, как отношение числа операций к суммарному объему входных и выходных данных, равна &amp;lt;math style=&amp;quot;vertical-align:-70%&amp;gt;\;\;\frac{k\,n^2}{0.5\,n^2+1.5\,n+k\,n+k+1}&amp;lt;/math&amp;gt; и &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;\approx 2\,k&amp;lt;/math&amp;gt;, так как на практике верно отношение &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;&amp;lt;n&amp;lt;/math&amp;gt; ;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
3) Для собственных значений формируемых матриц &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_j&amp;lt;/math&amp;gt; верно отношение (следствие теоремы Коши о перемежаемости): &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;\lambda_i(T_{k+1})\geq \lambda_i(T_{k})\geq \lambda_{i+1}(T_{k+1})\geq \lambda_{i+1}(T_{k})&amp;lt;/math&amp;gt; ;&amp;lt;ref&amp;gt;James W. Demmel - Вычислительная линейная алгебра. Теория и приложения //Мир. - 2001 (c. 383)&amp;lt;/ref&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
4) Крайние (наибольшие и наименьшие) собственные значения матриц &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_j&amp;lt;/math&amp;gt; сходятся к крайним собственным значениям матрицы &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;A&amp;lt;/math&amp;gt; первыми (это часто происходит уже на ранних шагах при &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j\approx 2\,\sqrt{n}&amp;lt;/math&amp;gt;&amp;lt;ref&amp;gt;http://num-anal.srcc.msu.ru/lib_na/int_ae/int_ae6.htm (пункт 6.5)&amp;lt;/ref&amp;gt;), а собственные значения в середине спектра - последними;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
5) Из-за ограниченной точности постепенно теряется ортогональность вектора Ланцоша &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;q_j&amp;lt;/math&amp;gt; к предыдущим векторам Ланцоша, поэтому необходимо примерно каждые 10-15 итераций проводить дорогостоящую операцию реортогонализации, но это уже будет иной алгоритм с очень малым различием в одной операции и в программном коде, реализующем его, соответственно; &amp;lt;ref&amp;gt;Sam Handler - The Lanczos Algorithm For Large-Scale Eigenvalue Problems (08.01.07), slide №8&amp;lt;/ref&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
6) Эффективность и быстрота выполнения алгоритма очень сильно зависит от скорости памяти (диска). Согласно тесту только &#039;&#039;6%&#039;&#039; времени работы программы приходится на вычисления, остальное время затрачивается на ожидание отклика диска;&amp;lt;ref&amp;gt;Sam Handler - The Lanczos Algorithm For Large-Scale Eigenvalue Problems (08.01.07), slide №10&amp;lt;/ref&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
7) Метод Ланцоша удобен тем, что не требует хранения исходной матрицы полным массивом: метод использует исходную матрицу только в операциях умножения матрицы на вектор, что позволяет эффективно использовать разреженность матрицы или регулярность структуры матрицы. Поэтому метод Ланцоша может быть использован для матриц таких больших порядков, когда методы вращений и отражений не могут быть применены.&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;
Для исследования масштабируемости рассматриваемого алгоритма Ланцоша без переортогонализации автором была реализована программа на языке С++ с использованием технологии MPI (&#039;&#039;&#039;не забыть вставить ссылку на код&#039;&#039;&#039;). Дальнейшее исследование выполнялось на суперкомпьютере &amp;quot;Ломоносов&amp;quot; Суперкомпьютерного комплекса МГУ. &amp;lt;br&amp;gt; Важно отметить, что реализованная программа выполняет только первую часть алгоритма - формирование матрицы &amp;lt;math &amp;gt;T_j&amp;lt;/math&amp;gt;. Вторая часть алгоритма (задача поиска собственных значений матрицы &amp;lt;math &amp;gt;T_j&amp;lt;/math&amp;gt;) может быть решена несколькими методами, каждый из которых обладает своей эффективностью распараллеливании и характерными свойствами. Подробно этот вопрос уже обсуждался в статье раннее, поэтому не будем ещё раз заострять на этом внимание и останавливаться.&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Сборка осуществлялась со следующими параметрами:&lt;br /&gt;
* Компилятор intel/15.0.090 &lt;br /&gt;
* Openmpi/1.8.4-icc&lt;br /&gt;
В серии проведённых расчётов рассматривались следующие числовые значения параметров:&lt;br /&gt;
* Размер &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;n&amp;lt;/math&amp;gt; задачи и, соответственно, матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt;, задействованной в операции умножения на вектор: [2000 : 30000] с шагом 1000&lt;br /&gt;
* Число процессоров: 1, 2, 4, 16, 32, 48, 64, 96, 128&lt;br /&gt;
* Число итераций в алгоритме: &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k=350&amp;lt;/math&amp;gt;&lt;br /&gt;
Число &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; взято таким вопреки информации в начале статьи, где говорится, что значение &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; редко превышает &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;10^2&amp;lt;/math&amp;gt; (хоть мы и имеем право брать его любым по нашему усмотрению). Это сделано исключительно для лучшей визуализации пиков на графиках в данном разделе и наглядности получаемых результатов, так как при меньших на порядок значениях &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; времена выполнения программ были слишком малы даже при минимальных числах процессоров и максимальных размерах исходной задачи.&lt;br /&gt;
&lt;br /&gt;
== Динамические характеристики и эффективность реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Выводы для классов архитектур ==&lt;br /&gt;
По заданию, во второй части требовалось описать только разделы 2.4 и 2.7, прошу не спрашивать с меня все разделы 2.1-2.6. Надеюсь на понимание, мне физически не хватает времени на это задание + 2 других в течение семестра, делаю всё, что в моих силах :)&lt;br /&gt;
&lt;br /&gt;
== Существующие реализации алгоритма ==&lt;br /&gt;
Несмотря на то, что алгоритм является далеко не самым популярным, алгоритмом, про который нельзя сказать, что он всегда «на слуху», на сегодняшний день существует множество реализаций на различных популярных языках.&amp;lt;br&amp;gt;&lt;br /&gt;
Перечислим далее некоторые из них, указывая язык программирования, лежащий в их основе, и некоторые важные характеристики, которые обсуждались в статье ранее:&lt;br /&gt;
*&#039;&#039;Code on netlib.org by Jane Cullum and Ralph Willoughby&#039;&#039; (&#039;&#039;&#039;Fortran 77&#039;&#039;&#039;; без реортогонализации векторов; без реализации распараллеливания)&amp;lt;ref&amp;gt;http://www.netlib.org/lanczos/leval&amp;lt;/ref&amp;gt;&lt;br /&gt;
*&#039;&#039;Lanczos algorithm on freesourcecode.net&#039;&#039; (&#039;&#039;&#039;Matlab&#039;&#039;&#039;; присутствует реортогонализация векторов; без реализации распараллеливания)&amp;lt;ref&amp;gt;http://freesourcecode.net/matlabprojects/61741/lanczos-algorithm--in-matlab&amp;lt;/ref&amp;gt;&lt;br /&gt;
*&#039;&#039;Lanczos for eigenvalues in Numerical Linear Algebra, Spring 2007&#039;&#039; (&#039;&#039;&#039;Matlab&#039;&#039;&#039;; частичная или полная реортогонализация - доступны оба варианта; без реализации распараллеливания)&amp;lt;ref&amp;gt;Ссылки на файлы lanso.m и lanfu.m можно найти на https://www.nada.kth.se/~ruhe/2D5219/labs2007.html&amp;lt;/ref&amp;gt;&lt;br /&gt;
*&#039;&#039;Planso&#039;&#039; (название происходит от parallel Lanso.f) &#039;&#039;code by Kesheng Wu and Horst D. Simon&#039;&#039; (&#039;&#039;&#039;Fortran 77&#039;&#039;&#039;; частичная реортогонализация векторов; использование MPI для коммуникаций)&amp;lt;ref&amp;gt;https://github.com/jiahao/planso.jl/tree/master/external/PLAN/plan К сожалению, ссылка в описании пакета на github, ведущая на сайт National Energy Research Scientific Computing Center (NERSC), с более подробной информацией о данной программе больше не активна и выдаёт результат &#039;&#039;Page not found&#039;&#039;&amp;lt;/ref&amp;gt; &lt;br /&gt;
* &#039;&#039;Lanczos.cpp in the Vienna Computing Library&#039;&#039;  (&#039;&#039;&#039;C++&#039;&#039;&#039;, частичная реортогонализация, без реализации распараллеливания) &amp;lt;ref&amp;gt;http://viennacl.sourceforge.net/doc/lanczos_8cpp_source.html&amp;lt;/ref&amp;gt;&lt;br /&gt;
* &#039;&#039;Parallel Eigen Values code using C++ AMP on microsoft msdn blog&#039;&#039; (&#039;&#039;&#039;C++&#039;&#039;&#039;; ? ; распараллеливание есть и реализовано через C++ AMP) &amp;lt;ref&amp;gt;https://blogs.msdn.microsoft.com/nativeconcurrency/2013/12/20/eigen-values/ Подробнее о C++ Accelerated Massive Parallelism можно почитать здесь: https://msdn.microsoft.com/ru-ru/library/hh265137(v=vs.140).aspx или здесь: http://professorweb.ru/my/csharp/optimization/level4/4_6.php &amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;br /&gt;
[[en:Description of algorithm properties and structure]]&lt;/div&gt;</summary>
		<author><name>AleksLevin</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:AleksLevin/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%9B%D0%B0%D0%BD%D1%86%D0%BE%D1%88%D0%B0_%D0%B2%D1%8B%D1%87%D0%B8%D1%81%D0%BB%D0%B5%D0%BD%D0%B8%D1%8F_%D1%81%D0%BE%D0%B1%D1%81%D1%82%D0%B2%D0%B5%D0%BD%D0%BD%D1%8B%D1%85_%D0%B7%D0%BD%D0%B0%D1%87%D0%B5%D0%BD%D0%B8%D0%B9_%D1%81%D0%B8%D0%BC%D0%BC%D0%B5%D1%82%D1%80%D0%B8%D1%87%D0%BD%D0%BE%D0%B9_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86%D1%8B_%D0%B4%D0%BB%D1%8F_%D1%82%D0%BE%D1%87%D0%BD%D0%BE%D0%B9_%D0%B0%D1%80%D0%B8%D1%84%D0%BC%D0%B5%D1%82%D0%B8%D0%BA%D0%B8_(%D0%B1%D0%B5%D0%B7_%D0%BF%D0%B5%D1%80%D0%B5%D0%BE%D1%80%D1%82%D0%BE%D0%B3%D0%BE%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D0%B8)&amp;diff=20210</id>
		<title>Участник:AleksLevin/Алгоритм Ланцоша вычисления собственных значений симметричной матрицы для точной арифметики (без переортогонализации)</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:AleksLevin/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%9B%D0%B0%D0%BD%D1%86%D0%BE%D1%88%D0%B0_%D0%B2%D1%8B%D1%87%D0%B8%D1%81%D0%BB%D0%B5%D0%BD%D0%B8%D1%8F_%D1%81%D0%BE%D0%B1%D1%81%D1%82%D0%B2%D0%B5%D0%BD%D0%BD%D1%8B%D1%85_%D0%B7%D0%BD%D0%B0%D1%87%D0%B5%D0%BD%D0%B8%D0%B9_%D1%81%D0%B8%D0%BC%D0%BC%D0%B5%D1%82%D1%80%D0%B8%D1%87%D0%BD%D0%BE%D0%B9_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86%D1%8B_%D0%B4%D0%BB%D1%8F_%D1%82%D0%BE%D1%87%D0%BD%D0%BE%D0%B9_%D0%B0%D1%80%D0%B8%D1%84%D0%BC%D0%B5%D1%82%D0%B8%D0%BA%D0%B8_(%D0%B1%D0%B5%D0%B7_%D0%BF%D0%B5%D1%80%D0%B5%D0%BE%D1%80%D1%82%D0%BE%D0%B3%D0%BE%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D0%B8)&amp;diff=20210"/>
		<updated>2016-12-06T21:53:30Z</updated>

		<summary type="html">&lt;p&gt;AleksLevin: /* Масштабируемость алгоритма и его реализации */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Основные авторы описания: Левин А.Д.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{algorithm&lt;br /&gt;
| name              = Алгоритм Ланцоша для точной арифметики (без переортогонализации)&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(k\,n^2)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(k\log_2 n)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;\frac{n^2+3n}{2} + 1&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;k\;(n + 1)&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритмов =&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Данный алгоритм появился в 1950 г. и носит имя венгерского физика и математика Корнелия Ланцоша (венг. Lánczos Kornél). Алгоритм Ланцоша относится к итерационным методам вычисления собственных значений для матриц столь больших порядков &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt; n&amp;lt;/math&amp;gt;, что к ним нельзя применить прямые методы из-за ограничений по времени и памяти.&lt;br /&gt;
&lt;br /&gt;
Сам Ланцош указывал, что его метод предназначен для отыскания нескольких собственных векторов симметричных матриц, хотя к методу сразу было обращено внимание, как к способу приведения всей матрицы к трёхдиагональному виду. Двадцатью годами позже канадский математик Крис Пэж показал, что, несмотря на чувствительность к округлениям, алгоритм Ланцоша - эффективное средство вычисления некоторых &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; собственных чисел и соответствующих им собственных векторов. &amp;lt;ref&amp;gt;Парлетт Б. - Симметричная проблема собственных значений. Численные методы //М.: Мир. - 1983. (c. 276)&amp;lt;/ref&amp;gt;&lt;br /&gt;
Обычно число &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; берут в два раза больше, чем количество собственных значений матрицы, которые поставлена цель найти, и оно имеет порядок не более &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;10^2&amp;lt;/math&amp;gt;.&amp;lt;ref&amp;gt;Susan W. Bostic - Lanczos Eigensolution Method for High-Perfomance Computers, page 7&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Алгоритм Ланцоша для вычисления собственных значений симметричной матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; соединяет в себе метод Ланцоша для построения последовательности подпространств Крылова и ортонормированных векторов Ланцоша и процедуру Рэлея-Ритца получения оптимальных приближений собственных значений и соответствующих собственных векторов исходной матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt;.&amp;lt;ref&amp;gt;James W. Demmel - Вычислительная линейная алгебра. Теория и приложения //Мир. - 2001 (c. 381)&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
В данной статье рассматривается вариант алгоритма Ланцоша, в котором опущено влияние ошибок округления на вычислительный процесс, хотя на практике этому посвящается отдельное внимание и существуют различные методы решения данной проблемы, такие как частичная или полная переортогонализация. Этим модифицированным методам посвящены отдельные статьи на данном ресурсе.&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
Обозначения и формулы, используемые в данном разделе, взяты из литературы, указанной по ссылке.&amp;lt;ref&amp;gt;James W. Demmel - Вычислительная линейная алгебра. Теория и приложения //Мир. - 2001 (c. 313, &#039;&#039;&amp;lt;math&amp;gt; \S &amp;lt;/math&amp;gt; 6.6 Методы Крыловского подпространства&#039;&#039;)&amp;lt;/ref&amp;gt; &lt;br /&gt;
&lt;br /&gt;
Алгоритм Ланцоша для вычисления &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; собственных значений и собственных векторов вещественной симметричной матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A=A^T&amp;lt;/math&amp;gt; в точной арифметике: &amp;lt;ref&amp;gt;James W. Demmel - Вычислительная линейная алгебра. Теория и приложения //Мир. - 2001 (c. 381)&amp;lt;/ref&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{align}&lt;br /&gt;
q_1 = &amp;amp; \,\frac{b}{\|b\|_2},\; \beta_0 = 0,\; q_0 = 0\\&lt;br /&gt;
\mathbf{for} \; &amp;amp; j = 1 \; to \; k \,\; \mathbf{do} \\&lt;br /&gt;
&amp;amp; z = A\,q_j\\&lt;br /&gt;
&amp;amp; \alpha_j = q^T_j z\\&lt;br /&gt;
&amp;amp; z = z - \alpha_j q_j - \beta_{j-1}q_{j-1}\\&lt;br /&gt;
&amp;amp; \beta_j = \|z\|_2\\&lt;br /&gt;
&amp;amp; \mathbf{If} \; (\beta_j == 0) \; \mathbf{then}\; stop\; the\; algorithm \\ &lt;br /&gt;
&amp;amp; \;  q_{j+1} = \frac{z}{\beta_j} \\&lt;br /&gt;
&amp;amp; compute\; eigenvalues\; and \;eigenvectors\;of \;matrix \;\;T_j= Q^T_j A Q\;\;and\;estimate \;the\; errors\\&lt;br /&gt;
\mathbf{end} \; &amp;amp; \mathbf{for}&lt;br /&gt;
\end{align}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
В продемонстрированном выше алгоритме &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;b&amp;lt;/math&amp;gt; - заданный вещественный вектор. Также полагается известным алгоритм вычисления произведения матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; на вектор &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;x&amp;lt;/math&amp;gt;. &lt;br /&gt;
Введём матрицу Крылова, определяемую следующим соотношением: &amp;lt;math&amp;gt;K_j = [b,Ab,A^2b,...,A^{j-1}b]&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Далее, на практике, матрица &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;K&amp;lt;/math&amp;gt; заменяется матрицей &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;Q&amp;lt;/math&amp;gt;, такой, что при любом числе &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; линейные оболочки первых &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; столбцов в &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;K&amp;lt;/math&amp;gt; и &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;Q&amp;lt;/math&amp;gt; являются одним и тем же подпространством.&amp;lt;ref&amp;gt;James W. Demmel - Вычислительная линейная алгебра. Теория и приложения //Мир. - 2001 (c. 315)&amp;lt;/ref&amp;gt; &lt;br /&gt;
Тогда матрица &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;Q&amp;lt;/math&amp;gt;, в отличие от матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;K&amp;lt;/math&amp;gt;, хорошо обусловлена и легко обратима. В результате получаем матрицу &amp;lt;math&amp;gt;Q_j = [q_1, q_2, \dots, q_j]&amp;lt;/math&amp;gt; размерности &amp;lt;math&amp;gt;n\times j&amp;lt;/math&amp;gt;, столбцы которой ортогональны, являются базисом подпространства Крылова и называются векторами Ланцоша.&lt;br /&gt;
&lt;br /&gt;
В алгоритме Ланцоша вычислению подлежит столько первых столбцов в матрице &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;Q_j&amp;lt;/math&amp;gt;, сколько необходимо для получения требуемого приближения к решению &amp;lt;math&amp;gt;A\,x\,=b\,\,(A\,x=\lambda \, x)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Получение нулевого &amp;lt;math&amp;gt;\beta_j&amp;lt;/math&amp;gt; в итерационном процессе - событие, желательное в том смысле, что оно свидетельствует о том, что найдено некоторое подпространство, являющееся в точности инвариантным, а все собственные значения матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;T_j&amp;lt;/math&amp;gt; являются собственными значениями матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt;. На практике же нулевое и близкие к нулю значения получаются редко.&amp;lt;ref&amp;gt;Голуб Дж., Ван Лоун Ч. - Матричные вычисления//М.: Мир. - 1999 (c. 429)&amp;lt;/ref&amp;gt; &lt;br /&gt;
&lt;br /&gt;
Затем на каждом шаге цикла формируется симметричная трёхдиагональная матрица &amp;lt;math&amp;gt;T_j = Q^T_j A Q&amp;lt;/math&amp;gt;, к которой применяется процесс Рэлея-Ритца для поиска её собственных значений (на практике для поиска этих собственных значений можно использовать любой из специальных методов в параграфе книги по ссылке).&amp;lt;ref&amp;gt;Голуб Дж., Ван Лоун Ч. - Матричные вычисления//М.: Мир. - 1999 (&amp;lt;math&amp;gt;\S&amp;lt;/math&amp;gt; 8.4)&amp;lt;/ref&amp;gt;  &lt;br /&gt;
Эти собственные значения, они же числа Ритца, и полагаются приближёнными собственными значениями исходной матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt;.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Существует множество методов для отыскания собственных значений вещественной симметричной трехдиагональной матрицы. Большинство из них требует &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt; операций &amp;lt;ref&amp;gt;Парлетт Б. Симметричная проблема собственных значений. Численные методы.,: Мир, 1983. с. 179-182&amp;lt;/ref&amp;gt;, но существуют и быстрые алгоритмы, требующие лишь &amp;lt;math&amp;gt;O(n\ln n)&amp;lt;/math&amp;gt; операций.&amp;lt;ref&amp;gt;https://en.wikipedia.org/wiki/Tridiagonal_matrix#Eigenvalues  Раздел eigenvalues&amp;lt;/ref&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Одним из возможных способов отыскать собственные значения симметричной трехдиагональной матрицы - прямое вычисление корней характеристического полинома &amp;lt;math&amp;gt;p_n(\lambda)&amp;lt;/math&amp;gt; через метод деления пополам, где формируется последовательность Штурма и локализуются собственные числа, являющиеся корнями характеристического полинома. Нахождение всех &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; собственных значений матрицы этим способом требует &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;2n^2t&amp;lt;/math&amp;gt; умножений и вычитаний, где &amp;lt;math&amp;gt;t&amp;lt;/math&amp;gt; - число сделанных шагов с применением метода деления пополам.&amp;lt;ref&amp;gt;Уилкинсон Дж. X. Алгебраическая проблема собственныx значений. Изд-во &amp;quot;Наука&amp;quot;, 1970. - глава 5, с. 272-278&amp;lt;/ref&amp;gt; Соответствующие собственные вектора могут быть найдены посредством обратных итераций за &amp;lt;math&amp;gt; O(n) &amp;lt;/math&amp;gt; флопов. &amp;lt;ref&amp;gt;Голуб Дж., Ван Лоун Ч. - Матричные вычисления//М.: Мир. - 1999 (c. 394-395)&amp;lt;/ref&amp;gt; &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;На практике, если требуется только небольшая часть от всей совокупности собственных векторов и значений, и матрица имеет Хессенбергову или трёхдиагональную форму, очень эффективными будут методы факторизации, как, например, QR-алгоритм или QL-алгоритм со сдвигами (c целью ускорить алгоритм и сделать порядок сходимости квадратичным) или же без них.&amp;lt;ref&amp;gt;http://algorithm.narod.ru/ln/eigen/ETridiag.html&amp;lt;/ref&amp;gt; &amp;lt;br&amp;gt;&lt;br /&gt;
Весьма молодые и не менее актуальные конкуренты QR и QL алгоритмов, применяющиеся для поиска собственных значений:&lt;br /&gt;
*Методы divide-and-conquer (разделяй и властвуй), появившиеся в 1980-ых годах &amp;lt;ref&amp;gt;https://goo.gl/dapvbn ссылку пришлось сократить с помощью Google url shortener, так как символы подчеркивания портили её и не давали перейти по 1 клику&amp;lt;/ref&amp;gt;&lt;br /&gt;
*Relatively robust representation методы, появившиеся в 1990-ых и позволяющие найти собственные числа симметричной матрицы порядка &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;n&amp;lt;/math&amp;gt; за &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt; операций&lt;br /&gt;
&lt;br /&gt;
Если требуется вычислить собственные векторы, то необходимо хранить вычисляемые векторы Ланцоша. Если работа при этом производится только с оперативной памятью, то при большом порядке исходной матрицы (а именно для таких матриц и предназначен метод Ланцоша) число шагов  &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;j&amp;lt;/math&amp;gt;, которые могут быть выполнены до того момента, как оперативная память будет исчерпана, будет очень незначительно, а следовательно, искомые собственные пары могут не успеть сойтись с требуемой точностью. В этом случае метод Ланцоша можно использовать итерационным образом: после выполнения заданного числа шагов процесс прерывается и, если еще не все требуемые пары Ритца сошлись с требуемой точностью, то формируется новый начальный вектор &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;q_1&amp;lt;/math&amp;gt;, являющийся линейной комбинацией векторов Ритца, еще не сошедшихся с заданной точностью, и процесс начинается заново.&amp;lt;ref&amp;gt;http://num-anal.srcc.msu.ru/lib_na/int_ae/int_ae6.htm (пункт 6.5)&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
Вычислительное ядро рассматриваемого алгоритма (наиболее ресурсно-затратная часть алгоритма) -  формирование на каждом шаге цикла промежуточного вектора &amp;lt;math&amp;gt;z&amp;lt;/math&amp;gt;, вычисляемого по формуле: &amp;lt;math&amp;gt;z = A\,q_j&amp;lt;/math&amp;gt;. Данная операция, по сравнению с другими операциями алгоритма, затратна и требовательна, как с точки зрения количества производимых операций, так и с точки зрения объема оперируемых данных. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Например, умножение матрицы размера &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;n\times n&amp;lt;/math&amp;gt; на вектор длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; требует: &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;n^2+(n-1)n = 2n^2-n&amp;lt;/math&amp;gt; операций умножения и сложения. В свою очередь аналогичная операция умножения матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;(n+1)\times (n+1)&amp;lt;/math&amp;gt; на вектор длины &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;(n+1)&amp;lt;/math&amp;gt; требует: &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;2n^2+3n+1&amp;lt;/math&amp;gt;  операций умножения и сложения. То есть повышение размерности задачи всего на 1 увеличивает число необходимых действий в этом шаге алгоритма на: &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;4n+1&amp;lt;/math&amp;gt;. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Так же, стоит помнить, что, согласно разделу 1.2, данную операцию умножения матрицы на вектор необходимо выполнить &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;k&amp;lt;/math&amp;gt; раз. Нетрудно понять, насколько возрастает и колоссален масштаб операций, если в задачах, где критична точность, размерности &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; могут иметь порядок &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;10^5&amp;lt;/math&amp;gt; или даже более.&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
Как уже было упомянуто в данной статье в описании алгоритма, рассматриваемый алгоритм состоит из двух последовательно выполненных алгоритмов: метод Ланцоша для построения последовательности подпространств Крылова и ортонормированных векторов Ланцоша и процедура Рэлея-Ритца получения оптимальных приближений собственных значений и соответствующих собственных векторов исходной матрицы.&lt;br /&gt;
&lt;br /&gt;
В первой части алгоритма, где итерационно строятся Крыловское подпространство и трёхдиагональная матрица &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&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 style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; разреженная. Именно она подлежит оптимизации с использованием техник распараллеливания, поскольку она является вычислительным ядром алгоритма, а весь упомянутый процесс построения матрицы &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&amp;lt;/math&amp;gt; выполняется последовательно.&lt;br /&gt;
&lt;br /&gt;
Рассмотрим вторую часть алгоритма - поиск собственных значений сформированной матрицы &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&amp;lt;/math&amp;gt;.&amp;lt;br&amp;gt;&lt;br /&gt;
Далее, наглядно, в виде псевдокода, представлен, упомянутый в разделе 1.2, QR-алгоритм (аналогично можно рассмотреть и QL-алгоритм) со сдвигами Релэя, который весьма популярен на практике.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{align}&lt;br /&gt;
\mathbf{Input}: \;&amp;amp;tridiagonal\;\;matrix \;T\;with\;\;n\times n\;\;size\\&lt;br /&gt;
T^{(0)}&amp;amp;:=T\\&lt;br /&gt;
\mathbf{for}&amp;amp; \;\;m=n,...,2 \;\; \mathbf{do}\\&lt;br /&gt;
&amp;amp;k=0\\&lt;br /&gt;
&amp;amp; \mathbf{repeat}\\&lt;br /&gt;
&amp;amp; \quad \;\; k=k+1\\&lt;br /&gt;
&amp;amp; \quad \;\; \mu^{(k)}=T_{m,m}^{(k-1)}\\&lt;br /&gt;
&amp;amp; \quad \;\; Q^{(k)}R^{(k)}=T^{(k-1)}-\mu^{(k)}I\;\;using\;\;QR\;decomposition\\&lt;br /&gt;
&amp;amp; \quad \;\; T^{(k)}=R^{(k)}Q^{(k)}+\mu^{(k)}I\\&lt;br /&gt;
&amp;amp; \mathbf{until} \;\;\; |T_{m,m-1}^{(k)}| \;is\;\;small\;\;enough\\&lt;br /&gt;
&amp;amp; Save  \;\;T_{m,m}^{(k)} \;\;as\;\; converged\;\;eigenvalue\;of\;T\\ &lt;br /&gt;
&amp;amp; Remove \;\boldsymbol{n}\,th\;row\;and\;\boldsymbol{n}\,th\;column\;\;from \;T \\&lt;br /&gt;
&amp;amp; and\;take\;this\;new\;cropped\;matrix\;as\;new\;T^{(0)}\;with\;\;(n-1)\times (n-1)\;\;size\\&lt;br /&gt;
 \mathbf{end}&amp;amp;\; \mathbf{for}&lt;br /&gt;
\end{align}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Малость наддиагональных и поддиагональных элементов матрицы (фраза &#039;&#039;&amp;quot;small enough&amp;quot;&#039;&#039; в псевдокоде) подразумевает:&lt;br /&gt;
&amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt; |T_{m,m-1}^{(k)}| \leq \varepsilon\,|T_{m,m}^{(k)}| \quad\quad &amp;lt;/math&amp;gt; , где &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt; \varepsilon &amp;lt;/math&amp;gt; - заданная точность&amp;lt;br&amp;gt;&lt;br /&gt;
Также вместо сдвига Релэя, обозначенного в алгоритме через &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;\mu^{(k)}&amp;lt;/math&amp;gt;, часто на практике используется сдвиг по Уилкинсону, который даёт гарантированную сходимость внедиагональных элементов матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt; T^{(k)} &amp;lt;/math&amp;gt;, формируемой на каждом шаге, к нулю, при этом жертвуя монотонностью их убывания.&amp;lt;ref&amp;gt;Голуб Дж., Ван Лоун Ч. - Матричные вычисления//М.: Мир. - 1999 (c. 378, вторая половина страницы)&amp;lt;/ref&amp;gt;&amp;lt;ref&amp;gt;Парлетт Б. Симметричная проблема собственных значений. Численные методы.,: Мир, 1983. с. 169&amp;lt;/ref&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Подробнее с различными сдвигами и соответствующими оценками скоростей и количествами операций можно ознакомиться по указанной ссылке:&amp;lt;ref&amp;gt;Парлетт Б. Симметричная проблема собственных значений. Численные методы.,: Мир, 1983. с. 179-182&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;Для совершения QR-декомпозиции на каждом шаге может использоваться любой из алгоритмов по ссылке.&amp;lt;ref&amp;gt;https://en.wikipedia.org/wiki/QR_decomposition&amp;lt;/ref&amp;gt; Подробные описания этих алгоритмов также доступны на данном ресурсе algowiki-project.&amp;lt;br&amp;gt;&lt;br /&gt;
Так как мы оперируем не обычной матрицей и даже не Хессенберговой, а симметричной и трёхдиагональной, то скорость таких алгоритмов значительно возрастёт. Например, согласно данному ресурсу &amp;lt;ref&amp;gt;http://algorithm.narod.ru/ln/eigen/ETridiag.html&amp;lt;/ref&amp;gt;, для QL-алгоритма с неявными сдвигами:&amp;lt;br&amp;gt;&lt;br /&gt;
Для трёхдиагональной матрицы объем арифметических действий составляет &amp;lt;math&amp;gt; O(n)&amp;lt;/math&amp;gt; на одну итерацию вместо &amp;lt;math&amp;gt; O(n^3)&amp;lt;/math&amp;gt; для матрицы общего вида, а число итераций для нахождения первых собственных значений примерно равно 4 - 5. Но на этих итерациях также уменьшаются внедиагональные элементы правого нижнего угла. И, таким образом, дальнейшие собственные значения ищутся значительно быстрее. Среднее число итераций на каждое собственное значение обычно составляет 1.3 - 1.6.&amp;lt;br&amp;gt; &lt;br /&gt;
Аналогично QL, QR-разложение трёхдиагольной матрицы также требует &amp;lt;math&amp;gt; O(n)&amp;lt;/math&amp;gt; флопов&amp;lt;ref&amp;gt;Голуб Дж., Ван Лоун Ч. - Матричные вычисления//М.: Мир. - 1999 (c. 378, начало раздела 8.2.2)&amp;lt;/ref&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Подводя итог, во второй части алгоритма Ланцоша можно выделить следующие макрооперации:&lt;br /&gt;
* умножение матрицы на вещественное число;&lt;br /&gt;
* перемножение матриц;&lt;br /&gt;
* умножение и сравнение вещественных чисел;&lt;br /&gt;
* + набор других макроопераций в зависимости от выбора метода, с помощью которого будет совершаться сама QR или QL-декомпозиция (выше продемонстрированы, уже, как минимум, 3 разных способа).&lt;br /&gt;
Так же, важно заметить, что набор макропераций может быть несколько другим, если выбрать какой-либо иной современный метод поиска собственных чисел трёхдиагональной матрицы, не использующий QR и QL разложения(факторизацию). Два таких метода были упомянуты в пункте 1.2.&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
С целью полностью не дублировать раздел 1.2 данной статьи, где представлен наглядный и доступный для понимания псевдокод алгоритма, постараемся лишь коротко просуммировать и обобщить весь перечень последовательных действий в рассматриваемом алгоритме.&lt;br /&gt;
&lt;br /&gt;
В качестве входных данных имеем: вещественная симметричная матрица &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; размера &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;n\times n&amp;lt;/math&amp;gt;, известный вещественный вектор &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;b&amp;lt;/math&amp;gt; длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; и число &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;n&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Далее:&lt;br /&gt;
* Инициализируем вещественную константу &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;\beta_0&amp;lt;/math&amp;gt; и векторы &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;q_0&amp;lt;/math&amp;gt; и &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;q_1&amp;lt;/math&amp;gt;&lt;br /&gt;
* Итерационно для всех &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j=1,...,k&amp;lt;/math&amp;gt;:&lt;br /&gt;
** Вычисляем вспомогательный вектор &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt;, используя умножение матрицы на вектор&lt;br /&gt;
** Вычисляем, используя скалярное произведение векторов, значение &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;\alpha_j&amp;lt;/math&amp;gt; - элемент на главной диагонали трёхдиагональной матрицы &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&amp;lt;/math&amp;gt;&lt;br /&gt;
** Вычисляем по формуле новое значение и перезаписываем вектор &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt;&lt;br /&gt;
** Вычисляем значение &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;\beta_j&amp;lt;/math&amp;gt; - элементы непосредственно над и под главной диагональю той же матрицы &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&amp;lt;/math&amp;gt;&lt;br /&gt;
** Вычисляем, зная вектор &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt;,  очередной столбец матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;Q&amp;lt;/math&amp;gt;, он же вектор Ланцоша : &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;\,\,q_{j+1}&amp;lt;/math&amp;gt;&lt;br /&gt;
** Теперь, когда матрица &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&amp;lt;/math&amp;gt; сформирована на очередном шаге, находим её собственные значения и вектора любым доступным способом, о чём было подробно сказано в пункте 1.2&lt;br /&gt;
** Переходим на следующую итерацию: &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j&amp;lt;/math&amp;gt;++&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
Оценим количество операций и сложность последовательного алгоритма, изложенного в предыдущем разделе.&lt;br /&gt;
*Для вычисления вектора &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt; умножается матрица размера &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;n\times n&amp;lt;/math&amp;gt; на вектор длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt;, и потребуется &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n^2&amp;lt;/math&amp;gt; операций умножения и &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n^2&amp;lt;/math&amp;gt; операций сложения.&lt;br /&gt;
*Умножение векторов &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;q^T_j&amp;lt;/math&amp;gt; и &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt; длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; потребует &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; операций умножения и &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; операций сложения.&lt;br /&gt;
*При вычислении нового значения вектора &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt; поэлементное сложение двух векторов длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; требует &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; операций сложения.&lt;br /&gt;
*Умножение вектора длины &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; на вещественное число требует &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; операций умножения.&lt;br /&gt;
*Нахождение квадратичной нормы вектора &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt;  длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; требует &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; умножений и &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; сложений и ещё 1 операцию извлечения квадратного корня.&lt;br /&gt;
*Заключительное нахождение собственных значений и собственных векторов трёхдиагональной матрицы &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;T_j&amp;lt;/math&amp;gt; размера &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j\times j&amp;lt;/math&amp;gt; с помощью QR-алгоритма потребует в худшем случае &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(j^3)&amp;lt;/math&amp;gt; операций.&amp;lt;ref&amp;gt;http://num-anal.srcc.msu.ru/lib_na/int_ae/int_ae6.htm (пункт 6.2, &amp;quot;Скорость сходимости при этом всегда не хуже квадратичной и почти всегда лучше кубической.&amp;quot;)&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Посчитаем теперь суммарное количество простейших операций на одной итерации алгоритма (без учёта записей в память):&lt;br /&gt;
*&amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n^2+5\,n&amp;lt;/math&amp;gt; операций умножения/деления&lt;br /&gt;
*&amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n^2+4\,n&amp;lt;/math&amp;gt; операций сложения/вычитания&lt;br /&gt;
*1 операция извлечения квадратного корня&amp;lt;br&amp;gt;&lt;br /&gt;
Отдельно после всех итераций при &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j=k&amp;lt;/math&amp;gt; :&lt;br /&gt;
*&amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(k^3)&amp;lt;/math&amp;gt; операций для поиска собственных значений и собственных векторов трёхдиагональной матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_k&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Итого можно утверждать следующее:&lt;br /&gt;
&lt;br /&gt;
Последовательная сложность одной итерации рассматриваемого алгоритма:  &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(n ^ 2) &amp;lt;/math&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Суммарная сложность алгоритма (&amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;/math&amp;gt; итераций): &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(k\,n ^ 2) + O(k ^ 3)&amp;lt;/math&amp;gt; &amp;lt;ref&amp;gt;Здесь мы полагаем, что мы не вычисляем собственные значения и векторы матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_j&amp;lt;/math&amp;gt; на каждом промежуточном шаге, а лишь единожды затрачиваем &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;O(k ^ 3)&amp;lt;/math&amp;gt; действий в конце для нахождения &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;/math&amp;gt; собственных значений и векторов матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_k&amp;lt;/math&amp;gt;&amp;lt;/ref&amp;gt; &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
На практике же обычно рассматривается число &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;&amp;lt;n&amp;lt;/math&amp;gt;, поэтому второе слагаемое можно опустить.&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
На рис. 1 продемонстрирован граф одной итерации (при каком-либо произвольном значении итератора &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j&amp;lt;/math&amp;gt;) описанного алгоритма без отображения входных и выходных данных. Наглядно продемонстрированы связи между всеми действиями, и с помощью деления на &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; потоков показано, какие операции возможно выполнять параллельно на каждом шаге с целью оптимизации и экономии машинного времени. В результате, после параллельно выполненных операций &#039;&#039;&#039;Division&#039;&#039;&#039; на заключительном ярусе, на выходе имеем значение следующего вектора Ланцоша &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;q_{j+1}&amp;lt;/math&amp;gt;, после чего следует переход на следующую итерацию, и процесс повторяется.&lt;br /&gt;
&lt;br /&gt;
[[Файл:Levin_graph.png|600px|thumb|center|Рис. 1]] &amp;lt;br&amp;gt;&lt;br /&gt;
Обозначения на рисунке: &amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Simp&#039;&#039;&#039; (от англ. simple) - операции сложения и умножения вещественных чисел при вычислении произведения матрицы на вектор;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Vec mult&#039;&#039;&#039; (от англ. vectors multiplication) - операция скалярного умножения двух векторов;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Vec subtr&#039;&#039;&#039; (от англ. vectors subtraction, из-за использованных в операции вычитаний векторов) - операция умножения вектора на число (выполняется дважды) и формирование нового значения &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;z_{new}&amp;lt;/math&amp;gt; по формуле: &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;z_{new} = z - \alpha_j q_j - \beta_{j-1}q_{j-1} \;&amp;lt;/math&amp;gt;;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;||\cdot||&amp;lt;/math&amp;gt; - операция вычисления нормы вектора;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Division&#039;&#039;&#039; - операция деления вектора на вещественное число  &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;\beta_j&amp;lt;/math&amp;gt; &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Важно отметить, что упомянутые выше операции также легко поддаются оптимизации. Например, попарные умножения вещественных координат векторов при вычислении скалярного произведения также легко выполняются параллельно на &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; потоках, а затем можно применить суммирование методом сдваивания, о котором сказано в следующем разделе. Умножение или деление вектора на вещественное число являющееся, по определению, умножением или делением всех его координат на это число тоже может быть выполнено эффективнее, если мы используем &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; потоков, а не выполняем эти действия последовательно.&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
Параллельные операции возможны только внутри итераций, так как рассматриваемый алгоритм является итерационным, и сами итерации строго последовательны.&amp;lt;br&amp;gt;&lt;br /&gt;
Рассмотрим в этом разделе подробнее, какой выигрыш мы можем получить при распараллеливании операций внутри одной итерации согласно графу из предыдущего раздела.&lt;br /&gt;
&lt;br /&gt;
Умножение вещественной симметричной матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; размера &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;n\times n&amp;lt;/math&amp;gt; на вектор &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;b&amp;lt;/math&amp;gt; длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; требует последовательного выполнения &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; ярусов умножений и сложений. Сложение элементов вектора длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; на каждом шаге перемножения можно оптимизировать и выполнить за &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;\log_2 n&amp;lt;/math&amp;gt; действий, если применять метод сдваивания.&lt;br /&gt;
&lt;br /&gt;
Дальнейшие операции выполняются последовательно, а вычисление значений векторов происходит за один ярус операций сложения или умножения.&lt;br /&gt;
&lt;br /&gt;
Ресурс параллелизма алгоритма вычисления собственных значений построенной трёхдиагональной матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_k&amp;lt;/math&amp;gt; размера &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k\times k&amp;lt;/math&amp;gt; зависит от выбранного алгоритма (об этих алгоритмах подробнее было сказано в разделах 1.2 и 1.4). Будет очень затратно с точки зрения объёма материала пытаться рассмотреть пусть даже часть этих методов в этой статье, а так же тонкости их распараллеливания. Предлагаем читателям при желании самим ознакомиться с этими алгоритмами на данном ресурсе или прибегнув к иным источникам.&lt;br /&gt;
&lt;br /&gt;
При классификации по высоте ЯПФ, таким образом, алгоритм Ланцоша без переортогонализации относится к алгоритмам с &#039;&#039;логарифмической сложностью&#039;&#039;, и его сложность равна &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(\log_2 n)&amp;lt;/math&amp;gt; с важным замечанием, что это сложность только одной итерации, а максимум в алгоритме может быть выполнено последовательно &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;/math&amp;gt; таких однотипных итераций, если не будет осуществлён ранний выход из цикла. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Несмотря на то, что на графе в предыдущем разделе для лучшей визуализации и понимания было изображено &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; потоков (никаких допущений мы не делали и нарушений с точки зрения логики и математики нет, можно изобразить большее число потоков, просто часть времени некоторые из них могут бездействовать и не использоваться), на самом деле правильным и разумным будет реализовать начальное параллельное выполнение &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n^2&amp;lt;/math&amp;gt; операций умножения всех вещественных элементов матрицы &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;A&amp;lt;/math&amp;gt; на соответствующие элементы вектора &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;q_j&amp;lt;/math&amp;gt;, после чего применять тот же самый упомянутый метод сдваивания. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Поэтому при классификации по ширине ЯПФ его сложность будет &#039;&#039;квадратичной&#039;&#039; и равна &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(n^2)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
&#039;&#039;&#039;Входные данные алгоритма:&#039;&#039;&#039; вещественная симметричная &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; размера &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;n\times n&amp;lt;/math&amp;gt;, вещественный вектор &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;b&amp;lt;/math&amp;gt; длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt;, и одно целое число &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;k&amp;lt;/math&amp;gt;, означающее количество итераций.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём входных данных:&#039;&#039;&#039; &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;n^2 +n + 1 &amp;lt;/math&amp;gt;. Если учесть, что матрица симметричная и достаточно для её однозначного определения задать элементы на главной диагонали и элементы над или под ней, то можно сократить объём входных данных с целью экономии памяти до: &amp;lt;math&amp;gt;\ \frac{n^2-n}{2}+n+n+1 =\frac{n^2+3n}{2} + 1&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные алгоритма:&#039;&#039;&#039; вектор собственных значений &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;\Theta^k&amp;lt;/math&amp;gt; длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;/math&amp;gt;, матрица &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;S^k&amp;lt;/math&amp;gt; из соответствующих собственных векторов размера &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n\times k&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём выходных данных:&#039;&#039;&#039; &amp;lt;math&amp;gt;k\;(n + 1)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
В данном разделе перечислены без какой-либо хронологии или связи друг с другом наиболее важные и разнообразные свойства алгоритма, на которые стоит и полезно обратить внимание, а также которые выгодно отличают его от схожих алгоритмов, решающих ту же задачу.&amp;lt;br&amp;gt;&lt;br /&gt;
1) Отношение последовательной сложности алгоритма к параллельной,с учётом &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;/math&amp;gt; итераций, равно &amp;lt;math&amp;gt;\;\;\frac{kn^2}{k \log_2{n}}=\frac{n^2}{\log_2{n}}&amp;lt;/math&amp;gt;;&amp;lt;br&amp;gt;&lt;br /&gt;
2) Вычислительная мощность алгоритма, как отношение числа операций к суммарному объему входных и выходных данных, равна &amp;lt;math style=&amp;quot;vertical-align:-70%&amp;gt;\;\;\frac{k\,n^2}{0.5\,n^2+1.5\,n+k\,n+k+1}&amp;lt;/math&amp;gt; и &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;\approx 2\,k&amp;lt;/math&amp;gt;, так как на практике верно отношение &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;&amp;lt;n&amp;lt;/math&amp;gt; ;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
3) Для собственных значений формируемых матриц &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_j&amp;lt;/math&amp;gt; верно отношение (следствие теоремы Коши о перемежаемости): &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;\lambda_i(T_{k+1})\geq \lambda_i(T_{k})\geq \lambda_{i+1}(T_{k+1})\geq \lambda_{i+1}(T_{k})&amp;lt;/math&amp;gt; ;&amp;lt;ref&amp;gt;James W. Demmel - Вычислительная линейная алгебра. Теория и приложения //Мир. - 2001 (c. 383)&amp;lt;/ref&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
4) Крайние (наибольшие и наименьшие) собственные значения матриц &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_j&amp;lt;/math&amp;gt; сходятся к крайним собственным значениям матрицы &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;A&amp;lt;/math&amp;gt; первыми (это часто происходит уже на ранних шагах при &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j\approx 2\,\sqrt{n}&amp;lt;/math&amp;gt;&amp;lt;ref&amp;gt;http://num-anal.srcc.msu.ru/lib_na/int_ae/int_ae6.htm (пункт 6.5)&amp;lt;/ref&amp;gt;), а собственные значения в середине спектра - последними;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
5) Из-за ограниченной точности постепенно теряется ортогональность вектора Ланцоша &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;q_j&amp;lt;/math&amp;gt; к предыдущим векторам Ланцоша, поэтому необходимо примерно каждые 10-15 итераций проводить дорогостоящую операцию реортогонализации, но это уже будет иной алгоритм с очень малым различием в одной операции и в программном коде, реализующем его, соответственно; &amp;lt;ref&amp;gt;Sam Handler - The Lanczos Algorithm For Large-Scale Eigenvalue Problems (08.01.07), slide №8&amp;lt;/ref&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
6) Эффективность и быстрота выполнения алгоритма очень сильно зависит от скорости памяти (диска). Согласно тесту только &#039;&#039;6%&#039;&#039; времени работы программы приходится на вычисления, остальное время затрачивается на ожидание отклика диска;&amp;lt;ref&amp;gt;Sam Handler - The Lanczos Algorithm For Large-Scale Eigenvalue Problems (08.01.07), slide №10&amp;lt;/ref&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
7) Метод Ланцоша удобен тем, что не требует хранения исходной матрицы полным массивом: метод использует исходную матрицу только в операциях умножения матрицы на вектор, что позволяет эффективно использовать разреженность матрицы или регулярность структуры матрицы. Поэтому метод Ланцоша может быть использован для матриц таких больших порядков, когда методы вращений и отражений не могут быть применены.&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;
Для исследования масштабируемости рассматриваемого алгоритма Ланцоша без переортогонализации автором была реализована программа на языке С++ с использованием технологии MPI (&#039;&#039;&#039;не забыть вставить ссылку на код&#039;&#039;&#039;). Дальнейшее исследование выполнялось на суперкомпьютере &amp;quot;Ломоносов&amp;quot; Суперкомпьютерного комплекса МГУ. &amp;lt;br&amp;gt; Важно отметить, что реализованная программа выполняет только первую часть алгоритма - формирование матрицы &amp;lt;math &amp;gt;T_j&amp;lt;/math&amp;gt;. Вторая часть алгоритма (задача поиска собственных значений матрицы &amp;lt;math &amp;gt;T_j&amp;lt;/math&amp;gt;) может быть решена несколькими методами, каждый из которых обладает своей эффективностью распараллеливании и характерными свойствами. Подробно этот вопрос уже обсуждался в статье раннее, поэтому не будем ещё раз заострять на этом внимание и останавливаться.&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Сборка осуществлялась со следующими параметрами:&lt;br /&gt;
* Компилятор intel/15.0.090 &lt;br /&gt;
* Openmpi/1.8.4-icc&lt;br /&gt;
В серии проведённых расчётов рассматривались следующие числовые значения параметров:&lt;br /&gt;
* Размер &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;n&amp;lt;/math&amp;gt; задачи и, соответственно, матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt;, задействованной в операции умножения на вектор: [2000 : 30000] с шагом 1000&lt;br /&gt;
* Число процессоров: 1, 2, 4, 16, 32, 48, 64, 96, 128&lt;br /&gt;
* Число итераций в алгоритме: &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k=350&amp;lt;/math&amp;gt;&lt;br /&gt;
Число &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; взято таким вопреки информации в начале статьи, где говорится, что значение &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; редко превышает &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;10^2&amp;lt;/math&amp;gt; (хотя и имеем право брать его любым по нашему усмотрению). Это сделано исключительно для лучшей визуализации пиков на графиках в данном разделе и наглядности получаемых результатов, так как при меньших на порядок значениях &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; времена выполнения программ были слишком малы даже при минимальных числах процессоров и максимальных размерах исходной задачи.&lt;br /&gt;
&lt;br /&gt;
== Динамические характеристики и эффективность реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Выводы для классов архитектур ==&lt;br /&gt;
По заданию, во второй части требовалось описать только разделы 2.4 и 2.7, прошу не спрашивать с меня все разделы 2.1-2.6. Надеюсь на понимание, мне физически не хватает времени на это задание + 2 других в течение семестра, делаю всё, что в моих силах :)&lt;br /&gt;
&lt;br /&gt;
== Существующие реализации алгоритма ==&lt;br /&gt;
Несмотря на то, что алгоритм является далеко не самым популярным, алгоритмом, про который нельзя сказать, что он всегда «на слуху», на сегодняшний день существует множество реализаций на различных популярных языках.&amp;lt;br&amp;gt;&lt;br /&gt;
Перечислим далее некоторые из них, указывая язык программирования, лежащий в их основе, и некоторые важные характеристики, которые обсуждались в статье ранее:&lt;br /&gt;
*&#039;&#039;Code on netlib.org by Jane Cullum and Ralph Willoughby&#039;&#039; (&#039;&#039;&#039;Fortran 77&#039;&#039;&#039;; без реортогонализации векторов; без реализации распараллеливания)&amp;lt;ref&amp;gt;http://www.netlib.org/lanczos/leval&amp;lt;/ref&amp;gt;&lt;br /&gt;
*&#039;&#039;Lanczos algorithm on freesourcecode.net&#039;&#039; (&#039;&#039;&#039;Matlab&#039;&#039;&#039;; присутствует реортогонализация векторов; без реализации распараллеливания)&amp;lt;ref&amp;gt;http://freesourcecode.net/matlabprojects/61741/lanczos-algorithm--in-matlab&amp;lt;/ref&amp;gt;&lt;br /&gt;
*&#039;&#039;Lanczos for eigenvalues in Numerical Linear Algebra, Spring 2007&#039;&#039; (&#039;&#039;&#039;Matlab&#039;&#039;&#039;; частичная или полная реортогонализация - доступны оба варианта; без реализации распараллеливания)&amp;lt;ref&amp;gt;Ссылки на файлы lanso.m и lanfu.m можно найти на https://www.nada.kth.se/~ruhe/2D5219/labs2007.html&amp;lt;/ref&amp;gt;&lt;br /&gt;
*&#039;&#039;Planso&#039;&#039; (название происходит от parallel Lanso.f) &#039;&#039;code by Kesheng Wu and Horst D. Simon&#039;&#039; (&#039;&#039;&#039;Fortran 77&#039;&#039;&#039;; частичная реортогонализация векторов; использование MPI для коммуникаций)&amp;lt;ref&amp;gt;https://github.com/jiahao/planso.jl/tree/master/external/PLAN/plan К сожалению, ссылка в описании пакета на github, ведущая на сайт National Energy Research Scientific Computing Center (NERSC), с более подробной информацией о данной программе больше не активна и выдаёт результат &#039;&#039;Page not found&#039;&#039;&amp;lt;/ref&amp;gt; &lt;br /&gt;
* &#039;&#039;Lanczos.cpp in the Vienna Computing Library&#039;&#039;  (&#039;&#039;&#039;C++&#039;&#039;&#039;, частичная реортогонализация, без реализации распараллеливания) &amp;lt;ref&amp;gt;http://viennacl.sourceforge.net/doc/lanczos_8cpp_source.html&amp;lt;/ref&amp;gt;&lt;br /&gt;
* &#039;&#039;Parallel Eigen Values code using C++ AMP on microsoft msdn blog&#039;&#039; (&#039;&#039;&#039;C++&#039;&#039;&#039;; ? ; распараллеливание есть и реализовано через C++ AMP) &amp;lt;ref&amp;gt;https://blogs.msdn.microsoft.com/nativeconcurrency/2013/12/20/eigen-values/ Подробнее о C++ Accelerated Massive Parallelism можно почитать здесь: https://msdn.microsoft.com/ru-ru/library/hh265137(v=vs.140).aspx или здесь: http://professorweb.ru/my/csharp/optimization/level4/4_6.php &amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;br /&gt;
[[en:Description of algorithm properties and structure]]&lt;/div&gt;</summary>
		<author><name>AleksLevin</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:AleksLevin/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%9B%D0%B0%D0%BD%D1%86%D0%BE%D1%88%D0%B0_%D0%B2%D1%8B%D1%87%D0%B8%D1%81%D0%BB%D0%B5%D0%BD%D0%B8%D1%8F_%D1%81%D0%BE%D0%B1%D1%81%D1%82%D0%B2%D0%B5%D0%BD%D0%BD%D1%8B%D1%85_%D0%B7%D0%BD%D0%B0%D1%87%D0%B5%D0%BD%D0%B8%D0%B9_%D1%81%D0%B8%D0%BC%D0%BC%D0%B5%D1%82%D1%80%D0%B8%D1%87%D0%BD%D0%BE%D0%B9_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86%D1%8B_%D0%B4%D0%BB%D1%8F_%D1%82%D0%BE%D1%87%D0%BD%D0%BE%D0%B9_%D0%B0%D1%80%D0%B8%D1%84%D0%BC%D0%B5%D1%82%D0%B8%D0%BA%D0%B8_(%D0%B1%D0%B5%D0%B7_%D0%BF%D0%B5%D1%80%D0%B5%D0%BE%D1%80%D1%82%D0%BE%D0%B3%D0%BE%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D0%B8)&amp;diff=20209</id>
		<title>Участник:AleksLevin/Алгоритм Ланцоша вычисления собственных значений симметричной матрицы для точной арифметики (без переортогонализации)</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:AleksLevin/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%9B%D0%B0%D0%BD%D1%86%D0%BE%D1%88%D0%B0_%D0%B2%D1%8B%D1%87%D0%B8%D1%81%D0%BB%D0%B5%D0%BD%D0%B8%D1%8F_%D1%81%D0%BE%D0%B1%D1%81%D1%82%D0%B2%D0%B5%D0%BD%D0%BD%D1%8B%D1%85_%D0%B7%D0%BD%D0%B0%D1%87%D0%B5%D0%BD%D0%B8%D0%B9_%D1%81%D0%B8%D0%BC%D0%BC%D0%B5%D1%82%D1%80%D0%B8%D1%87%D0%BD%D0%BE%D0%B9_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86%D1%8B_%D0%B4%D0%BB%D1%8F_%D1%82%D0%BE%D1%87%D0%BD%D0%BE%D0%B9_%D0%B0%D1%80%D0%B8%D1%84%D0%BC%D0%B5%D1%82%D0%B8%D0%BA%D0%B8_(%D0%B1%D0%B5%D0%B7_%D0%BF%D0%B5%D1%80%D0%B5%D0%BE%D1%80%D1%82%D0%BE%D0%B3%D0%BE%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D0%B8)&amp;diff=20209"/>
		<updated>2016-12-06T21:51:55Z</updated>

		<summary type="html">&lt;p&gt;AleksLevin: /* Масштабируемость алгоритма и его реализации */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Основные авторы описания: Левин А.Д.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{algorithm&lt;br /&gt;
| name              = Алгоритм Ланцоша для точной арифметики (без переортогонализации)&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(k\,n^2)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(k\log_2 n)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;\frac{n^2+3n}{2} + 1&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;k\;(n + 1)&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритмов =&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Данный алгоритм появился в 1950 г. и носит имя венгерского физика и математика Корнелия Ланцоша (венг. Lánczos Kornél). Алгоритм Ланцоша относится к итерационным методам вычисления собственных значений для матриц столь больших порядков &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt; n&amp;lt;/math&amp;gt;, что к ним нельзя применить прямые методы из-за ограничений по времени и памяти.&lt;br /&gt;
&lt;br /&gt;
Сам Ланцош указывал, что его метод предназначен для отыскания нескольких собственных векторов симметричных матриц, хотя к методу сразу было обращено внимание, как к способу приведения всей матрицы к трёхдиагональному виду. Двадцатью годами позже канадский математик Крис Пэж показал, что, несмотря на чувствительность к округлениям, алгоритм Ланцоша - эффективное средство вычисления некоторых &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; собственных чисел и соответствующих им собственных векторов. &amp;lt;ref&amp;gt;Парлетт Б. - Симметричная проблема собственных значений. Численные методы //М.: Мир. - 1983. (c. 276)&amp;lt;/ref&amp;gt;&lt;br /&gt;
Обычно число &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; берут в два раза больше, чем количество собственных значений матрицы, которые поставлена цель найти, и оно имеет порядок не более &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;10^2&amp;lt;/math&amp;gt;.&amp;lt;ref&amp;gt;Susan W. Bostic - Lanczos Eigensolution Method for High-Perfomance Computers, page 7&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Алгоритм Ланцоша для вычисления собственных значений симметричной матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; соединяет в себе метод Ланцоша для построения последовательности подпространств Крылова и ортонормированных векторов Ланцоша и процедуру Рэлея-Ритца получения оптимальных приближений собственных значений и соответствующих собственных векторов исходной матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt;.&amp;lt;ref&amp;gt;James W. Demmel - Вычислительная линейная алгебра. Теория и приложения //Мир. - 2001 (c. 381)&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
В данной статье рассматривается вариант алгоритма Ланцоша, в котором опущено влияние ошибок округления на вычислительный процесс, хотя на практике этому посвящается отдельное внимание и существуют различные методы решения данной проблемы, такие как частичная или полная переортогонализация. Этим модифицированным методам посвящены отдельные статьи на данном ресурсе.&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
Обозначения и формулы, используемые в данном разделе, взяты из литературы, указанной по ссылке.&amp;lt;ref&amp;gt;James W. Demmel - Вычислительная линейная алгебра. Теория и приложения //Мир. - 2001 (c. 313, &#039;&#039;&amp;lt;math&amp;gt; \S &amp;lt;/math&amp;gt; 6.6 Методы Крыловского подпространства&#039;&#039;)&amp;lt;/ref&amp;gt; &lt;br /&gt;
&lt;br /&gt;
Алгоритм Ланцоша для вычисления &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; собственных значений и собственных векторов вещественной симметричной матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A=A^T&amp;lt;/math&amp;gt; в точной арифметике: &amp;lt;ref&amp;gt;James W. Demmel - Вычислительная линейная алгебра. Теория и приложения //Мир. - 2001 (c. 381)&amp;lt;/ref&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{align}&lt;br /&gt;
q_1 = &amp;amp; \,\frac{b}{\|b\|_2},\; \beta_0 = 0,\; q_0 = 0\\&lt;br /&gt;
\mathbf{for} \; &amp;amp; j = 1 \; to \; k \,\; \mathbf{do} \\&lt;br /&gt;
&amp;amp; z = A\,q_j\\&lt;br /&gt;
&amp;amp; \alpha_j = q^T_j z\\&lt;br /&gt;
&amp;amp; z = z - \alpha_j q_j - \beta_{j-1}q_{j-1}\\&lt;br /&gt;
&amp;amp; \beta_j = \|z\|_2\\&lt;br /&gt;
&amp;amp; \mathbf{If} \; (\beta_j == 0) \; \mathbf{then}\; stop\; the\; algorithm \\ &lt;br /&gt;
&amp;amp; \;  q_{j+1} = \frac{z}{\beta_j} \\&lt;br /&gt;
&amp;amp; compute\; eigenvalues\; and \;eigenvectors\;of \;matrix \;\;T_j= Q^T_j A Q\;\;and\;estimate \;the\; errors\\&lt;br /&gt;
\mathbf{end} \; &amp;amp; \mathbf{for}&lt;br /&gt;
\end{align}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
В продемонстрированном выше алгоритме &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;b&amp;lt;/math&amp;gt; - заданный вещественный вектор. Также полагается известным алгоритм вычисления произведения матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; на вектор &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;x&amp;lt;/math&amp;gt;. &lt;br /&gt;
Введём матрицу Крылова, определяемую следующим соотношением: &amp;lt;math&amp;gt;K_j = [b,Ab,A^2b,...,A^{j-1}b]&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Далее, на практике, матрица &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;K&amp;lt;/math&amp;gt; заменяется матрицей &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;Q&amp;lt;/math&amp;gt;, такой, что при любом числе &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; линейные оболочки первых &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; столбцов в &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;K&amp;lt;/math&amp;gt; и &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;Q&amp;lt;/math&amp;gt; являются одним и тем же подпространством.&amp;lt;ref&amp;gt;James W. Demmel - Вычислительная линейная алгебра. Теория и приложения //Мир. - 2001 (c. 315)&amp;lt;/ref&amp;gt; &lt;br /&gt;
Тогда матрица &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;Q&amp;lt;/math&amp;gt;, в отличие от матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;K&amp;lt;/math&amp;gt;, хорошо обусловлена и легко обратима. В результате получаем матрицу &amp;lt;math&amp;gt;Q_j = [q_1, q_2, \dots, q_j]&amp;lt;/math&amp;gt; размерности &amp;lt;math&amp;gt;n\times j&amp;lt;/math&amp;gt;, столбцы которой ортогональны, являются базисом подпространства Крылова и называются векторами Ланцоша.&lt;br /&gt;
&lt;br /&gt;
В алгоритме Ланцоша вычислению подлежит столько первых столбцов в матрице &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;Q_j&amp;lt;/math&amp;gt;, сколько необходимо для получения требуемого приближения к решению &amp;lt;math&amp;gt;A\,x\,=b\,\,(A\,x=\lambda \, x)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Получение нулевого &amp;lt;math&amp;gt;\beta_j&amp;lt;/math&amp;gt; в итерационном процессе - событие, желательное в том смысле, что оно свидетельствует о том, что найдено некоторое подпространство, являющееся в точности инвариантным, а все собственные значения матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;T_j&amp;lt;/math&amp;gt; являются собственными значениями матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt;. На практике же нулевое и близкие к нулю значения получаются редко.&amp;lt;ref&amp;gt;Голуб Дж., Ван Лоун Ч. - Матричные вычисления//М.: Мир. - 1999 (c. 429)&amp;lt;/ref&amp;gt; &lt;br /&gt;
&lt;br /&gt;
Затем на каждом шаге цикла формируется симметричная трёхдиагональная матрица &amp;lt;math&amp;gt;T_j = Q^T_j A Q&amp;lt;/math&amp;gt;, к которой применяется процесс Рэлея-Ритца для поиска её собственных значений (на практике для поиска этих собственных значений можно использовать любой из специальных методов в параграфе книги по ссылке).&amp;lt;ref&amp;gt;Голуб Дж., Ван Лоун Ч. - Матричные вычисления//М.: Мир. - 1999 (&amp;lt;math&amp;gt;\S&amp;lt;/math&amp;gt; 8.4)&amp;lt;/ref&amp;gt;  &lt;br /&gt;
Эти собственные значения, они же числа Ритца, и полагаются приближёнными собственными значениями исходной матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt;.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Существует множество методов для отыскания собственных значений вещественной симметричной трехдиагональной матрицы. Большинство из них требует &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt; операций &amp;lt;ref&amp;gt;Парлетт Б. Симметричная проблема собственных значений. Численные методы.,: Мир, 1983. с. 179-182&amp;lt;/ref&amp;gt;, но существуют и быстрые алгоритмы, требующие лишь &amp;lt;math&amp;gt;O(n\ln n)&amp;lt;/math&amp;gt; операций.&amp;lt;ref&amp;gt;https://en.wikipedia.org/wiki/Tridiagonal_matrix#Eigenvalues  Раздел eigenvalues&amp;lt;/ref&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Одним из возможных способов отыскать собственные значения симметричной трехдиагональной матрицы - прямое вычисление корней характеристического полинома &amp;lt;math&amp;gt;p_n(\lambda)&amp;lt;/math&amp;gt; через метод деления пополам, где формируется последовательность Штурма и локализуются собственные числа, являющиеся корнями характеристического полинома. Нахождение всех &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; собственных значений матрицы этим способом требует &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;2n^2t&amp;lt;/math&amp;gt; умножений и вычитаний, где &amp;lt;math&amp;gt;t&amp;lt;/math&amp;gt; - число сделанных шагов с применением метода деления пополам.&amp;lt;ref&amp;gt;Уилкинсон Дж. X. Алгебраическая проблема собственныx значений. Изд-во &amp;quot;Наука&amp;quot;, 1970. - глава 5, с. 272-278&amp;lt;/ref&amp;gt; Соответствующие собственные вектора могут быть найдены посредством обратных итераций за &amp;lt;math&amp;gt; O(n) &amp;lt;/math&amp;gt; флопов. &amp;lt;ref&amp;gt;Голуб Дж., Ван Лоун Ч. - Матричные вычисления//М.: Мир. - 1999 (c. 394-395)&amp;lt;/ref&amp;gt; &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;На практике, если требуется только небольшая часть от всей совокупности собственных векторов и значений, и матрица имеет Хессенбергову или трёхдиагональную форму, очень эффективными будут методы факторизации, как, например, QR-алгоритм или QL-алгоритм со сдвигами (c целью ускорить алгоритм и сделать порядок сходимости квадратичным) или же без них.&amp;lt;ref&amp;gt;http://algorithm.narod.ru/ln/eigen/ETridiag.html&amp;lt;/ref&amp;gt; &amp;lt;br&amp;gt;&lt;br /&gt;
Весьма молодые и не менее актуальные конкуренты QR и QL алгоритмов, применяющиеся для поиска собственных значений:&lt;br /&gt;
*Методы divide-and-conquer (разделяй и властвуй), появившиеся в 1980-ых годах &amp;lt;ref&amp;gt;https://goo.gl/dapvbn ссылку пришлось сократить с помощью Google url shortener, так как символы подчеркивания портили её и не давали перейти по 1 клику&amp;lt;/ref&amp;gt;&lt;br /&gt;
*Relatively robust representation методы, появившиеся в 1990-ых и позволяющие найти собственные числа симметричной матрицы порядка &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;n&amp;lt;/math&amp;gt; за &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt; операций&lt;br /&gt;
&lt;br /&gt;
Если требуется вычислить собственные векторы, то необходимо хранить вычисляемые векторы Ланцоша. Если работа при этом производится только с оперативной памятью, то при большом порядке исходной матрицы (а именно для таких матриц и предназначен метод Ланцоша) число шагов  &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;j&amp;lt;/math&amp;gt;, которые могут быть выполнены до того момента, как оперативная память будет исчерпана, будет очень незначительно, а следовательно, искомые собственные пары могут не успеть сойтись с требуемой точностью. В этом случае метод Ланцоша можно использовать итерационным образом: после выполнения заданного числа шагов процесс прерывается и, если еще не все требуемые пары Ритца сошлись с требуемой точностью, то формируется новый начальный вектор &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;q_1&amp;lt;/math&amp;gt;, являющийся линейной комбинацией векторов Ритца, еще не сошедшихся с заданной точностью, и процесс начинается заново.&amp;lt;ref&amp;gt;http://num-anal.srcc.msu.ru/lib_na/int_ae/int_ae6.htm (пункт 6.5)&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
Вычислительное ядро рассматриваемого алгоритма (наиболее ресурсно-затратная часть алгоритма) -  формирование на каждом шаге цикла промежуточного вектора &amp;lt;math&amp;gt;z&amp;lt;/math&amp;gt;, вычисляемого по формуле: &amp;lt;math&amp;gt;z = A\,q_j&amp;lt;/math&amp;gt;. Данная операция, по сравнению с другими операциями алгоритма, затратна и требовательна, как с точки зрения количества производимых операций, так и с точки зрения объема оперируемых данных. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Например, умножение матрицы размера &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;n\times n&amp;lt;/math&amp;gt; на вектор длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; требует: &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;n^2+(n-1)n = 2n^2-n&amp;lt;/math&amp;gt; операций умножения и сложения. В свою очередь аналогичная операция умножения матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;(n+1)\times (n+1)&amp;lt;/math&amp;gt; на вектор длины &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;(n+1)&amp;lt;/math&amp;gt; требует: &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;2n^2+3n+1&amp;lt;/math&amp;gt;  операций умножения и сложения. То есть повышение размерности задачи всего на 1 увеличивает число необходимых действий в этом шаге алгоритма на: &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;4n+1&amp;lt;/math&amp;gt;. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Так же, стоит помнить, что, согласно разделу 1.2, данную операцию умножения матрицы на вектор необходимо выполнить &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;k&amp;lt;/math&amp;gt; раз. Нетрудно понять, насколько возрастает и колоссален масштаб операций, если в задачах, где критична точность, размерности &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; могут иметь порядок &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;10^5&amp;lt;/math&amp;gt; или даже более.&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
Как уже было упомянуто в данной статье в описании алгоритма, рассматриваемый алгоритм состоит из двух последовательно выполненных алгоритмов: метод Ланцоша для построения последовательности подпространств Крылова и ортонормированных векторов Ланцоша и процедура Рэлея-Ритца получения оптимальных приближений собственных значений и соответствующих собственных векторов исходной матрицы.&lt;br /&gt;
&lt;br /&gt;
В первой части алгоритма, где итерационно строятся Крыловское подпространство и трёхдиагональная матрица &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&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 style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; разреженная. Именно она подлежит оптимизации с использованием техник распараллеливания, поскольку она является вычислительным ядром алгоритма, а весь упомянутый процесс построения матрицы &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&amp;lt;/math&amp;gt; выполняется последовательно.&lt;br /&gt;
&lt;br /&gt;
Рассмотрим вторую часть алгоритма - поиск собственных значений сформированной матрицы &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&amp;lt;/math&amp;gt;.&amp;lt;br&amp;gt;&lt;br /&gt;
Далее, наглядно, в виде псевдокода, представлен, упомянутый в разделе 1.2, QR-алгоритм (аналогично можно рассмотреть и QL-алгоритм) со сдвигами Релэя, который весьма популярен на практике.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{align}&lt;br /&gt;
\mathbf{Input}: \;&amp;amp;tridiagonal\;\;matrix \;T\;with\;\;n\times n\;\;size\\&lt;br /&gt;
T^{(0)}&amp;amp;:=T\\&lt;br /&gt;
\mathbf{for}&amp;amp; \;\;m=n,...,2 \;\; \mathbf{do}\\&lt;br /&gt;
&amp;amp;k=0\\&lt;br /&gt;
&amp;amp; \mathbf{repeat}\\&lt;br /&gt;
&amp;amp; \quad \;\; k=k+1\\&lt;br /&gt;
&amp;amp; \quad \;\; \mu^{(k)}=T_{m,m}^{(k-1)}\\&lt;br /&gt;
&amp;amp; \quad \;\; Q^{(k)}R^{(k)}=T^{(k-1)}-\mu^{(k)}I\;\;using\;\;QR\;decomposition\\&lt;br /&gt;
&amp;amp; \quad \;\; T^{(k)}=R^{(k)}Q^{(k)}+\mu^{(k)}I\\&lt;br /&gt;
&amp;amp; \mathbf{until} \;\;\; |T_{m,m-1}^{(k)}| \;is\;\;small\;\;enough\\&lt;br /&gt;
&amp;amp; Save  \;\;T_{m,m}^{(k)} \;\;as\;\; converged\;\;eigenvalue\;of\;T\\ &lt;br /&gt;
&amp;amp; Remove \;\boldsymbol{n}\,th\;row\;and\;\boldsymbol{n}\,th\;column\;\;from \;T \\&lt;br /&gt;
&amp;amp; and\;take\;this\;new\;cropped\;matrix\;as\;new\;T^{(0)}\;with\;\;(n-1)\times (n-1)\;\;size\\&lt;br /&gt;
 \mathbf{end}&amp;amp;\; \mathbf{for}&lt;br /&gt;
\end{align}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Малость наддиагональных и поддиагональных элементов матрицы (фраза &#039;&#039;&amp;quot;small enough&amp;quot;&#039;&#039; в псевдокоде) подразумевает:&lt;br /&gt;
&amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt; |T_{m,m-1}^{(k)}| \leq \varepsilon\,|T_{m,m}^{(k)}| \quad\quad &amp;lt;/math&amp;gt; , где &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt; \varepsilon &amp;lt;/math&amp;gt; - заданная точность&amp;lt;br&amp;gt;&lt;br /&gt;
Также вместо сдвига Релэя, обозначенного в алгоритме через &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;\mu^{(k)}&amp;lt;/math&amp;gt;, часто на практике используется сдвиг по Уилкинсону, который даёт гарантированную сходимость внедиагональных элементов матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt; T^{(k)} &amp;lt;/math&amp;gt;, формируемой на каждом шаге, к нулю, при этом жертвуя монотонностью их убывания.&amp;lt;ref&amp;gt;Голуб Дж., Ван Лоун Ч. - Матричные вычисления//М.: Мир. - 1999 (c. 378, вторая половина страницы)&amp;lt;/ref&amp;gt;&amp;lt;ref&amp;gt;Парлетт Б. Симметричная проблема собственных значений. Численные методы.,: Мир, 1983. с. 169&amp;lt;/ref&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Подробнее с различными сдвигами и соответствующими оценками скоростей и количествами операций можно ознакомиться по указанной ссылке:&amp;lt;ref&amp;gt;Парлетт Б. Симметричная проблема собственных значений. Численные методы.,: Мир, 1983. с. 179-182&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;Для совершения QR-декомпозиции на каждом шаге может использоваться любой из алгоритмов по ссылке.&amp;lt;ref&amp;gt;https://en.wikipedia.org/wiki/QR_decomposition&amp;lt;/ref&amp;gt; Подробные описания этих алгоритмов также доступны на данном ресурсе algowiki-project.&amp;lt;br&amp;gt;&lt;br /&gt;
Так как мы оперируем не обычной матрицей и даже не Хессенберговой, а симметричной и трёхдиагональной, то скорость таких алгоритмов значительно возрастёт. Например, согласно данному ресурсу &amp;lt;ref&amp;gt;http://algorithm.narod.ru/ln/eigen/ETridiag.html&amp;lt;/ref&amp;gt;, для QL-алгоритма с неявными сдвигами:&amp;lt;br&amp;gt;&lt;br /&gt;
Для трёхдиагональной матрицы объем арифметических действий составляет &amp;lt;math&amp;gt; O(n)&amp;lt;/math&amp;gt; на одну итерацию вместо &amp;lt;math&amp;gt; O(n^3)&amp;lt;/math&amp;gt; для матрицы общего вида, а число итераций для нахождения первых собственных значений примерно равно 4 - 5. Но на этих итерациях также уменьшаются внедиагональные элементы правого нижнего угла. И, таким образом, дальнейшие собственные значения ищутся значительно быстрее. Среднее число итераций на каждое собственное значение обычно составляет 1.3 - 1.6.&amp;lt;br&amp;gt; &lt;br /&gt;
Аналогично QL, QR-разложение трёхдиагольной матрицы также требует &amp;lt;math&amp;gt; O(n)&amp;lt;/math&amp;gt; флопов&amp;lt;ref&amp;gt;Голуб Дж., Ван Лоун Ч. - Матричные вычисления//М.: Мир. - 1999 (c. 378, начало раздела 8.2.2)&amp;lt;/ref&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Подводя итог, во второй части алгоритма Ланцоша можно выделить следующие макрооперации:&lt;br /&gt;
* умножение матрицы на вещественное число;&lt;br /&gt;
* перемножение матриц;&lt;br /&gt;
* умножение и сравнение вещественных чисел;&lt;br /&gt;
* + набор других макроопераций в зависимости от выбора метода, с помощью которого будет совершаться сама QR или QL-декомпозиция (выше продемонстрированы, уже, как минимум, 3 разных способа).&lt;br /&gt;
Так же, важно заметить, что набор макропераций может быть несколько другим, если выбрать какой-либо иной современный метод поиска собственных чисел трёхдиагональной матрицы, не использующий QR и QL разложения(факторизацию). Два таких метода были упомянуты в пункте 1.2.&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
С целью полностью не дублировать раздел 1.2 данной статьи, где представлен наглядный и доступный для понимания псевдокод алгоритма, постараемся лишь коротко просуммировать и обобщить весь перечень последовательных действий в рассматриваемом алгоритме.&lt;br /&gt;
&lt;br /&gt;
В качестве входных данных имеем: вещественная симметричная матрица &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; размера &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;n\times n&amp;lt;/math&amp;gt;, известный вещественный вектор &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;b&amp;lt;/math&amp;gt; длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; и число &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;n&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Далее:&lt;br /&gt;
* Инициализируем вещественную константу &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;\beta_0&amp;lt;/math&amp;gt; и векторы &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;q_0&amp;lt;/math&amp;gt; и &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;q_1&amp;lt;/math&amp;gt;&lt;br /&gt;
* Итерационно для всех &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j=1,...,k&amp;lt;/math&amp;gt;:&lt;br /&gt;
** Вычисляем вспомогательный вектор &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt;, используя умножение матрицы на вектор&lt;br /&gt;
** Вычисляем, используя скалярное произведение векторов, значение &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;\alpha_j&amp;lt;/math&amp;gt; - элемент на главной диагонали трёхдиагональной матрицы &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&amp;lt;/math&amp;gt;&lt;br /&gt;
** Вычисляем по формуле новое значение и перезаписываем вектор &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt;&lt;br /&gt;
** Вычисляем значение &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;\beta_j&amp;lt;/math&amp;gt; - элементы непосредственно над и под главной диагональю той же матрицы &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&amp;lt;/math&amp;gt;&lt;br /&gt;
** Вычисляем, зная вектор &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt;,  очередной столбец матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;Q&amp;lt;/math&amp;gt;, он же вектор Ланцоша : &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;\,\,q_{j+1}&amp;lt;/math&amp;gt;&lt;br /&gt;
** Теперь, когда матрица &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&amp;lt;/math&amp;gt; сформирована на очередном шаге, находим её собственные значения и вектора любым доступным способом, о чём было подробно сказано в пункте 1.2&lt;br /&gt;
** Переходим на следующую итерацию: &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j&amp;lt;/math&amp;gt;++&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
Оценим количество операций и сложность последовательного алгоритма, изложенного в предыдущем разделе.&lt;br /&gt;
*Для вычисления вектора &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt; умножается матрица размера &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;n\times n&amp;lt;/math&amp;gt; на вектор длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt;, и потребуется &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n^2&amp;lt;/math&amp;gt; операций умножения и &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n^2&amp;lt;/math&amp;gt; операций сложения.&lt;br /&gt;
*Умножение векторов &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;q^T_j&amp;lt;/math&amp;gt; и &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt; длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; потребует &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; операций умножения и &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; операций сложения.&lt;br /&gt;
*При вычислении нового значения вектора &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt; поэлементное сложение двух векторов длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; требует &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; операций сложения.&lt;br /&gt;
*Умножение вектора длины &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; на вещественное число требует &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; операций умножения.&lt;br /&gt;
*Нахождение квадратичной нормы вектора &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt;  длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; требует &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; умножений и &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; сложений и ещё 1 операцию извлечения квадратного корня.&lt;br /&gt;
*Заключительное нахождение собственных значений и собственных векторов трёхдиагональной матрицы &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;T_j&amp;lt;/math&amp;gt; размера &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j\times j&amp;lt;/math&amp;gt; с помощью QR-алгоритма потребует в худшем случае &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(j^3)&amp;lt;/math&amp;gt; операций.&amp;lt;ref&amp;gt;http://num-anal.srcc.msu.ru/lib_na/int_ae/int_ae6.htm (пункт 6.2, &amp;quot;Скорость сходимости при этом всегда не хуже квадратичной и почти всегда лучше кубической.&amp;quot;)&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Посчитаем теперь суммарное количество простейших операций на одной итерации алгоритма (без учёта записей в память):&lt;br /&gt;
*&amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n^2+5\,n&amp;lt;/math&amp;gt; операций умножения/деления&lt;br /&gt;
*&amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n^2+4\,n&amp;lt;/math&amp;gt; операций сложения/вычитания&lt;br /&gt;
*1 операция извлечения квадратного корня&amp;lt;br&amp;gt;&lt;br /&gt;
Отдельно после всех итераций при &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j=k&amp;lt;/math&amp;gt; :&lt;br /&gt;
*&amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(k^3)&amp;lt;/math&amp;gt; операций для поиска собственных значений и собственных векторов трёхдиагональной матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_k&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Итого можно утверждать следующее:&lt;br /&gt;
&lt;br /&gt;
Последовательная сложность одной итерации рассматриваемого алгоритма:  &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(n ^ 2) &amp;lt;/math&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Суммарная сложность алгоритма (&amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;/math&amp;gt; итераций): &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(k\,n ^ 2) + O(k ^ 3)&amp;lt;/math&amp;gt; &amp;lt;ref&amp;gt;Здесь мы полагаем, что мы не вычисляем собственные значения и векторы матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_j&amp;lt;/math&amp;gt; на каждом промежуточном шаге, а лишь единожды затрачиваем &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;O(k ^ 3)&amp;lt;/math&amp;gt; действий в конце для нахождения &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;/math&amp;gt; собственных значений и векторов матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_k&amp;lt;/math&amp;gt;&amp;lt;/ref&amp;gt; &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
На практике же обычно рассматривается число &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;&amp;lt;n&amp;lt;/math&amp;gt;, поэтому второе слагаемое можно опустить.&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
На рис. 1 продемонстрирован граф одной итерации (при каком-либо произвольном значении итератора &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j&amp;lt;/math&amp;gt;) описанного алгоритма без отображения входных и выходных данных. Наглядно продемонстрированы связи между всеми действиями, и с помощью деления на &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; потоков показано, какие операции возможно выполнять параллельно на каждом шаге с целью оптимизации и экономии машинного времени. В результате, после параллельно выполненных операций &#039;&#039;&#039;Division&#039;&#039;&#039; на заключительном ярусе, на выходе имеем значение следующего вектора Ланцоша &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;q_{j+1}&amp;lt;/math&amp;gt;, после чего следует переход на следующую итерацию, и процесс повторяется.&lt;br /&gt;
&lt;br /&gt;
[[Файл:Levin_graph.png|600px|thumb|center|Рис. 1]] &amp;lt;br&amp;gt;&lt;br /&gt;
Обозначения на рисунке: &amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Simp&#039;&#039;&#039; (от англ. simple) - операции сложения и умножения вещественных чисел при вычислении произведения матрицы на вектор;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Vec mult&#039;&#039;&#039; (от англ. vectors multiplication) - операция скалярного умножения двух векторов;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Vec subtr&#039;&#039;&#039; (от англ. vectors subtraction, из-за использованных в операции вычитаний векторов) - операция умножения вектора на число (выполняется дважды) и формирование нового значения &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;z_{new}&amp;lt;/math&amp;gt; по формуле: &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;z_{new} = z - \alpha_j q_j - \beta_{j-1}q_{j-1} \;&amp;lt;/math&amp;gt;;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;||\cdot||&amp;lt;/math&amp;gt; - операция вычисления нормы вектора;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Division&#039;&#039;&#039; - операция деления вектора на вещественное число  &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;\beta_j&amp;lt;/math&amp;gt; &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Важно отметить, что упомянутые выше операции также легко поддаются оптимизации. Например, попарные умножения вещественных координат векторов при вычислении скалярного произведения также легко выполняются параллельно на &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; потоках, а затем можно применить суммирование методом сдваивания, о котором сказано в следующем разделе. Умножение или деление вектора на вещественное число являющееся, по определению, умножением или делением всех его координат на это число тоже может быть выполнено эффективнее, если мы используем &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; потоков, а не выполняем эти действия последовательно.&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
Параллельные операции возможны только внутри итераций, так как рассматриваемый алгоритм является итерационным, и сами итерации строго последовательны.&amp;lt;br&amp;gt;&lt;br /&gt;
Рассмотрим в этом разделе подробнее, какой выигрыш мы можем получить при распараллеливании операций внутри одной итерации согласно графу из предыдущего раздела.&lt;br /&gt;
&lt;br /&gt;
Умножение вещественной симметричной матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; размера &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;n\times n&amp;lt;/math&amp;gt; на вектор &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;b&amp;lt;/math&amp;gt; длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; требует последовательного выполнения &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; ярусов умножений и сложений. Сложение элементов вектора длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; на каждом шаге перемножения можно оптимизировать и выполнить за &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;\log_2 n&amp;lt;/math&amp;gt; действий, если применять метод сдваивания.&lt;br /&gt;
&lt;br /&gt;
Дальнейшие операции выполняются последовательно, а вычисление значений векторов происходит за один ярус операций сложения или умножения.&lt;br /&gt;
&lt;br /&gt;
Ресурс параллелизма алгоритма вычисления собственных значений построенной трёхдиагональной матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_k&amp;lt;/math&amp;gt; размера &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k\times k&amp;lt;/math&amp;gt; зависит от выбранного алгоритма (об этих алгоритмах подробнее было сказано в разделах 1.2 и 1.4). Будет очень затратно с точки зрения объёма материала пытаться рассмотреть пусть даже часть этих методов в этой статье, а так же тонкости их распараллеливания. Предлагаем читателям при желании самим ознакомиться с этими алгоритмами на данном ресурсе или прибегнув к иным источникам.&lt;br /&gt;
&lt;br /&gt;
При классификации по высоте ЯПФ, таким образом, алгоритм Ланцоша без переортогонализации относится к алгоритмам с &#039;&#039;логарифмической сложностью&#039;&#039;, и его сложность равна &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(\log_2 n)&amp;lt;/math&amp;gt; с важным замечанием, что это сложность только одной итерации, а максимум в алгоритме может быть выполнено последовательно &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;/math&amp;gt; таких однотипных итераций, если не будет осуществлён ранний выход из цикла. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Несмотря на то, что на графе в предыдущем разделе для лучшей визуализации и понимания было изображено &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; потоков (никаких допущений мы не делали и нарушений с точки зрения логики и математики нет, можно изобразить большее число потоков, просто часть времени некоторые из них могут бездействовать и не использоваться), на самом деле правильным и разумным будет реализовать начальное параллельное выполнение &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n^2&amp;lt;/math&amp;gt; операций умножения всех вещественных элементов матрицы &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;A&amp;lt;/math&amp;gt; на соответствующие элементы вектора &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;q_j&amp;lt;/math&amp;gt;, после чего применять тот же самый упомянутый метод сдваивания. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Поэтому при классификации по ширине ЯПФ его сложность будет &#039;&#039;квадратичной&#039;&#039; и равна &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(n^2)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
&#039;&#039;&#039;Входные данные алгоритма:&#039;&#039;&#039; вещественная симметричная &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; размера &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;n\times n&amp;lt;/math&amp;gt;, вещественный вектор &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;b&amp;lt;/math&amp;gt; длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt;, и одно целое число &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;k&amp;lt;/math&amp;gt;, означающее количество итераций.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём входных данных:&#039;&#039;&#039; &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;n^2 +n + 1 &amp;lt;/math&amp;gt;. Если учесть, что матрица симметричная и достаточно для её однозначного определения задать элементы на главной диагонали и элементы над или под ней, то можно сократить объём входных данных с целью экономии памяти до: &amp;lt;math&amp;gt;\ \frac{n^2-n}{2}+n+n+1 =\frac{n^2+3n}{2} + 1&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные алгоритма:&#039;&#039;&#039; вектор собственных значений &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;\Theta^k&amp;lt;/math&amp;gt; длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;/math&amp;gt;, матрица &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;S^k&amp;lt;/math&amp;gt; из соответствующих собственных векторов размера &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n\times k&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём выходных данных:&#039;&#039;&#039; &amp;lt;math&amp;gt;k\;(n + 1)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
В данном разделе перечислены без какой-либо хронологии или связи друг с другом наиболее важные и разнообразные свойства алгоритма, на которые стоит и полезно обратить внимание, а также которые выгодно отличают его от схожих алгоритмов, решающих ту же задачу.&amp;lt;br&amp;gt;&lt;br /&gt;
1) Отношение последовательной сложности алгоритма к параллельной,с учётом &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;/math&amp;gt; итераций, равно &amp;lt;math&amp;gt;\;\;\frac{kn^2}{k \log_2{n}}=\frac{n^2}{\log_2{n}}&amp;lt;/math&amp;gt;;&amp;lt;br&amp;gt;&lt;br /&gt;
2) Вычислительная мощность алгоритма, как отношение числа операций к суммарному объему входных и выходных данных, равна &amp;lt;math style=&amp;quot;vertical-align:-70%&amp;gt;\;\;\frac{k\,n^2}{0.5\,n^2+1.5\,n+k\,n+k+1}&amp;lt;/math&amp;gt; и &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;\approx 2\,k&amp;lt;/math&amp;gt;, так как на практике верно отношение &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;&amp;lt;n&amp;lt;/math&amp;gt; ;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
3) Для собственных значений формируемых матриц &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_j&amp;lt;/math&amp;gt; верно отношение (следствие теоремы Коши о перемежаемости): &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;\lambda_i(T_{k+1})\geq \lambda_i(T_{k})\geq \lambda_{i+1}(T_{k+1})\geq \lambda_{i+1}(T_{k})&amp;lt;/math&amp;gt; ;&amp;lt;ref&amp;gt;James W. Demmel - Вычислительная линейная алгебра. Теория и приложения //Мир. - 2001 (c. 383)&amp;lt;/ref&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
4) Крайние (наибольшие и наименьшие) собственные значения матриц &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_j&amp;lt;/math&amp;gt; сходятся к крайним собственным значениям матрицы &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;A&amp;lt;/math&amp;gt; первыми (это часто происходит уже на ранних шагах при &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j\approx 2\,\sqrt{n}&amp;lt;/math&amp;gt;&amp;lt;ref&amp;gt;http://num-anal.srcc.msu.ru/lib_na/int_ae/int_ae6.htm (пункт 6.5)&amp;lt;/ref&amp;gt;), а собственные значения в середине спектра - последними;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
5) Из-за ограниченной точности постепенно теряется ортогональность вектора Ланцоша &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;q_j&amp;lt;/math&amp;gt; к предыдущим векторам Ланцоша, поэтому необходимо примерно каждые 10-15 итераций проводить дорогостоящую операцию реортогонализации, но это уже будет иной алгоритм с очень малым различием в одной операции и в программном коде, реализующем его, соответственно; &amp;lt;ref&amp;gt;Sam Handler - The Lanczos Algorithm For Large-Scale Eigenvalue Problems (08.01.07), slide №8&amp;lt;/ref&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
6) Эффективность и быстрота выполнения алгоритма очень сильно зависит от скорости памяти (диска). Согласно тесту только &#039;&#039;6%&#039;&#039; времени работы программы приходится на вычисления, остальное время затрачивается на ожидание отклика диска;&amp;lt;ref&amp;gt;Sam Handler - The Lanczos Algorithm For Large-Scale Eigenvalue Problems (08.01.07), slide №10&amp;lt;/ref&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
7) Метод Ланцоша удобен тем, что не требует хранения исходной матрицы полным массивом: метод использует исходную матрицу только в операциях умножения матрицы на вектор, что позволяет эффективно использовать разреженность матрицы или регулярность структуры матрицы. Поэтому метод Ланцоша может быть использован для матриц таких больших порядков, когда методы вращений и отражений не могут быть применены.&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;
Для исследования масштабируемости рассматриваемого алгоритма Ланцоша без переортогонализации автором была реализована программа на языке С++ с использованием технологии MPI (&#039;&#039;&#039;не забыть вставить ссылку на код&#039;&#039;&#039;). Дальнейшее исследование выполнялось на суперкомпьютере &amp;quot;Ломоносов&amp;quot; Суперкомпьютерного комплекса МГУ. &amp;lt;br&amp;gt; Важно отметить, что реализованная программа выполняет только первую часть алгоритма - формирование матрицы &amp;lt;math &amp;gt;T_j&amp;lt;/math&amp;gt;. Вторая часть алгоритма (задача поиска собственных значений матрицы &amp;lt;math &amp;gt;T_j&amp;lt;/math&amp;gt;) может быть решена несколькими методами, каждый из которых обладает своей эффективностью распараллеливании и характерными свойствами. Подробно этот вопрос уже обсуждался в статье раннее, поэтому не будем ещё раз заострять на этом внимание и останавливаться.&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Сборка осуществлялась со следующими параметрами:&lt;br /&gt;
* Компилятор intel/15.0.090 &lt;br /&gt;
* Openmpi/1.8.4-icc&lt;br /&gt;
В серии проведённых расчётов рассматривались следующие числовые значения параметров:&lt;br /&gt;
* Размер &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;n&amp;lt;/math&amp;gt; задачи и, соответственно, матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt;, задействованной в операции умножения на вектор: [2000 : 30000] с шагом 1000&lt;br /&gt;
* Число процессоров: 1, 2, 4, 16, 32, 48, 64, 96, 128&lt;br /&gt;
* Число итераций в алгоритме: &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k=350&amp;lt;/math&amp;gt; . Взято таким вопреки информации в начале статьи, где говорится, что значение &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; редко превышает &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;10^2&amp;lt;/math&amp;gt; (хотя и имеем право брать его любым по нашему усмотрению). Это сделано исключительно для лучшей визуализации пиков на графиках в данном разделе и наглядности получаемых результатов, так как при меньших на порядок значениях &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; времена выполнения программ были слишком малы даже при минимальных числах процессоров и максимальных размерах исходной задачи.&lt;br /&gt;
&lt;br /&gt;
== Динамические характеристики и эффективность реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Выводы для классов архитектур ==&lt;br /&gt;
По заданию, во второй части требовалось описать только разделы 2.4 и 2.7, прошу не спрашивать с меня все разделы 2.1-2.6. Надеюсь на понимание, мне физически не хватает времени на это задание + 2 других в течение семестра, делаю всё, что в моих силах :)&lt;br /&gt;
&lt;br /&gt;
== Существующие реализации алгоритма ==&lt;br /&gt;
Несмотря на то, что алгоритм является далеко не самым популярным, алгоритмом, про который нельзя сказать, что он всегда «на слуху», на сегодняшний день существует множество реализаций на различных популярных языках.&amp;lt;br&amp;gt;&lt;br /&gt;
Перечислим далее некоторые из них, указывая язык программирования, лежащий в их основе, и некоторые важные характеристики, которые обсуждались в статье ранее:&lt;br /&gt;
*&#039;&#039;Code on netlib.org by Jane Cullum and Ralph Willoughby&#039;&#039; (&#039;&#039;&#039;Fortran 77&#039;&#039;&#039;; без реортогонализации векторов; без реализации распараллеливания)&amp;lt;ref&amp;gt;http://www.netlib.org/lanczos/leval&amp;lt;/ref&amp;gt;&lt;br /&gt;
*&#039;&#039;Lanczos algorithm on freesourcecode.net&#039;&#039; (&#039;&#039;&#039;Matlab&#039;&#039;&#039;; присутствует реортогонализация векторов; без реализации распараллеливания)&amp;lt;ref&amp;gt;http://freesourcecode.net/matlabprojects/61741/lanczos-algorithm--in-matlab&amp;lt;/ref&amp;gt;&lt;br /&gt;
*&#039;&#039;Lanczos for eigenvalues in Numerical Linear Algebra, Spring 2007&#039;&#039; (&#039;&#039;&#039;Matlab&#039;&#039;&#039;; частичная или полная реортогонализация - доступны оба варианта; без реализации распараллеливания)&amp;lt;ref&amp;gt;Ссылки на файлы lanso.m и lanfu.m можно найти на https://www.nada.kth.se/~ruhe/2D5219/labs2007.html&amp;lt;/ref&amp;gt;&lt;br /&gt;
*&#039;&#039;Planso&#039;&#039; (название происходит от parallel Lanso.f) &#039;&#039;code by Kesheng Wu and Horst D. Simon&#039;&#039; (&#039;&#039;&#039;Fortran 77&#039;&#039;&#039;; частичная реортогонализация векторов; использование MPI для коммуникаций)&amp;lt;ref&amp;gt;https://github.com/jiahao/planso.jl/tree/master/external/PLAN/plan К сожалению, ссылка в описании пакета на github, ведущая на сайт National Energy Research Scientific Computing Center (NERSC), с более подробной информацией о данной программе больше не активна и выдаёт результат &#039;&#039;Page not found&#039;&#039;&amp;lt;/ref&amp;gt; &lt;br /&gt;
* &#039;&#039;Lanczos.cpp in the Vienna Computing Library&#039;&#039;  (&#039;&#039;&#039;C++&#039;&#039;&#039;, частичная реортогонализация, без реализации распараллеливания) &amp;lt;ref&amp;gt;http://viennacl.sourceforge.net/doc/lanczos_8cpp_source.html&amp;lt;/ref&amp;gt;&lt;br /&gt;
* &#039;&#039;Parallel Eigen Values code using C++ AMP on microsoft msdn blog&#039;&#039; (&#039;&#039;&#039;C++&#039;&#039;&#039;; ? ; распараллеливание есть и реализовано через C++ AMP) &amp;lt;ref&amp;gt;https://blogs.msdn.microsoft.com/nativeconcurrency/2013/12/20/eigen-values/ Подробнее о C++ Accelerated Massive Parallelism можно почитать здесь: https://msdn.microsoft.com/ru-ru/library/hh265137(v=vs.140).aspx или здесь: http://professorweb.ru/my/csharp/optimization/level4/4_6.php &amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;br /&gt;
[[en:Description of algorithm properties and structure]]&lt;/div&gt;</summary>
		<author><name>AleksLevin</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:AleksLevin/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%9B%D0%B0%D0%BD%D1%86%D0%BE%D1%88%D0%B0_%D0%B2%D1%8B%D1%87%D0%B8%D1%81%D0%BB%D0%B5%D0%BD%D0%B8%D1%8F_%D1%81%D0%BE%D0%B1%D1%81%D1%82%D0%B2%D0%B5%D0%BD%D0%BD%D1%8B%D1%85_%D0%B7%D0%BD%D0%B0%D1%87%D0%B5%D0%BD%D0%B8%D0%B9_%D1%81%D0%B8%D0%BC%D0%BC%D0%B5%D1%82%D1%80%D0%B8%D1%87%D0%BD%D0%BE%D0%B9_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86%D1%8B_%D0%B4%D0%BB%D1%8F_%D1%82%D0%BE%D1%87%D0%BD%D0%BE%D0%B9_%D0%B0%D1%80%D0%B8%D1%84%D0%BC%D0%B5%D1%82%D0%B8%D0%BA%D0%B8_(%D0%B1%D0%B5%D0%B7_%D0%BF%D0%B5%D1%80%D0%B5%D0%BE%D1%80%D1%82%D0%BE%D0%B3%D0%BE%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D0%B8)&amp;diff=20208</id>
		<title>Участник:AleksLevin/Алгоритм Ланцоша вычисления собственных значений симметричной матрицы для точной арифметики (без переортогонализации)</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:AleksLevin/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%9B%D0%B0%D0%BD%D1%86%D0%BE%D1%88%D0%B0_%D0%B2%D1%8B%D1%87%D0%B8%D1%81%D0%BB%D0%B5%D0%BD%D0%B8%D1%8F_%D1%81%D0%BE%D0%B1%D1%81%D1%82%D0%B2%D0%B5%D0%BD%D0%BD%D1%8B%D1%85_%D0%B7%D0%BD%D0%B0%D1%87%D0%B5%D0%BD%D0%B8%D0%B9_%D1%81%D0%B8%D0%BC%D0%BC%D0%B5%D1%82%D1%80%D0%B8%D1%87%D0%BD%D0%BE%D0%B9_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86%D1%8B_%D0%B4%D0%BB%D1%8F_%D1%82%D0%BE%D1%87%D0%BD%D0%BE%D0%B9_%D0%B0%D1%80%D0%B8%D1%84%D0%BC%D0%B5%D1%82%D0%B8%D0%BA%D0%B8_(%D0%B1%D0%B5%D0%B7_%D0%BF%D0%B5%D1%80%D0%B5%D0%BE%D1%80%D1%82%D0%BE%D0%B3%D0%BE%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D0%B8)&amp;diff=20208"/>
		<updated>2016-12-06T21:51:09Z</updated>

		<summary type="html">&lt;p&gt;AleksLevin: /* Масштабируемость алгоритма и его реализации */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Основные авторы описания: Левин А.Д.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{algorithm&lt;br /&gt;
| name              = Алгоритм Ланцоша для точной арифметики (без переортогонализации)&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(k\,n^2)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(k\log_2 n)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;\frac{n^2+3n}{2} + 1&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;k\;(n + 1)&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритмов =&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Данный алгоритм появился в 1950 г. и носит имя венгерского физика и математика Корнелия Ланцоша (венг. Lánczos Kornél). Алгоритм Ланцоша относится к итерационным методам вычисления собственных значений для матриц столь больших порядков &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt; n&amp;lt;/math&amp;gt;, что к ним нельзя применить прямые методы из-за ограничений по времени и памяти.&lt;br /&gt;
&lt;br /&gt;
Сам Ланцош указывал, что его метод предназначен для отыскания нескольких собственных векторов симметричных матриц, хотя к методу сразу было обращено внимание, как к способу приведения всей матрицы к трёхдиагональному виду. Двадцатью годами позже канадский математик Крис Пэж показал, что, несмотря на чувствительность к округлениям, алгоритм Ланцоша - эффективное средство вычисления некоторых &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; собственных чисел и соответствующих им собственных векторов. &amp;lt;ref&amp;gt;Парлетт Б. - Симметричная проблема собственных значений. Численные методы //М.: Мир. - 1983. (c. 276)&amp;lt;/ref&amp;gt;&lt;br /&gt;
Обычно число &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; берут в два раза больше, чем количество собственных значений матрицы, которые поставлена цель найти, и оно имеет порядок не более &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;10^2&amp;lt;/math&amp;gt;.&amp;lt;ref&amp;gt;Susan W. Bostic - Lanczos Eigensolution Method for High-Perfomance Computers, page 7&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Алгоритм Ланцоша для вычисления собственных значений симметричной матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; соединяет в себе метод Ланцоша для построения последовательности подпространств Крылова и ортонормированных векторов Ланцоша и процедуру Рэлея-Ритца получения оптимальных приближений собственных значений и соответствующих собственных векторов исходной матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt;.&amp;lt;ref&amp;gt;James W. Demmel - Вычислительная линейная алгебра. Теория и приложения //Мир. - 2001 (c. 381)&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
В данной статье рассматривается вариант алгоритма Ланцоша, в котором опущено влияние ошибок округления на вычислительный процесс, хотя на практике этому посвящается отдельное внимание и существуют различные методы решения данной проблемы, такие как частичная или полная переортогонализация. Этим модифицированным методам посвящены отдельные статьи на данном ресурсе.&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
Обозначения и формулы, используемые в данном разделе, взяты из литературы, указанной по ссылке.&amp;lt;ref&amp;gt;James W. Demmel - Вычислительная линейная алгебра. Теория и приложения //Мир. - 2001 (c. 313, &#039;&#039;&amp;lt;math&amp;gt; \S &amp;lt;/math&amp;gt; 6.6 Методы Крыловского подпространства&#039;&#039;)&amp;lt;/ref&amp;gt; &lt;br /&gt;
&lt;br /&gt;
Алгоритм Ланцоша для вычисления &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; собственных значений и собственных векторов вещественной симметричной матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A=A^T&amp;lt;/math&amp;gt; в точной арифметике: &amp;lt;ref&amp;gt;James W. Demmel - Вычислительная линейная алгебра. Теория и приложения //Мир. - 2001 (c. 381)&amp;lt;/ref&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{align}&lt;br /&gt;
q_1 = &amp;amp; \,\frac{b}{\|b\|_2},\; \beta_0 = 0,\; q_0 = 0\\&lt;br /&gt;
\mathbf{for} \; &amp;amp; j = 1 \; to \; k \,\; \mathbf{do} \\&lt;br /&gt;
&amp;amp; z = A\,q_j\\&lt;br /&gt;
&amp;amp; \alpha_j = q^T_j z\\&lt;br /&gt;
&amp;amp; z = z - \alpha_j q_j - \beta_{j-1}q_{j-1}\\&lt;br /&gt;
&amp;amp; \beta_j = \|z\|_2\\&lt;br /&gt;
&amp;amp; \mathbf{If} \; (\beta_j == 0) \; \mathbf{then}\; stop\; the\; algorithm \\ &lt;br /&gt;
&amp;amp; \;  q_{j+1} = \frac{z}{\beta_j} \\&lt;br /&gt;
&amp;amp; compute\; eigenvalues\; and \;eigenvectors\;of \;matrix \;\;T_j= Q^T_j A Q\;\;and\;estimate \;the\; errors\\&lt;br /&gt;
\mathbf{end} \; &amp;amp; \mathbf{for}&lt;br /&gt;
\end{align}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
В продемонстрированном выше алгоритме &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;b&amp;lt;/math&amp;gt; - заданный вещественный вектор. Также полагается известным алгоритм вычисления произведения матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; на вектор &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;x&amp;lt;/math&amp;gt;. &lt;br /&gt;
Введём матрицу Крылова, определяемую следующим соотношением: &amp;lt;math&amp;gt;K_j = [b,Ab,A^2b,...,A^{j-1}b]&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Далее, на практике, матрица &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;K&amp;lt;/math&amp;gt; заменяется матрицей &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;Q&amp;lt;/math&amp;gt;, такой, что при любом числе &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; линейные оболочки первых &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; столбцов в &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;K&amp;lt;/math&amp;gt; и &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;Q&amp;lt;/math&amp;gt; являются одним и тем же подпространством.&amp;lt;ref&amp;gt;James W. Demmel - Вычислительная линейная алгебра. Теория и приложения //Мир. - 2001 (c. 315)&amp;lt;/ref&amp;gt; &lt;br /&gt;
Тогда матрица &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;Q&amp;lt;/math&amp;gt;, в отличие от матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;K&amp;lt;/math&amp;gt;, хорошо обусловлена и легко обратима. В результате получаем матрицу &amp;lt;math&amp;gt;Q_j = [q_1, q_2, \dots, q_j]&amp;lt;/math&amp;gt; размерности &amp;lt;math&amp;gt;n\times j&amp;lt;/math&amp;gt;, столбцы которой ортогональны, являются базисом подпространства Крылова и называются векторами Ланцоша.&lt;br /&gt;
&lt;br /&gt;
В алгоритме Ланцоша вычислению подлежит столько первых столбцов в матрице &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;Q_j&amp;lt;/math&amp;gt;, сколько необходимо для получения требуемого приближения к решению &amp;lt;math&amp;gt;A\,x\,=b\,\,(A\,x=\lambda \, x)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Получение нулевого &amp;lt;math&amp;gt;\beta_j&amp;lt;/math&amp;gt; в итерационном процессе - событие, желательное в том смысле, что оно свидетельствует о том, что найдено некоторое подпространство, являющееся в точности инвариантным, а все собственные значения матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;T_j&amp;lt;/math&amp;gt; являются собственными значениями матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt;. На практике же нулевое и близкие к нулю значения получаются редко.&amp;lt;ref&amp;gt;Голуб Дж., Ван Лоун Ч. - Матричные вычисления//М.: Мир. - 1999 (c. 429)&amp;lt;/ref&amp;gt; &lt;br /&gt;
&lt;br /&gt;
Затем на каждом шаге цикла формируется симметричная трёхдиагональная матрица &amp;lt;math&amp;gt;T_j = Q^T_j A Q&amp;lt;/math&amp;gt;, к которой применяется процесс Рэлея-Ритца для поиска её собственных значений (на практике для поиска этих собственных значений можно использовать любой из специальных методов в параграфе книги по ссылке).&amp;lt;ref&amp;gt;Голуб Дж., Ван Лоун Ч. - Матричные вычисления//М.: Мир. - 1999 (&amp;lt;math&amp;gt;\S&amp;lt;/math&amp;gt; 8.4)&amp;lt;/ref&amp;gt;  &lt;br /&gt;
Эти собственные значения, они же числа Ритца, и полагаются приближёнными собственными значениями исходной матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt;.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Существует множество методов для отыскания собственных значений вещественной симметричной трехдиагональной матрицы. Большинство из них требует &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt; операций &amp;lt;ref&amp;gt;Парлетт Б. Симметричная проблема собственных значений. Численные методы.,: Мир, 1983. с. 179-182&amp;lt;/ref&amp;gt;, но существуют и быстрые алгоритмы, требующие лишь &amp;lt;math&amp;gt;O(n\ln n)&amp;lt;/math&amp;gt; операций.&amp;lt;ref&amp;gt;https://en.wikipedia.org/wiki/Tridiagonal_matrix#Eigenvalues  Раздел eigenvalues&amp;lt;/ref&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Одним из возможных способов отыскать собственные значения симметричной трехдиагональной матрицы - прямое вычисление корней характеристического полинома &amp;lt;math&amp;gt;p_n(\lambda)&amp;lt;/math&amp;gt; через метод деления пополам, где формируется последовательность Штурма и локализуются собственные числа, являющиеся корнями характеристического полинома. Нахождение всех &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; собственных значений матрицы этим способом требует &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;2n^2t&amp;lt;/math&amp;gt; умножений и вычитаний, где &amp;lt;math&amp;gt;t&amp;lt;/math&amp;gt; - число сделанных шагов с применением метода деления пополам.&amp;lt;ref&amp;gt;Уилкинсон Дж. X. Алгебраическая проблема собственныx значений. Изд-во &amp;quot;Наука&amp;quot;, 1970. - глава 5, с. 272-278&amp;lt;/ref&amp;gt; Соответствующие собственные вектора могут быть найдены посредством обратных итераций за &amp;lt;math&amp;gt; O(n) &amp;lt;/math&amp;gt; флопов. &amp;lt;ref&amp;gt;Голуб Дж., Ван Лоун Ч. - Матричные вычисления//М.: Мир. - 1999 (c. 394-395)&amp;lt;/ref&amp;gt; &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;На практике, если требуется только небольшая часть от всей совокупности собственных векторов и значений, и матрица имеет Хессенбергову или трёхдиагональную форму, очень эффективными будут методы факторизации, как, например, QR-алгоритм или QL-алгоритм со сдвигами (c целью ускорить алгоритм и сделать порядок сходимости квадратичным) или же без них.&amp;lt;ref&amp;gt;http://algorithm.narod.ru/ln/eigen/ETridiag.html&amp;lt;/ref&amp;gt; &amp;lt;br&amp;gt;&lt;br /&gt;
Весьма молодые и не менее актуальные конкуренты QR и QL алгоритмов, применяющиеся для поиска собственных значений:&lt;br /&gt;
*Методы divide-and-conquer (разделяй и властвуй), появившиеся в 1980-ых годах &amp;lt;ref&amp;gt;https://goo.gl/dapvbn ссылку пришлось сократить с помощью Google url shortener, так как символы подчеркивания портили её и не давали перейти по 1 клику&amp;lt;/ref&amp;gt;&lt;br /&gt;
*Relatively robust representation методы, появившиеся в 1990-ых и позволяющие найти собственные числа симметричной матрицы порядка &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;n&amp;lt;/math&amp;gt; за &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt; операций&lt;br /&gt;
&lt;br /&gt;
Если требуется вычислить собственные векторы, то необходимо хранить вычисляемые векторы Ланцоша. Если работа при этом производится только с оперативной памятью, то при большом порядке исходной матрицы (а именно для таких матриц и предназначен метод Ланцоша) число шагов  &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;j&amp;lt;/math&amp;gt;, которые могут быть выполнены до того момента, как оперативная память будет исчерпана, будет очень незначительно, а следовательно, искомые собственные пары могут не успеть сойтись с требуемой точностью. В этом случае метод Ланцоша можно использовать итерационным образом: после выполнения заданного числа шагов процесс прерывается и, если еще не все требуемые пары Ритца сошлись с требуемой точностью, то формируется новый начальный вектор &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;q_1&amp;lt;/math&amp;gt;, являющийся линейной комбинацией векторов Ритца, еще не сошедшихся с заданной точностью, и процесс начинается заново.&amp;lt;ref&amp;gt;http://num-anal.srcc.msu.ru/lib_na/int_ae/int_ae6.htm (пункт 6.5)&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
Вычислительное ядро рассматриваемого алгоритма (наиболее ресурсно-затратная часть алгоритма) -  формирование на каждом шаге цикла промежуточного вектора &amp;lt;math&amp;gt;z&amp;lt;/math&amp;gt;, вычисляемого по формуле: &amp;lt;math&amp;gt;z = A\,q_j&amp;lt;/math&amp;gt;. Данная операция, по сравнению с другими операциями алгоритма, затратна и требовательна, как с точки зрения количества производимых операций, так и с точки зрения объема оперируемых данных. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Например, умножение матрицы размера &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;n\times n&amp;lt;/math&amp;gt; на вектор длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; требует: &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;n^2+(n-1)n = 2n^2-n&amp;lt;/math&amp;gt; операций умножения и сложения. В свою очередь аналогичная операция умножения матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;(n+1)\times (n+1)&amp;lt;/math&amp;gt; на вектор длины &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;(n+1)&amp;lt;/math&amp;gt; требует: &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;2n^2+3n+1&amp;lt;/math&amp;gt;  операций умножения и сложения. То есть повышение размерности задачи всего на 1 увеличивает число необходимых действий в этом шаге алгоритма на: &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;4n+1&amp;lt;/math&amp;gt;. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Так же, стоит помнить, что, согласно разделу 1.2, данную операцию умножения матрицы на вектор необходимо выполнить &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;k&amp;lt;/math&amp;gt; раз. Нетрудно понять, насколько возрастает и колоссален масштаб операций, если в задачах, где критична точность, размерности &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; могут иметь порядок &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;10^5&amp;lt;/math&amp;gt; или даже более.&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
Как уже было упомянуто в данной статье в описании алгоритма, рассматриваемый алгоритм состоит из двух последовательно выполненных алгоритмов: метод Ланцоша для построения последовательности подпространств Крылова и ортонормированных векторов Ланцоша и процедура Рэлея-Ритца получения оптимальных приближений собственных значений и соответствующих собственных векторов исходной матрицы.&lt;br /&gt;
&lt;br /&gt;
В первой части алгоритма, где итерационно строятся Крыловское подпространство и трёхдиагональная матрица &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&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 style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; разреженная. Именно она подлежит оптимизации с использованием техник распараллеливания, поскольку она является вычислительным ядром алгоритма, а весь упомянутый процесс построения матрицы &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&amp;lt;/math&amp;gt; выполняется последовательно.&lt;br /&gt;
&lt;br /&gt;
Рассмотрим вторую часть алгоритма - поиск собственных значений сформированной матрицы &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&amp;lt;/math&amp;gt;.&amp;lt;br&amp;gt;&lt;br /&gt;
Далее, наглядно, в виде псевдокода, представлен, упомянутый в разделе 1.2, QR-алгоритм (аналогично можно рассмотреть и QL-алгоритм) со сдвигами Релэя, который весьма популярен на практике.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{align}&lt;br /&gt;
\mathbf{Input}: \;&amp;amp;tridiagonal\;\;matrix \;T\;with\;\;n\times n\;\;size\\&lt;br /&gt;
T^{(0)}&amp;amp;:=T\\&lt;br /&gt;
\mathbf{for}&amp;amp; \;\;m=n,...,2 \;\; \mathbf{do}\\&lt;br /&gt;
&amp;amp;k=0\\&lt;br /&gt;
&amp;amp; \mathbf{repeat}\\&lt;br /&gt;
&amp;amp; \quad \;\; k=k+1\\&lt;br /&gt;
&amp;amp; \quad \;\; \mu^{(k)}=T_{m,m}^{(k-1)}\\&lt;br /&gt;
&amp;amp; \quad \;\; Q^{(k)}R^{(k)}=T^{(k-1)}-\mu^{(k)}I\;\;using\;\;QR\;decomposition\\&lt;br /&gt;
&amp;amp; \quad \;\; T^{(k)}=R^{(k)}Q^{(k)}+\mu^{(k)}I\\&lt;br /&gt;
&amp;amp; \mathbf{until} \;\;\; |T_{m,m-1}^{(k)}| \;is\;\;small\;\;enough\\&lt;br /&gt;
&amp;amp; Save  \;\;T_{m,m}^{(k)} \;\;as\;\; converged\;\;eigenvalue\;of\;T\\ &lt;br /&gt;
&amp;amp; Remove \;\boldsymbol{n}\,th\;row\;and\;\boldsymbol{n}\,th\;column\;\;from \;T \\&lt;br /&gt;
&amp;amp; and\;take\;this\;new\;cropped\;matrix\;as\;new\;T^{(0)}\;with\;\;(n-1)\times (n-1)\;\;size\\&lt;br /&gt;
 \mathbf{end}&amp;amp;\; \mathbf{for}&lt;br /&gt;
\end{align}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Малость наддиагональных и поддиагональных элементов матрицы (фраза &#039;&#039;&amp;quot;small enough&amp;quot;&#039;&#039; в псевдокоде) подразумевает:&lt;br /&gt;
&amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt; |T_{m,m-1}^{(k)}| \leq \varepsilon\,|T_{m,m}^{(k)}| \quad\quad &amp;lt;/math&amp;gt; , где &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt; \varepsilon &amp;lt;/math&amp;gt; - заданная точность&amp;lt;br&amp;gt;&lt;br /&gt;
Также вместо сдвига Релэя, обозначенного в алгоритме через &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;\mu^{(k)}&amp;lt;/math&amp;gt;, часто на практике используется сдвиг по Уилкинсону, который даёт гарантированную сходимость внедиагональных элементов матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt; T^{(k)} &amp;lt;/math&amp;gt;, формируемой на каждом шаге, к нулю, при этом жертвуя монотонностью их убывания.&amp;lt;ref&amp;gt;Голуб Дж., Ван Лоун Ч. - Матричные вычисления//М.: Мир. - 1999 (c. 378, вторая половина страницы)&amp;lt;/ref&amp;gt;&amp;lt;ref&amp;gt;Парлетт Б. Симметричная проблема собственных значений. Численные методы.,: Мир, 1983. с. 169&amp;lt;/ref&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Подробнее с различными сдвигами и соответствующими оценками скоростей и количествами операций можно ознакомиться по указанной ссылке:&amp;lt;ref&amp;gt;Парлетт Б. Симметричная проблема собственных значений. Численные методы.,: Мир, 1983. с. 179-182&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;Для совершения QR-декомпозиции на каждом шаге может использоваться любой из алгоритмов по ссылке.&amp;lt;ref&amp;gt;https://en.wikipedia.org/wiki/QR_decomposition&amp;lt;/ref&amp;gt; Подробные описания этих алгоритмов также доступны на данном ресурсе algowiki-project.&amp;lt;br&amp;gt;&lt;br /&gt;
Так как мы оперируем не обычной матрицей и даже не Хессенберговой, а симметричной и трёхдиагональной, то скорость таких алгоритмов значительно возрастёт. Например, согласно данному ресурсу &amp;lt;ref&amp;gt;http://algorithm.narod.ru/ln/eigen/ETridiag.html&amp;lt;/ref&amp;gt;, для QL-алгоритма с неявными сдвигами:&amp;lt;br&amp;gt;&lt;br /&gt;
Для трёхдиагональной матрицы объем арифметических действий составляет &amp;lt;math&amp;gt; O(n)&amp;lt;/math&amp;gt; на одну итерацию вместо &amp;lt;math&amp;gt; O(n^3)&amp;lt;/math&amp;gt; для матрицы общего вида, а число итераций для нахождения первых собственных значений примерно равно 4 - 5. Но на этих итерациях также уменьшаются внедиагональные элементы правого нижнего угла. И, таким образом, дальнейшие собственные значения ищутся значительно быстрее. Среднее число итераций на каждое собственное значение обычно составляет 1.3 - 1.6.&amp;lt;br&amp;gt; &lt;br /&gt;
Аналогично QL, QR-разложение трёхдиагольной матрицы также требует &amp;lt;math&amp;gt; O(n)&amp;lt;/math&amp;gt; флопов&amp;lt;ref&amp;gt;Голуб Дж., Ван Лоун Ч. - Матричные вычисления//М.: Мир. - 1999 (c. 378, начало раздела 8.2.2)&amp;lt;/ref&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Подводя итог, во второй части алгоритма Ланцоша можно выделить следующие макрооперации:&lt;br /&gt;
* умножение матрицы на вещественное число;&lt;br /&gt;
* перемножение матриц;&lt;br /&gt;
* умножение и сравнение вещественных чисел;&lt;br /&gt;
* + набор других макроопераций в зависимости от выбора метода, с помощью которого будет совершаться сама QR или QL-декомпозиция (выше продемонстрированы, уже, как минимум, 3 разных способа).&lt;br /&gt;
Так же, важно заметить, что набор макропераций может быть несколько другим, если выбрать какой-либо иной современный метод поиска собственных чисел трёхдиагональной матрицы, не использующий QR и QL разложения(факторизацию). Два таких метода были упомянуты в пункте 1.2.&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
С целью полностью не дублировать раздел 1.2 данной статьи, где представлен наглядный и доступный для понимания псевдокод алгоритма, постараемся лишь коротко просуммировать и обобщить весь перечень последовательных действий в рассматриваемом алгоритме.&lt;br /&gt;
&lt;br /&gt;
В качестве входных данных имеем: вещественная симметричная матрица &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; размера &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;n\times n&amp;lt;/math&amp;gt;, известный вещественный вектор &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;b&amp;lt;/math&amp;gt; длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; и число &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;n&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Далее:&lt;br /&gt;
* Инициализируем вещественную константу &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;\beta_0&amp;lt;/math&amp;gt; и векторы &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;q_0&amp;lt;/math&amp;gt; и &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;q_1&amp;lt;/math&amp;gt;&lt;br /&gt;
* Итерационно для всех &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j=1,...,k&amp;lt;/math&amp;gt;:&lt;br /&gt;
** Вычисляем вспомогательный вектор &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt;, используя умножение матрицы на вектор&lt;br /&gt;
** Вычисляем, используя скалярное произведение векторов, значение &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;\alpha_j&amp;lt;/math&amp;gt; - элемент на главной диагонали трёхдиагональной матрицы &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&amp;lt;/math&amp;gt;&lt;br /&gt;
** Вычисляем по формуле новое значение и перезаписываем вектор &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt;&lt;br /&gt;
** Вычисляем значение &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;\beta_j&amp;lt;/math&amp;gt; - элементы непосредственно над и под главной диагональю той же матрицы &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&amp;lt;/math&amp;gt;&lt;br /&gt;
** Вычисляем, зная вектор &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt;,  очередной столбец матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;Q&amp;lt;/math&amp;gt;, он же вектор Ланцоша : &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;\,\,q_{j+1}&amp;lt;/math&amp;gt;&lt;br /&gt;
** Теперь, когда матрица &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&amp;lt;/math&amp;gt; сформирована на очередном шаге, находим её собственные значения и вектора любым доступным способом, о чём было подробно сказано в пункте 1.2&lt;br /&gt;
** Переходим на следующую итерацию: &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j&amp;lt;/math&amp;gt;++&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
Оценим количество операций и сложность последовательного алгоритма, изложенного в предыдущем разделе.&lt;br /&gt;
*Для вычисления вектора &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt; умножается матрица размера &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;n\times n&amp;lt;/math&amp;gt; на вектор длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt;, и потребуется &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n^2&amp;lt;/math&amp;gt; операций умножения и &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n^2&amp;lt;/math&amp;gt; операций сложения.&lt;br /&gt;
*Умножение векторов &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;q^T_j&amp;lt;/math&amp;gt; и &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt; длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; потребует &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; операций умножения и &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; операций сложения.&lt;br /&gt;
*При вычислении нового значения вектора &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt; поэлементное сложение двух векторов длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; требует &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; операций сложения.&lt;br /&gt;
*Умножение вектора длины &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; на вещественное число требует &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; операций умножения.&lt;br /&gt;
*Нахождение квадратичной нормы вектора &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt;  длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; требует &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; умножений и &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; сложений и ещё 1 операцию извлечения квадратного корня.&lt;br /&gt;
*Заключительное нахождение собственных значений и собственных векторов трёхдиагональной матрицы &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;T_j&amp;lt;/math&amp;gt; размера &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j\times j&amp;lt;/math&amp;gt; с помощью QR-алгоритма потребует в худшем случае &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(j^3)&amp;lt;/math&amp;gt; операций.&amp;lt;ref&amp;gt;http://num-anal.srcc.msu.ru/lib_na/int_ae/int_ae6.htm (пункт 6.2, &amp;quot;Скорость сходимости при этом всегда не хуже квадратичной и почти всегда лучше кубической.&amp;quot;)&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Посчитаем теперь суммарное количество простейших операций на одной итерации алгоритма (без учёта записей в память):&lt;br /&gt;
*&amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n^2+5\,n&amp;lt;/math&amp;gt; операций умножения/деления&lt;br /&gt;
*&amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n^2+4\,n&amp;lt;/math&amp;gt; операций сложения/вычитания&lt;br /&gt;
*1 операция извлечения квадратного корня&amp;lt;br&amp;gt;&lt;br /&gt;
Отдельно после всех итераций при &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j=k&amp;lt;/math&amp;gt; :&lt;br /&gt;
*&amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(k^3)&amp;lt;/math&amp;gt; операций для поиска собственных значений и собственных векторов трёхдиагональной матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_k&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Итого можно утверждать следующее:&lt;br /&gt;
&lt;br /&gt;
Последовательная сложность одной итерации рассматриваемого алгоритма:  &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(n ^ 2) &amp;lt;/math&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Суммарная сложность алгоритма (&amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;/math&amp;gt; итераций): &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(k\,n ^ 2) + O(k ^ 3)&amp;lt;/math&amp;gt; &amp;lt;ref&amp;gt;Здесь мы полагаем, что мы не вычисляем собственные значения и векторы матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_j&amp;lt;/math&amp;gt; на каждом промежуточном шаге, а лишь единожды затрачиваем &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;O(k ^ 3)&amp;lt;/math&amp;gt; действий в конце для нахождения &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;/math&amp;gt; собственных значений и векторов матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_k&amp;lt;/math&amp;gt;&amp;lt;/ref&amp;gt; &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
На практике же обычно рассматривается число &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;&amp;lt;n&amp;lt;/math&amp;gt;, поэтому второе слагаемое можно опустить.&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
На рис. 1 продемонстрирован граф одной итерации (при каком-либо произвольном значении итератора &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j&amp;lt;/math&amp;gt;) описанного алгоритма без отображения входных и выходных данных. Наглядно продемонстрированы связи между всеми действиями, и с помощью деления на &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; потоков показано, какие операции возможно выполнять параллельно на каждом шаге с целью оптимизации и экономии машинного времени. В результате, после параллельно выполненных операций &#039;&#039;&#039;Division&#039;&#039;&#039; на заключительном ярусе, на выходе имеем значение следующего вектора Ланцоша &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;q_{j+1}&amp;lt;/math&amp;gt;, после чего следует переход на следующую итерацию, и процесс повторяется.&lt;br /&gt;
&lt;br /&gt;
[[Файл:Levin_graph.png|600px|thumb|center|Рис. 1]] &amp;lt;br&amp;gt;&lt;br /&gt;
Обозначения на рисунке: &amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Simp&#039;&#039;&#039; (от англ. simple) - операции сложения и умножения вещественных чисел при вычислении произведения матрицы на вектор;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Vec mult&#039;&#039;&#039; (от англ. vectors multiplication) - операция скалярного умножения двух векторов;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Vec subtr&#039;&#039;&#039; (от англ. vectors subtraction, из-за использованных в операции вычитаний векторов) - операция умножения вектора на число (выполняется дважды) и формирование нового значения &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;z_{new}&amp;lt;/math&amp;gt; по формуле: &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;z_{new} = z - \alpha_j q_j - \beta_{j-1}q_{j-1} \;&amp;lt;/math&amp;gt;;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;||\cdot||&amp;lt;/math&amp;gt; - операция вычисления нормы вектора;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Division&#039;&#039;&#039; - операция деления вектора на вещественное число  &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;\beta_j&amp;lt;/math&amp;gt; &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Важно отметить, что упомянутые выше операции также легко поддаются оптимизации. Например, попарные умножения вещественных координат векторов при вычислении скалярного произведения также легко выполняются параллельно на &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; потоках, а затем можно применить суммирование методом сдваивания, о котором сказано в следующем разделе. Умножение или деление вектора на вещественное число являющееся, по определению, умножением или делением всех его координат на это число тоже может быть выполнено эффективнее, если мы используем &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; потоков, а не выполняем эти действия последовательно.&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
Параллельные операции возможны только внутри итераций, так как рассматриваемый алгоритм является итерационным, и сами итерации строго последовательны.&amp;lt;br&amp;gt;&lt;br /&gt;
Рассмотрим в этом разделе подробнее, какой выигрыш мы можем получить при распараллеливании операций внутри одной итерации согласно графу из предыдущего раздела.&lt;br /&gt;
&lt;br /&gt;
Умножение вещественной симметричной матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; размера &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;n\times n&amp;lt;/math&amp;gt; на вектор &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;b&amp;lt;/math&amp;gt; длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; требует последовательного выполнения &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; ярусов умножений и сложений. Сложение элементов вектора длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; на каждом шаге перемножения можно оптимизировать и выполнить за &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;\log_2 n&amp;lt;/math&amp;gt; действий, если применять метод сдваивания.&lt;br /&gt;
&lt;br /&gt;
Дальнейшие операции выполняются последовательно, а вычисление значений векторов происходит за один ярус операций сложения или умножения.&lt;br /&gt;
&lt;br /&gt;
Ресурс параллелизма алгоритма вычисления собственных значений построенной трёхдиагональной матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_k&amp;lt;/math&amp;gt; размера &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k\times k&amp;lt;/math&amp;gt; зависит от выбранного алгоритма (об этих алгоритмах подробнее было сказано в разделах 1.2 и 1.4). Будет очень затратно с точки зрения объёма материала пытаться рассмотреть пусть даже часть этих методов в этой статье, а так же тонкости их распараллеливания. Предлагаем читателям при желании самим ознакомиться с этими алгоритмами на данном ресурсе или прибегнув к иным источникам.&lt;br /&gt;
&lt;br /&gt;
При классификации по высоте ЯПФ, таким образом, алгоритм Ланцоша без переортогонализации относится к алгоритмам с &#039;&#039;логарифмической сложностью&#039;&#039;, и его сложность равна &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(\log_2 n)&amp;lt;/math&amp;gt; с важным замечанием, что это сложность только одной итерации, а максимум в алгоритме может быть выполнено последовательно &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;/math&amp;gt; таких однотипных итераций, если не будет осуществлён ранний выход из цикла. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Несмотря на то, что на графе в предыдущем разделе для лучшей визуализации и понимания было изображено &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; потоков (никаких допущений мы не делали и нарушений с точки зрения логики и математики нет, можно изобразить большее число потоков, просто часть времени некоторые из них могут бездействовать и не использоваться), на самом деле правильным и разумным будет реализовать начальное параллельное выполнение &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n^2&amp;lt;/math&amp;gt; операций умножения всех вещественных элементов матрицы &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;A&amp;lt;/math&amp;gt; на соответствующие элементы вектора &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;q_j&amp;lt;/math&amp;gt;, после чего применять тот же самый упомянутый метод сдваивания. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Поэтому при классификации по ширине ЯПФ его сложность будет &#039;&#039;квадратичной&#039;&#039; и равна &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(n^2)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
&#039;&#039;&#039;Входные данные алгоритма:&#039;&#039;&#039; вещественная симметричная &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; размера &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;n\times n&amp;lt;/math&amp;gt;, вещественный вектор &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;b&amp;lt;/math&amp;gt; длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt;, и одно целое число &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;k&amp;lt;/math&amp;gt;, означающее количество итераций.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём входных данных:&#039;&#039;&#039; &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;n^2 +n + 1 &amp;lt;/math&amp;gt;. Если учесть, что матрица симметричная и достаточно для её однозначного определения задать элементы на главной диагонали и элементы над или под ней, то можно сократить объём входных данных с целью экономии памяти до: &amp;lt;math&amp;gt;\ \frac{n^2-n}{2}+n+n+1 =\frac{n^2+3n}{2} + 1&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные алгоритма:&#039;&#039;&#039; вектор собственных значений &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;\Theta^k&amp;lt;/math&amp;gt; длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;/math&amp;gt;, матрица &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;S^k&amp;lt;/math&amp;gt; из соответствующих собственных векторов размера &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n\times k&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём выходных данных:&#039;&#039;&#039; &amp;lt;math&amp;gt;k\;(n + 1)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
В данном разделе перечислены без какой-либо хронологии или связи друг с другом наиболее важные и разнообразные свойства алгоритма, на которые стоит и полезно обратить внимание, а также которые выгодно отличают его от схожих алгоритмов, решающих ту же задачу.&amp;lt;br&amp;gt;&lt;br /&gt;
1) Отношение последовательной сложности алгоритма к параллельной,с учётом &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;/math&amp;gt; итераций, равно &amp;lt;math&amp;gt;\;\;\frac{kn^2}{k \log_2{n}}=\frac{n^2}{\log_2{n}}&amp;lt;/math&amp;gt;;&amp;lt;br&amp;gt;&lt;br /&gt;
2) Вычислительная мощность алгоритма, как отношение числа операций к суммарному объему входных и выходных данных, равна &amp;lt;math style=&amp;quot;vertical-align:-70%&amp;gt;\;\;\frac{k\,n^2}{0.5\,n^2+1.5\,n+k\,n+k+1}&amp;lt;/math&amp;gt; и &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;\approx 2\,k&amp;lt;/math&amp;gt;, так как на практике верно отношение &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;&amp;lt;n&amp;lt;/math&amp;gt; ;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
3) Для собственных значений формируемых матриц &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_j&amp;lt;/math&amp;gt; верно отношение (следствие теоремы Коши о перемежаемости): &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;\lambda_i(T_{k+1})\geq \lambda_i(T_{k})\geq \lambda_{i+1}(T_{k+1})\geq \lambda_{i+1}(T_{k})&amp;lt;/math&amp;gt; ;&amp;lt;ref&amp;gt;James W. Demmel - Вычислительная линейная алгебра. Теория и приложения //Мир. - 2001 (c. 383)&amp;lt;/ref&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
4) Крайние (наибольшие и наименьшие) собственные значения матриц &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_j&amp;lt;/math&amp;gt; сходятся к крайним собственным значениям матрицы &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;A&amp;lt;/math&amp;gt; первыми (это часто происходит уже на ранних шагах при &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j\approx 2\,\sqrt{n}&amp;lt;/math&amp;gt;&amp;lt;ref&amp;gt;http://num-anal.srcc.msu.ru/lib_na/int_ae/int_ae6.htm (пункт 6.5)&amp;lt;/ref&amp;gt;), а собственные значения в середине спектра - последними;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
5) Из-за ограниченной точности постепенно теряется ортогональность вектора Ланцоша &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;q_j&amp;lt;/math&amp;gt; к предыдущим векторам Ланцоша, поэтому необходимо примерно каждые 10-15 итераций проводить дорогостоящую операцию реортогонализации, но это уже будет иной алгоритм с очень малым различием в одной операции и в программном коде, реализующем его, соответственно; &amp;lt;ref&amp;gt;Sam Handler - The Lanczos Algorithm For Large-Scale Eigenvalue Problems (08.01.07), slide №8&amp;lt;/ref&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
6) Эффективность и быстрота выполнения алгоритма очень сильно зависит от скорости памяти (диска). Согласно тесту только &#039;&#039;6%&#039;&#039; времени работы программы приходится на вычисления, остальное время затрачивается на ожидание отклика диска;&amp;lt;ref&amp;gt;Sam Handler - The Lanczos Algorithm For Large-Scale Eigenvalue Problems (08.01.07), slide №10&amp;lt;/ref&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
7) Метод Ланцоша удобен тем, что не требует хранения исходной матрицы полным массивом: метод использует исходную матрицу только в операциях умножения матрицы на вектор, что позволяет эффективно использовать разреженность матрицы или регулярность структуры матрицы. Поэтому метод Ланцоша может быть использован для матриц таких больших порядков, когда методы вращений и отражений не могут быть применены.&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;
Для исследования масштабируемости рассматриваемого алгоритма Ланцоша без переортогонализации автором была реализована программа на языке С++ с использованием технологии MPI (&#039;&#039;&#039;не забыть вставить ссылку на код&#039;&#039;&#039;). Дальнейшее исследование выполнялось на суперкомпьютере &amp;quot;Ломоносов&amp;quot; Суперкомпьютерного комплекса МГУ. &amp;lt;br&amp;gt; Важно отметить, что реализованная программа выполняет только первую часть алгоритма - формирование матрицы &amp;lt;math &amp;gt;T_j&amp;lt;/math&amp;gt;. Вторая часть алгоритма (задача поиска собственных значений матрицы &amp;lt;math &amp;gt;T_j&amp;lt;/math&amp;gt;) может быть решена несколькими методами, каждый из которых обладает своей эффективностью распараллеливании и характерными свойствами. Подробно этот вопрос уже обсуждался в статье раннее, поэтому не будем ещё раз заострять на этом внимание и останавливаться.&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Сборка осуществлялась со следующими параметрами:&lt;br /&gt;
* Компилятор intel/15.0.090 &lt;br /&gt;
* Openmpi/1.8.4-icc&lt;br /&gt;
В серии проведённых расчётов рассматривались следующие числовые значения параметров:&lt;br /&gt;
* Размер &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;n&amp;lt;/math&amp;gt; задачи и, соответственно, матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt;, задействованной в операции умножения на вектор: [2000 : 30000] с шагом 1000&lt;br /&gt;
* Число процессоров: 1, 2, 4, 16, 32, 48, 64, 96, 128&lt;br /&gt;
* Число итераций в алгоритме: &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k=350&amp;lt;/math&amp;gt; . Взято таким вопреки информации в начале статьи, где говорится, что значение &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; редко превышает &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;10^2&amp;lt;/math&amp;gt;. Это сделано исключительно для лучшей визуализации пиков на графиках в данном разделе и наглядности получаемых результатов, так как при меньших на порядок значениях &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; времена выполнения программ были слишком малы даже при минимальных числах процессоров и максимальных размерах исходной задачи.&lt;br /&gt;
&lt;br /&gt;
== Динамические характеристики и эффективность реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Выводы для классов архитектур ==&lt;br /&gt;
По заданию, во второй части требовалось описать только разделы 2.4 и 2.7, прошу не спрашивать с меня все разделы 2.1-2.6. Надеюсь на понимание, мне физически не хватает времени на это задание + 2 других в течение семестра, делаю всё, что в моих силах :)&lt;br /&gt;
&lt;br /&gt;
== Существующие реализации алгоритма ==&lt;br /&gt;
Несмотря на то, что алгоритм является далеко не самым популярным, алгоритмом, про который нельзя сказать, что он всегда «на слуху», на сегодняшний день существует множество реализаций на различных популярных языках.&amp;lt;br&amp;gt;&lt;br /&gt;
Перечислим далее некоторые из них, указывая язык программирования, лежащий в их основе, и некоторые важные характеристики, которые обсуждались в статье ранее:&lt;br /&gt;
*&#039;&#039;Code on netlib.org by Jane Cullum and Ralph Willoughby&#039;&#039; (&#039;&#039;&#039;Fortran 77&#039;&#039;&#039;; без реортогонализации векторов; без реализации распараллеливания)&amp;lt;ref&amp;gt;http://www.netlib.org/lanczos/leval&amp;lt;/ref&amp;gt;&lt;br /&gt;
*&#039;&#039;Lanczos algorithm on freesourcecode.net&#039;&#039; (&#039;&#039;&#039;Matlab&#039;&#039;&#039;; присутствует реортогонализация векторов; без реализации распараллеливания)&amp;lt;ref&amp;gt;http://freesourcecode.net/matlabprojects/61741/lanczos-algorithm--in-matlab&amp;lt;/ref&amp;gt;&lt;br /&gt;
*&#039;&#039;Lanczos for eigenvalues in Numerical Linear Algebra, Spring 2007&#039;&#039; (&#039;&#039;&#039;Matlab&#039;&#039;&#039;; частичная или полная реортогонализация - доступны оба варианта; без реализации распараллеливания)&amp;lt;ref&amp;gt;Ссылки на файлы lanso.m и lanfu.m можно найти на https://www.nada.kth.se/~ruhe/2D5219/labs2007.html&amp;lt;/ref&amp;gt;&lt;br /&gt;
*&#039;&#039;Planso&#039;&#039; (название происходит от parallel Lanso.f) &#039;&#039;code by Kesheng Wu and Horst D. Simon&#039;&#039; (&#039;&#039;&#039;Fortran 77&#039;&#039;&#039;; частичная реортогонализация векторов; использование MPI для коммуникаций)&amp;lt;ref&amp;gt;https://github.com/jiahao/planso.jl/tree/master/external/PLAN/plan К сожалению, ссылка в описании пакета на github, ведущая на сайт National Energy Research Scientific Computing Center (NERSC), с более подробной информацией о данной программе больше не активна и выдаёт результат &#039;&#039;Page not found&#039;&#039;&amp;lt;/ref&amp;gt; &lt;br /&gt;
* &#039;&#039;Lanczos.cpp in the Vienna Computing Library&#039;&#039;  (&#039;&#039;&#039;C++&#039;&#039;&#039;, частичная реортогонализация, без реализации распараллеливания) &amp;lt;ref&amp;gt;http://viennacl.sourceforge.net/doc/lanczos_8cpp_source.html&amp;lt;/ref&amp;gt;&lt;br /&gt;
* &#039;&#039;Parallel Eigen Values code using C++ AMP on microsoft msdn blog&#039;&#039; (&#039;&#039;&#039;C++&#039;&#039;&#039;; ? ; распараллеливание есть и реализовано через C++ AMP) &amp;lt;ref&amp;gt;https://blogs.msdn.microsoft.com/nativeconcurrency/2013/12/20/eigen-values/ Подробнее о C++ Accelerated Massive Parallelism можно почитать здесь: https://msdn.microsoft.com/ru-ru/library/hh265137(v=vs.140).aspx или здесь: http://professorweb.ru/my/csharp/optimization/level4/4_6.php &amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;br /&gt;
[[en:Description of algorithm properties and structure]]&lt;/div&gt;</summary>
		<author><name>AleksLevin</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:AleksLevin/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%9B%D0%B0%D0%BD%D1%86%D0%BE%D1%88%D0%B0_%D0%B2%D1%8B%D1%87%D0%B8%D1%81%D0%BB%D0%B5%D0%BD%D0%B8%D1%8F_%D1%81%D0%BE%D0%B1%D1%81%D1%82%D0%B2%D0%B5%D0%BD%D0%BD%D1%8B%D1%85_%D0%B7%D0%BD%D0%B0%D1%87%D0%B5%D0%BD%D0%B8%D0%B9_%D1%81%D0%B8%D0%BC%D0%BC%D0%B5%D1%82%D1%80%D0%B8%D1%87%D0%BD%D0%BE%D0%B9_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86%D1%8B_%D0%B4%D0%BB%D1%8F_%D1%82%D0%BE%D1%87%D0%BD%D0%BE%D0%B9_%D0%B0%D1%80%D0%B8%D1%84%D0%BC%D0%B5%D1%82%D0%B8%D0%BA%D0%B8_(%D0%B1%D0%B5%D0%B7_%D0%BF%D0%B5%D1%80%D0%B5%D0%BE%D1%80%D1%82%D0%BE%D0%B3%D0%BE%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D0%B8)&amp;diff=20207</id>
		<title>Участник:AleksLevin/Алгоритм Ланцоша вычисления собственных значений симметричной матрицы для точной арифметики (без переортогонализации)</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:AleksLevin/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%9B%D0%B0%D0%BD%D1%86%D0%BE%D1%88%D0%B0_%D0%B2%D1%8B%D1%87%D0%B8%D1%81%D0%BB%D0%B5%D0%BD%D0%B8%D1%8F_%D1%81%D0%BE%D0%B1%D1%81%D1%82%D0%B2%D0%B5%D0%BD%D0%BD%D1%8B%D1%85_%D0%B7%D0%BD%D0%B0%D1%87%D0%B5%D0%BD%D0%B8%D0%B9_%D1%81%D0%B8%D0%BC%D0%BC%D0%B5%D1%82%D1%80%D0%B8%D1%87%D0%BD%D0%BE%D0%B9_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86%D1%8B_%D0%B4%D0%BB%D1%8F_%D1%82%D0%BE%D1%87%D0%BD%D0%BE%D0%B9_%D0%B0%D1%80%D0%B8%D1%84%D0%BC%D0%B5%D1%82%D0%B8%D0%BA%D0%B8_(%D0%B1%D0%B5%D0%B7_%D0%BF%D0%B5%D1%80%D0%B5%D0%BE%D1%80%D1%82%D0%BE%D0%B3%D0%BE%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D0%B8)&amp;diff=20207"/>
		<updated>2016-12-06T21:50:15Z</updated>

		<summary type="html">&lt;p&gt;AleksLevin: /* Масштабируемость алгоритма и его реализации */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Основные авторы описания: Левин А.Д.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{algorithm&lt;br /&gt;
| name              = Алгоритм Ланцоша для точной арифметики (без переортогонализации)&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(k\,n^2)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(k\log_2 n)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;\frac{n^2+3n}{2} + 1&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;k\;(n + 1)&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритмов =&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Данный алгоритм появился в 1950 г. и носит имя венгерского физика и математика Корнелия Ланцоша (венг. Lánczos Kornél). Алгоритм Ланцоша относится к итерационным методам вычисления собственных значений для матриц столь больших порядков &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt; n&amp;lt;/math&amp;gt;, что к ним нельзя применить прямые методы из-за ограничений по времени и памяти.&lt;br /&gt;
&lt;br /&gt;
Сам Ланцош указывал, что его метод предназначен для отыскания нескольких собственных векторов симметричных матриц, хотя к методу сразу было обращено внимание, как к способу приведения всей матрицы к трёхдиагональному виду. Двадцатью годами позже канадский математик Крис Пэж показал, что, несмотря на чувствительность к округлениям, алгоритм Ланцоша - эффективное средство вычисления некоторых &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; собственных чисел и соответствующих им собственных векторов. &amp;lt;ref&amp;gt;Парлетт Б. - Симметричная проблема собственных значений. Численные методы //М.: Мир. - 1983. (c. 276)&amp;lt;/ref&amp;gt;&lt;br /&gt;
Обычно число &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; берут в два раза больше, чем количество собственных значений матрицы, которые поставлена цель найти, и оно имеет порядок не более &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;10^2&amp;lt;/math&amp;gt;.&amp;lt;ref&amp;gt;Susan W. Bostic - Lanczos Eigensolution Method for High-Perfomance Computers, page 7&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Алгоритм Ланцоша для вычисления собственных значений симметричной матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; соединяет в себе метод Ланцоша для построения последовательности подпространств Крылова и ортонормированных векторов Ланцоша и процедуру Рэлея-Ритца получения оптимальных приближений собственных значений и соответствующих собственных векторов исходной матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt;.&amp;lt;ref&amp;gt;James W. Demmel - Вычислительная линейная алгебра. Теория и приложения //Мир. - 2001 (c. 381)&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
В данной статье рассматривается вариант алгоритма Ланцоша, в котором опущено влияние ошибок округления на вычислительный процесс, хотя на практике этому посвящается отдельное внимание и существуют различные методы решения данной проблемы, такие как частичная или полная переортогонализация. Этим модифицированным методам посвящены отдельные статьи на данном ресурсе.&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
Обозначения и формулы, используемые в данном разделе, взяты из литературы, указанной по ссылке.&amp;lt;ref&amp;gt;James W. Demmel - Вычислительная линейная алгебра. Теория и приложения //Мир. - 2001 (c. 313, &#039;&#039;&amp;lt;math&amp;gt; \S &amp;lt;/math&amp;gt; 6.6 Методы Крыловского подпространства&#039;&#039;)&amp;lt;/ref&amp;gt; &lt;br /&gt;
&lt;br /&gt;
Алгоритм Ланцоша для вычисления &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; собственных значений и собственных векторов вещественной симметричной матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A=A^T&amp;lt;/math&amp;gt; в точной арифметике: &amp;lt;ref&amp;gt;James W. Demmel - Вычислительная линейная алгебра. Теория и приложения //Мир. - 2001 (c. 381)&amp;lt;/ref&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{align}&lt;br /&gt;
q_1 = &amp;amp; \,\frac{b}{\|b\|_2},\; \beta_0 = 0,\; q_0 = 0\\&lt;br /&gt;
\mathbf{for} \; &amp;amp; j = 1 \; to \; k \,\; \mathbf{do} \\&lt;br /&gt;
&amp;amp; z = A\,q_j\\&lt;br /&gt;
&amp;amp; \alpha_j = q^T_j z\\&lt;br /&gt;
&amp;amp; z = z - \alpha_j q_j - \beta_{j-1}q_{j-1}\\&lt;br /&gt;
&amp;amp; \beta_j = \|z\|_2\\&lt;br /&gt;
&amp;amp; \mathbf{If} \; (\beta_j == 0) \; \mathbf{then}\; stop\; the\; algorithm \\ &lt;br /&gt;
&amp;amp; \;  q_{j+1} = \frac{z}{\beta_j} \\&lt;br /&gt;
&amp;amp; compute\; eigenvalues\; and \;eigenvectors\;of \;matrix \;\;T_j= Q^T_j A Q\;\;and\;estimate \;the\; errors\\&lt;br /&gt;
\mathbf{end} \; &amp;amp; \mathbf{for}&lt;br /&gt;
\end{align}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
В продемонстрированном выше алгоритме &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;b&amp;lt;/math&amp;gt; - заданный вещественный вектор. Также полагается известным алгоритм вычисления произведения матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; на вектор &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;x&amp;lt;/math&amp;gt;. &lt;br /&gt;
Введём матрицу Крылова, определяемую следующим соотношением: &amp;lt;math&amp;gt;K_j = [b,Ab,A^2b,...,A^{j-1}b]&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Далее, на практике, матрица &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;K&amp;lt;/math&amp;gt; заменяется матрицей &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;Q&amp;lt;/math&amp;gt;, такой, что при любом числе &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; линейные оболочки первых &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; столбцов в &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;K&amp;lt;/math&amp;gt; и &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;Q&amp;lt;/math&amp;gt; являются одним и тем же подпространством.&amp;lt;ref&amp;gt;James W. Demmel - Вычислительная линейная алгебра. Теория и приложения //Мир. - 2001 (c. 315)&amp;lt;/ref&amp;gt; &lt;br /&gt;
Тогда матрица &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;Q&amp;lt;/math&amp;gt;, в отличие от матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;K&amp;lt;/math&amp;gt;, хорошо обусловлена и легко обратима. В результате получаем матрицу &amp;lt;math&amp;gt;Q_j = [q_1, q_2, \dots, q_j]&amp;lt;/math&amp;gt; размерности &amp;lt;math&amp;gt;n\times j&amp;lt;/math&amp;gt;, столбцы которой ортогональны, являются базисом подпространства Крылова и называются векторами Ланцоша.&lt;br /&gt;
&lt;br /&gt;
В алгоритме Ланцоша вычислению подлежит столько первых столбцов в матрице &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;Q_j&amp;lt;/math&amp;gt;, сколько необходимо для получения требуемого приближения к решению &amp;lt;math&amp;gt;A\,x\,=b\,\,(A\,x=\lambda \, x)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Получение нулевого &amp;lt;math&amp;gt;\beta_j&amp;lt;/math&amp;gt; в итерационном процессе - событие, желательное в том смысле, что оно свидетельствует о том, что найдено некоторое подпространство, являющееся в точности инвариантным, а все собственные значения матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;T_j&amp;lt;/math&amp;gt; являются собственными значениями матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt;. На практике же нулевое и близкие к нулю значения получаются редко.&amp;lt;ref&amp;gt;Голуб Дж., Ван Лоун Ч. - Матричные вычисления//М.: Мир. - 1999 (c. 429)&amp;lt;/ref&amp;gt; &lt;br /&gt;
&lt;br /&gt;
Затем на каждом шаге цикла формируется симметричная трёхдиагональная матрица &amp;lt;math&amp;gt;T_j = Q^T_j A Q&amp;lt;/math&amp;gt;, к которой применяется процесс Рэлея-Ритца для поиска её собственных значений (на практике для поиска этих собственных значений можно использовать любой из специальных методов в параграфе книги по ссылке).&amp;lt;ref&amp;gt;Голуб Дж., Ван Лоун Ч. - Матричные вычисления//М.: Мир. - 1999 (&amp;lt;math&amp;gt;\S&amp;lt;/math&amp;gt; 8.4)&amp;lt;/ref&amp;gt;  &lt;br /&gt;
Эти собственные значения, они же числа Ритца, и полагаются приближёнными собственными значениями исходной матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt;.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Существует множество методов для отыскания собственных значений вещественной симметричной трехдиагональной матрицы. Большинство из них требует &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt; операций &amp;lt;ref&amp;gt;Парлетт Б. Симметричная проблема собственных значений. Численные методы.,: Мир, 1983. с. 179-182&amp;lt;/ref&amp;gt;, но существуют и быстрые алгоритмы, требующие лишь &amp;lt;math&amp;gt;O(n\ln n)&amp;lt;/math&amp;gt; операций.&amp;lt;ref&amp;gt;https://en.wikipedia.org/wiki/Tridiagonal_matrix#Eigenvalues  Раздел eigenvalues&amp;lt;/ref&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Одним из возможных способов отыскать собственные значения симметричной трехдиагональной матрицы - прямое вычисление корней характеристического полинома &amp;lt;math&amp;gt;p_n(\lambda)&amp;lt;/math&amp;gt; через метод деления пополам, где формируется последовательность Штурма и локализуются собственные числа, являющиеся корнями характеристического полинома. Нахождение всех &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; собственных значений матрицы этим способом требует &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;2n^2t&amp;lt;/math&amp;gt; умножений и вычитаний, где &amp;lt;math&amp;gt;t&amp;lt;/math&amp;gt; - число сделанных шагов с применением метода деления пополам.&amp;lt;ref&amp;gt;Уилкинсон Дж. X. Алгебраическая проблема собственныx значений. Изд-во &amp;quot;Наука&amp;quot;, 1970. - глава 5, с. 272-278&amp;lt;/ref&amp;gt; Соответствующие собственные вектора могут быть найдены посредством обратных итераций за &amp;lt;math&amp;gt; O(n) &amp;lt;/math&amp;gt; флопов. &amp;lt;ref&amp;gt;Голуб Дж., Ван Лоун Ч. - Матричные вычисления//М.: Мир. - 1999 (c. 394-395)&amp;lt;/ref&amp;gt; &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;На практике, если требуется только небольшая часть от всей совокупности собственных векторов и значений, и матрица имеет Хессенбергову или трёхдиагональную форму, очень эффективными будут методы факторизации, как, например, QR-алгоритм или QL-алгоритм со сдвигами (c целью ускорить алгоритм и сделать порядок сходимости квадратичным) или же без них.&amp;lt;ref&amp;gt;http://algorithm.narod.ru/ln/eigen/ETridiag.html&amp;lt;/ref&amp;gt; &amp;lt;br&amp;gt;&lt;br /&gt;
Весьма молодые и не менее актуальные конкуренты QR и QL алгоритмов, применяющиеся для поиска собственных значений:&lt;br /&gt;
*Методы divide-and-conquer (разделяй и властвуй), появившиеся в 1980-ых годах &amp;lt;ref&amp;gt;https://goo.gl/dapvbn ссылку пришлось сократить с помощью Google url shortener, так как символы подчеркивания портили её и не давали перейти по 1 клику&amp;lt;/ref&amp;gt;&lt;br /&gt;
*Relatively robust representation методы, появившиеся в 1990-ых и позволяющие найти собственные числа симметричной матрицы порядка &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;n&amp;lt;/math&amp;gt; за &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt; операций&lt;br /&gt;
&lt;br /&gt;
Если требуется вычислить собственные векторы, то необходимо хранить вычисляемые векторы Ланцоша. Если работа при этом производится только с оперативной памятью, то при большом порядке исходной матрицы (а именно для таких матриц и предназначен метод Ланцоша) число шагов  &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;j&amp;lt;/math&amp;gt;, которые могут быть выполнены до того момента, как оперативная память будет исчерпана, будет очень незначительно, а следовательно, искомые собственные пары могут не успеть сойтись с требуемой точностью. В этом случае метод Ланцоша можно использовать итерационным образом: после выполнения заданного числа шагов процесс прерывается и, если еще не все требуемые пары Ритца сошлись с требуемой точностью, то формируется новый начальный вектор &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;q_1&amp;lt;/math&amp;gt;, являющийся линейной комбинацией векторов Ритца, еще не сошедшихся с заданной точностью, и процесс начинается заново.&amp;lt;ref&amp;gt;http://num-anal.srcc.msu.ru/lib_na/int_ae/int_ae6.htm (пункт 6.5)&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
Вычислительное ядро рассматриваемого алгоритма (наиболее ресурсно-затратная часть алгоритма) -  формирование на каждом шаге цикла промежуточного вектора &amp;lt;math&amp;gt;z&amp;lt;/math&amp;gt;, вычисляемого по формуле: &amp;lt;math&amp;gt;z = A\,q_j&amp;lt;/math&amp;gt;. Данная операция, по сравнению с другими операциями алгоритма, затратна и требовательна, как с точки зрения количества производимых операций, так и с точки зрения объема оперируемых данных. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Например, умножение матрицы размера &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;n\times n&amp;lt;/math&amp;gt; на вектор длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; требует: &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;n^2+(n-1)n = 2n^2-n&amp;lt;/math&amp;gt; операций умножения и сложения. В свою очередь аналогичная операция умножения матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;(n+1)\times (n+1)&amp;lt;/math&amp;gt; на вектор длины &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;(n+1)&amp;lt;/math&amp;gt; требует: &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;2n^2+3n+1&amp;lt;/math&amp;gt;  операций умножения и сложения. То есть повышение размерности задачи всего на 1 увеличивает число необходимых действий в этом шаге алгоритма на: &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;4n+1&amp;lt;/math&amp;gt;. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Так же, стоит помнить, что, согласно разделу 1.2, данную операцию умножения матрицы на вектор необходимо выполнить &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;k&amp;lt;/math&amp;gt; раз. Нетрудно понять, насколько возрастает и колоссален масштаб операций, если в задачах, где критична точность, размерности &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; могут иметь порядок &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;10^5&amp;lt;/math&amp;gt; или даже более.&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
Как уже было упомянуто в данной статье в описании алгоритма, рассматриваемый алгоритм состоит из двух последовательно выполненных алгоритмов: метод Ланцоша для построения последовательности подпространств Крылова и ортонормированных векторов Ланцоша и процедура Рэлея-Ритца получения оптимальных приближений собственных значений и соответствующих собственных векторов исходной матрицы.&lt;br /&gt;
&lt;br /&gt;
В первой части алгоритма, где итерационно строятся Крыловское подпространство и трёхдиагональная матрица &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&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 style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; разреженная. Именно она подлежит оптимизации с использованием техник распараллеливания, поскольку она является вычислительным ядром алгоритма, а весь упомянутый процесс построения матрицы &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&amp;lt;/math&amp;gt; выполняется последовательно.&lt;br /&gt;
&lt;br /&gt;
Рассмотрим вторую часть алгоритма - поиск собственных значений сформированной матрицы &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&amp;lt;/math&amp;gt;.&amp;lt;br&amp;gt;&lt;br /&gt;
Далее, наглядно, в виде псевдокода, представлен, упомянутый в разделе 1.2, QR-алгоритм (аналогично можно рассмотреть и QL-алгоритм) со сдвигами Релэя, который весьма популярен на практике.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{align}&lt;br /&gt;
\mathbf{Input}: \;&amp;amp;tridiagonal\;\;matrix \;T\;with\;\;n\times n\;\;size\\&lt;br /&gt;
T^{(0)}&amp;amp;:=T\\&lt;br /&gt;
\mathbf{for}&amp;amp; \;\;m=n,...,2 \;\; \mathbf{do}\\&lt;br /&gt;
&amp;amp;k=0\\&lt;br /&gt;
&amp;amp; \mathbf{repeat}\\&lt;br /&gt;
&amp;amp; \quad \;\; k=k+1\\&lt;br /&gt;
&amp;amp; \quad \;\; \mu^{(k)}=T_{m,m}^{(k-1)}\\&lt;br /&gt;
&amp;amp; \quad \;\; Q^{(k)}R^{(k)}=T^{(k-1)}-\mu^{(k)}I\;\;using\;\;QR\;decomposition\\&lt;br /&gt;
&amp;amp; \quad \;\; T^{(k)}=R^{(k)}Q^{(k)}+\mu^{(k)}I\\&lt;br /&gt;
&amp;amp; \mathbf{until} \;\;\; |T_{m,m-1}^{(k)}| \;is\;\;small\;\;enough\\&lt;br /&gt;
&amp;amp; Save  \;\;T_{m,m}^{(k)} \;\;as\;\; converged\;\;eigenvalue\;of\;T\\ &lt;br /&gt;
&amp;amp; Remove \;\boldsymbol{n}\,th\;row\;and\;\boldsymbol{n}\,th\;column\;\;from \;T \\&lt;br /&gt;
&amp;amp; and\;take\;this\;new\;cropped\;matrix\;as\;new\;T^{(0)}\;with\;\;(n-1)\times (n-1)\;\;size\\&lt;br /&gt;
 \mathbf{end}&amp;amp;\; \mathbf{for}&lt;br /&gt;
\end{align}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Малость наддиагональных и поддиагональных элементов матрицы (фраза &#039;&#039;&amp;quot;small enough&amp;quot;&#039;&#039; в псевдокоде) подразумевает:&lt;br /&gt;
&amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt; |T_{m,m-1}^{(k)}| \leq \varepsilon\,|T_{m,m}^{(k)}| \quad\quad &amp;lt;/math&amp;gt; , где &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt; \varepsilon &amp;lt;/math&amp;gt; - заданная точность&amp;lt;br&amp;gt;&lt;br /&gt;
Также вместо сдвига Релэя, обозначенного в алгоритме через &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;\mu^{(k)}&amp;lt;/math&amp;gt;, часто на практике используется сдвиг по Уилкинсону, который даёт гарантированную сходимость внедиагональных элементов матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt; T^{(k)} &amp;lt;/math&amp;gt;, формируемой на каждом шаге, к нулю, при этом жертвуя монотонностью их убывания.&amp;lt;ref&amp;gt;Голуб Дж., Ван Лоун Ч. - Матричные вычисления//М.: Мир. - 1999 (c. 378, вторая половина страницы)&amp;lt;/ref&amp;gt;&amp;lt;ref&amp;gt;Парлетт Б. Симметричная проблема собственных значений. Численные методы.,: Мир, 1983. с. 169&amp;lt;/ref&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Подробнее с различными сдвигами и соответствующими оценками скоростей и количествами операций можно ознакомиться по указанной ссылке:&amp;lt;ref&amp;gt;Парлетт Б. Симметричная проблема собственных значений. Численные методы.,: Мир, 1983. с. 179-182&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;Для совершения QR-декомпозиции на каждом шаге может использоваться любой из алгоритмов по ссылке.&amp;lt;ref&amp;gt;https://en.wikipedia.org/wiki/QR_decomposition&amp;lt;/ref&amp;gt; Подробные описания этих алгоритмов также доступны на данном ресурсе algowiki-project.&amp;lt;br&amp;gt;&lt;br /&gt;
Так как мы оперируем не обычной матрицей и даже не Хессенберговой, а симметричной и трёхдиагональной, то скорость таких алгоритмов значительно возрастёт. Например, согласно данному ресурсу &amp;lt;ref&amp;gt;http://algorithm.narod.ru/ln/eigen/ETridiag.html&amp;lt;/ref&amp;gt;, для QL-алгоритма с неявными сдвигами:&amp;lt;br&amp;gt;&lt;br /&gt;
Для трёхдиагональной матрицы объем арифметических действий составляет &amp;lt;math&amp;gt; O(n)&amp;lt;/math&amp;gt; на одну итерацию вместо &amp;lt;math&amp;gt; O(n^3)&amp;lt;/math&amp;gt; для матрицы общего вида, а число итераций для нахождения первых собственных значений примерно равно 4 - 5. Но на этих итерациях также уменьшаются внедиагональные элементы правого нижнего угла. И, таким образом, дальнейшие собственные значения ищутся значительно быстрее. Среднее число итераций на каждое собственное значение обычно составляет 1.3 - 1.6.&amp;lt;br&amp;gt; &lt;br /&gt;
Аналогично QL, QR-разложение трёхдиагольной матрицы также требует &amp;lt;math&amp;gt; O(n)&amp;lt;/math&amp;gt; флопов&amp;lt;ref&amp;gt;Голуб Дж., Ван Лоун Ч. - Матричные вычисления//М.: Мир. - 1999 (c. 378, начало раздела 8.2.2)&amp;lt;/ref&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Подводя итог, во второй части алгоритма Ланцоша можно выделить следующие макрооперации:&lt;br /&gt;
* умножение матрицы на вещественное число;&lt;br /&gt;
* перемножение матриц;&lt;br /&gt;
* умножение и сравнение вещественных чисел;&lt;br /&gt;
* + набор других макроопераций в зависимости от выбора метода, с помощью которого будет совершаться сама QR или QL-декомпозиция (выше продемонстрированы, уже, как минимум, 3 разных способа).&lt;br /&gt;
Так же, важно заметить, что набор макропераций может быть несколько другим, если выбрать какой-либо иной современный метод поиска собственных чисел трёхдиагональной матрицы, не использующий QR и QL разложения(факторизацию). Два таких метода были упомянуты в пункте 1.2.&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
С целью полностью не дублировать раздел 1.2 данной статьи, где представлен наглядный и доступный для понимания псевдокод алгоритма, постараемся лишь коротко просуммировать и обобщить весь перечень последовательных действий в рассматриваемом алгоритме.&lt;br /&gt;
&lt;br /&gt;
В качестве входных данных имеем: вещественная симметричная матрица &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; размера &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;n\times n&amp;lt;/math&amp;gt;, известный вещественный вектор &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;b&amp;lt;/math&amp;gt; длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; и число &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;n&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Далее:&lt;br /&gt;
* Инициализируем вещественную константу &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;\beta_0&amp;lt;/math&amp;gt; и векторы &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;q_0&amp;lt;/math&amp;gt; и &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;q_1&amp;lt;/math&amp;gt;&lt;br /&gt;
* Итерационно для всех &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j=1,...,k&amp;lt;/math&amp;gt;:&lt;br /&gt;
** Вычисляем вспомогательный вектор &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt;, используя умножение матрицы на вектор&lt;br /&gt;
** Вычисляем, используя скалярное произведение векторов, значение &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;\alpha_j&amp;lt;/math&amp;gt; - элемент на главной диагонали трёхдиагональной матрицы &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&amp;lt;/math&amp;gt;&lt;br /&gt;
** Вычисляем по формуле новое значение и перезаписываем вектор &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt;&lt;br /&gt;
** Вычисляем значение &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;\beta_j&amp;lt;/math&amp;gt; - элементы непосредственно над и под главной диагональю той же матрицы &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&amp;lt;/math&amp;gt;&lt;br /&gt;
** Вычисляем, зная вектор &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt;,  очередной столбец матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;Q&amp;lt;/math&amp;gt;, он же вектор Ланцоша : &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;\,\,q_{j+1}&amp;lt;/math&amp;gt;&lt;br /&gt;
** Теперь, когда матрица &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&amp;lt;/math&amp;gt; сформирована на очередном шаге, находим её собственные значения и вектора любым доступным способом, о чём было подробно сказано в пункте 1.2&lt;br /&gt;
** Переходим на следующую итерацию: &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j&amp;lt;/math&amp;gt;++&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
Оценим количество операций и сложность последовательного алгоритма, изложенного в предыдущем разделе.&lt;br /&gt;
*Для вычисления вектора &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt; умножается матрица размера &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;n\times n&amp;lt;/math&amp;gt; на вектор длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt;, и потребуется &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n^2&amp;lt;/math&amp;gt; операций умножения и &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n^2&amp;lt;/math&amp;gt; операций сложения.&lt;br /&gt;
*Умножение векторов &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;q^T_j&amp;lt;/math&amp;gt; и &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt; длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; потребует &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; операций умножения и &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; операций сложения.&lt;br /&gt;
*При вычислении нового значения вектора &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt; поэлементное сложение двух векторов длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; требует &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; операций сложения.&lt;br /&gt;
*Умножение вектора длины &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; на вещественное число требует &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; операций умножения.&lt;br /&gt;
*Нахождение квадратичной нормы вектора &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt;  длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; требует &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; умножений и &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; сложений и ещё 1 операцию извлечения квадратного корня.&lt;br /&gt;
*Заключительное нахождение собственных значений и собственных векторов трёхдиагональной матрицы &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;T_j&amp;lt;/math&amp;gt; размера &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j\times j&amp;lt;/math&amp;gt; с помощью QR-алгоритма потребует в худшем случае &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(j^3)&amp;lt;/math&amp;gt; операций.&amp;lt;ref&amp;gt;http://num-anal.srcc.msu.ru/lib_na/int_ae/int_ae6.htm (пункт 6.2, &amp;quot;Скорость сходимости при этом всегда не хуже квадратичной и почти всегда лучше кубической.&amp;quot;)&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Посчитаем теперь суммарное количество простейших операций на одной итерации алгоритма (без учёта записей в память):&lt;br /&gt;
*&amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n^2+5\,n&amp;lt;/math&amp;gt; операций умножения/деления&lt;br /&gt;
*&amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n^2+4\,n&amp;lt;/math&amp;gt; операций сложения/вычитания&lt;br /&gt;
*1 операция извлечения квадратного корня&amp;lt;br&amp;gt;&lt;br /&gt;
Отдельно после всех итераций при &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j=k&amp;lt;/math&amp;gt; :&lt;br /&gt;
*&amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(k^3)&amp;lt;/math&amp;gt; операций для поиска собственных значений и собственных векторов трёхдиагональной матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_k&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Итого можно утверждать следующее:&lt;br /&gt;
&lt;br /&gt;
Последовательная сложность одной итерации рассматриваемого алгоритма:  &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(n ^ 2) &amp;lt;/math&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Суммарная сложность алгоритма (&amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;/math&amp;gt; итераций): &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(k\,n ^ 2) + O(k ^ 3)&amp;lt;/math&amp;gt; &amp;lt;ref&amp;gt;Здесь мы полагаем, что мы не вычисляем собственные значения и векторы матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_j&amp;lt;/math&amp;gt; на каждом промежуточном шаге, а лишь единожды затрачиваем &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;O(k ^ 3)&amp;lt;/math&amp;gt; действий в конце для нахождения &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;/math&amp;gt; собственных значений и векторов матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_k&amp;lt;/math&amp;gt;&amp;lt;/ref&amp;gt; &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
На практике же обычно рассматривается число &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;&amp;lt;n&amp;lt;/math&amp;gt;, поэтому второе слагаемое можно опустить.&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
На рис. 1 продемонстрирован граф одной итерации (при каком-либо произвольном значении итератора &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j&amp;lt;/math&amp;gt;) описанного алгоритма без отображения входных и выходных данных. Наглядно продемонстрированы связи между всеми действиями, и с помощью деления на &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; потоков показано, какие операции возможно выполнять параллельно на каждом шаге с целью оптимизации и экономии машинного времени. В результате, после параллельно выполненных операций &#039;&#039;&#039;Division&#039;&#039;&#039; на заключительном ярусе, на выходе имеем значение следующего вектора Ланцоша &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;q_{j+1}&amp;lt;/math&amp;gt;, после чего следует переход на следующую итерацию, и процесс повторяется.&lt;br /&gt;
&lt;br /&gt;
[[Файл:Levin_graph.png|600px|thumb|center|Рис. 1]] &amp;lt;br&amp;gt;&lt;br /&gt;
Обозначения на рисунке: &amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Simp&#039;&#039;&#039; (от англ. simple) - операции сложения и умножения вещественных чисел при вычислении произведения матрицы на вектор;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Vec mult&#039;&#039;&#039; (от англ. vectors multiplication) - операция скалярного умножения двух векторов;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Vec subtr&#039;&#039;&#039; (от англ. vectors subtraction, из-за использованных в операции вычитаний векторов) - операция умножения вектора на число (выполняется дважды) и формирование нового значения &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;z_{new}&amp;lt;/math&amp;gt; по формуле: &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;z_{new} = z - \alpha_j q_j - \beta_{j-1}q_{j-1} \;&amp;lt;/math&amp;gt;;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;||\cdot||&amp;lt;/math&amp;gt; - операция вычисления нормы вектора;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Division&#039;&#039;&#039; - операция деления вектора на вещественное число  &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;\beta_j&amp;lt;/math&amp;gt; &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Важно отметить, что упомянутые выше операции также легко поддаются оптимизации. Например, попарные умножения вещественных координат векторов при вычислении скалярного произведения также легко выполняются параллельно на &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; потоках, а затем можно применить суммирование методом сдваивания, о котором сказано в следующем разделе. Умножение или деление вектора на вещественное число являющееся, по определению, умножением или делением всех его координат на это число тоже может быть выполнено эффективнее, если мы используем &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; потоков, а не выполняем эти действия последовательно.&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
Параллельные операции возможны только внутри итераций, так как рассматриваемый алгоритм является итерационным, и сами итерации строго последовательны.&amp;lt;br&amp;gt;&lt;br /&gt;
Рассмотрим в этом разделе подробнее, какой выигрыш мы можем получить при распараллеливании операций внутри одной итерации согласно графу из предыдущего раздела.&lt;br /&gt;
&lt;br /&gt;
Умножение вещественной симметричной матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; размера &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;n\times n&amp;lt;/math&amp;gt; на вектор &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;b&amp;lt;/math&amp;gt; длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; требует последовательного выполнения &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; ярусов умножений и сложений. Сложение элементов вектора длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; на каждом шаге перемножения можно оптимизировать и выполнить за &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;\log_2 n&amp;lt;/math&amp;gt; действий, если применять метод сдваивания.&lt;br /&gt;
&lt;br /&gt;
Дальнейшие операции выполняются последовательно, а вычисление значений векторов происходит за один ярус операций сложения или умножения.&lt;br /&gt;
&lt;br /&gt;
Ресурс параллелизма алгоритма вычисления собственных значений построенной трёхдиагональной матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_k&amp;lt;/math&amp;gt; размера &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k\times k&amp;lt;/math&amp;gt; зависит от выбранного алгоритма (об этих алгоритмах подробнее было сказано в разделах 1.2 и 1.4). Будет очень затратно с точки зрения объёма материала пытаться рассмотреть пусть даже часть этих методов в этой статье, а так же тонкости их распараллеливания. Предлагаем читателям при желании самим ознакомиться с этими алгоритмами на данном ресурсе или прибегнув к иным источникам.&lt;br /&gt;
&lt;br /&gt;
При классификации по высоте ЯПФ, таким образом, алгоритм Ланцоша без переортогонализации относится к алгоритмам с &#039;&#039;логарифмической сложностью&#039;&#039;, и его сложность равна &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(\log_2 n)&amp;lt;/math&amp;gt; с важным замечанием, что это сложность только одной итерации, а максимум в алгоритме может быть выполнено последовательно &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;/math&amp;gt; таких однотипных итераций, если не будет осуществлён ранний выход из цикла. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Несмотря на то, что на графе в предыдущем разделе для лучшей визуализации и понимания было изображено &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; потоков (никаких допущений мы не делали и нарушений с точки зрения логики и математики нет, можно изобразить большее число потоков, просто часть времени некоторые из них могут бездействовать и не использоваться), на самом деле правильным и разумным будет реализовать начальное параллельное выполнение &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n^2&amp;lt;/math&amp;gt; операций умножения всех вещественных элементов матрицы &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;A&amp;lt;/math&amp;gt; на соответствующие элементы вектора &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;q_j&amp;lt;/math&amp;gt;, после чего применять тот же самый упомянутый метод сдваивания. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Поэтому при классификации по ширине ЯПФ его сложность будет &#039;&#039;квадратичной&#039;&#039; и равна &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(n^2)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
&#039;&#039;&#039;Входные данные алгоритма:&#039;&#039;&#039; вещественная симметричная &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; размера &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;n\times n&amp;lt;/math&amp;gt;, вещественный вектор &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;b&amp;lt;/math&amp;gt; длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt;, и одно целое число &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;k&amp;lt;/math&amp;gt;, означающее количество итераций.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём входных данных:&#039;&#039;&#039; &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;n^2 +n + 1 &amp;lt;/math&amp;gt;. Если учесть, что матрица симметричная и достаточно для её однозначного определения задать элементы на главной диагонали и элементы над или под ней, то можно сократить объём входных данных с целью экономии памяти до: &amp;lt;math&amp;gt;\ \frac{n^2-n}{2}+n+n+1 =\frac{n^2+3n}{2} + 1&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные алгоритма:&#039;&#039;&#039; вектор собственных значений &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;\Theta^k&amp;lt;/math&amp;gt; длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;/math&amp;gt;, матрица &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;S^k&amp;lt;/math&amp;gt; из соответствующих собственных векторов размера &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n\times k&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём выходных данных:&#039;&#039;&#039; &amp;lt;math&amp;gt;k\;(n + 1)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
В данном разделе перечислены без какой-либо хронологии или связи друг с другом наиболее важные и разнообразные свойства алгоритма, на которые стоит и полезно обратить внимание, а также которые выгодно отличают его от схожих алгоритмов, решающих ту же задачу.&amp;lt;br&amp;gt;&lt;br /&gt;
1) Отношение последовательной сложности алгоритма к параллельной,с учётом &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;/math&amp;gt; итераций, равно &amp;lt;math&amp;gt;\;\;\frac{kn^2}{k \log_2{n}}=\frac{n^2}{\log_2{n}}&amp;lt;/math&amp;gt;;&amp;lt;br&amp;gt;&lt;br /&gt;
2) Вычислительная мощность алгоритма, как отношение числа операций к суммарному объему входных и выходных данных, равна &amp;lt;math style=&amp;quot;vertical-align:-70%&amp;gt;\;\;\frac{k\,n^2}{0.5\,n^2+1.5\,n+k\,n+k+1}&amp;lt;/math&amp;gt; и &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;\approx 2\,k&amp;lt;/math&amp;gt;, так как на практике верно отношение &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;&amp;lt;n&amp;lt;/math&amp;gt; ;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
3) Для собственных значений формируемых матриц &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_j&amp;lt;/math&amp;gt; верно отношение (следствие теоремы Коши о перемежаемости): &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;\lambda_i(T_{k+1})\geq \lambda_i(T_{k})\geq \lambda_{i+1}(T_{k+1})\geq \lambda_{i+1}(T_{k})&amp;lt;/math&amp;gt; ;&amp;lt;ref&amp;gt;James W. Demmel - Вычислительная линейная алгебра. Теория и приложения //Мир. - 2001 (c. 383)&amp;lt;/ref&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
4) Крайние (наибольшие и наименьшие) собственные значения матриц &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_j&amp;lt;/math&amp;gt; сходятся к крайним собственным значениям матрицы &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;A&amp;lt;/math&amp;gt; первыми (это часто происходит уже на ранних шагах при &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j\approx 2\,\sqrt{n}&amp;lt;/math&amp;gt;&amp;lt;ref&amp;gt;http://num-anal.srcc.msu.ru/lib_na/int_ae/int_ae6.htm (пункт 6.5)&amp;lt;/ref&amp;gt;), а собственные значения в середине спектра - последними;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
5) Из-за ограниченной точности постепенно теряется ортогональность вектора Ланцоша &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;q_j&amp;lt;/math&amp;gt; к предыдущим векторам Ланцоша, поэтому необходимо примерно каждые 10-15 итераций проводить дорогостоящую операцию реортогонализации, но это уже будет иной алгоритм с очень малым различием в одной операции и в программном коде, реализующем его, соответственно; &amp;lt;ref&amp;gt;Sam Handler - The Lanczos Algorithm For Large-Scale Eigenvalue Problems (08.01.07), slide №8&amp;lt;/ref&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
6) Эффективность и быстрота выполнения алгоритма очень сильно зависит от скорости памяти (диска). Согласно тесту только &#039;&#039;6%&#039;&#039; времени работы программы приходится на вычисления, остальное время затрачивается на ожидание отклика диска;&amp;lt;ref&amp;gt;Sam Handler - The Lanczos Algorithm For Large-Scale Eigenvalue Problems (08.01.07), slide №10&amp;lt;/ref&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
7) Метод Ланцоша удобен тем, что не требует хранения исходной матрицы полным массивом: метод использует исходную матрицу только в операциях умножения матрицы на вектор, что позволяет эффективно использовать разреженность матрицы или регулярность структуры матрицы. Поэтому метод Ланцоша может быть использован для матриц таких больших порядков, когда методы вращений и отражений не могут быть применены.&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;
Для исследования масштабируемости рассматриваемого алгоритма Ланцоша без переортогонализации автором была реализована программа на языке С++ с использованием технологии MPI (&#039;&#039;&#039;не забыть вставить ссылку на код&#039;&#039;&#039;). Дальнейшее исследование выполнялось на суперкомпьютере &amp;quot;Ломоносов&amp;quot; Суперкомпьютерного комплекса МГУ. &amp;lt;br&amp;gt; Важно отметить, что реализованная программа выполняет только первую часть алгоритма - формирование матрицы &amp;lt;math &amp;gt;T_j&amp;lt;/math&amp;gt;. Вторая часть алгоритма (задача поиска собственных значений матрицы &amp;lt;math &amp;gt;T_j&amp;lt;/math&amp;gt;) может быть решена несколькими методами, каждый из которых обладает своей эффективностью распараллеливании и характерными свойствами. Подробно этот вопрос уже обсуждался в статье раннее, поэтому не будем ещё раз заострять на этом внимание и останавливаться.&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Сборка осуществлялась со следующими параметрами:&lt;br /&gt;
* Компилятор intel/15.0.090 &lt;br /&gt;
* Openmpi/1.8.4-icc&lt;br /&gt;
В серии проведённых расчётов рассматривались следующие числовые значения параметров:&lt;br /&gt;
* Размер &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;n&amp;lt;/math&amp;gt; задачи и, соответственно, матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt;, задействованной в операции умножения на вектор: [2000 : 30000] с шагом 1000&lt;br /&gt;
* Число процессоров: 1,2,4,16,32,48,64,96,128&lt;br /&gt;
* Число итераций в алгоритме: &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k=350&amp;lt;/math&amp;gt; . Взято таким вопреки информации в начале статьи, где говорится, что значение &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; редко превышает &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;10^2&amp;lt;/math&amp;gt;. Это сделано исключительно для лучшей визуализации пиков на графиках в данном разделе и наглядности получаемых результатов, так как при меньших на порядок значениях &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; времена выполнения программ были слишком малы даже при минимальных числах процессоров и максимальных размерах исходной задачи.&lt;br /&gt;
&lt;br /&gt;
== Динамические характеристики и эффективность реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Выводы для классов архитектур ==&lt;br /&gt;
По заданию, во второй части требовалось описать только разделы 2.4 и 2.7, прошу не спрашивать с меня все разделы 2.1-2.6. Надеюсь на понимание, мне физически не хватает времени на это задание + 2 других в течение семестра, делаю всё, что в моих силах :)&lt;br /&gt;
&lt;br /&gt;
== Существующие реализации алгоритма ==&lt;br /&gt;
Несмотря на то, что алгоритм является далеко не самым популярным, алгоритмом, про который нельзя сказать, что он всегда «на слуху», на сегодняшний день существует множество реализаций на различных популярных языках.&amp;lt;br&amp;gt;&lt;br /&gt;
Перечислим далее некоторые из них, указывая язык программирования, лежащий в их основе, и некоторые важные характеристики, которые обсуждались в статье ранее:&lt;br /&gt;
*&#039;&#039;Code on netlib.org by Jane Cullum and Ralph Willoughby&#039;&#039; (&#039;&#039;&#039;Fortran 77&#039;&#039;&#039;; без реортогонализации векторов; без реализации распараллеливания)&amp;lt;ref&amp;gt;http://www.netlib.org/lanczos/leval&amp;lt;/ref&amp;gt;&lt;br /&gt;
*&#039;&#039;Lanczos algorithm on freesourcecode.net&#039;&#039; (&#039;&#039;&#039;Matlab&#039;&#039;&#039;; присутствует реортогонализация векторов; без реализации распараллеливания)&amp;lt;ref&amp;gt;http://freesourcecode.net/matlabprojects/61741/lanczos-algorithm--in-matlab&amp;lt;/ref&amp;gt;&lt;br /&gt;
*&#039;&#039;Lanczos for eigenvalues in Numerical Linear Algebra, Spring 2007&#039;&#039; (&#039;&#039;&#039;Matlab&#039;&#039;&#039;; частичная или полная реортогонализация - доступны оба варианта; без реализации распараллеливания)&amp;lt;ref&amp;gt;Ссылки на файлы lanso.m и lanfu.m можно найти на https://www.nada.kth.se/~ruhe/2D5219/labs2007.html&amp;lt;/ref&amp;gt;&lt;br /&gt;
*&#039;&#039;Planso&#039;&#039; (название происходит от parallel Lanso.f) &#039;&#039;code by Kesheng Wu and Horst D. Simon&#039;&#039; (&#039;&#039;&#039;Fortran 77&#039;&#039;&#039;; частичная реортогонализация векторов; использование MPI для коммуникаций)&amp;lt;ref&amp;gt;https://github.com/jiahao/planso.jl/tree/master/external/PLAN/plan К сожалению, ссылка в описании пакета на github, ведущая на сайт National Energy Research Scientific Computing Center (NERSC), с более подробной информацией о данной программе больше не активна и выдаёт результат &#039;&#039;Page not found&#039;&#039;&amp;lt;/ref&amp;gt; &lt;br /&gt;
* &#039;&#039;Lanczos.cpp in the Vienna Computing Library&#039;&#039;  (&#039;&#039;&#039;C++&#039;&#039;&#039;, частичная реортогонализация, без реализации распараллеливания) &amp;lt;ref&amp;gt;http://viennacl.sourceforge.net/doc/lanczos_8cpp_source.html&amp;lt;/ref&amp;gt;&lt;br /&gt;
* &#039;&#039;Parallel Eigen Values code using C++ AMP on microsoft msdn blog&#039;&#039; (&#039;&#039;&#039;C++&#039;&#039;&#039;; ? ; распараллеливание есть и реализовано через C++ AMP) &amp;lt;ref&amp;gt;https://blogs.msdn.microsoft.com/nativeconcurrency/2013/12/20/eigen-values/ Подробнее о C++ Accelerated Massive Parallelism можно почитать здесь: https://msdn.microsoft.com/ru-ru/library/hh265137(v=vs.140).aspx или здесь: http://professorweb.ru/my/csharp/optimization/level4/4_6.php &amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;br /&gt;
[[en:Description of algorithm properties and structure]]&lt;/div&gt;</summary>
		<author><name>AleksLevin</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:AleksLevin/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%9B%D0%B0%D0%BD%D1%86%D0%BE%D1%88%D0%B0_%D0%B2%D1%8B%D1%87%D0%B8%D1%81%D0%BB%D0%B5%D0%BD%D0%B8%D1%8F_%D1%81%D0%BE%D0%B1%D1%81%D1%82%D0%B2%D0%B5%D0%BD%D0%BD%D1%8B%D1%85_%D0%B7%D0%BD%D0%B0%D1%87%D0%B5%D0%BD%D0%B8%D0%B9_%D1%81%D0%B8%D0%BC%D0%BC%D0%B5%D1%82%D1%80%D0%B8%D1%87%D0%BD%D0%BE%D0%B9_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86%D1%8B_%D0%B4%D0%BB%D1%8F_%D1%82%D0%BE%D1%87%D0%BD%D0%BE%D0%B9_%D0%B0%D1%80%D0%B8%D1%84%D0%BC%D0%B5%D1%82%D0%B8%D0%BA%D0%B8_(%D0%B1%D0%B5%D0%B7_%D0%BF%D0%B5%D1%80%D0%B5%D0%BE%D1%80%D1%82%D0%BE%D0%B3%D0%BE%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D0%B8)&amp;diff=20206</id>
		<title>Участник:AleksLevin/Алгоритм Ланцоша вычисления собственных значений симметричной матрицы для точной арифметики (без переортогонализации)</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:AleksLevin/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%9B%D0%B0%D0%BD%D1%86%D0%BE%D1%88%D0%B0_%D0%B2%D1%8B%D1%87%D0%B8%D1%81%D0%BB%D0%B5%D0%BD%D0%B8%D1%8F_%D1%81%D0%BE%D0%B1%D1%81%D1%82%D0%B2%D0%B5%D0%BD%D0%BD%D1%8B%D1%85_%D0%B7%D0%BD%D0%B0%D1%87%D0%B5%D0%BD%D0%B8%D0%B9_%D1%81%D0%B8%D0%BC%D0%BC%D0%B5%D1%82%D1%80%D0%B8%D1%87%D0%BD%D0%BE%D0%B9_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86%D1%8B_%D0%B4%D0%BB%D1%8F_%D1%82%D0%BE%D1%87%D0%BD%D0%BE%D0%B9_%D0%B0%D1%80%D0%B8%D1%84%D0%BC%D0%B5%D1%82%D0%B8%D0%BA%D0%B8_(%D0%B1%D0%B5%D0%B7_%D0%BF%D0%B5%D1%80%D0%B5%D0%BE%D1%80%D1%82%D0%BE%D0%B3%D0%BE%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D0%B8)&amp;diff=20206"/>
		<updated>2016-12-06T21:49:24Z</updated>

		<summary type="html">&lt;p&gt;AleksLevin: /* Масштабируемость алгоритма и его реализации */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Основные авторы описания: Левин А.Д.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{algorithm&lt;br /&gt;
| name              = Алгоритм Ланцоша для точной арифметики (без переортогонализации)&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(k\,n^2)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(k\log_2 n)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;\frac{n^2+3n}{2} + 1&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;k\;(n + 1)&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритмов =&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Данный алгоритм появился в 1950 г. и носит имя венгерского физика и математика Корнелия Ланцоша (венг. Lánczos Kornél). Алгоритм Ланцоша относится к итерационным методам вычисления собственных значений для матриц столь больших порядков &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt; n&amp;lt;/math&amp;gt;, что к ним нельзя применить прямые методы из-за ограничений по времени и памяти.&lt;br /&gt;
&lt;br /&gt;
Сам Ланцош указывал, что его метод предназначен для отыскания нескольких собственных векторов симметричных матриц, хотя к методу сразу было обращено внимание, как к способу приведения всей матрицы к трёхдиагональному виду. Двадцатью годами позже канадский математик Крис Пэж показал, что, несмотря на чувствительность к округлениям, алгоритм Ланцоша - эффективное средство вычисления некоторых &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; собственных чисел и соответствующих им собственных векторов. &amp;lt;ref&amp;gt;Парлетт Б. - Симметричная проблема собственных значений. Численные методы //М.: Мир. - 1983. (c. 276)&amp;lt;/ref&amp;gt;&lt;br /&gt;
Обычно число &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; берут в два раза больше, чем количество собственных значений матрицы, которые поставлена цель найти, и оно имеет порядок не более &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;10^2&amp;lt;/math&amp;gt;.&amp;lt;ref&amp;gt;Susan W. Bostic - Lanczos Eigensolution Method for High-Perfomance Computers, page 7&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Алгоритм Ланцоша для вычисления собственных значений симметричной матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; соединяет в себе метод Ланцоша для построения последовательности подпространств Крылова и ортонормированных векторов Ланцоша и процедуру Рэлея-Ритца получения оптимальных приближений собственных значений и соответствующих собственных векторов исходной матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt;.&amp;lt;ref&amp;gt;James W. Demmel - Вычислительная линейная алгебра. Теория и приложения //Мир. - 2001 (c. 381)&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
В данной статье рассматривается вариант алгоритма Ланцоша, в котором опущено влияние ошибок округления на вычислительный процесс, хотя на практике этому посвящается отдельное внимание и существуют различные методы решения данной проблемы, такие как частичная или полная переортогонализация. Этим модифицированным методам посвящены отдельные статьи на данном ресурсе.&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
Обозначения и формулы, используемые в данном разделе, взяты из литературы, указанной по ссылке.&amp;lt;ref&amp;gt;James W. Demmel - Вычислительная линейная алгебра. Теория и приложения //Мир. - 2001 (c. 313, &#039;&#039;&amp;lt;math&amp;gt; \S &amp;lt;/math&amp;gt; 6.6 Методы Крыловского подпространства&#039;&#039;)&amp;lt;/ref&amp;gt; &lt;br /&gt;
&lt;br /&gt;
Алгоритм Ланцоша для вычисления &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; собственных значений и собственных векторов вещественной симметричной матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A=A^T&amp;lt;/math&amp;gt; в точной арифметике: &amp;lt;ref&amp;gt;James W. Demmel - Вычислительная линейная алгебра. Теория и приложения //Мир. - 2001 (c. 381)&amp;lt;/ref&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{align}&lt;br /&gt;
q_1 = &amp;amp; \,\frac{b}{\|b\|_2},\; \beta_0 = 0,\; q_0 = 0\\&lt;br /&gt;
\mathbf{for} \; &amp;amp; j = 1 \; to \; k \,\; \mathbf{do} \\&lt;br /&gt;
&amp;amp; z = A\,q_j\\&lt;br /&gt;
&amp;amp; \alpha_j = q^T_j z\\&lt;br /&gt;
&amp;amp; z = z - \alpha_j q_j - \beta_{j-1}q_{j-1}\\&lt;br /&gt;
&amp;amp; \beta_j = \|z\|_2\\&lt;br /&gt;
&amp;amp; \mathbf{If} \; (\beta_j == 0) \; \mathbf{then}\; stop\; the\; algorithm \\ &lt;br /&gt;
&amp;amp; \;  q_{j+1} = \frac{z}{\beta_j} \\&lt;br /&gt;
&amp;amp; compute\; eigenvalues\; and \;eigenvectors\;of \;matrix \;\;T_j= Q^T_j A Q\;\;and\;estimate \;the\; errors\\&lt;br /&gt;
\mathbf{end} \; &amp;amp; \mathbf{for}&lt;br /&gt;
\end{align}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
В продемонстрированном выше алгоритме &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;b&amp;lt;/math&amp;gt; - заданный вещественный вектор. Также полагается известным алгоритм вычисления произведения матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; на вектор &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;x&amp;lt;/math&amp;gt;. &lt;br /&gt;
Введём матрицу Крылова, определяемую следующим соотношением: &amp;lt;math&amp;gt;K_j = [b,Ab,A^2b,...,A^{j-1}b]&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Далее, на практике, матрица &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;K&amp;lt;/math&amp;gt; заменяется матрицей &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;Q&amp;lt;/math&amp;gt;, такой, что при любом числе &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; линейные оболочки первых &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; столбцов в &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;K&amp;lt;/math&amp;gt; и &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;Q&amp;lt;/math&amp;gt; являются одним и тем же подпространством.&amp;lt;ref&amp;gt;James W. Demmel - Вычислительная линейная алгебра. Теория и приложения //Мир. - 2001 (c. 315)&amp;lt;/ref&amp;gt; &lt;br /&gt;
Тогда матрица &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;Q&amp;lt;/math&amp;gt;, в отличие от матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;K&amp;lt;/math&amp;gt;, хорошо обусловлена и легко обратима. В результате получаем матрицу &amp;lt;math&amp;gt;Q_j = [q_1, q_2, \dots, q_j]&amp;lt;/math&amp;gt; размерности &amp;lt;math&amp;gt;n\times j&amp;lt;/math&amp;gt;, столбцы которой ортогональны, являются базисом подпространства Крылова и называются векторами Ланцоша.&lt;br /&gt;
&lt;br /&gt;
В алгоритме Ланцоша вычислению подлежит столько первых столбцов в матрице &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;Q_j&amp;lt;/math&amp;gt;, сколько необходимо для получения требуемого приближения к решению &amp;lt;math&amp;gt;A\,x\,=b\,\,(A\,x=\lambda \, x)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Получение нулевого &amp;lt;math&amp;gt;\beta_j&amp;lt;/math&amp;gt; в итерационном процессе - событие, желательное в том смысле, что оно свидетельствует о том, что найдено некоторое подпространство, являющееся в точности инвариантным, а все собственные значения матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;T_j&amp;lt;/math&amp;gt; являются собственными значениями матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt;. На практике же нулевое и близкие к нулю значения получаются редко.&amp;lt;ref&amp;gt;Голуб Дж., Ван Лоун Ч. - Матричные вычисления//М.: Мир. - 1999 (c. 429)&amp;lt;/ref&amp;gt; &lt;br /&gt;
&lt;br /&gt;
Затем на каждом шаге цикла формируется симметричная трёхдиагональная матрица &amp;lt;math&amp;gt;T_j = Q^T_j A Q&amp;lt;/math&amp;gt;, к которой применяется процесс Рэлея-Ритца для поиска её собственных значений (на практике для поиска этих собственных значений можно использовать любой из специальных методов в параграфе книги по ссылке).&amp;lt;ref&amp;gt;Голуб Дж., Ван Лоун Ч. - Матричные вычисления//М.: Мир. - 1999 (&amp;lt;math&amp;gt;\S&amp;lt;/math&amp;gt; 8.4)&amp;lt;/ref&amp;gt;  &lt;br /&gt;
Эти собственные значения, они же числа Ритца, и полагаются приближёнными собственными значениями исходной матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt;.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Существует множество методов для отыскания собственных значений вещественной симметричной трехдиагональной матрицы. Большинство из них требует &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt; операций &amp;lt;ref&amp;gt;Парлетт Б. Симметричная проблема собственных значений. Численные методы.,: Мир, 1983. с. 179-182&amp;lt;/ref&amp;gt;, но существуют и быстрые алгоритмы, требующие лишь &amp;lt;math&amp;gt;O(n\ln n)&amp;lt;/math&amp;gt; операций.&amp;lt;ref&amp;gt;https://en.wikipedia.org/wiki/Tridiagonal_matrix#Eigenvalues  Раздел eigenvalues&amp;lt;/ref&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Одним из возможных способов отыскать собственные значения симметричной трехдиагональной матрицы - прямое вычисление корней характеристического полинома &amp;lt;math&amp;gt;p_n(\lambda)&amp;lt;/math&amp;gt; через метод деления пополам, где формируется последовательность Штурма и локализуются собственные числа, являющиеся корнями характеристического полинома. Нахождение всех &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; собственных значений матрицы этим способом требует &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;2n^2t&amp;lt;/math&amp;gt; умножений и вычитаний, где &amp;lt;math&amp;gt;t&amp;lt;/math&amp;gt; - число сделанных шагов с применением метода деления пополам.&amp;lt;ref&amp;gt;Уилкинсон Дж. X. Алгебраическая проблема собственныx значений. Изд-во &amp;quot;Наука&amp;quot;, 1970. - глава 5, с. 272-278&amp;lt;/ref&amp;gt; Соответствующие собственные вектора могут быть найдены посредством обратных итераций за &amp;lt;math&amp;gt; O(n) &amp;lt;/math&amp;gt; флопов. &amp;lt;ref&amp;gt;Голуб Дж., Ван Лоун Ч. - Матричные вычисления//М.: Мир. - 1999 (c. 394-395)&amp;lt;/ref&amp;gt; &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;На практике, если требуется только небольшая часть от всей совокупности собственных векторов и значений, и матрица имеет Хессенбергову или трёхдиагональную форму, очень эффективными будут методы факторизации, как, например, QR-алгоритм или QL-алгоритм со сдвигами (c целью ускорить алгоритм и сделать порядок сходимости квадратичным) или же без них.&amp;lt;ref&amp;gt;http://algorithm.narod.ru/ln/eigen/ETridiag.html&amp;lt;/ref&amp;gt; &amp;lt;br&amp;gt;&lt;br /&gt;
Весьма молодые и не менее актуальные конкуренты QR и QL алгоритмов, применяющиеся для поиска собственных значений:&lt;br /&gt;
*Методы divide-and-conquer (разделяй и властвуй), появившиеся в 1980-ых годах &amp;lt;ref&amp;gt;https://goo.gl/dapvbn ссылку пришлось сократить с помощью Google url shortener, так как символы подчеркивания портили её и не давали перейти по 1 клику&amp;lt;/ref&amp;gt;&lt;br /&gt;
*Relatively robust representation методы, появившиеся в 1990-ых и позволяющие найти собственные числа симметричной матрицы порядка &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;n&amp;lt;/math&amp;gt; за &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt; операций&lt;br /&gt;
&lt;br /&gt;
Если требуется вычислить собственные векторы, то необходимо хранить вычисляемые векторы Ланцоша. Если работа при этом производится только с оперативной памятью, то при большом порядке исходной матрицы (а именно для таких матриц и предназначен метод Ланцоша) число шагов  &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;j&amp;lt;/math&amp;gt;, которые могут быть выполнены до того момента, как оперативная память будет исчерпана, будет очень незначительно, а следовательно, искомые собственные пары могут не успеть сойтись с требуемой точностью. В этом случае метод Ланцоша можно использовать итерационным образом: после выполнения заданного числа шагов процесс прерывается и, если еще не все требуемые пары Ритца сошлись с требуемой точностью, то формируется новый начальный вектор &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;q_1&amp;lt;/math&amp;gt;, являющийся линейной комбинацией векторов Ритца, еще не сошедшихся с заданной точностью, и процесс начинается заново.&amp;lt;ref&amp;gt;http://num-anal.srcc.msu.ru/lib_na/int_ae/int_ae6.htm (пункт 6.5)&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
Вычислительное ядро рассматриваемого алгоритма (наиболее ресурсно-затратная часть алгоритма) -  формирование на каждом шаге цикла промежуточного вектора &amp;lt;math&amp;gt;z&amp;lt;/math&amp;gt;, вычисляемого по формуле: &amp;lt;math&amp;gt;z = A\,q_j&amp;lt;/math&amp;gt;. Данная операция, по сравнению с другими операциями алгоритма, затратна и требовательна, как с точки зрения количества производимых операций, так и с точки зрения объема оперируемых данных. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Например, умножение матрицы размера &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;n\times n&amp;lt;/math&amp;gt; на вектор длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; требует: &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;n^2+(n-1)n = 2n^2-n&amp;lt;/math&amp;gt; операций умножения и сложения. В свою очередь аналогичная операция умножения матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;(n+1)\times (n+1)&amp;lt;/math&amp;gt; на вектор длины &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;(n+1)&amp;lt;/math&amp;gt; требует: &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;2n^2+3n+1&amp;lt;/math&amp;gt;  операций умножения и сложения. То есть повышение размерности задачи всего на 1 увеличивает число необходимых действий в этом шаге алгоритма на: &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;4n+1&amp;lt;/math&amp;gt;. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Так же, стоит помнить, что, согласно разделу 1.2, данную операцию умножения матрицы на вектор необходимо выполнить &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;k&amp;lt;/math&amp;gt; раз. Нетрудно понять, насколько возрастает и колоссален масштаб операций, если в задачах, где критична точность, размерности &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; могут иметь порядок &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;10^5&amp;lt;/math&amp;gt; или даже более.&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
Как уже было упомянуто в данной статье в описании алгоритма, рассматриваемый алгоритм состоит из двух последовательно выполненных алгоритмов: метод Ланцоша для построения последовательности подпространств Крылова и ортонормированных векторов Ланцоша и процедура Рэлея-Ритца получения оптимальных приближений собственных значений и соответствующих собственных векторов исходной матрицы.&lt;br /&gt;
&lt;br /&gt;
В первой части алгоритма, где итерационно строятся Крыловское подпространство и трёхдиагональная матрица &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&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 style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; разреженная. Именно она подлежит оптимизации с использованием техник распараллеливания, поскольку она является вычислительным ядром алгоритма, а весь упомянутый процесс построения матрицы &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&amp;lt;/math&amp;gt; выполняется последовательно.&lt;br /&gt;
&lt;br /&gt;
Рассмотрим вторую часть алгоритма - поиск собственных значений сформированной матрицы &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&amp;lt;/math&amp;gt;.&amp;lt;br&amp;gt;&lt;br /&gt;
Далее, наглядно, в виде псевдокода, представлен, упомянутый в разделе 1.2, QR-алгоритм (аналогично можно рассмотреть и QL-алгоритм) со сдвигами Релэя, который весьма популярен на практике.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{align}&lt;br /&gt;
\mathbf{Input}: \;&amp;amp;tridiagonal\;\;matrix \;T\;with\;\;n\times n\;\;size\\&lt;br /&gt;
T^{(0)}&amp;amp;:=T\\&lt;br /&gt;
\mathbf{for}&amp;amp; \;\;m=n,...,2 \;\; \mathbf{do}\\&lt;br /&gt;
&amp;amp;k=0\\&lt;br /&gt;
&amp;amp; \mathbf{repeat}\\&lt;br /&gt;
&amp;amp; \quad \;\; k=k+1\\&lt;br /&gt;
&amp;amp; \quad \;\; \mu^{(k)}=T_{m,m}^{(k-1)}\\&lt;br /&gt;
&amp;amp; \quad \;\; Q^{(k)}R^{(k)}=T^{(k-1)}-\mu^{(k)}I\;\;using\;\;QR\;decomposition\\&lt;br /&gt;
&amp;amp; \quad \;\; T^{(k)}=R^{(k)}Q^{(k)}+\mu^{(k)}I\\&lt;br /&gt;
&amp;amp; \mathbf{until} \;\;\; |T_{m,m-1}^{(k)}| \;is\;\;small\;\;enough\\&lt;br /&gt;
&amp;amp; Save  \;\;T_{m,m}^{(k)} \;\;as\;\; converged\;\;eigenvalue\;of\;T\\ &lt;br /&gt;
&amp;amp; Remove \;\boldsymbol{n}\,th\;row\;and\;\boldsymbol{n}\,th\;column\;\;from \;T \\&lt;br /&gt;
&amp;amp; and\;take\;this\;new\;cropped\;matrix\;as\;new\;T^{(0)}\;with\;\;(n-1)\times (n-1)\;\;size\\&lt;br /&gt;
 \mathbf{end}&amp;amp;\; \mathbf{for}&lt;br /&gt;
\end{align}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Малость наддиагональных и поддиагональных элементов матрицы (фраза &#039;&#039;&amp;quot;small enough&amp;quot;&#039;&#039; в псевдокоде) подразумевает:&lt;br /&gt;
&amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt; |T_{m,m-1}^{(k)}| \leq \varepsilon\,|T_{m,m}^{(k)}| \quad\quad &amp;lt;/math&amp;gt; , где &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt; \varepsilon &amp;lt;/math&amp;gt; - заданная точность&amp;lt;br&amp;gt;&lt;br /&gt;
Также вместо сдвига Релэя, обозначенного в алгоритме через &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;\mu^{(k)}&amp;lt;/math&amp;gt;, часто на практике используется сдвиг по Уилкинсону, который даёт гарантированную сходимость внедиагональных элементов матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt; T^{(k)} &amp;lt;/math&amp;gt;, формируемой на каждом шаге, к нулю, при этом жертвуя монотонностью их убывания.&amp;lt;ref&amp;gt;Голуб Дж., Ван Лоун Ч. - Матричные вычисления//М.: Мир. - 1999 (c. 378, вторая половина страницы)&amp;lt;/ref&amp;gt;&amp;lt;ref&amp;gt;Парлетт Б. Симметричная проблема собственных значений. Численные методы.,: Мир, 1983. с. 169&amp;lt;/ref&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Подробнее с различными сдвигами и соответствующими оценками скоростей и количествами операций можно ознакомиться по указанной ссылке:&amp;lt;ref&amp;gt;Парлетт Б. Симметричная проблема собственных значений. Численные методы.,: Мир, 1983. с. 179-182&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;Для совершения QR-декомпозиции на каждом шаге может использоваться любой из алгоритмов по ссылке.&amp;lt;ref&amp;gt;https://en.wikipedia.org/wiki/QR_decomposition&amp;lt;/ref&amp;gt; Подробные описания этих алгоритмов также доступны на данном ресурсе algowiki-project.&amp;lt;br&amp;gt;&lt;br /&gt;
Так как мы оперируем не обычной матрицей и даже не Хессенберговой, а симметричной и трёхдиагональной, то скорость таких алгоритмов значительно возрастёт. Например, согласно данному ресурсу &amp;lt;ref&amp;gt;http://algorithm.narod.ru/ln/eigen/ETridiag.html&amp;lt;/ref&amp;gt;, для QL-алгоритма с неявными сдвигами:&amp;lt;br&amp;gt;&lt;br /&gt;
Для трёхдиагональной матрицы объем арифметических действий составляет &amp;lt;math&amp;gt; O(n)&amp;lt;/math&amp;gt; на одну итерацию вместо &amp;lt;math&amp;gt; O(n^3)&amp;lt;/math&amp;gt; для матрицы общего вида, а число итераций для нахождения первых собственных значений примерно равно 4 - 5. Но на этих итерациях также уменьшаются внедиагональные элементы правого нижнего угла. И, таким образом, дальнейшие собственные значения ищутся значительно быстрее. Среднее число итераций на каждое собственное значение обычно составляет 1.3 - 1.6.&amp;lt;br&amp;gt; &lt;br /&gt;
Аналогично QL, QR-разложение трёхдиагольной матрицы также требует &amp;lt;math&amp;gt; O(n)&amp;lt;/math&amp;gt; флопов&amp;lt;ref&amp;gt;Голуб Дж., Ван Лоун Ч. - Матричные вычисления//М.: Мир. - 1999 (c. 378, начало раздела 8.2.2)&amp;lt;/ref&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Подводя итог, во второй части алгоритма Ланцоша можно выделить следующие макрооперации:&lt;br /&gt;
* умножение матрицы на вещественное число;&lt;br /&gt;
* перемножение матриц;&lt;br /&gt;
* умножение и сравнение вещественных чисел;&lt;br /&gt;
* + набор других макроопераций в зависимости от выбора метода, с помощью которого будет совершаться сама QR или QL-декомпозиция (выше продемонстрированы, уже, как минимум, 3 разных способа).&lt;br /&gt;
Так же, важно заметить, что набор макропераций может быть несколько другим, если выбрать какой-либо иной современный метод поиска собственных чисел трёхдиагональной матрицы, не использующий QR и QL разложения(факторизацию). Два таких метода были упомянуты в пункте 1.2.&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
С целью полностью не дублировать раздел 1.2 данной статьи, где представлен наглядный и доступный для понимания псевдокод алгоритма, постараемся лишь коротко просуммировать и обобщить весь перечень последовательных действий в рассматриваемом алгоритме.&lt;br /&gt;
&lt;br /&gt;
В качестве входных данных имеем: вещественная симметричная матрица &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; размера &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;n\times n&amp;lt;/math&amp;gt;, известный вещественный вектор &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;b&amp;lt;/math&amp;gt; длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; и число &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;n&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Далее:&lt;br /&gt;
* Инициализируем вещественную константу &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;\beta_0&amp;lt;/math&amp;gt; и векторы &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;q_0&amp;lt;/math&amp;gt; и &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;q_1&amp;lt;/math&amp;gt;&lt;br /&gt;
* Итерационно для всех &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j=1,...,k&amp;lt;/math&amp;gt;:&lt;br /&gt;
** Вычисляем вспомогательный вектор &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt;, используя умножение матрицы на вектор&lt;br /&gt;
** Вычисляем, используя скалярное произведение векторов, значение &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;\alpha_j&amp;lt;/math&amp;gt; - элемент на главной диагонали трёхдиагональной матрицы &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&amp;lt;/math&amp;gt;&lt;br /&gt;
** Вычисляем по формуле новое значение и перезаписываем вектор &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt;&lt;br /&gt;
** Вычисляем значение &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;\beta_j&amp;lt;/math&amp;gt; - элементы непосредственно над и под главной диагональю той же матрицы &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&amp;lt;/math&amp;gt;&lt;br /&gt;
** Вычисляем, зная вектор &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt;,  очередной столбец матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;Q&amp;lt;/math&amp;gt;, он же вектор Ланцоша : &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;\,\,q_{j+1}&amp;lt;/math&amp;gt;&lt;br /&gt;
** Теперь, когда матрица &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&amp;lt;/math&amp;gt; сформирована на очередном шаге, находим её собственные значения и вектора любым доступным способом, о чём было подробно сказано в пункте 1.2&lt;br /&gt;
** Переходим на следующую итерацию: &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j&amp;lt;/math&amp;gt;++&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
Оценим количество операций и сложность последовательного алгоритма, изложенного в предыдущем разделе.&lt;br /&gt;
*Для вычисления вектора &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt; умножается матрица размера &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;n\times n&amp;lt;/math&amp;gt; на вектор длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt;, и потребуется &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n^2&amp;lt;/math&amp;gt; операций умножения и &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n^2&amp;lt;/math&amp;gt; операций сложения.&lt;br /&gt;
*Умножение векторов &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;q^T_j&amp;lt;/math&amp;gt; и &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt; длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; потребует &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; операций умножения и &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; операций сложения.&lt;br /&gt;
*При вычислении нового значения вектора &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt; поэлементное сложение двух векторов длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; требует &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; операций сложения.&lt;br /&gt;
*Умножение вектора длины &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; на вещественное число требует &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; операций умножения.&lt;br /&gt;
*Нахождение квадратичной нормы вектора &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt;  длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; требует &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; умножений и &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; сложений и ещё 1 операцию извлечения квадратного корня.&lt;br /&gt;
*Заключительное нахождение собственных значений и собственных векторов трёхдиагональной матрицы &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;T_j&amp;lt;/math&amp;gt; размера &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j\times j&amp;lt;/math&amp;gt; с помощью QR-алгоритма потребует в худшем случае &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(j^3)&amp;lt;/math&amp;gt; операций.&amp;lt;ref&amp;gt;http://num-anal.srcc.msu.ru/lib_na/int_ae/int_ae6.htm (пункт 6.2, &amp;quot;Скорость сходимости при этом всегда не хуже квадратичной и почти всегда лучше кубической.&amp;quot;)&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Посчитаем теперь суммарное количество простейших операций на одной итерации алгоритма (без учёта записей в память):&lt;br /&gt;
*&amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n^2+5\,n&amp;lt;/math&amp;gt; операций умножения/деления&lt;br /&gt;
*&amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n^2+4\,n&amp;lt;/math&amp;gt; операций сложения/вычитания&lt;br /&gt;
*1 операция извлечения квадратного корня&amp;lt;br&amp;gt;&lt;br /&gt;
Отдельно после всех итераций при &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j=k&amp;lt;/math&amp;gt; :&lt;br /&gt;
*&amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(k^3)&amp;lt;/math&amp;gt; операций для поиска собственных значений и собственных векторов трёхдиагональной матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_k&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Итого можно утверждать следующее:&lt;br /&gt;
&lt;br /&gt;
Последовательная сложность одной итерации рассматриваемого алгоритма:  &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(n ^ 2) &amp;lt;/math&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Суммарная сложность алгоритма (&amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;/math&amp;gt; итераций): &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(k\,n ^ 2) + O(k ^ 3)&amp;lt;/math&amp;gt; &amp;lt;ref&amp;gt;Здесь мы полагаем, что мы не вычисляем собственные значения и векторы матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_j&amp;lt;/math&amp;gt; на каждом промежуточном шаге, а лишь единожды затрачиваем &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;O(k ^ 3)&amp;lt;/math&amp;gt; действий в конце для нахождения &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;/math&amp;gt; собственных значений и векторов матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_k&amp;lt;/math&amp;gt;&amp;lt;/ref&amp;gt; &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
На практике же обычно рассматривается число &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;&amp;lt;n&amp;lt;/math&amp;gt;, поэтому второе слагаемое можно опустить.&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
На рис. 1 продемонстрирован граф одной итерации (при каком-либо произвольном значении итератора &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j&amp;lt;/math&amp;gt;) описанного алгоритма без отображения входных и выходных данных. Наглядно продемонстрированы связи между всеми действиями, и с помощью деления на &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; потоков показано, какие операции возможно выполнять параллельно на каждом шаге с целью оптимизации и экономии машинного времени. В результате, после параллельно выполненных операций &#039;&#039;&#039;Division&#039;&#039;&#039; на заключительном ярусе, на выходе имеем значение следующего вектора Ланцоша &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;q_{j+1}&amp;lt;/math&amp;gt;, после чего следует переход на следующую итерацию, и процесс повторяется.&lt;br /&gt;
&lt;br /&gt;
[[Файл:Levin_graph.png|600px|thumb|center|Рис. 1]] &amp;lt;br&amp;gt;&lt;br /&gt;
Обозначения на рисунке: &amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Simp&#039;&#039;&#039; (от англ. simple) - операции сложения и умножения вещественных чисел при вычислении произведения матрицы на вектор;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Vec mult&#039;&#039;&#039; (от англ. vectors multiplication) - операция скалярного умножения двух векторов;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Vec subtr&#039;&#039;&#039; (от англ. vectors subtraction, из-за использованных в операции вычитаний векторов) - операция умножения вектора на число (выполняется дважды) и формирование нового значения &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;z_{new}&amp;lt;/math&amp;gt; по формуле: &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;z_{new} = z - \alpha_j q_j - \beta_{j-1}q_{j-1} \;&amp;lt;/math&amp;gt;;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;||\cdot||&amp;lt;/math&amp;gt; - операция вычисления нормы вектора;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Division&#039;&#039;&#039; - операция деления вектора на вещественное число  &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;\beta_j&amp;lt;/math&amp;gt; &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Важно отметить, что упомянутые выше операции также легко поддаются оптимизации. Например, попарные умножения вещественных координат векторов при вычислении скалярного произведения также легко выполняются параллельно на &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; потоках, а затем можно применить суммирование методом сдваивания, о котором сказано в следующем разделе. Умножение или деление вектора на вещественное число являющееся, по определению, умножением или делением всех его координат на это число тоже может быть выполнено эффективнее, если мы используем &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; потоков, а не выполняем эти действия последовательно.&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
Параллельные операции возможны только внутри итераций, так как рассматриваемый алгоритм является итерационным, и сами итерации строго последовательны.&amp;lt;br&amp;gt;&lt;br /&gt;
Рассмотрим в этом разделе подробнее, какой выигрыш мы можем получить при распараллеливании операций внутри одной итерации согласно графу из предыдущего раздела.&lt;br /&gt;
&lt;br /&gt;
Умножение вещественной симметричной матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; размера &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;n\times n&amp;lt;/math&amp;gt; на вектор &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;b&amp;lt;/math&amp;gt; длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; требует последовательного выполнения &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; ярусов умножений и сложений. Сложение элементов вектора длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; на каждом шаге перемножения можно оптимизировать и выполнить за &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;\log_2 n&amp;lt;/math&amp;gt; действий, если применять метод сдваивания.&lt;br /&gt;
&lt;br /&gt;
Дальнейшие операции выполняются последовательно, а вычисление значений векторов происходит за один ярус операций сложения или умножения.&lt;br /&gt;
&lt;br /&gt;
Ресурс параллелизма алгоритма вычисления собственных значений построенной трёхдиагональной матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_k&amp;lt;/math&amp;gt; размера &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k\times k&amp;lt;/math&amp;gt; зависит от выбранного алгоритма (об этих алгоритмах подробнее было сказано в разделах 1.2 и 1.4). Будет очень затратно с точки зрения объёма материала пытаться рассмотреть пусть даже часть этих методов в этой статье, а так же тонкости их распараллеливания. Предлагаем читателям при желании самим ознакомиться с этими алгоритмами на данном ресурсе или прибегнув к иным источникам.&lt;br /&gt;
&lt;br /&gt;
При классификации по высоте ЯПФ, таким образом, алгоритм Ланцоша без переортогонализации относится к алгоритмам с &#039;&#039;логарифмической сложностью&#039;&#039;, и его сложность равна &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(\log_2 n)&amp;lt;/math&amp;gt; с важным замечанием, что это сложность только одной итерации, а максимум в алгоритме может быть выполнено последовательно &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;/math&amp;gt; таких однотипных итераций, если не будет осуществлён ранний выход из цикла. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Несмотря на то, что на графе в предыдущем разделе для лучшей визуализации и понимания было изображено &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; потоков (никаких допущений мы не делали и нарушений с точки зрения логики и математики нет, можно изобразить большее число потоков, просто часть времени некоторые из них могут бездействовать и не использоваться), на самом деле правильным и разумным будет реализовать начальное параллельное выполнение &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n^2&amp;lt;/math&amp;gt; операций умножения всех вещественных элементов матрицы &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;A&amp;lt;/math&amp;gt; на соответствующие элементы вектора &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;q_j&amp;lt;/math&amp;gt;, после чего применять тот же самый упомянутый метод сдваивания. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Поэтому при классификации по ширине ЯПФ его сложность будет &#039;&#039;квадратичной&#039;&#039; и равна &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(n^2)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
&#039;&#039;&#039;Входные данные алгоритма:&#039;&#039;&#039; вещественная симметричная &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; размера &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;n\times n&amp;lt;/math&amp;gt;, вещественный вектор &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;b&amp;lt;/math&amp;gt; длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt;, и одно целое число &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;k&amp;lt;/math&amp;gt;, означающее количество итераций.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём входных данных:&#039;&#039;&#039; &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;n^2 +n + 1 &amp;lt;/math&amp;gt;. Если учесть, что матрица симметричная и достаточно для её однозначного определения задать элементы на главной диагонали и элементы над или под ней, то можно сократить объём входных данных с целью экономии памяти до: &amp;lt;math&amp;gt;\ \frac{n^2-n}{2}+n+n+1 =\frac{n^2+3n}{2} + 1&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные алгоритма:&#039;&#039;&#039; вектор собственных значений &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;\Theta^k&amp;lt;/math&amp;gt; длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;/math&amp;gt;, матрица &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;S^k&amp;lt;/math&amp;gt; из соответствующих собственных векторов размера &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n\times k&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём выходных данных:&#039;&#039;&#039; &amp;lt;math&amp;gt;k\;(n + 1)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
В данном разделе перечислены без какой-либо хронологии или связи друг с другом наиболее важные и разнообразные свойства алгоритма, на которые стоит и полезно обратить внимание, а также которые выгодно отличают его от схожих алгоритмов, решающих ту же задачу.&amp;lt;br&amp;gt;&lt;br /&gt;
1) Отношение последовательной сложности алгоритма к параллельной,с учётом &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;/math&amp;gt; итераций, равно &amp;lt;math&amp;gt;\;\;\frac{kn^2}{k \log_2{n}}=\frac{n^2}{\log_2{n}}&amp;lt;/math&amp;gt;;&amp;lt;br&amp;gt;&lt;br /&gt;
2) Вычислительная мощность алгоритма, как отношение числа операций к суммарному объему входных и выходных данных, равна &amp;lt;math style=&amp;quot;vertical-align:-70%&amp;gt;\;\;\frac{k\,n^2}{0.5\,n^2+1.5\,n+k\,n+k+1}&amp;lt;/math&amp;gt; и &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;\approx 2\,k&amp;lt;/math&amp;gt;, так как на практике верно отношение &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;&amp;lt;n&amp;lt;/math&amp;gt; ;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
3) Для собственных значений формируемых матриц &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_j&amp;lt;/math&amp;gt; верно отношение (следствие теоремы Коши о перемежаемости): &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;\lambda_i(T_{k+1})\geq \lambda_i(T_{k})\geq \lambda_{i+1}(T_{k+1})\geq \lambda_{i+1}(T_{k})&amp;lt;/math&amp;gt; ;&amp;lt;ref&amp;gt;James W. Demmel - Вычислительная линейная алгебра. Теория и приложения //Мир. - 2001 (c. 383)&amp;lt;/ref&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
4) Крайние (наибольшие и наименьшие) собственные значения матриц &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_j&amp;lt;/math&amp;gt; сходятся к крайним собственным значениям матрицы &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;A&amp;lt;/math&amp;gt; первыми (это часто происходит уже на ранних шагах при &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j\approx 2\,\sqrt{n}&amp;lt;/math&amp;gt;&amp;lt;ref&amp;gt;http://num-anal.srcc.msu.ru/lib_na/int_ae/int_ae6.htm (пункт 6.5)&amp;lt;/ref&amp;gt;), а собственные значения в середине спектра - последними;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
5) Из-за ограниченной точности постепенно теряется ортогональность вектора Ланцоша &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;q_j&amp;lt;/math&amp;gt; к предыдущим векторам Ланцоша, поэтому необходимо примерно каждые 10-15 итераций проводить дорогостоящую операцию реортогонализации, но это уже будет иной алгоритм с очень малым различием в одной операции и в программном коде, реализующем его, соответственно; &amp;lt;ref&amp;gt;Sam Handler - The Lanczos Algorithm For Large-Scale Eigenvalue Problems (08.01.07), slide №8&amp;lt;/ref&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
6) Эффективность и быстрота выполнения алгоритма очень сильно зависит от скорости памяти (диска). Согласно тесту только &#039;&#039;6%&#039;&#039; времени работы программы приходится на вычисления, остальное время затрачивается на ожидание отклика диска;&amp;lt;ref&amp;gt;Sam Handler - The Lanczos Algorithm For Large-Scale Eigenvalue Problems (08.01.07), slide №10&amp;lt;/ref&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
7) Метод Ланцоша удобен тем, что не требует хранения исходной матрицы полным массивом: метод использует исходную матрицу только в операциях умножения матрицы на вектор, что позволяет эффективно использовать разреженность матрицы или регулярность структуры матрицы. Поэтому метод Ланцоша может быть использован для матриц таких больших порядков, когда методы вращений и отражений не могут быть применены.&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;
Для исследования масштабируемости рассматриваемого алгоритма Ланцоша без переортогонализации автором была реализована программа на языке С++ с использованием технологии MPI (&#039;&#039;&#039;не забыть вставить ссылку на код&#039;&#039;&#039;). Дальнейшее исследование выполнялось на суперкомпьютере &amp;quot;Ломоносов&amp;quot; Суперкомпьютерного комплекса МГУ. &amp;lt;br&amp;gt; Важно отметить, что реализованная программа выполняет только первую часть алгоритма - формирование матрицы &amp;lt;math &amp;gt;T_j&amp;lt;/math&amp;gt;. Вторая часть алгоритма - задача поиска её собственных значений может быть решена несколькими методами, каждый из которых обладает своей эффективностью распараллеливании и характерными свойствами. Подробно этот вопрос уже обсуждался в статье раннее, поэтому не будем ещё раз заострять на этом внимание и останавливаться.&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Сборка осуществлялась со следующими параметрами:&lt;br /&gt;
* Компилятор intel/15.0.090 &lt;br /&gt;
* Openmpi/1.8.4-icc&lt;br /&gt;
В серии проведённых расчётов рассматривались следующие числовые значения параметров:&lt;br /&gt;
* Размер &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;n&amp;lt;/math&amp;gt; задачи и, соответственно, матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt;, задействованной в операции умножения на вектор: [2000 : 30000] с шагом 1000&lt;br /&gt;
* Число процессоров: 1,2,4,16,32,48,64,96,128&lt;br /&gt;
* Число итераций в алгоритме: &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k=350&amp;lt;/math&amp;gt; . Взято таким вопреки информации в начале статьи, где говорится, что значение &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; редко превышает &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;10^2&amp;lt;/math&amp;gt;. Это сделано исключительно для лучшей визуализации пиков на графиках в данном разделе и наглядности получаемых результатов, так как при меньших на порядок значениях &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; времена выполнения программ были слишком малы даже при минимальных числах процессоров и максимальных размерах исходной задачи.&lt;br /&gt;
&lt;br /&gt;
== Динамические характеристики и эффективность реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Выводы для классов архитектур ==&lt;br /&gt;
По заданию, во второй части требовалось описать только разделы 2.4 и 2.7, прошу не спрашивать с меня все разделы 2.1-2.6. Надеюсь на понимание, мне физически не хватает времени на это задание + 2 других в течение семестра, делаю всё, что в моих силах :)&lt;br /&gt;
&lt;br /&gt;
== Существующие реализации алгоритма ==&lt;br /&gt;
Несмотря на то, что алгоритм является далеко не самым популярным, алгоритмом, про который нельзя сказать, что он всегда «на слуху», на сегодняшний день существует множество реализаций на различных популярных языках.&amp;lt;br&amp;gt;&lt;br /&gt;
Перечислим далее некоторые из них, указывая язык программирования, лежащий в их основе, и некоторые важные характеристики, которые обсуждались в статье ранее:&lt;br /&gt;
*&#039;&#039;Code on netlib.org by Jane Cullum and Ralph Willoughby&#039;&#039; (&#039;&#039;&#039;Fortran 77&#039;&#039;&#039;; без реортогонализации векторов; без реализации распараллеливания)&amp;lt;ref&amp;gt;http://www.netlib.org/lanczos/leval&amp;lt;/ref&amp;gt;&lt;br /&gt;
*&#039;&#039;Lanczos algorithm on freesourcecode.net&#039;&#039; (&#039;&#039;&#039;Matlab&#039;&#039;&#039;; присутствует реортогонализация векторов; без реализации распараллеливания)&amp;lt;ref&amp;gt;http://freesourcecode.net/matlabprojects/61741/lanczos-algorithm--in-matlab&amp;lt;/ref&amp;gt;&lt;br /&gt;
*&#039;&#039;Lanczos for eigenvalues in Numerical Linear Algebra, Spring 2007&#039;&#039; (&#039;&#039;&#039;Matlab&#039;&#039;&#039;; частичная или полная реортогонализация - доступны оба варианта; без реализации распараллеливания)&amp;lt;ref&amp;gt;Ссылки на файлы lanso.m и lanfu.m можно найти на https://www.nada.kth.se/~ruhe/2D5219/labs2007.html&amp;lt;/ref&amp;gt;&lt;br /&gt;
*&#039;&#039;Planso&#039;&#039; (название происходит от parallel Lanso.f) &#039;&#039;code by Kesheng Wu and Horst D. Simon&#039;&#039; (&#039;&#039;&#039;Fortran 77&#039;&#039;&#039;; частичная реортогонализация векторов; использование MPI для коммуникаций)&amp;lt;ref&amp;gt;https://github.com/jiahao/planso.jl/tree/master/external/PLAN/plan К сожалению, ссылка в описании пакета на github, ведущая на сайт National Energy Research Scientific Computing Center (NERSC), с более подробной информацией о данной программе больше не активна и выдаёт результат &#039;&#039;Page not found&#039;&#039;&amp;lt;/ref&amp;gt; &lt;br /&gt;
* &#039;&#039;Lanczos.cpp in the Vienna Computing Library&#039;&#039;  (&#039;&#039;&#039;C++&#039;&#039;&#039;, частичная реортогонализация, без реализации распараллеливания) &amp;lt;ref&amp;gt;http://viennacl.sourceforge.net/doc/lanczos_8cpp_source.html&amp;lt;/ref&amp;gt;&lt;br /&gt;
* &#039;&#039;Parallel Eigen Values code using C++ AMP on microsoft msdn blog&#039;&#039; (&#039;&#039;&#039;C++&#039;&#039;&#039;; ? ; распараллеливание есть и реализовано через C++ AMP) &amp;lt;ref&amp;gt;https://blogs.msdn.microsoft.com/nativeconcurrency/2013/12/20/eigen-values/ Подробнее о C++ Accelerated Massive Parallelism можно почитать здесь: https://msdn.microsoft.com/ru-ru/library/hh265137(v=vs.140).aspx или здесь: http://professorweb.ru/my/csharp/optimization/level4/4_6.php &amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;br /&gt;
[[en:Description of algorithm properties and structure]]&lt;/div&gt;</summary>
		<author><name>AleksLevin</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:AleksLevin/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%9B%D0%B0%D0%BD%D1%86%D0%BE%D1%88%D0%B0_%D0%B2%D1%8B%D1%87%D0%B8%D1%81%D0%BB%D0%B5%D0%BD%D0%B8%D1%8F_%D1%81%D0%BE%D0%B1%D1%81%D1%82%D0%B2%D0%B5%D0%BD%D0%BD%D1%8B%D1%85_%D0%B7%D0%BD%D0%B0%D1%87%D0%B5%D0%BD%D0%B8%D0%B9_%D1%81%D0%B8%D0%BC%D0%BC%D0%B5%D1%82%D1%80%D0%B8%D1%87%D0%BD%D0%BE%D0%B9_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86%D1%8B_%D0%B4%D0%BB%D1%8F_%D1%82%D0%BE%D1%87%D0%BD%D0%BE%D0%B9_%D0%B0%D1%80%D0%B8%D1%84%D0%BC%D0%B5%D1%82%D0%B8%D0%BA%D0%B8_(%D0%B1%D0%B5%D0%B7_%D0%BF%D0%B5%D1%80%D0%B5%D0%BE%D1%80%D1%82%D0%BE%D0%B3%D0%BE%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D0%B8)&amp;diff=20205</id>
		<title>Участник:AleksLevin/Алгоритм Ланцоша вычисления собственных значений симметричной матрицы для точной арифметики (без переортогонализации)</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:AleksLevin/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%9B%D0%B0%D0%BD%D1%86%D0%BE%D1%88%D0%B0_%D0%B2%D1%8B%D1%87%D0%B8%D1%81%D0%BB%D0%B5%D0%BD%D0%B8%D1%8F_%D1%81%D0%BE%D0%B1%D1%81%D1%82%D0%B2%D0%B5%D0%BD%D0%BD%D1%8B%D1%85_%D0%B7%D0%BD%D0%B0%D1%87%D0%B5%D0%BD%D0%B8%D0%B9_%D1%81%D0%B8%D0%BC%D0%BC%D0%B5%D1%82%D1%80%D0%B8%D1%87%D0%BD%D0%BE%D0%B9_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86%D1%8B_%D0%B4%D0%BB%D1%8F_%D1%82%D0%BE%D1%87%D0%BD%D0%BE%D0%B9_%D0%B0%D1%80%D0%B8%D1%84%D0%BC%D0%B5%D1%82%D0%B8%D0%BA%D0%B8_(%D0%B1%D0%B5%D0%B7_%D0%BF%D0%B5%D1%80%D0%B5%D0%BE%D1%80%D1%82%D0%BE%D0%B3%D0%BE%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D0%B8)&amp;diff=20205"/>
		<updated>2016-12-06T21:49:00Z</updated>

		<summary type="html">&lt;p&gt;AleksLevin: /* Масштабируемость алгоритма и его реализации */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Основные авторы описания: Левин А.Д.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{algorithm&lt;br /&gt;
| name              = Алгоритм Ланцоша для точной арифметики (без переортогонализации)&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(k\,n^2)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(k\log_2 n)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;\frac{n^2+3n}{2} + 1&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;k\;(n + 1)&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритмов =&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Данный алгоритм появился в 1950 г. и носит имя венгерского физика и математика Корнелия Ланцоша (венг. Lánczos Kornél). Алгоритм Ланцоша относится к итерационным методам вычисления собственных значений для матриц столь больших порядков &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt; n&amp;lt;/math&amp;gt;, что к ним нельзя применить прямые методы из-за ограничений по времени и памяти.&lt;br /&gt;
&lt;br /&gt;
Сам Ланцош указывал, что его метод предназначен для отыскания нескольких собственных векторов симметричных матриц, хотя к методу сразу было обращено внимание, как к способу приведения всей матрицы к трёхдиагональному виду. Двадцатью годами позже канадский математик Крис Пэж показал, что, несмотря на чувствительность к округлениям, алгоритм Ланцоша - эффективное средство вычисления некоторых &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; собственных чисел и соответствующих им собственных векторов. &amp;lt;ref&amp;gt;Парлетт Б. - Симметричная проблема собственных значений. Численные методы //М.: Мир. - 1983. (c. 276)&amp;lt;/ref&amp;gt;&lt;br /&gt;
Обычно число &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; берут в два раза больше, чем количество собственных значений матрицы, которые поставлена цель найти, и оно имеет порядок не более &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;10^2&amp;lt;/math&amp;gt;.&amp;lt;ref&amp;gt;Susan W. Bostic - Lanczos Eigensolution Method for High-Perfomance Computers, page 7&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Алгоритм Ланцоша для вычисления собственных значений симметричной матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; соединяет в себе метод Ланцоша для построения последовательности подпространств Крылова и ортонормированных векторов Ланцоша и процедуру Рэлея-Ритца получения оптимальных приближений собственных значений и соответствующих собственных векторов исходной матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt;.&amp;lt;ref&amp;gt;James W. Demmel - Вычислительная линейная алгебра. Теория и приложения //Мир. - 2001 (c. 381)&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
В данной статье рассматривается вариант алгоритма Ланцоша, в котором опущено влияние ошибок округления на вычислительный процесс, хотя на практике этому посвящается отдельное внимание и существуют различные методы решения данной проблемы, такие как частичная или полная переортогонализация. Этим модифицированным методам посвящены отдельные статьи на данном ресурсе.&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
Обозначения и формулы, используемые в данном разделе, взяты из литературы, указанной по ссылке.&amp;lt;ref&amp;gt;James W. Demmel - Вычислительная линейная алгебра. Теория и приложения //Мир. - 2001 (c. 313, &#039;&#039;&amp;lt;math&amp;gt; \S &amp;lt;/math&amp;gt; 6.6 Методы Крыловского подпространства&#039;&#039;)&amp;lt;/ref&amp;gt; &lt;br /&gt;
&lt;br /&gt;
Алгоритм Ланцоша для вычисления &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; собственных значений и собственных векторов вещественной симметричной матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A=A^T&amp;lt;/math&amp;gt; в точной арифметике: &amp;lt;ref&amp;gt;James W. Demmel - Вычислительная линейная алгебра. Теория и приложения //Мир. - 2001 (c. 381)&amp;lt;/ref&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{align}&lt;br /&gt;
q_1 = &amp;amp; \,\frac{b}{\|b\|_2},\; \beta_0 = 0,\; q_0 = 0\\&lt;br /&gt;
\mathbf{for} \; &amp;amp; j = 1 \; to \; k \,\; \mathbf{do} \\&lt;br /&gt;
&amp;amp; z = A\,q_j\\&lt;br /&gt;
&amp;amp; \alpha_j = q^T_j z\\&lt;br /&gt;
&amp;amp; z = z - \alpha_j q_j - \beta_{j-1}q_{j-1}\\&lt;br /&gt;
&amp;amp; \beta_j = \|z\|_2\\&lt;br /&gt;
&amp;amp; \mathbf{If} \; (\beta_j == 0) \; \mathbf{then}\; stop\; the\; algorithm \\ &lt;br /&gt;
&amp;amp; \;  q_{j+1} = \frac{z}{\beta_j} \\&lt;br /&gt;
&amp;amp; compute\; eigenvalues\; and \;eigenvectors\;of \;matrix \;\;T_j= Q^T_j A Q\;\;and\;estimate \;the\; errors\\&lt;br /&gt;
\mathbf{end} \; &amp;amp; \mathbf{for}&lt;br /&gt;
\end{align}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
В продемонстрированном выше алгоритме &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;b&amp;lt;/math&amp;gt; - заданный вещественный вектор. Также полагается известным алгоритм вычисления произведения матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; на вектор &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;x&amp;lt;/math&amp;gt;. &lt;br /&gt;
Введём матрицу Крылова, определяемую следующим соотношением: &amp;lt;math&amp;gt;K_j = [b,Ab,A^2b,...,A^{j-1}b]&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Далее, на практике, матрица &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;K&amp;lt;/math&amp;gt; заменяется матрицей &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;Q&amp;lt;/math&amp;gt;, такой, что при любом числе &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; линейные оболочки первых &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; столбцов в &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;K&amp;lt;/math&amp;gt; и &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;Q&amp;lt;/math&amp;gt; являются одним и тем же подпространством.&amp;lt;ref&amp;gt;James W. Demmel - Вычислительная линейная алгебра. Теория и приложения //Мир. - 2001 (c. 315)&amp;lt;/ref&amp;gt; &lt;br /&gt;
Тогда матрица &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;Q&amp;lt;/math&amp;gt;, в отличие от матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;K&amp;lt;/math&amp;gt;, хорошо обусловлена и легко обратима. В результате получаем матрицу &amp;lt;math&amp;gt;Q_j = [q_1, q_2, \dots, q_j]&amp;lt;/math&amp;gt; размерности &amp;lt;math&amp;gt;n\times j&amp;lt;/math&amp;gt;, столбцы которой ортогональны, являются базисом подпространства Крылова и называются векторами Ланцоша.&lt;br /&gt;
&lt;br /&gt;
В алгоритме Ланцоша вычислению подлежит столько первых столбцов в матрице &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;Q_j&amp;lt;/math&amp;gt;, сколько необходимо для получения требуемого приближения к решению &amp;lt;math&amp;gt;A\,x\,=b\,\,(A\,x=\lambda \, x)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Получение нулевого &amp;lt;math&amp;gt;\beta_j&amp;lt;/math&amp;gt; в итерационном процессе - событие, желательное в том смысле, что оно свидетельствует о том, что найдено некоторое подпространство, являющееся в точности инвариантным, а все собственные значения матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;T_j&amp;lt;/math&amp;gt; являются собственными значениями матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt;. На практике же нулевое и близкие к нулю значения получаются редко.&amp;lt;ref&amp;gt;Голуб Дж., Ван Лоун Ч. - Матричные вычисления//М.: Мир. - 1999 (c. 429)&amp;lt;/ref&amp;gt; &lt;br /&gt;
&lt;br /&gt;
Затем на каждом шаге цикла формируется симметричная трёхдиагональная матрица &amp;lt;math&amp;gt;T_j = Q^T_j A Q&amp;lt;/math&amp;gt;, к которой применяется процесс Рэлея-Ритца для поиска её собственных значений (на практике для поиска этих собственных значений можно использовать любой из специальных методов в параграфе книги по ссылке).&amp;lt;ref&amp;gt;Голуб Дж., Ван Лоун Ч. - Матричные вычисления//М.: Мир. - 1999 (&amp;lt;math&amp;gt;\S&amp;lt;/math&amp;gt; 8.4)&amp;lt;/ref&amp;gt;  &lt;br /&gt;
Эти собственные значения, они же числа Ритца, и полагаются приближёнными собственными значениями исходной матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt;.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Существует множество методов для отыскания собственных значений вещественной симметричной трехдиагональной матрицы. Большинство из них требует &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt; операций &amp;lt;ref&amp;gt;Парлетт Б. Симметричная проблема собственных значений. Численные методы.,: Мир, 1983. с. 179-182&amp;lt;/ref&amp;gt;, но существуют и быстрые алгоритмы, требующие лишь &amp;lt;math&amp;gt;O(n\ln n)&amp;lt;/math&amp;gt; операций.&amp;lt;ref&amp;gt;https://en.wikipedia.org/wiki/Tridiagonal_matrix#Eigenvalues  Раздел eigenvalues&amp;lt;/ref&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Одним из возможных способов отыскать собственные значения симметричной трехдиагональной матрицы - прямое вычисление корней характеристического полинома &amp;lt;math&amp;gt;p_n(\lambda)&amp;lt;/math&amp;gt; через метод деления пополам, где формируется последовательность Штурма и локализуются собственные числа, являющиеся корнями характеристического полинома. Нахождение всех &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; собственных значений матрицы этим способом требует &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;2n^2t&amp;lt;/math&amp;gt; умножений и вычитаний, где &amp;lt;math&amp;gt;t&amp;lt;/math&amp;gt; - число сделанных шагов с применением метода деления пополам.&amp;lt;ref&amp;gt;Уилкинсон Дж. X. Алгебраическая проблема собственныx значений. Изд-во &amp;quot;Наука&amp;quot;, 1970. - глава 5, с. 272-278&amp;lt;/ref&amp;gt; Соответствующие собственные вектора могут быть найдены посредством обратных итераций за &amp;lt;math&amp;gt; O(n) &amp;lt;/math&amp;gt; флопов. &amp;lt;ref&amp;gt;Голуб Дж., Ван Лоун Ч. - Матричные вычисления//М.: Мир. - 1999 (c. 394-395)&amp;lt;/ref&amp;gt; &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;На практике, если требуется только небольшая часть от всей совокупности собственных векторов и значений, и матрица имеет Хессенбергову или трёхдиагональную форму, очень эффективными будут методы факторизации, как, например, QR-алгоритм или QL-алгоритм со сдвигами (c целью ускорить алгоритм и сделать порядок сходимости квадратичным) или же без них.&amp;lt;ref&amp;gt;http://algorithm.narod.ru/ln/eigen/ETridiag.html&amp;lt;/ref&amp;gt; &amp;lt;br&amp;gt;&lt;br /&gt;
Весьма молодые и не менее актуальные конкуренты QR и QL алгоритмов, применяющиеся для поиска собственных значений:&lt;br /&gt;
*Методы divide-and-conquer (разделяй и властвуй), появившиеся в 1980-ых годах &amp;lt;ref&amp;gt;https://goo.gl/dapvbn ссылку пришлось сократить с помощью Google url shortener, так как символы подчеркивания портили её и не давали перейти по 1 клику&amp;lt;/ref&amp;gt;&lt;br /&gt;
*Relatively robust representation методы, появившиеся в 1990-ых и позволяющие найти собственные числа симметричной матрицы порядка &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;n&amp;lt;/math&amp;gt; за &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt; операций&lt;br /&gt;
&lt;br /&gt;
Если требуется вычислить собственные векторы, то необходимо хранить вычисляемые векторы Ланцоша. Если работа при этом производится только с оперативной памятью, то при большом порядке исходной матрицы (а именно для таких матриц и предназначен метод Ланцоша) число шагов  &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;j&amp;lt;/math&amp;gt;, которые могут быть выполнены до того момента, как оперативная память будет исчерпана, будет очень незначительно, а следовательно, искомые собственные пары могут не успеть сойтись с требуемой точностью. В этом случае метод Ланцоша можно использовать итерационным образом: после выполнения заданного числа шагов процесс прерывается и, если еще не все требуемые пары Ритца сошлись с требуемой точностью, то формируется новый начальный вектор &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;q_1&amp;lt;/math&amp;gt;, являющийся линейной комбинацией векторов Ритца, еще не сошедшихся с заданной точностью, и процесс начинается заново.&amp;lt;ref&amp;gt;http://num-anal.srcc.msu.ru/lib_na/int_ae/int_ae6.htm (пункт 6.5)&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
Вычислительное ядро рассматриваемого алгоритма (наиболее ресурсно-затратная часть алгоритма) -  формирование на каждом шаге цикла промежуточного вектора &amp;lt;math&amp;gt;z&amp;lt;/math&amp;gt;, вычисляемого по формуле: &amp;lt;math&amp;gt;z = A\,q_j&amp;lt;/math&amp;gt;. Данная операция, по сравнению с другими операциями алгоритма, затратна и требовательна, как с точки зрения количества производимых операций, так и с точки зрения объема оперируемых данных. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Например, умножение матрицы размера &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;n\times n&amp;lt;/math&amp;gt; на вектор длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; требует: &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;n^2+(n-1)n = 2n^2-n&amp;lt;/math&amp;gt; операций умножения и сложения. В свою очередь аналогичная операция умножения матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;(n+1)\times (n+1)&amp;lt;/math&amp;gt; на вектор длины &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;(n+1)&amp;lt;/math&amp;gt; требует: &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;2n^2+3n+1&amp;lt;/math&amp;gt;  операций умножения и сложения. То есть повышение размерности задачи всего на 1 увеличивает число необходимых действий в этом шаге алгоритма на: &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;4n+1&amp;lt;/math&amp;gt;. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Так же, стоит помнить, что, согласно разделу 1.2, данную операцию умножения матрицы на вектор необходимо выполнить &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;k&amp;lt;/math&amp;gt; раз. Нетрудно понять, насколько возрастает и колоссален масштаб операций, если в задачах, где критична точность, размерности &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; могут иметь порядок &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;10^5&amp;lt;/math&amp;gt; или даже более.&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
Как уже было упомянуто в данной статье в описании алгоритма, рассматриваемый алгоритм состоит из двух последовательно выполненных алгоритмов: метод Ланцоша для построения последовательности подпространств Крылова и ортонормированных векторов Ланцоша и процедура Рэлея-Ритца получения оптимальных приближений собственных значений и соответствующих собственных векторов исходной матрицы.&lt;br /&gt;
&lt;br /&gt;
В первой части алгоритма, где итерационно строятся Крыловское подпространство и трёхдиагональная матрица &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&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 style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; разреженная. Именно она подлежит оптимизации с использованием техник распараллеливания, поскольку она является вычислительным ядром алгоритма, а весь упомянутый процесс построения матрицы &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&amp;lt;/math&amp;gt; выполняется последовательно.&lt;br /&gt;
&lt;br /&gt;
Рассмотрим вторую часть алгоритма - поиск собственных значений сформированной матрицы &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&amp;lt;/math&amp;gt;.&amp;lt;br&amp;gt;&lt;br /&gt;
Далее, наглядно, в виде псевдокода, представлен, упомянутый в разделе 1.2, QR-алгоритм (аналогично можно рассмотреть и QL-алгоритм) со сдвигами Релэя, который весьма популярен на практике.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{align}&lt;br /&gt;
\mathbf{Input}: \;&amp;amp;tridiagonal\;\;matrix \;T\;with\;\;n\times n\;\;size\\&lt;br /&gt;
T^{(0)}&amp;amp;:=T\\&lt;br /&gt;
\mathbf{for}&amp;amp; \;\;m=n,...,2 \;\; \mathbf{do}\\&lt;br /&gt;
&amp;amp;k=0\\&lt;br /&gt;
&amp;amp; \mathbf{repeat}\\&lt;br /&gt;
&amp;amp; \quad \;\; k=k+1\\&lt;br /&gt;
&amp;amp; \quad \;\; \mu^{(k)}=T_{m,m}^{(k-1)}\\&lt;br /&gt;
&amp;amp; \quad \;\; Q^{(k)}R^{(k)}=T^{(k-1)}-\mu^{(k)}I\;\;using\;\;QR\;decomposition\\&lt;br /&gt;
&amp;amp; \quad \;\; T^{(k)}=R^{(k)}Q^{(k)}+\mu^{(k)}I\\&lt;br /&gt;
&amp;amp; \mathbf{until} \;\;\; |T_{m,m-1}^{(k)}| \;is\;\;small\;\;enough\\&lt;br /&gt;
&amp;amp; Save  \;\;T_{m,m}^{(k)} \;\;as\;\; converged\;\;eigenvalue\;of\;T\\ &lt;br /&gt;
&amp;amp; Remove \;\boldsymbol{n}\,th\;row\;and\;\boldsymbol{n}\,th\;column\;\;from \;T \\&lt;br /&gt;
&amp;amp; and\;take\;this\;new\;cropped\;matrix\;as\;new\;T^{(0)}\;with\;\;(n-1)\times (n-1)\;\;size\\&lt;br /&gt;
 \mathbf{end}&amp;amp;\; \mathbf{for}&lt;br /&gt;
\end{align}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Малость наддиагональных и поддиагональных элементов матрицы (фраза &#039;&#039;&amp;quot;small enough&amp;quot;&#039;&#039; в псевдокоде) подразумевает:&lt;br /&gt;
&amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt; |T_{m,m-1}^{(k)}| \leq \varepsilon\,|T_{m,m}^{(k)}| \quad\quad &amp;lt;/math&amp;gt; , где &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt; \varepsilon &amp;lt;/math&amp;gt; - заданная точность&amp;lt;br&amp;gt;&lt;br /&gt;
Также вместо сдвига Релэя, обозначенного в алгоритме через &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;\mu^{(k)}&amp;lt;/math&amp;gt;, часто на практике используется сдвиг по Уилкинсону, который даёт гарантированную сходимость внедиагональных элементов матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt; T^{(k)} &amp;lt;/math&amp;gt;, формируемой на каждом шаге, к нулю, при этом жертвуя монотонностью их убывания.&amp;lt;ref&amp;gt;Голуб Дж., Ван Лоун Ч. - Матричные вычисления//М.: Мир. - 1999 (c. 378, вторая половина страницы)&amp;lt;/ref&amp;gt;&amp;lt;ref&amp;gt;Парлетт Б. Симметричная проблема собственных значений. Численные методы.,: Мир, 1983. с. 169&amp;lt;/ref&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Подробнее с различными сдвигами и соответствующими оценками скоростей и количествами операций можно ознакомиться по указанной ссылке:&amp;lt;ref&amp;gt;Парлетт Б. Симметричная проблема собственных значений. Численные методы.,: Мир, 1983. с. 179-182&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;Для совершения QR-декомпозиции на каждом шаге может использоваться любой из алгоритмов по ссылке.&amp;lt;ref&amp;gt;https://en.wikipedia.org/wiki/QR_decomposition&amp;lt;/ref&amp;gt; Подробные описания этих алгоритмов также доступны на данном ресурсе algowiki-project.&amp;lt;br&amp;gt;&lt;br /&gt;
Так как мы оперируем не обычной матрицей и даже не Хессенберговой, а симметричной и трёхдиагональной, то скорость таких алгоритмов значительно возрастёт. Например, согласно данному ресурсу &amp;lt;ref&amp;gt;http://algorithm.narod.ru/ln/eigen/ETridiag.html&amp;lt;/ref&amp;gt;, для QL-алгоритма с неявными сдвигами:&amp;lt;br&amp;gt;&lt;br /&gt;
Для трёхдиагональной матрицы объем арифметических действий составляет &amp;lt;math&amp;gt; O(n)&amp;lt;/math&amp;gt; на одну итерацию вместо &amp;lt;math&amp;gt; O(n^3)&amp;lt;/math&amp;gt; для матрицы общего вида, а число итераций для нахождения первых собственных значений примерно равно 4 - 5. Но на этих итерациях также уменьшаются внедиагональные элементы правого нижнего угла. И, таким образом, дальнейшие собственные значения ищутся значительно быстрее. Среднее число итераций на каждое собственное значение обычно составляет 1.3 - 1.6.&amp;lt;br&amp;gt; &lt;br /&gt;
Аналогично QL, QR-разложение трёхдиагольной матрицы также требует &amp;lt;math&amp;gt; O(n)&amp;lt;/math&amp;gt; флопов&amp;lt;ref&amp;gt;Голуб Дж., Ван Лоун Ч. - Матричные вычисления//М.: Мир. - 1999 (c. 378, начало раздела 8.2.2)&amp;lt;/ref&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Подводя итог, во второй части алгоритма Ланцоша можно выделить следующие макрооперации:&lt;br /&gt;
* умножение матрицы на вещественное число;&lt;br /&gt;
* перемножение матриц;&lt;br /&gt;
* умножение и сравнение вещественных чисел;&lt;br /&gt;
* + набор других макроопераций в зависимости от выбора метода, с помощью которого будет совершаться сама QR или QL-декомпозиция (выше продемонстрированы, уже, как минимум, 3 разных способа).&lt;br /&gt;
Так же, важно заметить, что набор макропераций может быть несколько другим, если выбрать какой-либо иной современный метод поиска собственных чисел трёхдиагональной матрицы, не использующий QR и QL разложения(факторизацию). Два таких метода были упомянуты в пункте 1.2.&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
С целью полностью не дублировать раздел 1.2 данной статьи, где представлен наглядный и доступный для понимания псевдокод алгоритма, постараемся лишь коротко просуммировать и обобщить весь перечень последовательных действий в рассматриваемом алгоритме.&lt;br /&gt;
&lt;br /&gt;
В качестве входных данных имеем: вещественная симметричная матрица &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; размера &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;n\times n&amp;lt;/math&amp;gt;, известный вещественный вектор &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;b&amp;lt;/math&amp;gt; длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; и число &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;n&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Далее:&lt;br /&gt;
* Инициализируем вещественную константу &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;\beta_0&amp;lt;/math&amp;gt; и векторы &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;q_0&amp;lt;/math&amp;gt; и &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;q_1&amp;lt;/math&amp;gt;&lt;br /&gt;
* Итерационно для всех &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j=1,...,k&amp;lt;/math&amp;gt;:&lt;br /&gt;
** Вычисляем вспомогательный вектор &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt;, используя умножение матрицы на вектор&lt;br /&gt;
** Вычисляем, используя скалярное произведение векторов, значение &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;\alpha_j&amp;lt;/math&amp;gt; - элемент на главной диагонали трёхдиагональной матрицы &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&amp;lt;/math&amp;gt;&lt;br /&gt;
** Вычисляем по формуле новое значение и перезаписываем вектор &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt;&lt;br /&gt;
** Вычисляем значение &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;\beta_j&amp;lt;/math&amp;gt; - элементы непосредственно над и под главной диагональю той же матрицы &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&amp;lt;/math&amp;gt;&lt;br /&gt;
** Вычисляем, зная вектор &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt;,  очередной столбец матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;Q&amp;lt;/math&amp;gt;, он же вектор Ланцоша : &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;\,\,q_{j+1}&amp;lt;/math&amp;gt;&lt;br /&gt;
** Теперь, когда матрица &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&amp;lt;/math&amp;gt; сформирована на очередном шаге, находим её собственные значения и вектора любым доступным способом, о чём было подробно сказано в пункте 1.2&lt;br /&gt;
** Переходим на следующую итерацию: &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j&amp;lt;/math&amp;gt;++&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
Оценим количество операций и сложность последовательного алгоритма, изложенного в предыдущем разделе.&lt;br /&gt;
*Для вычисления вектора &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt; умножается матрица размера &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;n\times n&amp;lt;/math&amp;gt; на вектор длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt;, и потребуется &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n^2&amp;lt;/math&amp;gt; операций умножения и &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n^2&amp;lt;/math&amp;gt; операций сложения.&lt;br /&gt;
*Умножение векторов &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;q^T_j&amp;lt;/math&amp;gt; и &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt; длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; потребует &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; операций умножения и &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; операций сложения.&lt;br /&gt;
*При вычислении нового значения вектора &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt; поэлементное сложение двух векторов длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; требует &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; операций сложения.&lt;br /&gt;
*Умножение вектора длины &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; на вещественное число требует &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; операций умножения.&lt;br /&gt;
*Нахождение квадратичной нормы вектора &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt;  длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; требует &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; умножений и &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; сложений и ещё 1 операцию извлечения квадратного корня.&lt;br /&gt;
*Заключительное нахождение собственных значений и собственных векторов трёхдиагональной матрицы &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;T_j&amp;lt;/math&amp;gt; размера &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j\times j&amp;lt;/math&amp;gt; с помощью QR-алгоритма потребует в худшем случае &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(j^3)&amp;lt;/math&amp;gt; операций.&amp;lt;ref&amp;gt;http://num-anal.srcc.msu.ru/lib_na/int_ae/int_ae6.htm (пункт 6.2, &amp;quot;Скорость сходимости при этом всегда не хуже квадратичной и почти всегда лучше кубической.&amp;quot;)&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Посчитаем теперь суммарное количество простейших операций на одной итерации алгоритма (без учёта записей в память):&lt;br /&gt;
*&amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n^2+5\,n&amp;lt;/math&amp;gt; операций умножения/деления&lt;br /&gt;
*&amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n^2+4\,n&amp;lt;/math&amp;gt; операций сложения/вычитания&lt;br /&gt;
*1 операция извлечения квадратного корня&amp;lt;br&amp;gt;&lt;br /&gt;
Отдельно после всех итераций при &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j=k&amp;lt;/math&amp;gt; :&lt;br /&gt;
*&amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(k^3)&amp;lt;/math&amp;gt; операций для поиска собственных значений и собственных векторов трёхдиагональной матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_k&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Итого можно утверждать следующее:&lt;br /&gt;
&lt;br /&gt;
Последовательная сложность одной итерации рассматриваемого алгоритма:  &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(n ^ 2) &amp;lt;/math&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Суммарная сложность алгоритма (&amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;/math&amp;gt; итераций): &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(k\,n ^ 2) + O(k ^ 3)&amp;lt;/math&amp;gt; &amp;lt;ref&amp;gt;Здесь мы полагаем, что мы не вычисляем собственные значения и векторы матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_j&amp;lt;/math&amp;gt; на каждом промежуточном шаге, а лишь единожды затрачиваем &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;O(k ^ 3)&amp;lt;/math&amp;gt; действий в конце для нахождения &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;/math&amp;gt; собственных значений и векторов матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_k&amp;lt;/math&amp;gt;&amp;lt;/ref&amp;gt; &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
На практике же обычно рассматривается число &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;&amp;lt;n&amp;lt;/math&amp;gt;, поэтому второе слагаемое можно опустить.&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
На рис. 1 продемонстрирован граф одной итерации (при каком-либо произвольном значении итератора &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j&amp;lt;/math&amp;gt;) описанного алгоритма без отображения входных и выходных данных. Наглядно продемонстрированы связи между всеми действиями, и с помощью деления на &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; потоков показано, какие операции возможно выполнять параллельно на каждом шаге с целью оптимизации и экономии машинного времени. В результате, после параллельно выполненных операций &#039;&#039;&#039;Division&#039;&#039;&#039; на заключительном ярусе, на выходе имеем значение следующего вектора Ланцоша &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;q_{j+1}&amp;lt;/math&amp;gt;, после чего следует переход на следующую итерацию, и процесс повторяется.&lt;br /&gt;
&lt;br /&gt;
[[Файл:Levin_graph.png|600px|thumb|center|Рис. 1]] &amp;lt;br&amp;gt;&lt;br /&gt;
Обозначения на рисунке: &amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Simp&#039;&#039;&#039; (от англ. simple) - операции сложения и умножения вещественных чисел при вычислении произведения матрицы на вектор;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Vec mult&#039;&#039;&#039; (от англ. vectors multiplication) - операция скалярного умножения двух векторов;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Vec subtr&#039;&#039;&#039; (от англ. vectors subtraction, из-за использованных в операции вычитаний векторов) - операция умножения вектора на число (выполняется дважды) и формирование нового значения &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;z_{new}&amp;lt;/math&amp;gt; по формуле: &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;z_{new} = z - \alpha_j q_j - \beta_{j-1}q_{j-1} \;&amp;lt;/math&amp;gt;;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;||\cdot||&amp;lt;/math&amp;gt; - операция вычисления нормы вектора;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Division&#039;&#039;&#039; - операция деления вектора на вещественное число  &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;\beta_j&amp;lt;/math&amp;gt; &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Важно отметить, что упомянутые выше операции также легко поддаются оптимизации. Например, попарные умножения вещественных координат векторов при вычислении скалярного произведения также легко выполняются параллельно на &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; потоках, а затем можно применить суммирование методом сдваивания, о котором сказано в следующем разделе. Умножение или деление вектора на вещественное число являющееся, по определению, умножением или делением всех его координат на это число тоже может быть выполнено эффективнее, если мы используем &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; потоков, а не выполняем эти действия последовательно.&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
Параллельные операции возможны только внутри итераций, так как рассматриваемый алгоритм является итерационным, и сами итерации строго последовательны.&amp;lt;br&amp;gt;&lt;br /&gt;
Рассмотрим в этом разделе подробнее, какой выигрыш мы можем получить при распараллеливании операций внутри одной итерации согласно графу из предыдущего раздела.&lt;br /&gt;
&lt;br /&gt;
Умножение вещественной симметричной матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; размера &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;n\times n&amp;lt;/math&amp;gt; на вектор &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;b&amp;lt;/math&amp;gt; длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; требует последовательного выполнения &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; ярусов умножений и сложений. Сложение элементов вектора длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; на каждом шаге перемножения можно оптимизировать и выполнить за &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;\log_2 n&amp;lt;/math&amp;gt; действий, если применять метод сдваивания.&lt;br /&gt;
&lt;br /&gt;
Дальнейшие операции выполняются последовательно, а вычисление значений векторов происходит за один ярус операций сложения или умножения.&lt;br /&gt;
&lt;br /&gt;
Ресурс параллелизма алгоритма вычисления собственных значений построенной трёхдиагональной матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_k&amp;lt;/math&amp;gt; размера &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k\times k&amp;lt;/math&amp;gt; зависит от выбранного алгоритма (об этих алгоритмах подробнее было сказано в разделах 1.2 и 1.4). Будет очень затратно с точки зрения объёма материала пытаться рассмотреть пусть даже часть этих методов в этой статье, а так же тонкости их распараллеливания. Предлагаем читателям при желании самим ознакомиться с этими алгоритмами на данном ресурсе или прибегнув к иным источникам.&lt;br /&gt;
&lt;br /&gt;
При классификации по высоте ЯПФ, таким образом, алгоритм Ланцоша без переортогонализации относится к алгоритмам с &#039;&#039;логарифмической сложностью&#039;&#039;, и его сложность равна &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(\log_2 n)&amp;lt;/math&amp;gt; с важным замечанием, что это сложность только одной итерации, а максимум в алгоритме может быть выполнено последовательно &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;/math&amp;gt; таких однотипных итераций, если не будет осуществлён ранний выход из цикла. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Несмотря на то, что на графе в предыдущем разделе для лучшей визуализации и понимания было изображено &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; потоков (никаких допущений мы не делали и нарушений с точки зрения логики и математики нет, можно изобразить большее число потоков, просто часть времени некоторые из них могут бездействовать и не использоваться), на самом деле правильным и разумным будет реализовать начальное параллельное выполнение &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n^2&amp;lt;/math&amp;gt; операций умножения всех вещественных элементов матрицы &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;A&amp;lt;/math&amp;gt; на соответствующие элементы вектора &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;q_j&amp;lt;/math&amp;gt;, после чего применять тот же самый упомянутый метод сдваивания. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Поэтому при классификации по ширине ЯПФ его сложность будет &#039;&#039;квадратичной&#039;&#039; и равна &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(n^2)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
&#039;&#039;&#039;Входные данные алгоритма:&#039;&#039;&#039; вещественная симметричная &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; размера &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;n\times n&amp;lt;/math&amp;gt;, вещественный вектор &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;b&amp;lt;/math&amp;gt; длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt;, и одно целое число &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;k&amp;lt;/math&amp;gt;, означающее количество итераций.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём входных данных:&#039;&#039;&#039; &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;n^2 +n + 1 &amp;lt;/math&amp;gt;. Если учесть, что матрица симметричная и достаточно для её однозначного определения задать элементы на главной диагонали и элементы над или под ней, то можно сократить объём входных данных с целью экономии памяти до: &amp;lt;math&amp;gt;\ \frac{n^2-n}{2}+n+n+1 =\frac{n^2+3n}{2} + 1&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные алгоритма:&#039;&#039;&#039; вектор собственных значений &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;\Theta^k&amp;lt;/math&amp;gt; длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;/math&amp;gt;, матрица &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;S^k&amp;lt;/math&amp;gt; из соответствующих собственных векторов размера &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n\times k&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём выходных данных:&#039;&#039;&#039; &amp;lt;math&amp;gt;k\;(n + 1)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
В данном разделе перечислены без какой-либо хронологии или связи друг с другом наиболее важные и разнообразные свойства алгоритма, на которые стоит и полезно обратить внимание, а также которые выгодно отличают его от схожих алгоритмов, решающих ту же задачу.&amp;lt;br&amp;gt;&lt;br /&gt;
1) Отношение последовательной сложности алгоритма к параллельной,с учётом &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;/math&amp;gt; итераций, равно &amp;lt;math&amp;gt;\;\;\frac{kn^2}{k \log_2{n}}=\frac{n^2}{\log_2{n}}&amp;lt;/math&amp;gt;;&amp;lt;br&amp;gt;&lt;br /&gt;
2) Вычислительная мощность алгоритма, как отношение числа операций к суммарному объему входных и выходных данных, равна &amp;lt;math style=&amp;quot;vertical-align:-70%&amp;gt;\;\;\frac{k\,n^2}{0.5\,n^2+1.5\,n+k\,n+k+1}&amp;lt;/math&amp;gt; и &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;\approx 2\,k&amp;lt;/math&amp;gt;, так как на практике верно отношение &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;&amp;lt;n&amp;lt;/math&amp;gt; ;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
3) Для собственных значений формируемых матриц &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_j&amp;lt;/math&amp;gt; верно отношение (следствие теоремы Коши о перемежаемости): &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;\lambda_i(T_{k+1})\geq \lambda_i(T_{k})\geq \lambda_{i+1}(T_{k+1})\geq \lambda_{i+1}(T_{k})&amp;lt;/math&amp;gt; ;&amp;lt;ref&amp;gt;James W. Demmel - Вычислительная линейная алгебра. Теория и приложения //Мир. - 2001 (c. 383)&amp;lt;/ref&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
4) Крайние (наибольшие и наименьшие) собственные значения матриц &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_j&amp;lt;/math&amp;gt; сходятся к крайним собственным значениям матрицы &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;A&amp;lt;/math&amp;gt; первыми (это часто происходит уже на ранних шагах при &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j\approx 2\,\sqrt{n}&amp;lt;/math&amp;gt;&amp;lt;ref&amp;gt;http://num-anal.srcc.msu.ru/lib_na/int_ae/int_ae6.htm (пункт 6.5)&amp;lt;/ref&amp;gt;), а собственные значения в середине спектра - последними;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
5) Из-за ограниченной точности постепенно теряется ортогональность вектора Ланцоша &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;q_j&amp;lt;/math&amp;gt; к предыдущим векторам Ланцоша, поэтому необходимо примерно каждые 10-15 итераций проводить дорогостоящую операцию реортогонализации, но это уже будет иной алгоритм с очень малым различием в одной операции и в программном коде, реализующем его, соответственно; &amp;lt;ref&amp;gt;Sam Handler - The Lanczos Algorithm For Large-Scale Eigenvalue Problems (08.01.07), slide №8&amp;lt;/ref&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
6) Эффективность и быстрота выполнения алгоритма очень сильно зависит от скорости памяти (диска). Согласно тесту только &#039;&#039;6%&#039;&#039; времени работы программы приходится на вычисления, остальное время затрачивается на ожидание отклика диска;&amp;lt;ref&amp;gt;Sam Handler - The Lanczos Algorithm For Large-Scale Eigenvalue Problems (08.01.07), slide №10&amp;lt;/ref&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
7) Метод Ланцоша удобен тем, что не требует хранения исходной матрицы полным массивом: метод использует исходную матрицу только в операциях умножения матрицы на вектор, что позволяет эффективно использовать разреженность матрицы или регулярность структуры матрицы. Поэтому метод Ланцоша может быть использован для матриц таких больших порядков, когда методы вращений и отражений не могут быть применены.&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;
Для исследования масштабируемости рассматриваемого алгоритма Ланцоша без переортогонализации автором была реализована программа на языке С++ с использованием технологии MPI (&#039;&#039;&#039;не забыть вставить ссылку на код&#039;&#039;&#039;). Дальнейшее исследование выполнялось на суперкомпьютере &amp;quot;Ломоносов&amp;quot; Суперкомпьютерного комплекса МГУ. Важно отметить, что реализованная программа выполняет только первую часть алгоритма - формирование матрицы &amp;lt;math &amp;gt;T_j&amp;lt;/math&amp;gt;. Вторая часть алгоритма - задача поиска её собственных значений может быть решена несколькими методами, каждый из которых обладает своей эффективностью распараллеливании и характерными свойствами. Подробно этот вопрос уже обсуждался в статье раннее, поэтому не будем ещё раз заострять на этом внимание и останавливаться.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Сборка осуществлялась со следующими параметрами:&lt;br /&gt;
* Компилятор intel/15.0.090 &lt;br /&gt;
* Openmpi/1.8.4-icc&lt;br /&gt;
В серии проведённых расчётов рассматривались следующие числовые значения параметров:&lt;br /&gt;
* Размер &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;n&amp;lt;/math&amp;gt; задачи и, соответственно, матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt;, задействованной в операции умножения на вектор: [2000 : 30000] с шагом 1000&lt;br /&gt;
* Число процессоров: 1,2,4,16,32,48,64,96,128&lt;br /&gt;
* Число итераций в алгоритме: &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k=350&amp;lt;/math&amp;gt; . Взято таким вопреки информации в начале статьи, где говорится, что значение &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; редко превышает &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;10^2&amp;lt;/math&amp;gt;. Это сделано исключительно для лучшей визуализации пиков на графиках в данном разделе и наглядности получаемых результатов, так как при меньших на порядок значениях &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; времена выполнения программ были слишком малы даже при минимальных числах процессоров и максимальных размерах исходной задачи.&lt;br /&gt;
&lt;br /&gt;
== Динамические характеристики и эффективность реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Выводы для классов архитектур ==&lt;br /&gt;
По заданию, во второй части требовалось описать только разделы 2.4 и 2.7, прошу не спрашивать с меня все разделы 2.1-2.6. Надеюсь на понимание, мне физически не хватает времени на это задание + 2 других в течение семестра, делаю всё, что в моих силах :)&lt;br /&gt;
&lt;br /&gt;
== Существующие реализации алгоритма ==&lt;br /&gt;
Несмотря на то, что алгоритм является далеко не самым популярным, алгоритмом, про который нельзя сказать, что он всегда «на слуху», на сегодняшний день существует множество реализаций на различных популярных языках.&amp;lt;br&amp;gt;&lt;br /&gt;
Перечислим далее некоторые из них, указывая язык программирования, лежащий в их основе, и некоторые важные характеристики, которые обсуждались в статье ранее:&lt;br /&gt;
*&#039;&#039;Code on netlib.org by Jane Cullum and Ralph Willoughby&#039;&#039; (&#039;&#039;&#039;Fortran 77&#039;&#039;&#039;; без реортогонализации векторов; без реализации распараллеливания)&amp;lt;ref&amp;gt;http://www.netlib.org/lanczos/leval&amp;lt;/ref&amp;gt;&lt;br /&gt;
*&#039;&#039;Lanczos algorithm on freesourcecode.net&#039;&#039; (&#039;&#039;&#039;Matlab&#039;&#039;&#039;; присутствует реортогонализация векторов; без реализации распараллеливания)&amp;lt;ref&amp;gt;http://freesourcecode.net/matlabprojects/61741/lanczos-algorithm--in-matlab&amp;lt;/ref&amp;gt;&lt;br /&gt;
*&#039;&#039;Lanczos for eigenvalues in Numerical Linear Algebra, Spring 2007&#039;&#039; (&#039;&#039;&#039;Matlab&#039;&#039;&#039;; частичная или полная реортогонализация - доступны оба варианта; без реализации распараллеливания)&amp;lt;ref&amp;gt;Ссылки на файлы lanso.m и lanfu.m можно найти на https://www.nada.kth.se/~ruhe/2D5219/labs2007.html&amp;lt;/ref&amp;gt;&lt;br /&gt;
*&#039;&#039;Planso&#039;&#039; (название происходит от parallel Lanso.f) &#039;&#039;code by Kesheng Wu and Horst D. Simon&#039;&#039; (&#039;&#039;&#039;Fortran 77&#039;&#039;&#039;; частичная реортогонализация векторов; использование MPI для коммуникаций)&amp;lt;ref&amp;gt;https://github.com/jiahao/planso.jl/tree/master/external/PLAN/plan К сожалению, ссылка в описании пакета на github, ведущая на сайт National Energy Research Scientific Computing Center (NERSC), с более подробной информацией о данной программе больше не активна и выдаёт результат &#039;&#039;Page not found&#039;&#039;&amp;lt;/ref&amp;gt; &lt;br /&gt;
* &#039;&#039;Lanczos.cpp in the Vienna Computing Library&#039;&#039;  (&#039;&#039;&#039;C++&#039;&#039;&#039;, частичная реортогонализация, без реализации распараллеливания) &amp;lt;ref&amp;gt;http://viennacl.sourceforge.net/doc/lanczos_8cpp_source.html&amp;lt;/ref&amp;gt;&lt;br /&gt;
* &#039;&#039;Parallel Eigen Values code using C++ AMP on microsoft msdn blog&#039;&#039; (&#039;&#039;&#039;C++&#039;&#039;&#039;; ? ; распараллеливание есть и реализовано через C++ AMP) &amp;lt;ref&amp;gt;https://blogs.msdn.microsoft.com/nativeconcurrency/2013/12/20/eigen-values/ Подробнее о C++ Accelerated Massive Parallelism можно почитать здесь: https://msdn.microsoft.com/ru-ru/library/hh265137(v=vs.140).aspx или здесь: http://professorweb.ru/my/csharp/optimization/level4/4_6.php &amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;br /&gt;
[[en:Description of algorithm properties and structure]]&lt;/div&gt;</summary>
		<author><name>AleksLevin</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:AleksLevin/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%9B%D0%B0%D0%BD%D1%86%D0%BE%D1%88%D0%B0_%D0%B2%D1%8B%D1%87%D0%B8%D1%81%D0%BB%D0%B5%D0%BD%D0%B8%D1%8F_%D1%81%D0%BE%D0%B1%D1%81%D1%82%D0%B2%D0%B5%D0%BD%D0%BD%D1%8B%D1%85_%D0%B7%D0%BD%D0%B0%D1%87%D0%B5%D0%BD%D0%B8%D0%B9_%D1%81%D0%B8%D0%BC%D0%BC%D0%B5%D1%82%D1%80%D0%B8%D1%87%D0%BD%D0%BE%D0%B9_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86%D1%8B_%D0%B4%D0%BB%D1%8F_%D1%82%D0%BE%D1%87%D0%BD%D0%BE%D0%B9_%D0%B0%D1%80%D0%B8%D1%84%D0%BC%D0%B5%D1%82%D0%B8%D0%BA%D0%B8_(%D0%B1%D0%B5%D0%B7_%D0%BF%D0%B5%D1%80%D0%B5%D0%BE%D1%80%D1%82%D0%BE%D0%B3%D0%BE%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D0%B8)&amp;diff=20204</id>
		<title>Участник:AleksLevin/Алгоритм Ланцоша вычисления собственных значений симметричной матрицы для точной арифметики (без переортогонализации)</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:AleksLevin/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%9B%D0%B0%D0%BD%D1%86%D0%BE%D1%88%D0%B0_%D0%B2%D1%8B%D1%87%D0%B8%D1%81%D0%BB%D0%B5%D0%BD%D0%B8%D1%8F_%D1%81%D0%BE%D0%B1%D1%81%D1%82%D0%B2%D0%B5%D0%BD%D0%BD%D1%8B%D1%85_%D0%B7%D0%BD%D0%B0%D1%87%D0%B5%D0%BD%D0%B8%D0%B9_%D1%81%D0%B8%D0%BC%D0%BC%D0%B5%D1%82%D1%80%D0%B8%D1%87%D0%BD%D0%BE%D0%B9_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86%D1%8B_%D0%B4%D0%BB%D1%8F_%D1%82%D0%BE%D1%87%D0%BD%D0%BE%D0%B9_%D0%B0%D1%80%D0%B8%D1%84%D0%BC%D0%B5%D1%82%D0%B8%D0%BA%D0%B8_(%D0%B1%D0%B5%D0%B7_%D0%BF%D0%B5%D1%80%D0%B5%D0%BE%D1%80%D1%82%D0%BE%D0%B3%D0%BE%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D0%B8)&amp;diff=20204"/>
		<updated>2016-12-06T21:47:03Z</updated>

		<summary type="html">&lt;p&gt;AleksLevin: /* Масштабируемость алгоритма и его реализации */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Основные авторы описания: Левин А.Д.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{algorithm&lt;br /&gt;
| name              = Алгоритм Ланцоша для точной арифметики (без переортогонализации)&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(k\,n^2)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(k\log_2 n)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;\frac{n^2+3n}{2} + 1&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;k\;(n + 1)&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритмов =&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Данный алгоритм появился в 1950 г. и носит имя венгерского физика и математика Корнелия Ланцоша (венг. Lánczos Kornél). Алгоритм Ланцоша относится к итерационным методам вычисления собственных значений для матриц столь больших порядков &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt; n&amp;lt;/math&amp;gt;, что к ним нельзя применить прямые методы из-за ограничений по времени и памяти.&lt;br /&gt;
&lt;br /&gt;
Сам Ланцош указывал, что его метод предназначен для отыскания нескольких собственных векторов симметричных матриц, хотя к методу сразу было обращено внимание, как к способу приведения всей матрицы к трёхдиагональному виду. Двадцатью годами позже канадский математик Крис Пэж показал, что, несмотря на чувствительность к округлениям, алгоритм Ланцоша - эффективное средство вычисления некоторых &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; собственных чисел и соответствующих им собственных векторов. &amp;lt;ref&amp;gt;Парлетт Б. - Симметричная проблема собственных значений. Численные методы //М.: Мир. - 1983. (c. 276)&amp;lt;/ref&amp;gt;&lt;br /&gt;
Обычно число &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; берут в два раза больше, чем количество собственных значений матрицы, которые поставлена цель найти, и оно имеет порядок не более &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;10^2&amp;lt;/math&amp;gt;.&amp;lt;ref&amp;gt;Susan W. Bostic - Lanczos Eigensolution Method for High-Perfomance Computers, page 7&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Алгоритм Ланцоша для вычисления собственных значений симметричной матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; соединяет в себе метод Ланцоша для построения последовательности подпространств Крылова и ортонормированных векторов Ланцоша и процедуру Рэлея-Ритца получения оптимальных приближений собственных значений и соответствующих собственных векторов исходной матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt;.&amp;lt;ref&amp;gt;James W. Demmel - Вычислительная линейная алгебра. Теория и приложения //Мир. - 2001 (c. 381)&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
В данной статье рассматривается вариант алгоритма Ланцоша, в котором опущено влияние ошибок округления на вычислительный процесс, хотя на практике этому посвящается отдельное внимание и существуют различные методы решения данной проблемы, такие как частичная или полная переортогонализация. Этим модифицированным методам посвящены отдельные статьи на данном ресурсе.&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
Обозначения и формулы, используемые в данном разделе, взяты из литературы, указанной по ссылке.&amp;lt;ref&amp;gt;James W. Demmel - Вычислительная линейная алгебра. Теория и приложения //Мир. - 2001 (c. 313, &#039;&#039;&amp;lt;math&amp;gt; \S &amp;lt;/math&amp;gt; 6.6 Методы Крыловского подпространства&#039;&#039;)&amp;lt;/ref&amp;gt; &lt;br /&gt;
&lt;br /&gt;
Алгоритм Ланцоша для вычисления &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; собственных значений и собственных векторов вещественной симметричной матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A=A^T&amp;lt;/math&amp;gt; в точной арифметике: &amp;lt;ref&amp;gt;James W. Demmel - Вычислительная линейная алгебра. Теория и приложения //Мир. - 2001 (c. 381)&amp;lt;/ref&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{align}&lt;br /&gt;
q_1 = &amp;amp; \,\frac{b}{\|b\|_2},\; \beta_0 = 0,\; q_0 = 0\\&lt;br /&gt;
\mathbf{for} \; &amp;amp; j = 1 \; to \; k \,\; \mathbf{do} \\&lt;br /&gt;
&amp;amp; z = A\,q_j\\&lt;br /&gt;
&amp;amp; \alpha_j = q^T_j z\\&lt;br /&gt;
&amp;amp; z = z - \alpha_j q_j - \beta_{j-1}q_{j-1}\\&lt;br /&gt;
&amp;amp; \beta_j = \|z\|_2\\&lt;br /&gt;
&amp;amp; \mathbf{If} \; (\beta_j == 0) \; \mathbf{then}\; stop\; the\; algorithm \\ &lt;br /&gt;
&amp;amp; \;  q_{j+1} = \frac{z}{\beta_j} \\&lt;br /&gt;
&amp;amp; compute\; eigenvalues\; and \;eigenvectors\;of \;matrix \;\;T_j= Q^T_j A Q\;\;and\;estimate \;the\; errors\\&lt;br /&gt;
\mathbf{end} \; &amp;amp; \mathbf{for}&lt;br /&gt;
\end{align}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
В продемонстрированном выше алгоритме &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;b&amp;lt;/math&amp;gt; - заданный вещественный вектор. Также полагается известным алгоритм вычисления произведения матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; на вектор &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;x&amp;lt;/math&amp;gt;. &lt;br /&gt;
Введём матрицу Крылова, определяемую следующим соотношением: &amp;lt;math&amp;gt;K_j = [b,Ab,A^2b,...,A^{j-1}b]&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Далее, на практике, матрица &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;K&amp;lt;/math&amp;gt; заменяется матрицей &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;Q&amp;lt;/math&amp;gt;, такой, что при любом числе &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; линейные оболочки первых &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; столбцов в &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;K&amp;lt;/math&amp;gt; и &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;Q&amp;lt;/math&amp;gt; являются одним и тем же подпространством.&amp;lt;ref&amp;gt;James W. Demmel - Вычислительная линейная алгебра. Теория и приложения //Мир. - 2001 (c. 315)&amp;lt;/ref&amp;gt; &lt;br /&gt;
Тогда матрица &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;Q&amp;lt;/math&amp;gt;, в отличие от матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;K&amp;lt;/math&amp;gt;, хорошо обусловлена и легко обратима. В результате получаем матрицу &amp;lt;math&amp;gt;Q_j = [q_1, q_2, \dots, q_j]&amp;lt;/math&amp;gt; размерности &amp;lt;math&amp;gt;n\times j&amp;lt;/math&amp;gt;, столбцы которой ортогональны, являются базисом подпространства Крылова и называются векторами Ланцоша.&lt;br /&gt;
&lt;br /&gt;
В алгоритме Ланцоша вычислению подлежит столько первых столбцов в матрице &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;Q_j&amp;lt;/math&amp;gt;, сколько необходимо для получения требуемого приближения к решению &amp;lt;math&amp;gt;A\,x\,=b\,\,(A\,x=\lambda \, x)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Получение нулевого &amp;lt;math&amp;gt;\beta_j&amp;lt;/math&amp;gt; в итерационном процессе - событие, желательное в том смысле, что оно свидетельствует о том, что найдено некоторое подпространство, являющееся в точности инвариантным, а все собственные значения матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;T_j&amp;lt;/math&amp;gt; являются собственными значениями матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt;. На практике же нулевое и близкие к нулю значения получаются редко.&amp;lt;ref&amp;gt;Голуб Дж., Ван Лоун Ч. - Матричные вычисления//М.: Мир. - 1999 (c. 429)&amp;lt;/ref&amp;gt; &lt;br /&gt;
&lt;br /&gt;
Затем на каждом шаге цикла формируется симметричная трёхдиагональная матрица &amp;lt;math&amp;gt;T_j = Q^T_j A Q&amp;lt;/math&amp;gt;, к которой применяется процесс Рэлея-Ритца для поиска её собственных значений (на практике для поиска этих собственных значений можно использовать любой из специальных методов в параграфе книги по ссылке).&amp;lt;ref&amp;gt;Голуб Дж., Ван Лоун Ч. - Матричные вычисления//М.: Мир. - 1999 (&amp;lt;math&amp;gt;\S&amp;lt;/math&amp;gt; 8.4)&amp;lt;/ref&amp;gt;  &lt;br /&gt;
Эти собственные значения, они же числа Ритца, и полагаются приближёнными собственными значениями исходной матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt;.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Существует множество методов для отыскания собственных значений вещественной симметричной трехдиагональной матрицы. Большинство из них требует &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt; операций &amp;lt;ref&amp;gt;Парлетт Б. Симметричная проблема собственных значений. Численные методы.,: Мир, 1983. с. 179-182&amp;lt;/ref&amp;gt;, но существуют и быстрые алгоритмы, требующие лишь &amp;lt;math&amp;gt;O(n\ln n)&amp;lt;/math&amp;gt; операций.&amp;lt;ref&amp;gt;https://en.wikipedia.org/wiki/Tridiagonal_matrix#Eigenvalues  Раздел eigenvalues&amp;lt;/ref&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Одним из возможных способов отыскать собственные значения симметричной трехдиагональной матрицы - прямое вычисление корней характеристического полинома &amp;lt;math&amp;gt;p_n(\lambda)&amp;lt;/math&amp;gt; через метод деления пополам, где формируется последовательность Штурма и локализуются собственные числа, являющиеся корнями характеристического полинома. Нахождение всех &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; собственных значений матрицы этим способом требует &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;2n^2t&amp;lt;/math&amp;gt; умножений и вычитаний, где &amp;lt;math&amp;gt;t&amp;lt;/math&amp;gt; - число сделанных шагов с применением метода деления пополам.&amp;lt;ref&amp;gt;Уилкинсон Дж. X. Алгебраическая проблема собственныx значений. Изд-во &amp;quot;Наука&amp;quot;, 1970. - глава 5, с. 272-278&amp;lt;/ref&amp;gt; Соответствующие собственные вектора могут быть найдены посредством обратных итераций за &amp;lt;math&amp;gt; O(n) &amp;lt;/math&amp;gt; флопов. &amp;lt;ref&amp;gt;Голуб Дж., Ван Лоун Ч. - Матричные вычисления//М.: Мир. - 1999 (c. 394-395)&amp;lt;/ref&amp;gt; &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;На практике, если требуется только небольшая часть от всей совокупности собственных векторов и значений, и матрица имеет Хессенбергову или трёхдиагональную форму, очень эффективными будут методы факторизации, как, например, QR-алгоритм или QL-алгоритм со сдвигами (c целью ускорить алгоритм и сделать порядок сходимости квадратичным) или же без них.&amp;lt;ref&amp;gt;http://algorithm.narod.ru/ln/eigen/ETridiag.html&amp;lt;/ref&amp;gt; &amp;lt;br&amp;gt;&lt;br /&gt;
Весьма молодые и не менее актуальные конкуренты QR и QL алгоритмов, применяющиеся для поиска собственных значений:&lt;br /&gt;
*Методы divide-and-conquer (разделяй и властвуй), появившиеся в 1980-ых годах &amp;lt;ref&amp;gt;https://goo.gl/dapvbn ссылку пришлось сократить с помощью Google url shortener, так как символы подчеркивания портили её и не давали перейти по 1 клику&amp;lt;/ref&amp;gt;&lt;br /&gt;
*Relatively robust representation методы, появившиеся в 1990-ых и позволяющие найти собственные числа симметричной матрицы порядка &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;n&amp;lt;/math&amp;gt; за &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt; операций&lt;br /&gt;
&lt;br /&gt;
Если требуется вычислить собственные векторы, то необходимо хранить вычисляемые векторы Ланцоша. Если работа при этом производится только с оперативной памятью, то при большом порядке исходной матрицы (а именно для таких матриц и предназначен метод Ланцоша) число шагов  &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;j&amp;lt;/math&amp;gt;, которые могут быть выполнены до того момента, как оперативная память будет исчерпана, будет очень незначительно, а следовательно, искомые собственные пары могут не успеть сойтись с требуемой точностью. В этом случае метод Ланцоша можно использовать итерационным образом: после выполнения заданного числа шагов процесс прерывается и, если еще не все требуемые пары Ритца сошлись с требуемой точностью, то формируется новый начальный вектор &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;q_1&amp;lt;/math&amp;gt;, являющийся линейной комбинацией векторов Ритца, еще не сошедшихся с заданной точностью, и процесс начинается заново.&amp;lt;ref&amp;gt;http://num-anal.srcc.msu.ru/lib_na/int_ae/int_ae6.htm (пункт 6.5)&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
Вычислительное ядро рассматриваемого алгоритма (наиболее ресурсно-затратная часть алгоритма) -  формирование на каждом шаге цикла промежуточного вектора &amp;lt;math&amp;gt;z&amp;lt;/math&amp;gt;, вычисляемого по формуле: &amp;lt;math&amp;gt;z = A\,q_j&amp;lt;/math&amp;gt;. Данная операция, по сравнению с другими операциями алгоритма, затратна и требовательна, как с точки зрения количества производимых операций, так и с точки зрения объема оперируемых данных. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Например, умножение матрицы размера &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;n\times n&amp;lt;/math&amp;gt; на вектор длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; требует: &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;n^2+(n-1)n = 2n^2-n&amp;lt;/math&amp;gt; операций умножения и сложения. В свою очередь аналогичная операция умножения матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;(n+1)\times (n+1)&amp;lt;/math&amp;gt; на вектор длины &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;(n+1)&amp;lt;/math&amp;gt; требует: &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;2n^2+3n+1&amp;lt;/math&amp;gt;  операций умножения и сложения. То есть повышение размерности задачи всего на 1 увеличивает число необходимых действий в этом шаге алгоритма на: &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;4n+1&amp;lt;/math&amp;gt;. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Так же, стоит помнить, что, согласно разделу 1.2, данную операцию умножения матрицы на вектор необходимо выполнить &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;k&amp;lt;/math&amp;gt; раз. Нетрудно понять, насколько возрастает и колоссален масштаб операций, если в задачах, где критична точность, размерности &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; могут иметь порядок &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;10^5&amp;lt;/math&amp;gt; или даже более.&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
Как уже было упомянуто в данной статье в описании алгоритма, рассматриваемый алгоритм состоит из двух последовательно выполненных алгоритмов: метод Ланцоша для построения последовательности подпространств Крылова и ортонормированных векторов Ланцоша и процедура Рэлея-Ритца получения оптимальных приближений собственных значений и соответствующих собственных векторов исходной матрицы.&lt;br /&gt;
&lt;br /&gt;
В первой части алгоритма, где итерационно строятся Крыловское подпространство и трёхдиагональная матрица &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&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 style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; разреженная. Именно она подлежит оптимизации с использованием техник распараллеливания, поскольку она является вычислительным ядром алгоритма, а весь упомянутый процесс построения матрицы &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&amp;lt;/math&amp;gt; выполняется последовательно.&lt;br /&gt;
&lt;br /&gt;
Рассмотрим вторую часть алгоритма - поиск собственных значений сформированной матрицы &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&amp;lt;/math&amp;gt;.&amp;lt;br&amp;gt;&lt;br /&gt;
Далее, наглядно, в виде псевдокода, представлен, упомянутый в разделе 1.2, QR-алгоритм (аналогично можно рассмотреть и QL-алгоритм) со сдвигами Релэя, который весьма популярен на практике.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{align}&lt;br /&gt;
\mathbf{Input}: \;&amp;amp;tridiagonal\;\;matrix \;T\;with\;\;n\times n\;\;size\\&lt;br /&gt;
T^{(0)}&amp;amp;:=T\\&lt;br /&gt;
\mathbf{for}&amp;amp; \;\;m=n,...,2 \;\; \mathbf{do}\\&lt;br /&gt;
&amp;amp;k=0\\&lt;br /&gt;
&amp;amp; \mathbf{repeat}\\&lt;br /&gt;
&amp;amp; \quad \;\; k=k+1\\&lt;br /&gt;
&amp;amp; \quad \;\; \mu^{(k)}=T_{m,m}^{(k-1)}\\&lt;br /&gt;
&amp;amp; \quad \;\; Q^{(k)}R^{(k)}=T^{(k-1)}-\mu^{(k)}I\;\;using\;\;QR\;decomposition\\&lt;br /&gt;
&amp;amp; \quad \;\; T^{(k)}=R^{(k)}Q^{(k)}+\mu^{(k)}I\\&lt;br /&gt;
&amp;amp; \mathbf{until} \;\;\; |T_{m,m-1}^{(k)}| \;is\;\;small\;\;enough\\&lt;br /&gt;
&amp;amp; Save  \;\;T_{m,m}^{(k)} \;\;as\;\; converged\;\;eigenvalue\;of\;T\\ &lt;br /&gt;
&amp;amp; Remove \;\boldsymbol{n}\,th\;row\;and\;\boldsymbol{n}\,th\;column\;\;from \;T \\&lt;br /&gt;
&amp;amp; and\;take\;this\;new\;cropped\;matrix\;as\;new\;T^{(0)}\;with\;\;(n-1)\times (n-1)\;\;size\\&lt;br /&gt;
 \mathbf{end}&amp;amp;\; \mathbf{for}&lt;br /&gt;
\end{align}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Малость наддиагональных и поддиагональных элементов матрицы (фраза &#039;&#039;&amp;quot;small enough&amp;quot;&#039;&#039; в псевдокоде) подразумевает:&lt;br /&gt;
&amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt; |T_{m,m-1}^{(k)}| \leq \varepsilon\,|T_{m,m}^{(k)}| \quad\quad &amp;lt;/math&amp;gt; , где &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt; \varepsilon &amp;lt;/math&amp;gt; - заданная точность&amp;lt;br&amp;gt;&lt;br /&gt;
Также вместо сдвига Релэя, обозначенного в алгоритме через &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;\mu^{(k)}&amp;lt;/math&amp;gt;, часто на практике используется сдвиг по Уилкинсону, который даёт гарантированную сходимость внедиагональных элементов матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt; T^{(k)} &amp;lt;/math&amp;gt;, формируемой на каждом шаге, к нулю, при этом жертвуя монотонностью их убывания.&amp;lt;ref&amp;gt;Голуб Дж., Ван Лоун Ч. - Матричные вычисления//М.: Мир. - 1999 (c. 378, вторая половина страницы)&amp;lt;/ref&amp;gt;&amp;lt;ref&amp;gt;Парлетт Б. Симметричная проблема собственных значений. Численные методы.,: Мир, 1983. с. 169&amp;lt;/ref&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Подробнее с различными сдвигами и соответствующими оценками скоростей и количествами операций можно ознакомиться по указанной ссылке:&amp;lt;ref&amp;gt;Парлетт Б. Симметричная проблема собственных значений. Численные методы.,: Мир, 1983. с. 179-182&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;Для совершения QR-декомпозиции на каждом шаге может использоваться любой из алгоритмов по ссылке.&amp;lt;ref&amp;gt;https://en.wikipedia.org/wiki/QR_decomposition&amp;lt;/ref&amp;gt; Подробные описания этих алгоритмов также доступны на данном ресурсе algowiki-project.&amp;lt;br&amp;gt;&lt;br /&gt;
Так как мы оперируем не обычной матрицей и даже не Хессенберговой, а симметричной и трёхдиагональной, то скорость таких алгоритмов значительно возрастёт. Например, согласно данному ресурсу &amp;lt;ref&amp;gt;http://algorithm.narod.ru/ln/eigen/ETridiag.html&amp;lt;/ref&amp;gt;, для QL-алгоритма с неявными сдвигами:&amp;lt;br&amp;gt;&lt;br /&gt;
Для трёхдиагональной матрицы объем арифметических действий составляет &amp;lt;math&amp;gt; O(n)&amp;lt;/math&amp;gt; на одну итерацию вместо &amp;lt;math&amp;gt; O(n^3)&amp;lt;/math&amp;gt; для матрицы общего вида, а число итераций для нахождения первых собственных значений примерно равно 4 - 5. Но на этих итерациях также уменьшаются внедиагональные элементы правого нижнего угла. И, таким образом, дальнейшие собственные значения ищутся значительно быстрее. Среднее число итераций на каждое собственное значение обычно составляет 1.3 - 1.6.&amp;lt;br&amp;gt; &lt;br /&gt;
Аналогично QL, QR-разложение трёхдиагольной матрицы также требует &amp;lt;math&amp;gt; O(n)&amp;lt;/math&amp;gt; флопов&amp;lt;ref&amp;gt;Голуб Дж., Ван Лоун Ч. - Матричные вычисления//М.: Мир. - 1999 (c. 378, начало раздела 8.2.2)&amp;lt;/ref&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Подводя итог, во второй части алгоритма Ланцоша можно выделить следующие макрооперации:&lt;br /&gt;
* умножение матрицы на вещественное число;&lt;br /&gt;
* перемножение матриц;&lt;br /&gt;
* умножение и сравнение вещественных чисел;&lt;br /&gt;
* + набор других макроопераций в зависимости от выбора метода, с помощью которого будет совершаться сама QR или QL-декомпозиция (выше продемонстрированы, уже, как минимум, 3 разных способа).&lt;br /&gt;
Так же, важно заметить, что набор макропераций может быть несколько другим, если выбрать какой-либо иной современный метод поиска собственных чисел трёхдиагональной матрицы, не использующий QR и QL разложения(факторизацию). Два таких метода были упомянуты в пункте 1.2.&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
С целью полностью не дублировать раздел 1.2 данной статьи, где представлен наглядный и доступный для понимания псевдокод алгоритма, постараемся лишь коротко просуммировать и обобщить весь перечень последовательных действий в рассматриваемом алгоритме.&lt;br /&gt;
&lt;br /&gt;
В качестве входных данных имеем: вещественная симметричная матрица &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; размера &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;n\times n&amp;lt;/math&amp;gt;, известный вещественный вектор &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;b&amp;lt;/math&amp;gt; длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; и число &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;n&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Далее:&lt;br /&gt;
* Инициализируем вещественную константу &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;\beta_0&amp;lt;/math&amp;gt; и векторы &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;q_0&amp;lt;/math&amp;gt; и &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;q_1&amp;lt;/math&amp;gt;&lt;br /&gt;
* Итерационно для всех &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j=1,...,k&amp;lt;/math&amp;gt;:&lt;br /&gt;
** Вычисляем вспомогательный вектор &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt;, используя умножение матрицы на вектор&lt;br /&gt;
** Вычисляем, используя скалярное произведение векторов, значение &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;\alpha_j&amp;lt;/math&amp;gt; - элемент на главной диагонали трёхдиагональной матрицы &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&amp;lt;/math&amp;gt;&lt;br /&gt;
** Вычисляем по формуле новое значение и перезаписываем вектор &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt;&lt;br /&gt;
** Вычисляем значение &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;\beta_j&amp;lt;/math&amp;gt; - элементы непосредственно над и под главной диагональю той же матрицы &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&amp;lt;/math&amp;gt;&lt;br /&gt;
** Вычисляем, зная вектор &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt;,  очередной столбец матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;Q&amp;lt;/math&amp;gt;, он же вектор Ланцоша : &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;\,\,q_{j+1}&amp;lt;/math&amp;gt;&lt;br /&gt;
** Теперь, когда матрица &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&amp;lt;/math&amp;gt; сформирована на очередном шаге, находим её собственные значения и вектора любым доступным способом, о чём было подробно сказано в пункте 1.2&lt;br /&gt;
** Переходим на следующую итерацию: &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j&amp;lt;/math&amp;gt;++&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
Оценим количество операций и сложность последовательного алгоритма, изложенного в предыдущем разделе.&lt;br /&gt;
*Для вычисления вектора &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt; умножается матрица размера &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;n\times n&amp;lt;/math&amp;gt; на вектор длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt;, и потребуется &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n^2&amp;lt;/math&amp;gt; операций умножения и &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n^2&amp;lt;/math&amp;gt; операций сложения.&lt;br /&gt;
*Умножение векторов &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;q^T_j&amp;lt;/math&amp;gt; и &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt; длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; потребует &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; операций умножения и &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; операций сложения.&lt;br /&gt;
*При вычислении нового значения вектора &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt; поэлементное сложение двух векторов длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; требует &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; операций сложения.&lt;br /&gt;
*Умножение вектора длины &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; на вещественное число требует &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; операций умножения.&lt;br /&gt;
*Нахождение квадратичной нормы вектора &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt;  длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; требует &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; умножений и &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; сложений и ещё 1 операцию извлечения квадратного корня.&lt;br /&gt;
*Заключительное нахождение собственных значений и собственных векторов трёхдиагональной матрицы &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;T_j&amp;lt;/math&amp;gt; размера &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j\times j&amp;lt;/math&amp;gt; с помощью QR-алгоритма потребует в худшем случае &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(j^3)&amp;lt;/math&amp;gt; операций.&amp;lt;ref&amp;gt;http://num-anal.srcc.msu.ru/lib_na/int_ae/int_ae6.htm (пункт 6.2, &amp;quot;Скорость сходимости при этом всегда не хуже квадратичной и почти всегда лучше кубической.&amp;quot;)&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Посчитаем теперь суммарное количество простейших операций на одной итерации алгоритма (без учёта записей в память):&lt;br /&gt;
*&amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n^2+5\,n&amp;lt;/math&amp;gt; операций умножения/деления&lt;br /&gt;
*&amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n^2+4\,n&amp;lt;/math&amp;gt; операций сложения/вычитания&lt;br /&gt;
*1 операция извлечения квадратного корня&amp;lt;br&amp;gt;&lt;br /&gt;
Отдельно после всех итераций при &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j=k&amp;lt;/math&amp;gt; :&lt;br /&gt;
*&amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(k^3)&amp;lt;/math&amp;gt; операций для поиска собственных значений и собственных векторов трёхдиагональной матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_k&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Итого можно утверждать следующее:&lt;br /&gt;
&lt;br /&gt;
Последовательная сложность одной итерации рассматриваемого алгоритма:  &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(n ^ 2) &amp;lt;/math&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Суммарная сложность алгоритма (&amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;/math&amp;gt; итераций): &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(k\,n ^ 2) + O(k ^ 3)&amp;lt;/math&amp;gt; &amp;lt;ref&amp;gt;Здесь мы полагаем, что мы не вычисляем собственные значения и векторы матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_j&amp;lt;/math&amp;gt; на каждом промежуточном шаге, а лишь единожды затрачиваем &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;O(k ^ 3)&amp;lt;/math&amp;gt; действий в конце для нахождения &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;/math&amp;gt; собственных значений и векторов матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_k&amp;lt;/math&amp;gt;&amp;lt;/ref&amp;gt; &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
На практике же обычно рассматривается число &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;&amp;lt;n&amp;lt;/math&amp;gt;, поэтому второе слагаемое можно опустить.&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
На рис. 1 продемонстрирован граф одной итерации (при каком-либо произвольном значении итератора &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j&amp;lt;/math&amp;gt;) описанного алгоритма без отображения входных и выходных данных. Наглядно продемонстрированы связи между всеми действиями, и с помощью деления на &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; потоков показано, какие операции возможно выполнять параллельно на каждом шаге с целью оптимизации и экономии машинного времени. В результате, после параллельно выполненных операций &#039;&#039;&#039;Division&#039;&#039;&#039; на заключительном ярусе, на выходе имеем значение следующего вектора Ланцоша &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;q_{j+1}&amp;lt;/math&amp;gt;, после чего следует переход на следующую итерацию, и процесс повторяется.&lt;br /&gt;
&lt;br /&gt;
[[Файл:Levin_graph.png|600px|thumb|center|Рис. 1]] &amp;lt;br&amp;gt;&lt;br /&gt;
Обозначения на рисунке: &amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Simp&#039;&#039;&#039; (от англ. simple) - операции сложения и умножения вещественных чисел при вычислении произведения матрицы на вектор;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Vec mult&#039;&#039;&#039; (от англ. vectors multiplication) - операция скалярного умножения двух векторов;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Vec subtr&#039;&#039;&#039; (от англ. vectors subtraction, из-за использованных в операции вычитаний векторов) - операция умножения вектора на число (выполняется дважды) и формирование нового значения &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;z_{new}&amp;lt;/math&amp;gt; по формуле: &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;z_{new} = z - \alpha_j q_j - \beta_{j-1}q_{j-1} \;&amp;lt;/math&amp;gt;;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;||\cdot||&amp;lt;/math&amp;gt; - операция вычисления нормы вектора;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Division&#039;&#039;&#039; - операция деления вектора на вещественное число  &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;\beta_j&amp;lt;/math&amp;gt; &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Важно отметить, что упомянутые выше операции также легко поддаются оптимизации. Например, попарные умножения вещественных координат векторов при вычислении скалярного произведения также легко выполняются параллельно на &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; потоках, а затем можно применить суммирование методом сдваивания, о котором сказано в следующем разделе. Умножение или деление вектора на вещественное число являющееся, по определению, умножением или делением всех его координат на это число тоже может быть выполнено эффективнее, если мы используем &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; потоков, а не выполняем эти действия последовательно.&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
Параллельные операции возможны только внутри итераций, так как рассматриваемый алгоритм является итерационным, и сами итерации строго последовательны.&amp;lt;br&amp;gt;&lt;br /&gt;
Рассмотрим в этом разделе подробнее, какой выигрыш мы можем получить при распараллеливании операций внутри одной итерации согласно графу из предыдущего раздела.&lt;br /&gt;
&lt;br /&gt;
Умножение вещественной симметричной матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; размера &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;n\times n&amp;lt;/math&amp;gt; на вектор &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;b&amp;lt;/math&amp;gt; длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; требует последовательного выполнения &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; ярусов умножений и сложений. Сложение элементов вектора длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; на каждом шаге перемножения можно оптимизировать и выполнить за &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;\log_2 n&amp;lt;/math&amp;gt; действий, если применять метод сдваивания.&lt;br /&gt;
&lt;br /&gt;
Дальнейшие операции выполняются последовательно, а вычисление значений векторов происходит за один ярус операций сложения или умножения.&lt;br /&gt;
&lt;br /&gt;
Ресурс параллелизма алгоритма вычисления собственных значений построенной трёхдиагональной матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_k&amp;lt;/math&amp;gt; размера &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k\times k&amp;lt;/math&amp;gt; зависит от выбранного алгоритма (об этих алгоритмах подробнее было сказано в разделах 1.2 и 1.4). Будет очень затратно с точки зрения объёма материала пытаться рассмотреть пусть даже часть этих методов в этой статье, а так же тонкости их распараллеливания. Предлагаем читателям при желании самим ознакомиться с этими алгоритмами на данном ресурсе или прибегнув к иным источникам.&lt;br /&gt;
&lt;br /&gt;
При классификации по высоте ЯПФ, таким образом, алгоритм Ланцоша без переортогонализации относится к алгоритмам с &#039;&#039;логарифмической сложностью&#039;&#039;, и его сложность равна &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(\log_2 n)&amp;lt;/math&amp;gt; с важным замечанием, что это сложность только одной итерации, а максимум в алгоритме может быть выполнено последовательно &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;/math&amp;gt; таких однотипных итераций, если не будет осуществлён ранний выход из цикла. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Несмотря на то, что на графе в предыдущем разделе для лучшей визуализации и понимания было изображено &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; потоков (никаких допущений мы не делали и нарушений с точки зрения логики и математики нет, можно изобразить большее число потоков, просто часть времени некоторые из них могут бездействовать и не использоваться), на самом деле правильным и разумным будет реализовать начальное параллельное выполнение &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n^2&amp;lt;/math&amp;gt; операций умножения всех вещественных элементов матрицы &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;A&amp;lt;/math&amp;gt; на соответствующие элементы вектора &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;q_j&amp;lt;/math&amp;gt;, после чего применять тот же самый упомянутый метод сдваивания. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Поэтому при классификации по ширине ЯПФ его сложность будет &#039;&#039;квадратичной&#039;&#039; и равна &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(n^2)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
&#039;&#039;&#039;Входные данные алгоритма:&#039;&#039;&#039; вещественная симметричная &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; размера &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;n\times n&amp;lt;/math&amp;gt;, вещественный вектор &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;b&amp;lt;/math&amp;gt; длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt;, и одно целое число &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;k&amp;lt;/math&amp;gt;, означающее количество итераций.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём входных данных:&#039;&#039;&#039; &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;n^2 +n + 1 &amp;lt;/math&amp;gt;. Если учесть, что матрица симметричная и достаточно для её однозначного определения задать элементы на главной диагонали и элементы над или под ней, то можно сократить объём входных данных с целью экономии памяти до: &amp;lt;math&amp;gt;\ \frac{n^2-n}{2}+n+n+1 =\frac{n^2+3n}{2} + 1&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные алгоритма:&#039;&#039;&#039; вектор собственных значений &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;\Theta^k&amp;lt;/math&amp;gt; длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;/math&amp;gt;, матрица &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;S^k&amp;lt;/math&amp;gt; из соответствующих собственных векторов размера &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n\times k&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём выходных данных:&#039;&#039;&#039; &amp;lt;math&amp;gt;k\;(n + 1)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
В данном разделе перечислены без какой-либо хронологии или связи друг с другом наиболее важные и разнообразные свойства алгоритма, на которые стоит и полезно обратить внимание, а также которые выгодно отличают его от схожих алгоритмов, решающих ту же задачу.&amp;lt;br&amp;gt;&lt;br /&gt;
1) Отношение последовательной сложности алгоритма к параллельной,с учётом &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;/math&amp;gt; итераций, равно &amp;lt;math&amp;gt;\;\;\frac{kn^2}{k \log_2{n}}=\frac{n^2}{\log_2{n}}&amp;lt;/math&amp;gt;;&amp;lt;br&amp;gt;&lt;br /&gt;
2) Вычислительная мощность алгоритма, как отношение числа операций к суммарному объему входных и выходных данных, равна &amp;lt;math style=&amp;quot;vertical-align:-70%&amp;gt;\;\;\frac{k\,n^2}{0.5\,n^2+1.5\,n+k\,n+k+1}&amp;lt;/math&amp;gt; и &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;\approx 2\,k&amp;lt;/math&amp;gt;, так как на практике верно отношение &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;&amp;lt;n&amp;lt;/math&amp;gt; ;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
3) Для собственных значений формируемых матриц &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_j&amp;lt;/math&amp;gt; верно отношение (следствие теоремы Коши о перемежаемости): &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;\lambda_i(T_{k+1})\geq \lambda_i(T_{k})\geq \lambda_{i+1}(T_{k+1})\geq \lambda_{i+1}(T_{k})&amp;lt;/math&amp;gt; ;&amp;lt;ref&amp;gt;James W. Demmel - Вычислительная линейная алгебра. Теория и приложения //Мир. - 2001 (c. 383)&amp;lt;/ref&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
4) Крайние (наибольшие и наименьшие) собственные значения матриц &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_j&amp;lt;/math&amp;gt; сходятся к крайним собственным значениям матрицы &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;A&amp;lt;/math&amp;gt; первыми (это часто происходит уже на ранних шагах при &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j\approx 2\,\sqrt{n}&amp;lt;/math&amp;gt;&amp;lt;ref&amp;gt;http://num-anal.srcc.msu.ru/lib_na/int_ae/int_ae6.htm (пункт 6.5)&amp;lt;/ref&amp;gt;), а собственные значения в середине спектра - последними;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
5) Из-за ограниченной точности постепенно теряется ортогональность вектора Ланцоша &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;q_j&amp;lt;/math&amp;gt; к предыдущим векторам Ланцоша, поэтому необходимо примерно каждые 10-15 итераций проводить дорогостоящую операцию реортогонализации, но это уже будет иной алгоритм с очень малым различием в одной операции и в программном коде, реализующем его, соответственно; &amp;lt;ref&amp;gt;Sam Handler - The Lanczos Algorithm For Large-Scale Eigenvalue Problems (08.01.07), slide №8&amp;lt;/ref&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
6) Эффективность и быстрота выполнения алгоритма очень сильно зависит от скорости памяти (диска). Согласно тесту только &#039;&#039;6%&#039;&#039; времени работы программы приходится на вычисления, остальное время затрачивается на ожидание отклика диска;&amp;lt;ref&amp;gt;Sam Handler - The Lanczos Algorithm For Large-Scale Eigenvalue Problems (08.01.07), slide №10&amp;lt;/ref&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
7) Метод Ланцоша удобен тем, что не требует хранения исходной матрицы полным массивом: метод использует исходную матрицу только в операциях умножения матрицы на вектор, что позволяет эффективно использовать разреженность матрицы или регулярность структуры матрицы. Поэтому метод Ланцоша может быть использован для матриц таких больших порядков, когда методы вращений и отражений не могут быть применены.&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;
Для исследования масштабируемости рассматриваемого алгоритма Ланцоша без переортогонализации автором была реализована программа на языке С++ с использованием технологии MPI (&#039;&#039;&#039;не забыть вставить ссылку на код&#039;&#039;&#039;). Дальнейшее исследование выполнялось на суперкомпьютере &amp;quot;Ломоносов&amp;quot; Суперкомпьютерного комплекса МГУ. Важно отметить, что реализованная программа выполняет только первую часть алгоритма - формирование матрицы &amp;lt;math &amp;gt;T_j&amp;lt;/math&amp;gt;. Вторая часть алгоритма - задача поиска её собственных значений может быть решена несколькими методами, каждый из которых обладает своей эффективностью распараллеливании и характерными свойствами. Подробно этот вопрос уже обсуждался в статье раннее, поэтому не будем ещё раз заострять на этом внимание и останавливаться.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Сборка осуществлялась со следующими параметрами:&lt;br /&gt;
* Компилятор intel/15.0.090 &lt;br /&gt;
* Openmpi/1.8.4-icc&lt;br /&gt;
В серии проведённых расчётов рассматривались следующие числовые значения параметров:&lt;br /&gt;
* Размер задачи и, соответственно, матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt;, задействованной в операции умножения на вектор: [2000 : 30000] с шагом 1000&lt;br /&gt;
* Число процессоров: 1,2,4,16,32,48,64,96,128&lt;br /&gt;
* Число итераций в алгоритме: &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k=350&amp;lt;/math&amp;gt; . Взято таким вопреки информации в начале статьи, где говорится, что значение &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; редко превышает &amp;lt;math&amp;gt;10^2&amp;lt;/math&amp;gt;. Это сделано исключительно для лучшей визуализации пиков на графиках в данном разделе и наглядности получаемых результатов, так как при меньших на порядок значениях &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; времена выполнения программ были слишком малы даже при минимальных числах процессоров и максимальных размерах исходной задачи.&lt;br /&gt;
&lt;br /&gt;
== Динамические характеристики и эффективность реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Выводы для классов архитектур ==&lt;br /&gt;
По заданию, во второй части требовалось описать только разделы 2.4 и 2.7, прошу не спрашивать с меня все разделы 2.1-2.6. Надеюсь на понимание, мне физически не хватает времени на это задание + 2 других в течение семестра, делаю всё, что в моих силах :)&lt;br /&gt;
&lt;br /&gt;
== Существующие реализации алгоритма ==&lt;br /&gt;
Несмотря на то, что алгоритм является далеко не самым популярным, алгоритмом, про который нельзя сказать, что он всегда «на слуху», на сегодняшний день существует множество реализаций на различных популярных языках.&amp;lt;br&amp;gt;&lt;br /&gt;
Перечислим далее некоторые из них, указывая язык программирования, лежащий в их основе, и некоторые важные характеристики, которые обсуждались в статье ранее:&lt;br /&gt;
*&#039;&#039;Code on netlib.org by Jane Cullum and Ralph Willoughby&#039;&#039; (&#039;&#039;&#039;Fortran 77&#039;&#039;&#039;; без реортогонализации векторов; без реализации распараллеливания)&amp;lt;ref&amp;gt;http://www.netlib.org/lanczos/leval&amp;lt;/ref&amp;gt;&lt;br /&gt;
*&#039;&#039;Lanczos algorithm on freesourcecode.net&#039;&#039; (&#039;&#039;&#039;Matlab&#039;&#039;&#039;; присутствует реортогонализация векторов; без реализации распараллеливания)&amp;lt;ref&amp;gt;http://freesourcecode.net/matlabprojects/61741/lanczos-algorithm--in-matlab&amp;lt;/ref&amp;gt;&lt;br /&gt;
*&#039;&#039;Lanczos for eigenvalues in Numerical Linear Algebra, Spring 2007&#039;&#039; (&#039;&#039;&#039;Matlab&#039;&#039;&#039;; частичная или полная реортогонализация - доступны оба варианта; без реализации распараллеливания)&amp;lt;ref&amp;gt;Ссылки на файлы lanso.m и lanfu.m можно найти на https://www.nada.kth.se/~ruhe/2D5219/labs2007.html&amp;lt;/ref&amp;gt;&lt;br /&gt;
*&#039;&#039;Planso&#039;&#039; (название происходит от parallel Lanso.f) &#039;&#039;code by Kesheng Wu and Horst D. Simon&#039;&#039; (&#039;&#039;&#039;Fortran 77&#039;&#039;&#039;; частичная реортогонализация векторов; использование MPI для коммуникаций)&amp;lt;ref&amp;gt;https://github.com/jiahao/planso.jl/tree/master/external/PLAN/plan К сожалению, ссылка в описании пакета на github, ведущая на сайт National Energy Research Scientific Computing Center (NERSC), с более подробной информацией о данной программе больше не активна и выдаёт результат &#039;&#039;Page not found&#039;&#039;&amp;lt;/ref&amp;gt; &lt;br /&gt;
* &#039;&#039;Lanczos.cpp in the Vienna Computing Library&#039;&#039;  (&#039;&#039;&#039;C++&#039;&#039;&#039;, частичная реортогонализация, без реализации распараллеливания) &amp;lt;ref&amp;gt;http://viennacl.sourceforge.net/doc/lanczos_8cpp_source.html&amp;lt;/ref&amp;gt;&lt;br /&gt;
* &#039;&#039;Parallel Eigen Values code using C++ AMP on microsoft msdn blog&#039;&#039; (&#039;&#039;&#039;C++&#039;&#039;&#039;; ? ; распараллеливание есть и реализовано через C++ AMP) &amp;lt;ref&amp;gt;https://blogs.msdn.microsoft.com/nativeconcurrency/2013/12/20/eigen-values/ Подробнее о C++ Accelerated Massive Parallelism можно почитать здесь: https://msdn.microsoft.com/ru-ru/library/hh265137(v=vs.140).aspx или здесь: http://professorweb.ru/my/csharp/optimization/level4/4_6.php &amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;br /&gt;
[[en:Description of algorithm properties and structure]]&lt;/div&gt;</summary>
		<author><name>AleksLevin</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:AleksLevin/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%9B%D0%B0%D0%BD%D1%86%D0%BE%D1%88%D0%B0_%D0%B2%D1%8B%D1%87%D0%B8%D1%81%D0%BB%D0%B5%D0%BD%D0%B8%D1%8F_%D1%81%D0%BE%D0%B1%D1%81%D1%82%D0%B2%D0%B5%D0%BD%D0%BD%D1%8B%D1%85_%D0%B7%D0%BD%D0%B0%D1%87%D0%B5%D0%BD%D0%B8%D0%B9_%D1%81%D0%B8%D0%BC%D0%BC%D0%B5%D1%82%D1%80%D0%B8%D1%87%D0%BD%D0%BE%D0%B9_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86%D1%8B_%D0%B4%D0%BB%D1%8F_%D1%82%D0%BE%D1%87%D0%BD%D0%BE%D0%B9_%D0%B0%D1%80%D0%B8%D1%84%D0%BC%D0%B5%D1%82%D0%B8%D0%BA%D0%B8_(%D0%B1%D0%B5%D0%B7_%D0%BF%D0%B5%D1%80%D0%B5%D0%BE%D1%80%D1%82%D0%BE%D0%B3%D0%BE%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D0%B8)&amp;diff=20203</id>
		<title>Участник:AleksLevin/Алгоритм Ланцоша вычисления собственных значений симметричной матрицы для точной арифметики (без переортогонализации)</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:AleksLevin/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%9B%D0%B0%D0%BD%D1%86%D0%BE%D1%88%D0%B0_%D0%B2%D1%8B%D1%87%D0%B8%D1%81%D0%BB%D0%B5%D0%BD%D0%B8%D1%8F_%D1%81%D0%BE%D0%B1%D1%81%D1%82%D0%B2%D0%B5%D0%BD%D0%BD%D1%8B%D1%85_%D0%B7%D0%BD%D0%B0%D1%87%D0%B5%D0%BD%D0%B8%D0%B9_%D1%81%D0%B8%D0%BC%D0%BC%D0%B5%D1%82%D1%80%D0%B8%D1%87%D0%BD%D0%BE%D0%B9_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86%D1%8B_%D0%B4%D0%BB%D1%8F_%D1%82%D0%BE%D1%87%D0%BD%D0%BE%D0%B9_%D0%B0%D1%80%D0%B8%D1%84%D0%BC%D0%B5%D1%82%D0%B8%D0%BA%D0%B8_(%D0%B1%D0%B5%D0%B7_%D0%BF%D0%B5%D1%80%D0%B5%D0%BE%D1%80%D1%82%D0%BE%D0%B3%D0%BE%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D0%B8)&amp;diff=20203"/>
		<updated>2016-12-06T21:43:07Z</updated>

		<summary type="html">&lt;p&gt;AleksLevin: /* Масштабируемость алгоритма и его реализации */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Основные авторы описания: Левин А.Д.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{algorithm&lt;br /&gt;
| name              = Алгоритм Ланцоша для точной арифметики (без переортогонализации)&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(k\,n^2)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(k\log_2 n)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;\frac{n^2+3n}{2} + 1&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;k\;(n + 1)&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритмов =&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Данный алгоритм появился в 1950 г. и носит имя венгерского физика и математика Корнелия Ланцоша (венг. Lánczos Kornél). Алгоритм Ланцоша относится к итерационным методам вычисления собственных значений для матриц столь больших порядков &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt; n&amp;lt;/math&amp;gt;, что к ним нельзя применить прямые методы из-за ограничений по времени и памяти.&lt;br /&gt;
&lt;br /&gt;
Сам Ланцош указывал, что его метод предназначен для отыскания нескольких собственных векторов симметричных матриц, хотя к методу сразу было обращено внимание, как к способу приведения всей матрицы к трёхдиагональному виду. Двадцатью годами позже канадский математик Крис Пэж показал, что, несмотря на чувствительность к округлениям, алгоритм Ланцоша - эффективное средство вычисления некоторых &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; собственных чисел и соответствующих им собственных векторов. &amp;lt;ref&amp;gt;Парлетт Б. - Симметричная проблема собственных значений. Численные методы //М.: Мир. - 1983. (c. 276)&amp;lt;/ref&amp;gt;&lt;br /&gt;
Обычно число &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; берут в два раза больше, чем количество собственных значений матрицы, которые поставлена цель найти, и оно имеет порядок не более &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;10^2&amp;lt;/math&amp;gt;.&amp;lt;ref&amp;gt;Susan W. Bostic - Lanczos Eigensolution Method for High-Perfomance Computers, page 7&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Алгоритм Ланцоша для вычисления собственных значений симметричной матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; соединяет в себе метод Ланцоша для построения последовательности подпространств Крылова и ортонормированных векторов Ланцоша и процедуру Рэлея-Ритца получения оптимальных приближений собственных значений и соответствующих собственных векторов исходной матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt;.&amp;lt;ref&amp;gt;James W. Demmel - Вычислительная линейная алгебра. Теория и приложения //Мир. - 2001 (c. 381)&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
В данной статье рассматривается вариант алгоритма Ланцоша, в котором опущено влияние ошибок округления на вычислительный процесс, хотя на практике этому посвящается отдельное внимание и существуют различные методы решения данной проблемы, такие как частичная или полная переортогонализация. Этим модифицированным методам посвящены отдельные статьи на данном ресурсе.&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
Обозначения и формулы, используемые в данном разделе, взяты из литературы, указанной по ссылке.&amp;lt;ref&amp;gt;James W. Demmel - Вычислительная линейная алгебра. Теория и приложения //Мир. - 2001 (c. 313, &#039;&#039;&amp;lt;math&amp;gt; \S &amp;lt;/math&amp;gt; 6.6 Методы Крыловского подпространства&#039;&#039;)&amp;lt;/ref&amp;gt; &lt;br /&gt;
&lt;br /&gt;
Алгоритм Ланцоша для вычисления &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; собственных значений и собственных векторов вещественной симметричной матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A=A^T&amp;lt;/math&amp;gt; в точной арифметике: &amp;lt;ref&amp;gt;James W. Demmel - Вычислительная линейная алгебра. Теория и приложения //Мир. - 2001 (c. 381)&amp;lt;/ref&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{align}&lt;br /&gt;
q_1 = &amp;amp; \,\frac{b}{\|b\|_2},\; \beta_0 = 0,\; q_0 = 0\\&lt;br /&gt;
\mathbf{for} \; &amp;amp; j = 1 \; to \; k \,\; \mathbf{do} \\&lt;br /&gt;
&amp;amp; z = A\,q_j\\&lt;br /&gt;
&amp;amp; \alpha_j = q^T_j z\\&lt;br /&gt;
&amp;amp; z = z - \alpha_j q_j - \beta_{j-1}q_{j-1}\\&lt;br /&gt;
&amp;amp; \beta_j = \|z\|_2\\&lt;br /&gt;
&amp;amp; \mathbf{If} \; (\beta_j == 0) \; \mathbf{then}\; stop\; the\; algorithm \\ &lt;br /&gt;
&amp;amp; \;  q_{j+1} = \frac{z}{\beta_j} \\&lt;br /&gt;
&amp;amp; compute\; eigenvalues\; and \;eigenvectors\;of \;matrix \;\;T_j= Q^T_j A Q\;\;and\;estimate \;the\; errors\\&lt;br /&gt;
\mathbf{end} \; &amp;amp; \mathbf{for}&lt;br /&gt;
\end{align}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
В продемонстрированном выше алгоритме &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;b&amp;lt;/math&amp;gt; - заданный вещественный вектор. Также полагается известным алгоритм вычисления произведения матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; на вектор &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;x&amp;lt;/math&amp;gt;. &lt;br /&gt;
Введём матрицу Крылова, определяемую следующим соотношением: &amp;lt;math&amp;gt;K_j = [b,Ab,A^2b,...,A^{j-1}b]&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Далее, на практике, матрица &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;K&amp;lt;/math&amp;gt; заменяется матрицей &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;Q&amp;lt;/math&amp;gt;, такой, что при любом числе &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; линейные оболочки первых &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; столбцов в &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;K&amp;lt;/math&amp;gt; и &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;Q&amp;lt;/math&amp;gt; являются одним и тем же подпространством.&amp;lt;ref&amp;gt;James W. Demmel - Вычислительная линейная алгебра. Теория и приложения //Мир. - 2001 (c. 315)&amp;lt;/ref&amp;gt; &lt;br /&gt;
Тогда матрица &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;Q&amp;lt;/math&amp;gt;, в отличие от матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;K&amp;lt;/math&amp;gt;, хорошо обусловлена и легко обратима. В результате получаем матрицу &amp;lt;math&amp;gt;Q_j = [q_1, q_2, \dots, q_j]&amp;lt;/math&amp;gt; размерности &amp;lt;math&amp;gt;n\times j&amp;lt;/math&amp;gt;, столбцы которой ортогональны, являются базисом подпространства Крылова и называются векторами Ланцоша.&lt;br /&gt;
&lt;br /&gt;
В алгоритме Ланцоша вычислению подлежит столько первых столбцов в матрице &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;Q_j&amp;lt;/math&amp;gt;, сколько необходимо для получения требуемого приближения к решению &amp;lt;math&amp;gt;A\,x\,=b\,\,(A\,x=\lambda \, x)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Получение нулевого &amp;lt;math&amp;gt;\beta_j&amp;lt;/math&amp;gt; в итерационном процессе - событие, желательное в том смысле, что оно свидетельствует о том, что найдено некоторое подпространство, являющееся в точности инвариантным, а все собственные значения матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;T_j&amp;lt;/math&amp;gt; являются собственными значениями матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt;. На практике же нулевое и близкие к нулю значения получаются редко.&amp;lt;ref&amp;gt;Голуб Дж., Ван Лоун Ч. - Матричные вычисления//М.: Мир. - 1999 (c. 429)&amp;lt;/ref&amp;gt; &lt;br /&gt;
&lt;br /&gt;
Затем на каждом шаге цикла формируется симметричная трёхдиагональная матрица &amp;lt;math&amp;gt;T_j = Q^T_j A Q&amp;lt;/math&amp;gt;, к которой применяется процесс Рэлея-Ритца для поиска её собственных значений (на практике для поиска этих собственных значений можно использовать любой из специальных методов в параграфе книги по ссылке).&amp;lt;ref&amp;gt;Голуб Дж., Ван Лоун Ч. - Матричные вычисления//М.: Мир. - 1999 (&amp;lt;math&amp;gt;\S&amp;lt;/math&amp;gt; 8.4)&amp;lt;/ref&amp;gt;  &lt;br /&gt;
Эти собственные значения, они же числа Ритца, и полагаются приближёнными собственными значениями исходной матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt;.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Существует множество методов для отыскания собственных значений вещественной симметричной трехдиагональной матрицы. Большинство из них требует &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt; операций &amp;lt;ref&amp;gt;Парлетт Б. Симметричная проблема собственных значений. Численные методы.,: Мир, 1983. с. 179-182&amp;lt;/ref&amp;gt;, но существуют и быстрые алгоритмы, требующие лишь &amp;lt;math&amp;gt;O(n\ln n)&amp;lt;/math&amp;gt; операций.&amp;lt;ref&amp;gt;https://en.wikipedia.org/wiki/Tridiagonal_matrix#Eigenvalues  Раздел eigenvalues&amp;lt;/ref&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Одним из возможных способов отыскать собственные значения симметричной трехдиагональной матрицы - прямое вычисление корней характеристического полинома &amp;lt;math&amp;gt;p_n(\lambda)&amp;lt;/math&amp;gt; через метод деления пополам, где формируется последовательность Штурма и локализуются собственные числа, являющиеся корнями характеристического полинома. Нахождение всех &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; собственных значений матрицы этим способом требует &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;2n^2t&amp;lt;/math&amp;gt; умножений и вычитаний, где &amp;lt;math&amp;gt;t&amp;lt;/math&amp;gt; - число сделанных шагов с применением метода деления пополам.&amp;lt;ref&amp;gt;Уилкинсон Дж. X. Алгебраическая проблема собственныx значений. Изд-во &amp;quot;Наука&amp;quot;, 1970. - глава 5, с. 272-278&amp;lt;/ref&amp;gt; Соответствующие собственные вектора могут быть найдены посредством обратных итераций за &amp;lt;math&amp;gt; O(n) &amp;lt;/math&amp;gt; флопов. &amp;lt;ref&amp;gt;Голуб Дж., Ван Лоун Ч. - Матричные вычисления//М.: Мир. - 1999 (c. 394-395)&amp;lt;/ref&amp;gt; &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;На практике, если требуется только небольшая часть от всей совокупности собственных векторов и значений, и матрица имеет Хессенбергову или трёхдиагональную форму, очень эффективными будут методы факторизации, как, например, QR-алгоритм или QL-алгоритм со сдвигами (c целью ускорить алгоритм и сделать порядок сходимости квадратичным) или же без них.&amp;lt;ref&amp;gt;http://algorithm.narod.ru/ln/eigen/ETridiag.html&amp;lt;/ref&amp;gt; &amp;lt;br&amp;gt;&lt;br /&gt;
Весьма молодые и не менее актуальные конкуренты QR и QL алгоритмов, применяющиеся для поиска собственных значений:&lt;br /&gt;
*Методы divide-and-conquer (разделяй и властвуй), появившиеся в 1980-ых годах &amp;lt;ref&amp;gt;https://goo.gl/dapvbn ссылку пришлось сократить с помощью Google url shortener, так как символы подчеркивания портили её и не давали перейти по 1 клику&amp;lt;/ref&amp;gt;&lt;br /&gt;
*Relatively robust representation методы, появившиеся в 1990-ых и позволяющие найти собственные числа симметричной матрицы порядка &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;n&amp;lt;/math&amp;gt; за &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt; операций&lt;br /&gt;
&lt;br /&gt;
Если требуется вычислить собственные векторы, то необходимо хранить вычисляемые векторы Ланцоша. Если работа при этом производится только с оперативной памятью, то при большом порядке исходной матрицы (а именно для таких матриц и предназначен метод Ланцоша) число шагов  &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;j&amp;lt;/math&amp;gt;, которые могут быть выполнены до того момента, как оперативная память будет исчерпана, будет очень незначительно, а следовательно, искомые собственные пары могут не успеть сойтись с требуемой точностью. В этом случае метод Ланцоша можно использовать итерационным образом: после выполнения заданного числа шагов процесс прерывается и, если еще не все требуемые пары Ритца сошлись с требуемой точностью, то формируется новый начальный вектор &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;q_1&amp;lt;/math&amp;gt;, являющийся линейной комбинацией векторов Ритца, еще не сошедшихся с заданной точностью, и процесс начинается заново.&amp;lt;ref&amp;gt;http://num-anal.srcc.msu.ru/lib_na/int_ae/int_ae6.htm (пункт 6.5)&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
Вычислительное ядро рассматриваемого алгоритма (наиболее ресурсно-затратная часть алгоритма) -  формирование на каждом шаге цикла промежуточного вектора &amp;lt;math&amp;gt;z&amp;lt;/math&amp;gt;, вычисляемого по формуле: &amp;lt;math&amp;gt;z = A\,q_j&amp;lt;/math&amp;gt;. Данная операция, по сравнению с другими операциями алгоритма, затратна и требовательна, как с точки зрения количества производимых операций, так и с точки зрения объема оперируемых данных. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Например, умножение матрицы размера &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;n\times n&amp;lt;/math&amp;gt; на вектор длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; требует: &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;n^2+(n-1)n = 2n^2-n&amp;lt;/math&amp;gt; операций умножения и сложения. В свою очередь аналогичная операция умножения матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;(n+1)\times (n+1)&amp;lt;/math&amp;gt; на вектор длины &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;(n+1)&amp;lt;/math&amp;gt; требует: &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;2n^2+3n+1&amp;lt;/math&amp;gt;  операций умножения и сложения. То есть повышение размерности задачи всего на 1 увеличивает число необходимых действий в этом шаге алгоритма на: &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;4n+1&amp;lt;/math&amp;gt;. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Так же, стоит помнить, что, согласно разделу 1.2, данную операцию умножения матрицы на вектор необходимо выполнить &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;k&amp;lt;/math&amp;gt; раз. Нетрудно понять, насколько возрастает и колоссален масштаб операций, если в задачах, где критична точность, размерности &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; могут иметь порядок &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;10^5&amp;lt;/math&amp;gt; или даже более.&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
Как уже было упомянуто в данной статье в описании алгоритма, рассматриваемый алгоритм состоит из двух последовательно выполненных алгоритмов: метод Ланцоша для построения последовательности подпространств Крылова и ортонормированных векторов Ланцоша и процедура Рэлея-Ритца получения оптимальных приближений собственных значений и соответствующих собственных векторов исходной матрицы.&lt;br /&gt;
&lt;br /&gt;
В первой части алгоритма, где итерационно строятся Крыловское подпространство и трёхдиагональная матрица &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&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 style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; разреженная. Именно она подлежит оптимизации с использованием техник распараллеливания, поскольку она является вычислительным ядром алгоритма, а весь упомянутый процесс построения матрицы &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&amp;lt;/math&amp;gt; выполняется последовательно.&lt;br /&gt;
&lt;br /&gt;
Рассмотрим вторую часть алгоритма - поиск собственных значений сформированной матрицы &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&amp;lt;/math&amp;gt;.&amp;lt;br&amp;gt;&lt;br /&gt;
Далее, наглядно, в виде псевдокода, представлен, упомянутый в разделе 1.2, QR-алгоритм (аналогично можно рассмотреть и QL-алгоритм) со сдвигами Релэя, который весьма популярен на практике.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{align}&lt;br /&gt;
\mathbf{Input}: \;&amp;amp;tridiagonal\;\;matrix \;T\;with\;\;n\times n\;\;size\\&lt;br /&gt;
T^{(0)}&amp;amp;:=T\\&lt;br /&gt;
\mathbf{for}&amp;amp; \;\;m=n,...,2 \;\; \mathbf{do}\\&lt;br /&gt;
&amp;amp;k=0\\&lt;br /&gt;
&amp;amp; \mathbf{repeat}\\&lt;br /&gt;
&amp;amp; \quad \;\; k=k+1\\&lt;br /&gt;
&amp;amp; \quad \;\; \mu^{(k)}=T_{m,m}^{(k-1)}\\&lt;br /&gt;
&amp;amp; \quad \;\; Q^{(k)}R^{(k)}=T^{(k-1)}-\mu^{(k)}I\;\;using\;\;QR\;decomposition\\&lt;br /&gt;
&amp;amp; \quad \;\; T^{(k)}=R^{(k)}Q^{(k)}+\mu^{(k)}I\\&lt;br /&gt;
&amp;amp; \mathbf{until} \;\;\; |T_{m,m-1}^{(k)}| \;is\;\;small\;\;enough\\&lt;br /&gt;
&amp;amp; Save  \;\;T_{m,m}^{(k)} \;\;as\;\; converged\;\;eigenvalue\;of\;T\\ &lt;br /&gt;
&amp;amp; Remove \;\boldsymbol{n}\,th\;row\;and\;\boldsymbol{n}\,th\;column\;\;from \;T \\&lt;br /&gt;
&amp;amp; and\;take\;this\;new\;cropped\;matrix\;as\;new\;T^{(0)}\;with\;\;(n-1)\times (n-1)\;\;size\\&lt;br /&gt;
 \mathbf{end}&amp;amp;\; \mathbf{for}&lt;br /&gt;
\end{align}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Малость наддиагональных и поддиагональных элементов матрицы (фраза &#039;&#039;&amp;quot;small enough&amp;quot;&#039;&#039; в псевдокоде) подразумевает:&lt;br /&gt;
&amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt; |T_{m,m-1}^{(k)}| \leq \varepsilon\,|T_{m,m}^{(k)}| \quad\quad &amp;lt;/math&amp;gt; , где &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt; \varepsilon &amp;lt;/math&amp;gt; - заданная точность&amp;lt;br&amp;gt;&lt;br /&gt;
Также вместо сдвига Релэя, обозначенного в алгоритме через &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;\mu^{(k)}&amp;lt;/math&amp;gt;, часто на практике используется сдвиг по Уилкинсону, который даёт гарантированную сходимость внедиагональных элементов матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt; T^{(k)} &amp;lt;/math&amp;gt;, формируемой на каждом шаге, к нулю, при этом жертвуя монотонностью их убывания.&amp;lt;ref&amp;gt;Голуб Дж., Ван Лоун Ч. - Матричные вычисления//М.: Мир. - 1999 (c. 378, вторая половина страницы)&amp;lt;/ref&amp;gt;&amp;lt;ref&amp;gt;Парлетт Б. Симметричная проблема собственных значений. Численные методы.,: Мир, 1983. с. 169&amp;lt;/ref&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Подробнее с различными сдвигами и соответствующими оценками скоростей и количествами операций можно ознакомиться по указанной ссылке:&amp;lt;ref&amp;gt;Парлетт Б. Симметричная проблема собственных значений. Численные методы.,: Мир, 1983. с. 179-182&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;Для совершения QR-декомпозиции на каждом шаге может использоваться любой из алгоритмов по ссылке.&amp;lt;ref&amp;gt;https://en.wikipedia.org/wiki/QR_decomposition&amp;lt;/ref&amp;gt; Подробные описания этих алгоритмов также доступны на данном ресурсе algowiki-project.&amp;lt;br&amp;gt;&lt;br /&gt;
Так как мы оперируем не обычной матрицей и даже не Хессенберговой, а симметричной и трёхдиагональной, то скорость таких алгоритмов значительно возрастёт. Например, согласно данному ресурсу &amp;lt;ref&amp;gt;http://algorithm.narod.ru/ln/eigen/ETridiag.html&amp;lt;/ref&amp;gt;, для QL-алгоритма с неявными сдвигами:&amp;lt;br&amp;gt;&lt;br /&gt;
Для трёхдиагональной матрицы объем арифметических действий составляет &amp;lt;math&amp;gt; O(n)&amp;lt;/math&amp;gt; на одну итерацию вместо &amp;lt;math&amp;gt; O(n^3)&amp;lt;/math&amp;gt; для матрицы общего вида, а число итераций для нахождения первых собственных значений примерно равно 4 - 5. Но на этих итерациях также уменьшаются внедиагональные элементы правого нижнего угла. И, таким образом, дальнейшие собственные значения ищутся значительно быстрее. Среднее число итераций на каждое собственное значение обычно составляет 1.3 - 1.6.&amp;lt;br&amp;gt; &lt;br /&gt;
Аналогично QL, QR-разложение трёхдиагольной матрицы также требует &amp;lt;math&amp;gt; O(n)&amp;lt;/math&amp;gt; флопов&amp;lt;ref&amp;gt;Голуб Дж., Ван Лоун Ч. - Матричные вычисления//М.: Мир. - 1999 (c. 378, начало раздела 8.2.2)&amp;lt;/ref&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Подводя итог, во второй части алгоритма Ланцоша можно выделить следующие макрооперации:&lt;br /&gt;
* умножение матрицы на вещественное число;&lt;br /&gt;
* перемножение матриц;&lt;br /&gt;
* умножение и сравнение вещественных чисел;&lt;br /&gt;
* + набор других макроопераций в зависимости от выбора метода, с помощью которого будет совершаться сама QR или QL-декомпозиция (выше продемонстрированы, уже, как минимум, 3 разных способа).&lt;br /&gt;
Так же, важно заметить, что набор макропераций может быть несколько другим, если выбрать какой-либо иной современный метод поиска собственных чисел трёхдиагональной матрицы, не использующий QR и QL разложения(факторизацию). Два таких метода были упомянуты в пункте 1.2.&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
С целью полностью не дублировать раздел 1.2 данной статьи, где представлен наглядный и доступный для понимания псевдокод алгоритма, постараемся лишь коротко просуммировать и обобщить весь перечень последовательных действий в рассматриваемом алгоритме.&lt;br /&gt;
&lt;br /&gt;
В качестве входных данных имеем: вещественная симметричная матрица &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; размера &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;n\times n&amp;lt;/math&amp;gt;, известный вещественный вектор &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;b&amp;lt;/math&amp;gt; длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; и число &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;n&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Далее:&lt;br /&gt;
* Инициализируем вещественную константу &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;\beta_0&amp;lt;/math&amp;gt; и векторы &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;q_0&amp;lt;/math&amp;gt; и &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;q_1&amp;lt;/math&amp;gt;&lt;br /&gt;
* Итерационно для всех &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j=1,...,k&amp;lt;/math&amp;gt;:&lt;br /&gt;
** Вычисляем вспомогательный вектор &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt;, используя умножение матрицы на вектор&lt;br /&gt;
** Вычисляем, используя скалярное произведение векторов, значение &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;\alpha_j&amp;lt;/math&amp;gt; - элемент на главной диагонали трёхдиагональной матрицы &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&amp;lt;/math&amp;gt;&lt;br /&gt;
** Вычисляем по формуле новое значение и перезаписываем вектор &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt;&lt;br /&gt;
** Вычисляем значение &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;\beta_j&amp;lt;/math&amp;gt; - элементы непосредственно над и под главной диагональю той же матрицы &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&amp;lt;/math&amp;gt;&lt;br /&gt;
** Вычисляем, зная вектор &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt;,  очередной столбец матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;Q&amp;lt;/math&amp;gt;, он же вектор Ланцоша : &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;\,\,q_{j+1}&amp;lt;/math&amp;gt;&lt;br /&gt;
** Теперь, когда матрица &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&amp;lt;/math&amp;gt; сформирована на очередном шаге, находим её собственные значения и вектора любым доступным способом, о чём было подробно сказано в пункте 1.2&lt;br /&gt;
** Переходим на следующую итерацию: &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j&amp;lt;/math&amp;gt;++&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
Оценим количество операций и сложность последовательного алгоритма, изложенного в предыдущем разделе.&lt;br /&gt;
*Для вычисления вектора &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt; умножается матрица размера &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;n\times n&amp;lt;/math&amp;gt; на вектор длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt;, и потребуется &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n^2&amp;lt;/math&amp;gt; операций умножения и &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n^2&amp;lt;/math&amp;gt; операций сложения.&lt;br /&gt;
*Умножение векторов &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;q^T_j&amp;lt;/math&amp;gt; и &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt; длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; потребует &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; операций умножения и &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; операций сложения.&lt;br /&gt;
*При вычислении нового значения вектора &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt; поэлементное сложение двух векторов длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; требует &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; операций сложения.&lt;br /&gt;
*Умножение вектора длины &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; на вещественное число требует &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; операций умножения.&lt;br /&gt;
*Нахождение квадратичной нормы вектора &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt;  длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; требует &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; умножений и &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; сложений и ещё 1 операцию извлечения квадратного корня.&lt;br /&gt;
*Заключительное нахождение собственных значений и собственных векторов трёхдиагональной матрицы &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;T_j&amp;lt;/math&amp;gt; размера &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j\times j&amp;lt;/math&amp;gt; с помощью QR-алгоритма потребует в худшем случае &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(j^3)&amp;lt;/math&amp;gt; операций.&amp;lt;ref&amp;gt;http://num-anal.srcc.msu.ru/lib_na/int_ae/int_ae6.htm (пункт 6.2, &amp;quot;Скорость сходимости при этом всегда не хуже квадратичной и почти всегда лучше кубической.&amp;quot;)&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Посчитаем теперь суммарное количество простейших операций на одной итерации алгоритма (без учёта записей в память):&lt;br /&gt;
*&amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n^2+5\,n&amp;lt;/math&amp;gt; операций умножения/деления&lt;br /&gt;
*&amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n^2+4\,n&amp;lt;/math&amp;gt; операций сложения/вычитания&lt;br /&gt;
*1 операция извлечения квадратного корня&amp;lt;br&amp;gt;&lt;br /&gt;
Отдельно после всех итераций при &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j=k&amp;lt;/math&amp;gt; :&lt;br /&gt;
*&amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(k^3)&amp;lt;/math&amp;gt; операций для поиска собственных значений и собственных векторов трёхдиагональной матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_k&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Итого можно утверждать следующее:&lt;br /&gt;
&lt;br /&gt;
Последовательная сложность одной итерации рассматриваемого алгоритма:  &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(n ^ 2) &amp;lt;/math&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Суммарная сложность алгоритма (&amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;/math&amp;gt; итераций): &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(k\,n ^ 2) + O(k ^ 3)&amp;lt;/math&amp;gt; &amp;lt;ref&amp;gt;Здесь мы полагаем, что мы не вычисляем собственные значения и векторы матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_j&amp;lt;/math&amp;gt; на каждом промежуточном шаге, а лишь единожды затрачиваем &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;O(k ^ 3)&amp;lt;/math&amp;gt; действий в конце для нахождения &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;/math&amp;gt; собственных значений и векторов матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_k&amp;lt;/math&amp;gt;&amp;lt;/ref&amp;gt; &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
На практике же обычно рассматривается число &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;&amp;lt;n&amp;lt;/math&amp;gt;, поэтому второе слагаемое можно опустить.&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
На рис. 1 продемонстрирован граф одной итерации (при каком-либо произвольном значении итератора &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j&amp;lt;/math&amp;gt;) описанного алгоритма без отображения входных и выходных данных. Наглядно продемонстрированы связи между всеми действиями, и с помощью деления на &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; потоков показано, какие операции возможно выполнять параллельно на каждом шаге с целью оптимизации и экономии машинного времени. В результате, после параллельно выполненных операций &#039;&#039;&#039;Division&#039;&#039;&#039; на заключительном ярусе, на выходе имеем значение следующего вектора Ланцоша &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;q_{j+1}&amp;lt;/math&amp;gt;, после чего следует переход на следующую итерацию, и процесс повторяется.&lt;br /&gt;
&lt;br /&gt;
[[Файл:Levin_graph.png|600px|thumb|center|Рис. 1]] &amp;lt;br&amp;gt;&lt;br /&gt;
Обозначения на рисунке: &amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Simp&#039;&#039;&#039; (от англ. simple) - операции сложения и умножения вещественных чисел при вычислении произведения матрицы на вектор;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Vec mult&#039;&#039;&#039; (от англ. vectors multiplication) - операция скалярного умножения двух векторов;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Vec subtr&#039;&#039;&#039; (от англ. vectors subtraction, из-за использованных в операции вычитаний векторов) - операция умножения вектора на число (выполняется дважды) и формирование нового значения &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;z_{new}&amp;lt;/math&amp;gt; по формуле: &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;z_{new} = z - \alpha_j q_j - \beta_{j-1}q_{j-1} \;&amp;lt;/math&amp;gt;;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;||\cdot||&amp;lt;/math&amp;gt; - операция вычисления нормы вектора;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Division&#039;&#039;&#039; - операция деления вектора на вещественное число  &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;\beta_j&amp;lt;/math&amp;gt; &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Важно отметить, что упомянутые выше операции также легко поддаются оптимизации. Например, попарные умножения вещественных координат векторов при вычислении скалярного произведения также легко выполняются параллельно на &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; потоках, а затем можно применить суммирование методом сдваивания, о котором сказано в следующем разделе. Умножение или деление вектора на вещественное число являющееся, по определению, умножением или делением всех его координат на это число тоже может быть выполнено эффективнее, если мы используем &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; потоков, а не выполняем эти действия последовательно.&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
Параллельные операции возможны только внутри итераций, так как рассматриваемый алгоритм является итерационным, и сами итерации строго последовательны.&amp;lt;br&amp;gt;&lt;br /&gt;
Рассмотрим в этом разделе подробнее, какой выигрыш мы можем получить при распараллеливании операций внутри одной итерации согласно графу из предыдущего раздела.&lt;br /&gt;
&lt;br /&gt;
Умножение вещественной симметричной матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; размера &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;n\times n&amp;lt;/math&amp;gt; на вектор &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;b&amp;lt;/math&amp;gt; длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; требует последовательного выполнения &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; ярусов умножений и сложений. Сложение элементов вектора длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; на каждом шаге перемножения можно оптимизировать и выполнить за &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;\log_2 n&amp;lt;/math&amp;gt; действий, если применять метод сдваивания.&lt;br /&gt;
&lt;br /&gt;
Дальнейшие операции выполняются последовательно, а вычисление значений векторов происходит за один ярус операций сложения или умножения.&lt;br /&gt;
&lt;br /&gt;
Ресурс параллелизма алгоритма вычисления собственных значений построенной трёхдиагональной матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_k&amp;lt;/math&amp;gt; размера &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k\times k&amp;lt;/math&amp;gt; зависит от выбранного алгоритма (об этих алгоритмах подробнее было сказано в разделах 1.2 и 1.4). Будет очень затратно с точки зрения объёма материала пытаться рассмотреть пусть даже часть этих методов в этой статье, а так же тонкости их распараллеливания. Предлагаем читателям при желании самим ознакомиться с этими алгоритмами на данном ресурсе или прибегнув к иным источникам.&lt;br /&gt;
&lt;br /&gt;
При классификации по высоте ЯПФ, таким образом, алгоритм Ланцоша без переортогонализации относится к алгоритмам с &#039;&#039;логарифмической сложностью&#039;&#039;, и его сложность равна &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(\log_2 n)&amp;lt;/math&amp;gt; с важным замечанием, что это сложность только одной итерации, а максимум в алгоритме может быть выполнено последовательно &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;/math&amp;gt; таких однотипных итераций, если не будет осуществлён ранний выход из цикла. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Несмотря на то, что на графе в предыдущем разделе для лучшей визуализации и понимания было изображено &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; потоков (никаких допущений мы не делали и нарушений с точки зрения логики и математики нет, можно изобразить большее число потоков, просто часть времени некоторые из них могут бездействовать и не использоваться), на самом деле правильным и разумным будет реализовать начальное параллельное выполнение &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n^2&amp;lt;/math&amp;gt; операций умножения всех вещественных элементов матрицы &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;A&amp;lt;/math&amp;gt; на соответствующие элементы вектора &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;q_j&amp;lt;/math&amp;gt;, после чего применять тот же самый упомянутый метод сдваивания. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Поэтому при классификации по ширине ЯПФ его сложность будет &#039;&#039;квадратичной&#039;&#039; и равна &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(n^2)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
&#039;&#039;&#039;Входные данные алгоритма:&#039;&#039;&#039; вещественная симметричная &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; размера &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;n\times n&amp;lt;/math&amp;gt;, вещественный вектор &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;b&amp;lt;/math&amp;gt; длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt;, и одно целое число &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;k&amp;lt;/math&amp;gt;, означающее количество итераций.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём входных данных:&#039;&#039;&#039; &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;n^2 +n + 1 &amp;lt;/math&amp;gt;. Если учесть, что матрица симметричная и достаточно для её однозначного определения задать элементы на главной диагонали и элементы над или под ней, то можно сократить объём входных данных с целью экономии памяти до: &amp;lt;math&amp;gt;\ \frac{n^2-n}{2}+n+n+1 =\frac{n^2+3n}{2} + 1&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные алгоритма:&#039;&#039;&#039; вектор собственных значений &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;\Theta^k&amp;lt;/math&amp;gt; длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;/math&amp;gt;, матрица &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;S^k&amp;lt;/math&amp;gt; из соответствующих собственных векторов размера &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n\times k&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём выходных данных:&#039;&#039;&#039; &amp;lt;math&amp;gt;k\;(n + 1)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
В данном разделе перечислены без какой-либо хронологии или связи друг с другом наиболее важные и разнообразные свойства алгоритма, на которые стоит и полезно обратить внимание, а также которые выгодно отличают его от схожих алгоритмов, решающих ту же задачу.&amp;lt;br&amp;gt;&lt;br /&gt;
1) Отношение последовательной сложности алгоритма к параллельной,с учётом &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;/math&amp;gt; итераций, равно &amp;lt;math&amp;gt;\;\;\frac{kn^2}{k \log_2{n}}=\frac{n^2}{\log_2{n}}&amp;lt;/math&amp;gt;;&amp;lt;br&amp;gt;&lt;br /&gt;
2) Вычислительная мощность алгоритма, как отношение числа операций к суммарному объему входных и выходных данных, равна &amp;lt;math style=&amp;quot;vertical-align:-70%&amp;gt;\;\;\frac{k\,n^2}{0.5\,n^2+1.5\,n+k\,n+k+1}&amp;lt;/math&amp;gt; и &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;\approx 2\,k&amp;lt;/math&amp;gt;, так как на практике верно отношение &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;&amp;lt;n&amp;lt;/math&amp;gt; ;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
3) Для собственных значений формируемых матриц &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_j&amp;lt;/math&amp;gt; верно отношение (следствие теоремы Коши о перемежаемости): &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;\lambda_i(T_{k+1})\geq \lambda_i(T_{k})\geq \lambda_{i+1}(T_{k+1})\geq \lambda_{i+1}(T_{k})&amp;lt;/math&amp;gt; ;&amp;lt;ref&amp;gt;James W. Demmel - Вычислительная линейная алгебра. Теория и приложения //Мир. - 2001 (c. 383)&amp;lt;/ref&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
4) Крайние (наибольшие и наименьшие) собственные значения матриц &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_j&amp;lt;/math&amp;gt; сходятся к крайним собственным значениям матрицы &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;A&amp;lt;/math&amp;gt; первыми (это часто происходит уже на ранних шагах при &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j\approx 2\,\sqrt{n}&amp;lt;/math&amp;gt;&amp;lt;ref&amp;gt;http://num-anal.srcc.msu.ru/lib_na/int_ae/int_ae6.htm (пункт 6.5)&amp;lt;/ref&amp;gt;), а собственные значения в середине спектра - последними;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
5) Из-за ограниченной точности постепенно теряется ортогональность вектора Ланцоша &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;q_j&amp;lt;/math&amp;gt; к предыдущим векторам Ланцоша, поэтому необходимо примерно каждые 10-15 итераций проводить дорогостоящую операцию реортогонализации, но это уже будет иной алгоритм с очень малым различием в одной операции и в программном коде, реализующем его, соответственно; &amp;lt;ref&amp;gt;Sam Handler - The Lanczos Algorithm For Large-Scale Eigenvalue Problems (08.01.07), slide №8&amp;lt;/ref&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
6) Эффективность и быстрота выполнения алгоритма очень сильно зависит от скорости памяти (диска). Согласно тесту только &#039;&#039;6%&#039;&#039; времени работы программы приходится на вычисления, остальное время затрачивается на ожидание отклика диска;&amp;lt;ref&amp;gt;Sam Handler - The Lanczos Algorithm For Large-Scale Eigenvalue Problems (08.01.07), slide №10&amp;lt;/ref&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
7) Метод Ланцоша удобен тем, что не требует хранения исходной матрицы полным массивом: метод использует исходную матрицу только в операциях умножения матрицы на вектор, что позволяет эффективно использовать разреженность матрицы или регулярность структуры матрицы. Поэтому метод Ланцоша может быть использован для матриц таких больших порядков, когда методы вращений и отражений не могут быть применены.&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;
Для исследования масштабируемости рассматриваемого алгоритма Ланцоша без переортогонализации автором была реализована программа на языке С++ с использованием технологии MPI (&#039;&#039;&#039;не забыть вставить ссылку на код&#039;&#039;&#039;). Дальнейшее исследование выполнялось на суперкомпьютере &amp;quot;Ломоносов&amp;quot; Суперкомпьютерного комплекса МГУ. Важно отметить, что реализованная программа выполняет только первую часть алгоритма - формирование матрицы &amp;lt;math &amp;gt;T_j&amp;lt;/math&amp;gt;. Вторая часть алгоритма - задача поиска её собственных значений может быть решена несколькими методами, каждый из которых обладает своей эффективностью распараллеливании и характерными свойствами. Подробно этот вопрос уже обсуждался в статье раннее, поэтому не будем ещё раз заострять на этом внимание и останавливаться.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Сборка осуществлялась со следующими параметрами:&lt;br /&gt;
* Компилятор intel/15.0.090 &lt;br /&gt;
* Openmpi/1.8.4-icc&lt;br /&gt;
В серии проведённых расчётов рассматривались следующие числовые значения параметров:&lt;br /&gt;
* Размер задачи и, соответственно, матрицы А, задействованной в операции умножения на вектор: [2000 : 30000] с шагом 1000&lt;br /&gt;
* Число процессоров: 1,2,4,16,32,48,64,96,128&lt;br /&gt;
* Число итераций: &amp;lt;math&amp;gt;k=350&amp;lt;/math&amp;gt; . Взято таким вопреки информации выше, где говорится, что значение &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; редко превышает &amp;lt;math&amp;gt;10^2&amp;lt;/math&amp;gt;. Сделано это исключительно для лучшей визуализации пиков на графиках и наглядности получаемых результатов, так как при меньших на порядок значениях &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; времена выполнения программ были слишком малы даже при минимальных числах процессоров и максимальных размерах исходной задачи.&lt;br /&gt;
&lt;br /&gt;
== Динамические характеристики и эффективность реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Выводы для классов архитектур ==&lt;br /&gt;
По заданию, во второй части требовалось описать только разделы 2.4 и 2.7, прошу не спрашивать с меня все разделы 2.1-2.6. Надеюсь на понимание, мне физически не хватает времени на это задание + 2 других в течение семестра, делаю всё, что в моих силах :)&lt;br /&gt;
&lt;br /&gt;
== Существующие реализации алгоритма ==&lt;br /&gt;
Несмотря на то, что алгоритм является далеко не самым популярным, алгоритмом, про который нельзя сказать, что он всегда «на слуху», на сегодняшний день существует множество реализаций на различных популярных языках.&amp;lt;br&amp;gt;&lt;br /&gt;
Перечислим далее некоторые из них, указывая язык программирования, лежащий в их основе, и некоторые важные характеристики, которые обсуждались в статье ранее:&lt;br /&gt;
*&#039;&#039;Code on netlib.org by Jane Cullum and Ralph Willoughby&#039;&#039; (&#039;&#039;&#039;Fortran 77&#039;&#039;&#039;; без реортогонализации векторов; без реализации распараллеливания)&amp;lt;ref&amp;gt;http://www.netlib.org/lanczos/leval&amp;lt;/ref&amp;gt;&lt;br /&gt;
*&#039;&#039;Lanczos algorithm on freesourcecode.net&#039;&#039; (&#039;&#039;&#039;Matlab&#039;&#039;&#039;; присутствует реортогонализация векторов; без реализации распараллеливания)&amp;lt;ref&amp;gt;http://freesourcecode.net/matlabprojects/61741/lanczos-algorithm--in-matlab&amp;lt;/ref&amp;gt;&lt;br /&gt;
*&#039;&#039;Lanczos for eigenvalues in Numerical Linear Algebra, Spring 2007&#039;&#039; (&#039;&#039;&#039;Matlab&#039;&#039;&#039;; частичная или полная реортогонализация - доступны оба варианта; без реализации распараллеливания)&amp;lt;ref&amp;gt;Ссылки на файлы lanso.m и lanfu.m можно найти на https://www.nada.kth.se/~ruhe/2D5219/labs2007.html&amp;lt;/ref&amp;gt;&lt;br /&gt;
*&#039;&#039;Planso&#039;&#039; (название происходит от parallel Lanso.f) &#039;&#039;code by Kesheng Wu and Horst D. Simon&#039;&#039; (&#039;&#039;&#039;Fortran 77&#039;&#039;&#039;; частичная реортогонализация векторов; использование MPI для коммуникаций)&amp;lt;ref&amp;gt;https://github.com/jiahao/planso.jl/tree/master/external/PLAN/plan К сожалению, ссылка в описании пакета на github, ведущая на сайт National Energy Research Scientific Computing Center (NERSC), с более подробной информацией о данной программе больше не активна и выдаёт результат &#039;&#039;Page not found&#039;&#039;&amp;lt;/ref&amp;gt; &lt;br /&gt;
* &#039;&#039;Lanczos.cpp in the Vienna Computing Library&#039;&#039;  (&#039;&#039;&#039;C++&#039;&#039;&#039;, частичная реортогонализация, без реализации распараллеливания) &amp;lt;ref&amp;gt;http://viennacl.sourceforge.net/doc/lanczos_8cpp_source.html&amp;lt;/ref&amp;gt;&lt;br /&gt;
* &#039;&#039;Parallel Eigen Values code using C++ AMP on microsoft msdn blog&#039;&#039; (&#039;&#039;&#039;C++&#039;&#039;&#039;; ? ; распараллеливание есть и реализовано через C++ AMP) &amp;lt;ref&amp;gt;https://blogs.msdn.microsoft.com/nativeconcurrency/2013/12/20/eigen-values/ Подробнее о C++ Accelerated Massive Parallelism можно почитать здесь: https://msdn.microsoft.com/ru-ru/library/hh265137(v=vs.140).aspx или здесь: http://professorweb.ru/my/csharp/optimization/level4/4_6.php &amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;br /&gt;
[[en:Description of algorithm properties and structure]]&lt;/div&gt;</summary>
		<author><name>AleksLevin</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:AleksLevin/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%9B%D0%B0%D0%BD%D1%86%D0%BE%D1%88%D0%B0_%D0%B2%D1%8B%D1%87%D0%B8%D1%81%D0%BB%D0%B5%D0%BD%D0%B8%D1%8F_%D1%81%D0%BE%D0%B1%D1%81%D1%82%D0%B2%D0%B5%D0%BD%D0%BD%D1%8B%D1%85_%D0%B7%D0%BD%D0%B0%D1%87%D0%B5%D0%BD%D0%B8%D0%B9_%D1%81%D0%B8%D0%BC%D0%BC%D0%B5%D1%82%D1%80%D0%B8%D1%87%D0%BD%D0%BE%D0%B9_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86%D1%8B_%D0%B4%D0%BB%D1%8F_%D1%82%D0%BE%D1%87%D0%BD%D0%BE%D0%B9_%D0%B0%D1%80%D0%B8%D1%84%D0%BC%D0%B5%D1%82%D0%B8%D0%BA%D0%B8_(%D0%B1%D0%B5%D0%B7_%D0%BF%D0%B5%D1%80%D0%B5%D0%BE%D1%80%D1%82%D0%BE%D0%B3%D0%BE%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D0%B8)&amp;diff=20202</id>
		<title>Участник:AleksLevin/Алгоритм Ланцоша вычисления собственных значений симметричной матрицы для точной арифметики (без переортогонализации)</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:AleksLevin/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%9B%D0%B0%D0%BD%D1%86%D0%BE%D1%88%D0%B0_%D0%B2%D1%8B%D1%87%D0%B8%D1%81%D0%BB%D0%B5%D0%BD%D0%B8%D1%8F_%D1%81%D0%BE%D0%B1%D1%81%D1%82%D0%B2%D0%B5%D0%BD%D0%BD%D1%8B%D1%85_%D0%B7%D0%BD%D0%B0%D1%87%D0%B5%D0%BD%D0%B8%D0%B9_%D1%81%D0%B8%D0%BC%D0%BC%D0%B5%D1%82%D1%80%D0%B8%D1%87%D0%BD%D0%BE%D0%B9_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86%D1%8B_%D0%B4%D0%BB%D1%8F_%D1%82%D0%BE%D1%87%D0%BD%D0%BE%D0%B9_%D0%B0%D1%80%D0%B8%D1%84%D0%BC%D0%B5%D1%82%D0%B8%D0%BA%D0%B8_(%D0%B1%D0%B5%D0%B7_%D0%BF%D0%B5%D1%80%D0%B5%D0%BE%D1%80%D1%82%D0%BE%D0%B3%D0%BE%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D0%B8)&amp;diff=20202"/>
		<updated>2016-12-06T21:42:29Z</updated>

		<summary type="html">&lt;p&gt;AleksLevin: /* Масштабируемость алгоритма и его реализации */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Основные авторы описания: Левин А.Д.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{algorithm&lt;br /&gt;
| name              = Алгоритм Ланцоша для точной арифметики (без переортогонализации)&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(k\,n^2)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(k\log_2 n)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;\frac{n^2+3n}{2} + 1&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;k\;(n + 1)&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритмов =&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Данный алгоритм появился в 1950 г. и носит имя венгерского физика и математика Корнелия Ланцоша (венг. Lánczos Kornél). Алгоритм Ланцоша относится к итерационным методам вычисления собственных значений для матриц столь больших порядков &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt; n&amp;lt;/math&amp;gt;, что к ним нельзя применить прямые методы из-за ограничений по времени и памяти.&lt;br /&gt;
&lt;br /&gt;
Сам Ланцош указывал, что его метод предназначен для отыскания нескольких собственных векторов симметричных матриц, хотя к методу сразу было обращено внимание, как к способу приведения всей матрицы к трёхдиагональному виду. Двадцатью годами позже канадский математик Крис Пэж показал, что, несмотря на чувствительность к округлениям, алгоритм Ланцоша - эффективное средство вычисления некоторых &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; собственных чисел и соответствующих им собственных векторов. &amp;lt;ref&amp;gt;Парлетт Б. - Симметричная проблема собственных значений. Численные методы //М.: Мир. - 1983. (c. 276)&amp;lt;/ref&amp;gt;&lt;br /&gt;
Обычно число &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; берут в два раза больше, чем количество собственных значений матрицы, которые поставлена цель найти, и оно имеет порядок не более &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;10^2&amp;lt;/math&amp;gt;.&amp;lt;ref&amp;gt;Susan W. Bostic - Lanczos Eigensolution Method for High-Perfomance Computers, page 7&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Алгоритм Ланцоша для вычисления собственных значений симметричной матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; соединяет в себе метод Ланцоша для построения последовательности подпространств Крылова и ортонормированных векторов Ланцоша и процедуру Рэлея-Ритца получения оптимальных приближений собственных значений и соответствующих собственных векторов исходной матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt;.&amp;lt;ref&amp;gt;James W. Demmel - Вычислительная линейная алгебра. Теория и приложения //Мир. - 2001 (c. 381)&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
В данной статье рассматривается вариант алгоритма Ланцоша, в котором опущено влияние ошибок округления на вычислительный процесс, хотя на практике этому посвящается отдельное внимание и существуют различные методы решения данной проблемы, такие как частичная или полная переортогонализация. Этим модифицированным методам посвящены отдельные статьи на данном ресурсе.&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
Обозначения и формулы, используемые в данном разделе, взяты из литературы, указанной по ссылке.&amp;lt;ref&amp;gt;James W. Demmel - Вычислительная линейная алгебра. Теория и приложения //Мир. - 2001 (c. 313, &#039;&#039;&amp;lt;math&amp;gt; \S &amp;lt;/math&amp;gt; 6.6 Методы Крыловского подпространства&#039;&#039;)&amp;lt;/ref&amp;gt; &lt;br /&gt;
&lt;br /&gt;
Алгоритм Ланцоша для вычисления &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; собственных значений и собственных векторов вещественной симметричной матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A=A^T&amp;lt;/math&amp;gt; в точной арифметике: &amp;lt;ref&amp;gt;James W. Demmel - Вычислительная линейная алгебра. Теория и приложения //Мир. - 2001 (c. 381)&amp;lt;/ref&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{align}&lt;br /&gt;
q_1 = &amp;amp; \,\frac{b}{\|b\|_2},\; \beta_0 = 0,\; q_0 = 0\\&lt;br /&gt;
\mathbf{for} \; &amp;amp; j = 1 \; to \; k \,\; \mathbf{do} \\&lt;br /&gt;
&amp;amp; z = A\,q_j\\&lt;br /&gt;
&amp;amp; \alpha_j = q^T_j z\\&lt;br /&gt;
&amp;amp; z = z - \alpha_j q_j - \beta_{j-1}q_{j-1}\\&lt;br /&gt;
&amp;amp; \beta_j = \|z\|_2\\&lt;br /&gt;
&amp;amp; \mathbf{If} \; (\beta_j == 0) \; \mathbf{then}\; stop\; the\; algorithm \\ &lt;br /&gt;
&amp;amp; \;  q_{j+1} = \frac{z}{\beta_j} \\&lt;br /&gt;
&amp;amp; compute\; eigenvalues\; and \;eigenvectors\;of \;matrix \;\;T_j= Q^T_j A Q\;\;and\;estimate \;the\; errors\\&lt;br /&gt;
\mathbf{end} \; &amp;amp; \mathbf{for}&lt;br /&gt;
\end{align}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
В продемонстрированном выше алгоритме &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;b&amp;lt;/math&amp;gt; - заданный вещественный вектор. Также полагается известным алгоритм вычисления произведения матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; на вектор &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;x&amp;lt;/math&amp;gt;. &lt;br /&gt;
Введём матрицу Крылова, определяемую следующим соотношением: &amp;lt;math&amp;gt;K_j = [b,Ab,A^2b,...,A^{j-1}b]&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Далее, на практике, матрица &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;K&amp;lt;/math&amp;gt; заменяется матрицей &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;Q&amp;lt;/math&amp;gt;, такой, что при любом числе &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; линейные оболочки первых &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; столбцов в &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;K&amp;lt;/math&amp;gt; и &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;Q&amp;lt;/math&amp;gt; являются одним и тем же подпространством.&amp;lt;ref&amp;gt;James W. Demmel - Вычислительная линейная алгебра. Теория и приложения //Мир. - 2001 (c. 315)&amp;lt;/ref&amp;gt; &lt;br /&gt;
Тогда матрица &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;Q&amp;lt;/math&amp;gt;, в отличие от матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;K&amp;lt;/math&amp;gt;, хорошо обусловлена и легко обратима. В результате получаем матрицу &amp;lt;math&amp;gt;Q_j = [q_1, q_2, \dots, q_j]&amp;lt;/math&amp;gt; размерности &amp;lt;math&amp;gt;n\times j&amp;lt;/math&amp;gt;, столбцы которой ортогональны, являются базисом подпространства Крылова и называются векторами Ланцоша.&lt;br /&gt;
&lt;br /&gt;
В алгоритме Ланцоша вычислению подлежит столько первых столбцов в матрице &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;Q_j&amp;lt;/math&amp;gt;, сколько необходимо для получения требуемого приближения к решению &amp;lt;math&amp;gt;A\,x\,=b\,\,(A\,x=\lambda \, x)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Получение нулевого &amp;lt;math&amp;gt;\beta_j&amp;lt;/math&amp;gt; в итерационном процессе - событие, желательное в том смысле, что оно свидетельствует о том, что найдено некоторое подпространство, являющееся в точности инвариантным, а все собственные значения матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;T_j&amp;lt;/math&amp;gt; являются собственными значениями матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt;. На практике же нулевое и близкие к нулю значения получаются редко.&amp;lt;ref&amp;gt;Голуб Дж., Ван Лоун Ч. - Матричные вычисления//М.: Мир. - 1999 (c. 429)&amp;lt;/ref&amp;gt; &lt;br /&gt;
&lt;br /&gt;
Затем на каждом шаге цикла формируется симметричная трёхдиагональная матрица &amp;lt;math&amp;gt;T_j = Q^T_j A Q&amp;lt;/math&amp;gt;, к которой применяется процесс Рэлея-Ритца для поиска её собственных значений (на практике для поиска этих собственных значений можно использовать любой из специальных методов в параграфе книги по ссылке).&amp;lt;ref&amp;gt;Голуб Дж., Ван Лоун Ч. - Матричные вычисления//М.: Мир. - 1999 (&amp;lt;math&amp;gt;\S&amp;lt;/math&amp;gt; 8.4)&amp;lt;/ref&amp;gt;  &lt;br /&gt;
Эти собственные значения, они же числа Ритца, и полагаются приближёнными собственными значениями исходной матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt;.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Существует множество методов для отыскания собственных значений вещественной симметричной трехдиагональной матрицы. Большинство из них требует &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt; операций &amp;lt;ref&amp;gt;Парлетт Б. Симметричная проблема собственных значений. Численные методы.,: Мир, 1983. с. 179-182&amp;lt;/ref&amp;gt;, но существуют и быстрые алгоритмы, требующие лишь &amp;lt;math&amp;gt;O(n\ln n)&amp;lt;/math&amp;gt; операций.&amp;lt;ref&amp;gt;https://en.wikipedia.org/wiki/Tridiagonal_matrix#Eigenvalues  Раздел eigenvalues&amp;lt;/ref&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Одним из возможных способов отыскать собственные значения симметричной трехдиагональной матрицы - прямое вычисление корней характеристического полинома &amp;lt;math&amp;gt;p_n(\lambda)&amp;lt;/math&amp;gt; через метод деления пополам, где формируется последовательность Штурма и локализуются собственные числа, являющиеся корнями характеристического полинома. Нахождение всех &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; собственных значений матрицы этим способом требует &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;2n^2t&amp;lt;/math&amp;gt; умножений и вычитаний, где &amp;lt;math&amp;gt;t&amp;lt;/math&amp;gt; - число сделанных шагов с применением метода деления пополам.&amp;lt;ref&amp;gt;Уилкинсон Дж. X. Алгебраическая проблема собственныx значений. Изд-во &amp;quot;Наука&amp;quot;, 1970. - глава 5, с. 272-278&amp;lt;/ref&amp;gt; Соответствующие собственные вектора могут быть найдены посредством обратных итераций за &amp;lt;math&amp;gt; O(n) &amp;lt;/math&amp;gt; флопов. &amp;lt;ref&amp;gt;Голуб Дж., Ван Лоун Ч. - Матричные вычисления//М.: Мир. - 1999 (c. 394-395)&amp;lt;/ref&amp;gt; &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;На практике, если требуется только небольшая часть от всей совокупности собственных векторов и значений, и матрица имеет Хессенбергову или трёхдиагональную форму, очень эффективными будут методы факторизации, как, например, QR-алгоритм или QL-алгоритм со сдвигами (c целью ускорить алгоритм и сделать порядок сходимости квадратичным) или же без них.&amp;lt;ref&amp;gt;http://algorithm.narod.ru/ln/eigen/ETridiag.html&amp;lt;/ref&amp;gt; &amp;lt;br&amp;gt;&lt;br /&gt;
Весьма молодые и не менее актуальные конкуренты QR и QL алгоритмов, применяющиеся для поиска собственных значений:&lt;br /&gt;
*Методы divide-and-conquer (разделяй и властвуй), появившиеся в 1980-ых годах &amp;lt;ref&amp;gt;https://goo.gl/dapvbn ссылку пришлось сократить с помощью Google url shortener, так как символы подчеркивания портили её и не давали перейти по 1 клику&amp;lt;/ref&amp;gt;&lt;br /&gt;
*Relatively robust representation методы, появившиеся в 1990-ых и позволяющие найти собственные числа симметричной матрицы порядка &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;n&amp;lt;/math&amp;gt; за &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt; операций&lt;br /&gt;
&lt;br /&gt;
Если требуется вычислить собственные векторы, то необходимо хранить вычисляемые векторы Ланцоша. Если работа при этом производится только с оперативной памятью, то при большом порядке исходной матрицы (а именно для таких матриц и предназначен метод Ланцоша) число шагов  &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;j&amp;lt;/math&amp;gt;, которые могут быть выполнены до того момента, как оперативная память будет исчерпана, будет очень незначительно, а следовательно, искомые собственные пары могут не успеть сойтись с требуемой точностью. В этом случае метод Ланцоша можно использовать итерационным образом: после выполнения заданного числа шагов процесс прерывается и, если еще не все требуемые пары Ритца сошлись с требуемой точностью, то формируется новый начальный вектор &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;q_1&amp;lt;/math&amp;gt;, являющийся линейной комбинацией векторов Ритца, еще не сошедшихся с заданной точностью, и процесс начинается заново.&amp;lt;ref&amp;gt;http://num-anal.srcc.msu.ru/lib_na/int_ae/int_ae6.htm (пункт 6.5)&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
Вычислительное ядро рассматриваемого алгоритма (наиболее ресурсно-затратная часть алгоритма) -  формирование на каждом шаге цикла промежуточного вектора &amp;lt;math&amp;gt;z&amp;lt;/math&amp;gt;, вычисляемого по формуле: &amp;lt;math&amp;gt;z = A\,q_j&amp;lt;/math&amp;gt;. Данная операция, по сравнению с другими операциями алгоритма, затратна и требовательна, как с точки зрения количества производимых операций, так и с точки зрения объема оперируемых данных. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Например, умножение матрицы размера &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;n\times n&amp;lt;/math&amp;gt; на вектор длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; требует: &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;n^2+(n-1)n = 2n^2-n&amp;lt;/math&amp;gt; операций умножения и сложения. В свою очередь аналогичная операция умножения матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;(n+1)\times (n+1)&amp;lt;/math&amp;gt; на вектор длины &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;(n+1)&amp;lt;/math&amp;gt; требует: &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;2n^2+3n+1&amp;lt;/math&amp;gt;  операций умножения и сложения. То есть повышение размерности задачи всего на 1 увеличивает число необходимых действий в этом шаге алгоритма на: &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;4n+1&amp;lt;/math&amp;gt;. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Так же, стоит помнить, что, согласно разделу 1.2, данную операцию умножения матрицы на вектор необходимо выполнить &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;k&amp;lt;/math&amp;gt; раз. Нетрудно понять, насколько возрастает и колоссален масштаб операций, если в задачах, где критична точность, размерности &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; могут иметь порядок &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;10^5&amp;lt;/math&amp;gt; или даже более.&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
Как уже было упомянуто в данной статье в описании алгоритма, рассматриваемый алгоритм состоит из двух последовательно выполненных алгоритмов: метод Ланцоша для построения последовательности подпространств Крылова и ортонормированных векторов Ланцоша и процедура Рэлея-Ритца получения оптимальных приближений собственных значений и соответствующих собственных векторов исходной матрицы.&lt;br /&gt;
&lt;br /&gt;
В первой части алгоритма, где итерационно строятся Крыловское подпространство и трёхдиагональная матрица &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&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 style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; разреженная. Именно она подлежит оптимизации с использованием техник распараллеливания, поскольку она является вычислительным ядром алгоритма, а весь упомянутый процесс построения матрицы &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&amp;lt;/math&amp;gt; выполняется последовательно.&lt;br /&gt;
&lt;br /&gt;
Рассмотрим вторую часть алгоритма - поиск собственных значений сформированной матрицы &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&amp;lt;/math&amp;gt;.&amp;lt;br&amp;gt;&lt;br /&gt;
Далее, наглядно, в виде псевдокода, представлен, упомянутый в разделе 1.2, QR-алгоритм (аналогично можно рассмотреть и QL-алгоритм) со сдвигами Релэя, который весьма популярен на практике.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{align}&lt;br /&gt;
\mathbf{Input}: \;&amp;amp;tridiagonal\;\;matrix \;T\;with\;\;n\times n\;\;size\\&lt;br /&gt;
T^{(0)}&amp;amp;:=T\\&lt;br /&gt;
\mathbf{for}&amp;amp; \;\;m=n,...,2 \;\; \mathbf{do}\\&lt;br /&gt;
&amp;amp;k=0\\&lt;br /&gt;
&amp;amp; \mathbf{repeat}\\&lt;br /&gt;
&amp;amp; \quad \;\; k=k+1\\&lt;br /&gt;
&amp;amp; \quad \;\; \mu^{(k)}=T_{m,m}^{(k-1)}\\&lt;br /&gt;
&amp;amp; \quad \;\; Q^{(k)}R^{(k)}=T^{(k-1)}-\mu^{(k)}I\;\;using\;\;QR\;decomposition\\&lt;br /&gt;
&amp;amp; \quad \;\; T^{(k)}=R^{(k)}Q^{(k)}+\mu^{(k)}I\\&lt;br /&gt;
&amp;amp; \mathbf{until} \;\;\; |T_{m,m-1}^{(k)}| \;is\;\;small\;\;enough\\&lt;br /&gt;
&amp;amp; Save  \;\;T_{m,m}^{(k)} \;\;as\;\; converged\;\;eigenvalue\;of\;T\\ &lt;br /&gt;
&amp;amp; Remove \;\boldsymbol{n}\,th\;row\;and\;\boldsymbol{n}\,th\;column\;\;from \;T \\&lt;br /&gt;
&amp;amp; and\;take\;this\;new\;cropped\;matrix\;as\;new\;T^{(0)}\;with\;\;(n-1)\times (n-1)\;\;size\\&lt;br /&gt;
 \mathbf{end}&amp;amp;\; \mathbf{for}&lt;br /&gt;
\end{align}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Малость наддиагональных и поддиагональных элементов матрицы (фраза &#039;&#039;&amp;quot;small enough&amp;quot;&#039;&#039; в псевдокоде) подразумевает:&lt;br /&gt;
&amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt; |T_{m,m-1}^{(k)}| \leq \varepsilon\,|T_{m,m}^{(k)}| \quad\quad &amp;lt;/math&amp;gt; , где &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt; \varepsilon &amp;lt;/math&amp;gt; - заданная точность&amp;lt;br&amp;gt;&lt;br /&gt;
Также вместо сдвига Релэя, обозначенного в алгоритме через &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;\mu^{(k)}&amp;lt;/math&amp;gt;, часто на практике используется сдвиг по Уилкинсону, который даёт гарантированную сходимость внедиагональных элементов матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt; T^{(k)} &amp;lt;/math&amp;gt;, формируемой на каждом шаге, к нулю, при этом жертвуя монотонностью их убывания.&amp;lt;ref&amp;gt;Голуб Дж., Ван Лоун Ч. - Матричные вычисления//М.: Мир. - 1999 (c. 378, вторая половина страницы)&amp;lt;/ref&amp;gt;&amp;lt;ref&amp;gt;Парлетт Б. Симметричная проблема собственных значений. Численные методы.,: Мир, 1983. с. 169&amp;lt;/ref&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Подробнее с различными сдвигами и соответствующими оценками скоростей и количествами операций можно ознакомиться по указанной ссылке:&amp;lt;ref&amp;gt;Парлетт Б. Симметричная проблема собственных значений. Численные методы.,: Мир, 1983. с. 179-182&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;Для совершения QR-декомпозиции на каждом шаге может использоваться любой из алгоритмов по ссылке.&amp;lt;ref&amp;gt;https://en.wikipedia.org/wiki/QR_decomposition&amp;lt;/ref&amp;gt; Подробные описания этих алгоритмов также доступны на данном ресурсе algowiki-project.&amp;lt;br&amp;gt;&lt;br /&gt;
Так как мы оперируем не обычной матрицей и даже не Хессенберговой, а симметричной и трёхдиагональной, то скорость таких алгоритмов значительно возрастёт. Например, согласно данному ресурсу &amp;lt;ref&amp;gt;http://algorithm.narod.ru/ln/eigen/ETridiag.html&amp;lt;/ref&amp;gt;, для QL-алгоритма с неявными сдвигами:&amp;lt;br&amp;gt;&lt;br /&gt;
Для трёхдиагональной матрицы объем арифметических действий составляет &amp;lt;math&amp;gt; O(n)&amp;lt;/math&amp;gt; на одну итерацию вместо &amp;lt;math&amp;gt; O(n^3)&amp;lt;/math&amp;gt; для матрицы общего вида, а число итераций для нахождения первых собственных значений примерно равно 4 - 5. Но на этих итерациях также уменьшаются внедиагональные элементы правого нижнего угла. И, таким образом, дальнейшие собственные значения ищутся значительно быстрее. Среднее число итераций на каждое собственное значение обычно составляет 1.3 - 1.6.&amp;lt;br&amp;gt; &lt;br /&gt;
Аналогично QL, QR-разложение трёхдиагольной матрицы также требует &amp;lt;math&amp;gt; O(n)&amp;lt;/math&amp;gt; флопов&amp;lt;ref&amp;gt;Голуб Дж., Ван Лоун Ч. - Матричные вычисления//М.: Мир. - 1999 (c. 378, начало раздела 8.2.2)&amp;lt;/ref&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Подводя итог, во второй части алгоритма Ланцоша можно выделить следующие макрооперации:&lt;br /&gt;
* умножение матрицы на вещественное число;&lt;br /&gt;
* перемножение матриц;&lt;br /&gt;
* умножение и сравнение вещественных чисел;&lt;br /&gt;
* + набор других макроопераций в зависимости от выбора метода, с помощью которого будет совершаться сама QR или QL-декомпозиция (выше продемонстрированы, уже, как минимум, 3 разных способа).&lt;br /&gt;
Так же, важно заметить, что набор макропераций может быть несколько другим, если выбрать какой-либо иной современный метод поиска собственных чисел трёхдиагональной матрицы, не использующий QR и QL разложения(факторизацию). Два таких метода были упомянуты в пункте 1.2.&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
С целью полностью не дублировать раздел 1.2 данной статьи, где представлен наглядный и доступный для понимания псевдокод алгоритма, постараемся лишь коротко просуммировать и обобщить весь перечень последовательных действий в рассматриваемом алгоритме.&lt;br /&gt;
&lt;br /&gt;
В качестве входных данных имеем: вещественная симметричная матрица &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; размера &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;n\times n&amp;lt;/math&amp;gt;, известный вещественный вектор &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;b&amp;lt;/math&amp;gt; длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; и число &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;n&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Далее:&lt;br /&gt;
* Инициализируем вещественную константу &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;\beta_0&amp;lt;/math&amp;gt; и векторы &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;q_0&amp;lt;/math&amp;gt; и &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;q_1&amp;lt;/math&amp;gt;&lt;br /&gt;
* Итерационно для всех &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j=1,...,k&amp;lt;/math&amp;gt;:&lt;br /&gt;
** Вычисляем вспомогательный вектор &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt;, используя умножение матрицы на вектор&lt;br /&gt;
** Вычисляем, используя скалярное произведение векторов, значение &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;\alpha_j&amp;lt;/math&amp;gt; - элемент на главной диагонали трёхдиагональной матрицы &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&amp;lt;/math&amp;gt;&lt;br /&gt;
** Вычисляем по формуле новое значение и перезаписываем вектор &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt;&lt;br /&gt;
** Вычисляем значение &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;\beta_j&amp;lt;/math&amp;gt; - элементы непосредственно над и под главной диагональю той же матрицы &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&amp;lt;/math&amp;gt;&lt;br /&gt;
** Вычисляем, зная вектор &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt;,  очередной столбец матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;Q&amp;lt;/math&amp;gt;, он же вектор Ланцоша : &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;\,\,q_{j+1}&amp;lt;/math&amp;gt;&lt;br /&gt;
** Теперь, когда матрица &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&amp;lt;/math&amp;gt; сформирована на очередном шаге, находим её собственные значения и вектора любым доступным способом, о чём было подробно сказано в пункте 1.2&lt;br /&gt;
** Переходим на следующую итерацию: &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j&amp;lt;/math&amp;gt;++&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
Оценим количество операций и сложность последовательного алгоритма, изложенного в предыдущем разделе.&lt;br /&gt;
*Для вычисления вектора &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt; умножается матрица размера &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;n\times n&amp;lt;/math&amp;gt; на вектор длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt;, и потребуется &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n^2&amp;lt;/math&amp;gt; операций умножения и &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n^2&amp;lt;/math&amp;gt; операций сложения.&lt;br /&gt;
*Умножение векторов &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;q^T_j&amp;lt;/math&amp;gt; и &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt; длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; потребует &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; операций умножения и &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; операций сложения.&lt;br /&gt;
*При вычислении нового значения вектора &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt; поэлементное сложение двух векторов длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; требует &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; операций сложения.&lt;br /&gt;
*Умножение вектора длины &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; на вещественное число требует &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; операций умножения.&lt;br /&gt;
*Нахождение квадратичной нормы вектора &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt;  длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; требует &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; умножений и &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; сложений и ещё 1 операцию извлечения квадратного корня.&lt;br /&gt;
*Заключительное нахождение собственных значений и собственных векторов трёхдиагональной матрицы &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;T_j&amp;lt;/math&amp;gt; размера &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j\times j&amp;lt;/math&amp;gt; с помощью QR-алгоритма потребует в худшем случае &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(j^3)&amp;lt;/math&amp;gt; операций.&amp;lt;ref&amp;gt;http://num-anal.srcc.msu.ru/lib_na/int_ae/int_ae6.htm (пункт 6.2, &amp;quot;Скорость сходимости при этом всегда не хуже квадратичной и почти всегда лучше кубической.&amp;quot;)&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Посчитаем теперь суммарное количество простейших операций на одной итерации алгоритма (без учёта записей в память):&lt;br /&gt;
*&amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n^2+5\,n&amp;lt;/math&amp;gt; операций умножения/деления&lt;br /&gt;
*&amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n^2+4\,n&amp;lt;/math&amp;gt; операций сложения/вычитания&lt;br /&gt;
*1 операция извлечения квадратного корня&amp;lt;br&amp;gt;&lt;br /&gt;
Отдельно после всех итераций при &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j=k&amp;lt;/math&amp;gt; :&lt;br /&gt;
*&amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(k^3)&amp;lt;/math&amp;gt; операций для поиска собственных значений и собственных векторов трёхдиагональной матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_k&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Итого можно утверждать следующее:&lt;br /&gt;
&lt;br /&gt;
Последовательная сложность одной итерации рассматриваемого алгоритма:  &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(n ^ 2) &amp;lt;/math&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Суммарная сложность алгоритма (&amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;/math&amp;gt; итераций): &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(k\,n ^ 2) + O(k ^ 3)&amp;lt;/math&amp;gt; &amp;lt;ref&amp;gt;Здесь мы полагаем, что мы не вычисляем собственные значения и векторы матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_j&amp;lt;/math&amp;gt; на каждом промежуточном шаге, а лишь единожды затрачиваем &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;O(k ^ 3)&amp;lt;/math&amp;gt; действий в конце для нахождения &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;/math&amp;gt; собственных значений и векторов матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_k&amp;lt;/math&amp;gt;&amp;lt;/ref&amp;gt; &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
На практике же обычно рассматривается число &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;&amp;lt;n&amp;lt;/math&amp;gt;, поэтому второе слагаемое можно опустить.&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
На рис. 1 продемонстрирован граф одной итерации (при каком-либо произвольном значении итератора &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j&amp;lt;/math&amp;gt;) описанного алгоритма без отображения входных и выходных данных. Наглядно продемонстрированы связи между всеми действиями, и с помощью деления на &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; потоков показано, какие операции возможно выполнять параллельно на каждом шаге с целью оптимизации и экономии машинного времени. В результате, после параллельно выполненных операций &#039;&#039;&#039;Division&#039;&#039;&#039; на заключительном ярусе, на выходе имеем значение следующего вектора Ланцоша &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;q_{j+1}&amp;lt;/math&amp;gt;, после чего следует переход на следующую итерацию, и процесс повторяется.&lt;br /&gt;
&lt;br /&gt;
[[Файл:Levin_graph.png|600px|thumb|center|Рис. 1]] &amp;lt;br&amp;gt;&lt;br /&gt;
Обозначения на рисунке: &amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Simp&#039;&#039;&#039; (от англ. simple) - операции сложения и умножения вещественных чисел при вычислении произведения матрицы на вектор;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Vec mult&#039;&#039;&#039; (от англ. vectors multiplication) - операция скалярного умножения двух векторов;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Vec subtr&#039;&#039;&#039; (от англ. vectors subtraction, из-за использованных в операции вычитаний векторов) - операция умножения вектора на число (выполняется дважды) и формирование нового значения &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;z_{new}&amp;lt;/math&amp;gt; по формуле: &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;z_{new} = z - \alpha_j q_j - \beta_{j-1}q_{j-1} \;&amp;lt;/math&amp;gt;;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;||\cdot||&amp;lt;/math&amp;gt; - операция вычисления нормы вектора;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Division&#039;&#039;&#039; - операция деления вектора на вещественное число  &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;\beta_j&amp;lt;/math&amp;gt; &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Важно отметить, что упомянутые выше операции также легко поддаются оптимизации. Например, попарные умножения вещественных координат векторов при вычислении скалярного произведения также легко выполняются параллельно на &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; потоках, а затем можно применить суммирование методом сдваивания, о котором сказано в следующем разделе. Умножение или деление вектора на вещественное число являющееся, по определению, умножением или делением всех его координат на это число тоже может быть выполнено эффективнее, если мы используем &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; потоков, а не выполняем эти действия последовательно.&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
Параллельные операции возможны только внутри итераций, так как рассматриваемый алгоритм является итерационным, и сами итерации строго последовательны.&amp;lt;br&amp;gt;&lt;br /&gt;
Рассмотрим в этом разделе подробнее, какой выигрыш мы можем получить при распараллеливании операций внутри одной итерации согласно графу из предыдущего раздела.&lt;br /&gt;
&lt;br /&gt;
Умножение вещественной симметричной матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; размера &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;n\times n&amp;lt;/math&amp;gt; на вектор &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;b&amp;lt;/math&amp;gt; длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; требует последовательного выполнения &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; ярусов умножений и сложений. Сложение элементов вектора длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; на каждом шаге перемножения можно оптимизировать и выполнить за &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;\log_2 n&amp;lt;/math&amp;gt; действий, если применять метод сдваивания.&lt;br /&gt;
&lt;br /&gt;
Дальнейшие операции выполняются последовательно, а вычисление значений векторов происходит за один ярус операций сложения или умножения.&lt;br /&gt;
&lt;br /&gt;
Ресурс параллелизма алгоритма вычисления собственных значений построенной трёхдиагональной матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_k&amp;lt;/math&amp;gt; размера &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k\times k&amp;lt;/math&amp;gt; зависит от выбранного алгоритма (об этих алгоритмах подробнее было сказано в разделах 1.2 и 1.4). Будет очень затратно с точки зрения объёма материала пытаться рассмотреть пусть даже часть этих методов в этой статье, а так же тонкости их распараллеливания. Предлагаем читателям при желании самим ознакомиться с этими алгоритмами на данном ресурсе или прибегнув к иным источникам.&lt;br /&gt;
&lt;br /&gt;
При классификации по высоте ЯПФ, таким образом, алгоритм Ланцоша без переортогонализации относится к алгоритмам с &#039;&#039;логарифмической сложностью&#039;&#039;, и его сложность равна &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(\log_2 n)&amp;lt;/math&amp;gt; с важным замечанием, что это сложность только одной итерации, а максимум в алгоритме может быть выполнено последовательно &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;/math&amp;gt; таких однотипных итераций, если не будет осуществлён ранний выход из цикла. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Несмотря на то, что на графе в предыдущем разделе для лучшей визуализации и понимания было изображено &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; потоков (никаких допущений мы не делали и нарушений с точки зрения логики и математики нет, можно изобразить большее число потоков, просто часть времени некоторые из них могут бездействовать и не использоваться), на самом деле правильным и разумным будет реализовать начальное параллельное выполнение &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n^2&amp;lt;/math&amp;gt; операций умножения всех вещественных элементов матрицы &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;A&amp;lt;/math&amp;gt; на соответствующие элементы вектора &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;q_j&amp;lt;/math&amp;gt;, после чего применять тот же самый упомянутый метод сдваивания. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Поэтому при классификации по ширине ЯПФ его сложность будет &#039;&#039;квадратичной&#039;&#039; и равна &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(n^2)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
&#039;&#039;&#039;Входные данные алгоритма:&#039;&#039;&#039; вещественная симметричная &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; размера &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;n\times n&amp;lt;/math&amp;gt;, вещественный вектор &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;b&amp;lt;/math&amp;gt; длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt;, и одно целое число &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;k&amp;lt;/math&amp;gt;, означающее количество итераций.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём входных данных:&#039;&#039;&#039; &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;n^2 +n + 1 &amp;lt;/math&amp;gt;. Если учесть, что матрица симметричная и достаточно для её однозначного определения задать элементы на главной диагонали и элементы над или под ней, то можно сократить объём входных данных с целью экономии памяти до: &amp;lt;math&amp;gt;\ \frac{n^2-n}{2}+n+n+1 =\frac{n^2+3n}{2} + 1&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные алгоритма:&#039;&#039;&#039; вектор собственных значений &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;\Theta^k&amp;lt;/math&amp;gt; длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;/math&amp;gt;, матрица &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;S^k&amp;lt;/math&amp;gt; из соответствующих собственных векторов размера &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n\times k&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём выходных данных:&#039;&#039;&#039; &amp;lt;math&amp;gt;k\;(n + 1)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
В данном разделе перечислены без какой-либо хронологии или связи друг с другом наиболее важные и разнообразные свойства алгоритма, на которые стоит и полезно обратить внимание, а также которые выгодно отличают его от схожих алгоритмов, решающих ту же задачу.&amp;lt;br&amp;gt;&lt;br /&gt;
1) Отношение последовательной сложности алгоритма к параллельной,с учётом &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;/math&amp;gt; итераций, равно &amp;lt;math&amp;gt;\;\;\frac{kn^2}{k \log_2{n}}=\frac{n^2}{\log_2{n}}&amp;lt;/math&amp;gt;;&amp;lt;br&amp;gt;&lt;br /&gt;
2) Вычислительная мощность алгоритма, как отношение числа операций к суммарному объему входных и выходных данных, равна &amp;lt;math style=&amp;quot;vertical-align:-70%&amp;gt;\;\;\frac{k\,n^2}{0.5\,n^2+1.5\,n+k\,n+k+1}&amp;lt;/math&amp;gt; и &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;\approx 2\,k&amp;lt;/math&amp;gt;, так как на практике верно отношение &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;&amp;lt;n&amp;lt;/math&amp;gt; ;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
3) Для собственных значений формируемых матриц &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_j&amp;lt;/math&amp;gt; верно отношение (следствие теоремы Коши о перемежаемости): &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;\lambda_i(T_{k+1})\geq \lambda_i(T_{k})\geq \lambda_{i+1}(T_{k+1})\geq \lambda_{i+1}(T_{k})&amp;lt;/math&amp;gt; ;&amp;lt;ref&amp;gt;James W. Demmel - Вычислительная линейная алгебра. Теория и приложения //Мир. - 2001 (c. 383)&amp;lt;/ref&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
4) Крайние (наибольшие и наименьшие) собственные значения матриц &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_j&amp;lt;/math&amp;gt; сходятся к крайним собственным значениям матрицы &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;A&amp;lt;/math&amp;gt; первыми (это часто происходит уже на ранних шагах при &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j\approx 2\,\sqrt{n}&amp;lt;/math&amp;gt;&amp;lt;ref&amp;gt;http://num-anal.srcc.msu.ru/lib_na/int_ae/int_ae6.htm (пункт 6.5)&amp;lt;/ref&amp;gt;), а собственные значения в середине спектра - последними;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
5) Из-за ограниченной точности постепенно теряется ортогональность вектора Ланцоша &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;q_j&amp;lt;/math&amp;gt; к предыдущим векторам Ланцоша, поэтому необходимо примерно каждые 10-15 итераций проводить дорогостоящую операцию реортогонализации, но это уже будет иной алгоритм с очень малым различием в одной операции и в программном коде, реализующем его, соответственно; &amp;lt;ref&amp;gt;Sam Handler - The Lanczos Algorithm For Large-Scale Eigenvalue Problems (08.01.07), slide №8&amp;lt;/ref&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
6) Эффективность и быстрота выполнения алгоритма очень сильно зависит от скорости памяти (диска). Согласно тесту только &#039;&#039;6%&#039;&#039; времени работы программы приходится на вычисления, остальное время затрачивается на ожидание отклика диска;&amp;lt;ref&amp;gt;Sam Handler - The Lanczos Algorithm For Large-Scale Eigenvalue Problems (08.01.07), slide №10&amp;lt;/ref&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
7) Метод Ланцоша удобен тем, что не требует хранения исходной матрицы полным массивом: метод использует исходную матрицу только в операциях умножения матрицы на вектор, что позволяет эффективно использовать разреженность матрицы или регулярность структуры матрицы. Поэтому метод Ланцоша может быть использован для матриц таких больших порядков, когда методы вращений и отражений не могут быть применены.&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;
Для исследования масштабируемости рассматриваемого алгоритма Ланцоша без переортогонализации автором была реализована программа на языке С++ с использованием технологии MPI (&#039;&#039;&#039;не забыть вставить ссылку на код&#039;&#039;&#039;). Дальнейшее исследование выполнялось на суперкомпьютере &amp;quot;Ломоносов&amp;quot; Суперкомпьютерного комплекса МГУ. Важно отметить, что реализованная программа выполняет только первую часть алгоритма - формирование матрицы &amp;lt;math &amp;gt;T_j&amp;lt;/math&amp;gt;. Вторая часть алгоритма - задача поиска её собственных значений может быть решена несколькими методами, каждый из которых обладает своей эффективностью распараллеливании и характерными свойствами. Подробно этот вопрос уже обсуждался в статье раннее, поэтому не будем ещё раз заострять на этом внимание и останавливаться.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Сборка осуществлялась со следующими параметрами:&lt;br /&gt;
* Компилятор intel/15.0.090 &lt;br /&gt;
* Openmpi/1.8.4-icc&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
В серии проведённых расчётов рассматривались следующие числовые значения параметров:&lt;br /&gt;
* Размер задачи и, соответственно, матрицы А, задействованной в операции умножения на вектор: [2000 : 30000] с шагом 100&lt;br /&gt;
* Число процессоров: 1,2,4,16,32,48,64,96,128&lt;br /&gt;
* Число итераций: &amp;lt;math&amp;gt;k=350&amp;lt;/math&amp;gt; . Взято таким вопреки информации выше, где говорится, что значение &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; редко превышает &amp;lt;math&amp;gt;10^2&amp;lt;/math&amp;gt;. Сделано это исключительно для лучшей визуализации пиков на графиках и наглядности получаемых результатов, так как при меньших на порядок значениях &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; времена выполнения программ были слишком малы даже при минимальных числах процессоров и максимальных размерах исходной задачи.&lt;br /&gt;
&lt;br /&gt;
== Динамические характеристики и эффективность реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Выводы для классов архитектур ==&lt;br /&gt;
По заданию, во второй части требовалось описать только разделы 2.4 и 2.7, прошу не спрашивать с меня все разделы 2.1-2.6. Надеюсь на понимание, мне физически не хватает времени на это задание + 2 других в течение семестра, делаю всё, что в моих силах :)&lt;br /&gt;
&lt;br /&gt;
== Существующие реализации алгоритма ==&lt;br /&gt;
Несмотря на то, что алгоритм является далеко не самым популярным, алгоритмом, про который нельзя сказать, что он всегда «на слуху», на сегодняшний день существует множество реализаций на различных популярных языках.&amp;lt;br&amp;gt;&lt;br /&gt;
Перечислим далее некоторые из них, указывая язык программирования, лежащий в их основе, и некоторые важные характеристики, которые обсуждались в статье ранее:&lt;br /&gt;
*&#039;&#039;Code on netlib.org by Jane Cullum and Ralph Willoughby&#039;&#039; (&#039;&#039;&#039;Fortran 77&#039;&#039;&#039;; без реортогонализации векторов; без реализации распараллеливания)&amp;lt;ref&amp;gt;http://www.netlib.org/lanczos/leval&amp;lt;/ref&amp;gt;&lt;br /&gt;
*&#039;&#039;Lanczos algorithm on freesourcecode.net&#039;&#039; (&#039;&#039;&#039;Matlab&#039;&#039;&#039;; присутствует реортогонализация векторов; без реализации распараллеливания)&amp;lt;ref&amp;gt;http://freesourcecode.net/matlabprojects/61741/lanczos-algorithm--in-matlab&amp;lt;/ref&amp;gt;&lt;br /&gt;
*&#039;&#039;Lanczos for eigenvalues in Numerical Linear Algebra, Spring 2007&#039;&#039; (&#039;&#039;&#039;Matlab&#039;&#039;&#039;; частичная или полная реортогонализация - доступны оба варианта; без реализации распараллеливания)&amp;lt;ref&amp;gt;Ссылки на файлы lanso.m и lanfu.m можно найти на https://www.nada.kth.se/~ruhe/2D5219/labs2007.html&amp;lt;/ref&amp;gt;&lt;br /&gt;
*&#039;&#039;Planso&#039;&#039; (название происходит от parallel Lanso.f) &#039;&#039;code by Kesheng Wu and Horst D. Simon&#039;&#039; (&#039;&#039;&#039;Fortran 77&#039;&#039;&#039;; частичная реортогонализация векторов; использование MPI для коммуникаций)&amp;lt;ref&amp;gt;https://github.com/jiahao/planso.jl/tree/master/external/PLAN/plan К сожалению, ссылка в описании пакета на github, ведущая на сайт National Energy Research Scientific Computing Center (NERSC), с более подробной информацией о данной программе больше не активна и выдаёт результат &#039;&#039;Page not found&#039;&#039;&amp;lt;/ref&amp;gt; &lt;br /&gt;
* &#039;&#039;Lanczos.cpp in the Vienna Computing Library&#039;&#039;  (&#039;&#039;&#039;C++&#039;&#039;&#039;, частичная реортогонализация, без реализации распараллеливания) &amp;lt;ref&amp;gt;http://viennacl.sourceforge.net/doc/lanczos_8cpp_source.html&amp;lt;/ref&amp;gt;&lt;br /&gt;
* &#039;&#039;Parallel Eigen Values code using C++ AMP on microsoft msdn blog&#039;&#039; (&#039;&#039;&#039;C++&#039;&#039;&#039;; ? ; распараллеливание есть и реализовано через C++ AMP) &amp;lt;ref&amp;gt;https://blogs.msdn.microsoft.com/nativeconcurrency/2013/12/20/eigen-values/ Подробнее о C++ Accelerated Massive Parallelism можно почитать здесь: https://msdn.microsoft.com/ru-ru/library/hh265137(v=vs.140).aspx или здесь: http://professorweb.ru/my/csharp/optimization/level4/4_6.php &amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;br /&gt;
[[en:Description of algorithm properties and structure]]&lt;/div&gt;</summary>
		<author><name>AleksLevin</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:AleksLevin/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%9B%D0%B0%D0%BD%D1%86%D0%BE%D1%88%D0%B0_%D0%B2%D1%8B%D1%87%D0%B8%D1%81%D0%BB%D0%B5%D0%BD%D0%B8%D1%8F_%D1%81%D0%BE%D0%B1%D1%81%D1%82%D0%B2%D0%B5%D0%BD%D0%BD%D1%8B%D1%85_%D0%B7%D0%BD%D0%B0%D1%87%D0%B5%D0%BD%D0%B8%D0%B9_%D1%81%D0%B8%D0%BC%D0%BC%D0%B5%D1%82%D1%80%D0%B8%D1%87%D0%BD%D0%BE%D0%B9_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86%D1%8B_%D0%B4%D0%BB%D1%8F_%D1%82%D0%BE%D1%87%D0%BD%D0%BE%D0%B9_%D0%B0%D1%80%D0%B8%D1%84%D0%BC%D0%B5%D1%82%D0%B8%D0%BA%D0%B8_(%D0%B1%D0%B5%D0%B7_%D0%BF%D0%B5%D1%80%D0%B5%D0%BE%D1%80%D1%82%D0%BE%D0%B3%D0%BE%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D0%B8)&amp;diff=19952</id>
		<title>Участник:AleksLevin/Алгоритм Ланцоша вычисления собственных значений симметричной матрицы для точной арифметики (без переортогонализации)</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:AleksLevin/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%9B%D0%B0%D0%BD%D1%86%D0%BE%D1%88%D0%B0_%D0%B2%D1%8B%D1%87%D0%B8%D1%81%D0%BB%D0%B5%D0%BD%D0%B8%D1%8F_%D1%81%D0%BE%D0%B1%D1%81%D1%82%D0%B2%D0%B5%D0%BD%D0%BD%D1%8B%D1%85_%D0%B7%D0%BD%D0%B0%D1%87%D0%B5%D0%BD%D0%B8%D0%B9_%D1%81%D0%B8%D0%BC%D0%BC%D0%B5%D1%82%D1%80%D0%B8%D1%87%D0%BD%D0%BE%D0%B9_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86%D1%8B_%D0%B4%D0%BB%D1%8F_%D1%82%D0%BE%D1%87%D0%BD%D0%BE%D0%B9_%D0%B0%D1%80%D0%B8%D1%84%D0%BC%D0%B5%D1%82%D0%B8%D0%BA%D0%B8_(%D0%B1%D0%B5%D0%B7_%D0%BF%D0%B5%D1%80%D0%B5%D0%BE%D1%80%D1%82%D0%BE%D0%B3%D0%BE%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D0%B8)&amp;diff=19952"/>
		<updated>2016-12-02T19:29:54Z</updated>

		<summary type="html">&lt;p&gt;AleksLevin: /* Математическое описание алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Основные авторы описания: Левин А.Д.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{algorithm&lt;br /&gt;
| name              = Алгоритм Ланцоша для точной арифметики (без переортогонализации)&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(k\,n^2)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(k\log_2 n)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;\frac{n^2+3n}{2} + 1&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;k\;(n + 1)&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритмов =&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Данный алгоритм появился в 1950 г. и носит имя венгерского физика и математика Корнелия Ланцоша (венг. Lánczos Kornél). Алгоритм Ланцоша относится к итерационным методам вычисления собственных значений для матриц столь больших порядков &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt; n&amp;lt;/math&amp;gt;, что к ним нельзя применить прямые методы из-за ограничений по времени и памяти.&lt;br /&gt;
&lt;br /&gt;
Сам Ланцош указывал, что его метод предназначен для отыскания нескольких собственных векторов симметричных матриц, хотя к методу сразу было обращено внимание, как к способу приведения всей матрицы к трёхдиагональному виду. Двадцатью годами позже канадский математик Крис Пэж показал, что, несмотря на чувствительность к округлениям, алгоритм Ланцоша - эффективное средство вычисления некоторых &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; собственных чисел и соответствующих им собственных векторов. &amp;lt;ref&amp;gt;Парлетт Б. - Симметричная проблема собственных значений. Численные методы //М.: Мир. - 1983. (c. 276)&amp;lt;/ref&amp;gt;&lt;br /&gt;
Обычно число &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; берут в два раза больше, чем количество собственных значений матрицы, которые поставлена цель найти, и оно имеет порядок не более &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;10^2&amp;lt;/math&amp;gt;.&amp;lt;ref&amp;gt;Susan W. Bostic - Lanczos Eigensolution Method for High-Perfomance Computers, page 7&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Алгоритм Ланцоша для вычисления собственных значений симметричной матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; соединяет в себе метод Ланцоша для построения последовательности подпространств Крылова и ортонормированных векторов Ланцоша и процедуру Рэлея-Ритца получения оптимальных приближений собственных значений и соответствующих собственных векторов исходной матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt;.&amp;lt;ref&amp;gt;James W. Demmel - Вычислительная линейная алгебра. Теория и приложения //Мир. - 2001 (c. 381)&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
В данной статье рассматривается вариант алгоритма Ланцоша, в котором опущено влияние ошибок округления на вычислительный процесс, хотя на практике этому посвящается отдельное внимание и существуют различные методы решения данной проблемы, такие как частичная или полная переортогонализация. Этим модифицированным методам посвящены отдельные статьи на данном ресурсе.&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
Обозначения и формулы, используемые в данном разделе, взяты из литературы, указанной по ссылке.&amp;lt;ref&amp;gt;James W. Demmel - Вычислительная линейная алгебра. Теория и приложения //Мир. - 2001 (c. 313, &#039;&#039;&amp;lt;math&amp;gt; \S &amp;lt;/math&amp;gt; 6.6 Методы Крыловского подпространства&#039;&#039;)&amp;lt;/ref&amp;gt; &lt;br /&gt;
&lt;br /&gt;
Алгоритм Ланцоша для вычисления &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; собственных значений и собственных векторов вещественной симметричной матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A=A^T&amp;lt;/math&amp;gt; в точной арифметике: &amp;lt;ref&amp;gt;James W. Demmel - Вычислительная линейная алгебра. Теория и приложения //Мир. - 2001 (c. 381)&amp;lt;/ref&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{align}&lt;br /&gt;
q_1 = &amp;amp; \,\frac{b}{\|b\|_2},\; \beta_0 = 0,\; q_0 = 0\\&lt;br /&gt;
\mathbf{for} \; &amp;amp; j = 1 \; to \; k \,\; \mathbf{do} \\&lt;br /&gt;
&amp;amp; z = A\,q_j\\&lt;br /&gt;
&amp;amp; \alpha_j = q^T_j z\\&lt;br /&gt;
&amp;amp; z = z - \alpha_j q_j - \beta_{j-1}q_{j-1}\\&lt;br /&gt;
&amp;amp; \beta_j = \|z\|_2\\&lt;br /&gt;
&amp;amp; \mathbf{If} \; (\beta_j == 0) \; \mathbf{then}\; stop\; the\; algorithm \\ &lt;br /&gt;
&amp;amp; \;  q_{j+1} = \frac{z}{\beta_j} \\&lt;br /&gt;
&amp;amp; compute\; eigenvalues\; and \;eigenvectors\;of \;matrix \;\;T_j= Q^T_j A Q\;\;and\;estimate \;the\; errors\\&lt;br /&gt;
\mathbf{end} \; &amp;amp; \mathbf{for}&lt;br /&gt;
\end{align}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
В продемонстрированном выше алгоритме &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;b&amp;lt;/math&amp;gt; - заданный вещественный вектор. Также полагается известным алгоритм вычисления произведения матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; на вектор &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;x&amp;lt;/math&amp;gt;. &lt;br /&gt;
Введём матрицу Крылова, определяемую следующим соотношением: &amp;lt;math&amp;gt;K_j = [b,Ab,A^2b,...,A^{j-1}b]&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Далее, на практике, матрица &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;K&amp;lt;/math&amp;gt; заменяется матрицей &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;Q&amp;lt;/math&amp;gt;, такой, что при любом числе &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; линейные оболочки первых &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; столбцов в &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;K&amp;lt;/math&amp;gt; и &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;Q&amp;lt;/math&amp;gt; являются одним и тем же подпространством.&amp;lt;ref&amp;gt;James W. Demmel - Вычислительная линейная алгебра. Теория и приложения //Мир. - 2001 (c. 315)&amp;lt;/ref&amp;gt; &lt;br /&gt;
Тогда матрица &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;Q&amp;lt;/math&amp;gt;, в отличие от матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;K&amp;lt;/math&amp;gt;, хорошо обусловлена и легко обратима. В результате получаем матрицу &amp;lt;math&amp;gt;Q_j = [q_1, q_2, \dots, q_j]&amp;lt;/math&amp;gt; размерности &amp;lt;math&amp;gt;n\times j&amp;lt;/math&amp;gt;, столбцы которой ортогональны, являются базисом подпространства Крылова и называются векторами Ланцоша.&lt;br /&gt;
&lt;br /&gt;
В алгоритме Ланцоша вычислению подлежит столько первых столбцов в матрице &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;Q_j&amp;lt;/math&amp;gt;, сколько необходимо для получения требуемого приближения к решению &amp;lt;math&amp;gt;A\,x\,=b\,\,(A\,x=\lambda \, x)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Получение нулевого &amp;lt;math&amp;gt;\beta_j&amp;lt;/math&amp;gt; в итерационном процессе - событие, желательное в том смысле, что оно свидетельствует о том, что найдено некоторое подпространство, являющееся в точности инвариантным, а все собственные значения матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;T_j&amp;lt;/math&amp;gt; являются собственными значениями матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt;. На практике же нулевое и близкие к нулю значения получаются редко.&amp;lt;ref&amp;gt;Голуб Дж., Ван Лоун Ч. - Матричные вычисления//М.: Мир. - 1999 (c. 429)&amp;lt;/ref&amp;gt; &lt;br /&gt;
&lt;br /&gt;
Затем на каждом шаге цикла формируется симметричная трёхдиагональная матрица &amp;lt;math&amp;gt;T_j = Q^T_j A Q&amp;lt;/math&amp;gt;, к которой применяется процесс Рэлея-Ритца для поиска её собственных значений (на практике для поиска этих собственных значений можно использовать любой из специальных методов в параграфе книги по ссылке).&amp;lt;ref&amp;gt;Голуб Дж., Ван Лоун Ч. - Матричные вычисления//М.: Мир. - 1999 (&amp;lt;math&amp;gt;\S&amp;lt;/math&amp;gt; 8.4)&amp;lt;/ref&amp;gt;  &lt;br /&gt;
Эти собственные значения, они же числа Ритца, и полагаются приближёнными собственными значениями исходной матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt;.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Существует множество методов для отыскания собственных значений вещественной симметричной трехдиагональной матрицы. Большинство из них требует &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt; операций &amp;lt;ref&amp;gt;Парлетт Б. Симметричная проблема собственных значений. Численные методы.,: Мир, 1983. с. 179-182&amp;lt;/ref&amp;gt;, но существуют и быстрые алгоритмы, требующие лишь &amp;lt;math&amp;gt;O(n\ln n)&amp;lt;/math&amp;gt; операций.&amp;lt;ref&amp;gt;https://en.wikipedia.org/wiki/Tridiagonal_matrix#Eigenvalues  Раздел eigenvalues&amp;lt;/ref&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Одним из возможных способов отыскать собственные значения симметричной трехдиагональной матрицы - прямое вычисление корней характеристического полинома &amp;lt;math&amp;gt;p_n(\lambda)&amp;lt;/math&amp;gt; через метод деления пополам, где формируется последовательность Штурма и локализуются собственные числа, являющиеся корнями характеристического полинома. Нахождение всех &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; собственных значений матрицы этим способом требует &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;2n^2t&amp;lt;/math&amp;gt; умножений и вычитаний, где &amp;lt;math&amp;gt;t&amp;lt;/math&amp;gt; - число сделанных шагов с применением метода деления пополам.&amp;lt;ref&amp;gt;Уилкинсон Дж. X. Алгебраическая проблема собственныx значений. Изд-во &amp;quot;Наука&amp;quot;, 1970. - глава 5, с. 272-278&amp;lt;/ref&amp;gt; Соответствующие собственные вектора могут быть найдены посредством обратных итераций за &amp;lt;math&amp;gt; O(n) &amp;lt;/math&amp;gt; флопов. &amp;lt;ref&amp;gt;Голуб Дж., Ван Лоун Ч. - Матричные вычисления//М.: Мир. - 1999 (c. 394-395)&amp;lt;/ref&amp;gt; &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;На практике, если требуется только небольшая часть от всей совокупности собственных векторов и значений, и матрица имеет Хессенбергову или трёхдиагональную форму, очень эффективными будут методы факторизации, как, например, QR-алгоритм или QL-алгоритм со сдвигами (c целью ускорить алгоритм и сделать порядок сходимости квадратичным) или же без них.&amp;lt;ref&amp;gt;http://algorithm.narod.ru/ln/eigen/ETridiag.html&amp;lt;/ref&amp;gt; &amp;lt;br&amp;gt;&lt;br /&gt;
Весьма молодые и не менее актуальные конкуренты QR и QL алгоритмов, применяющиеся для поиска собственных значений:&lt;br /&gt;
*Методы divide-and-conquer (разделяй и властвуй), появившиеся в 1980-ых годах &amp;lt;ref&amp;gt;https://goo.gl/dapvbn ссылку пришлось сократить с помощью Google url shortener, так как символы подчеркивания портили её и не давали перейти по 1 клику&amp;lt;/ref&amp;gt;&lt;br /&gt;
*Relatively robust representation методы, появившиеся в 1990-ых и позволяющие найти собственные числа симметричной матрицы порядка &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;n&amp;lt;/math&amp;gt; за &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt; операций&lt;br /&gt;
&lt;br /&gt;
Если требуется вычислить собственные векторы, то необходимо хранить вычисляемые векторы Ланцоша. Если работа при этом производится только с оперативной памятью, то при большом порядке исходной матрицы (а именно для таких матриц и предназначен метод Ланцоша) число шагов  &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;j&amp;lt;/math&amp;gt;, которые могут быть выполнены до того момента, как оперативная память будет исчерпана, будет очень незначительно, а следовательно, искомые собственные пары могут не успеть сойтись с требуемой точностью. В этом случае метод Ланцоша можно использовать итерационным образом: после выполнения заданного числа шагов процесс прерывается и, если еще не все требуемые пары Ритца сошлись с требуемой точностью, то формируется новый начальный вектор &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;q_1&amp;lt;/math&amp;gt;, являющийся линейной комбинацией векторов Ритца, еще не сошедшихся с заданной точностью, и процесс начинается заново.&amp;lt;ref&amp;gt;http://num-anal.srcc.msu.ru/lib_na/int_ae/int_ae6.htm (пункт 6.5)&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
Вычислительное ядро рассматриваемого алгоритма (наиболее ресурсно-затратная часть алгоритма) -  формирование на каждом шаге цикла промежуточного вектора &amp;lt;math&amp;gt;z&amp;lt;/math&amp;gt;, вычисляемого по формуле: &amp;lt;math&amp;gt;z = A\,q_j&amp;lt;/math&amp;gt;. Данная операция, по сравнению с другими операциями алгоритма, затратна и требовательна, как с точки зрения количества производимых операций, так и с точки зрения объема оперируемых данных. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Например, умножение матрицы размера &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;n\times n&amp;lt;/math&amp;gt; на вектор длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; требует: &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;n^2+(n-1)n = 2n^2-n&amp;lt;/math&amp;gt; операций умножения и сложения. В свою очередь аналогичная операция умножения матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;(n+1)\times (n+1)&amp;lt;/math&amp;gt; на вектор длины &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;(n+1)&amp;lt;/math&amp;gt; требует: &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;2n^2+3n+1&amp;lt;/math&amp;gt;  операций умножения и сложения. То есть повышение размерности задачи всего на 1 увеличивает число необходимых действий в этом шаге алгоритма на: &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;4n+1&amp;lt;/math&amp;gt;. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Так же, стоит помнить, что, согласно разделу 1.2, данную операцию умножения матрицы на вектор необходимо выполнить &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;k&amp;lt;/math&amp;gt; раз. Нетрудно понять, насколько возрастает и колоссален масштаб операций, если в задачах, где критична точность, размерности &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; могут иметь порядок &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;10^5&amp;lt;/math&amp;gt; или даже более.&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
Как уже было упомянуто в данной статье в описании алгоритма, рассматриваемый алгоритм состоит из двух последовательно выполненных алгоритмов: метод Ланцоша для построения последовательности подпространств Крылова и ортонормированных векторов Ланцоша и процедура Рэлея-Ритца получения оптимальных приближений собственных значений и соответствующих собственных векторов исходной матрицы.&lt;br /&gt;
&lt;br /&gt;
В первой части алгоритма, где итерационно строятся Крыловское подпространство и трёхдиагональная матрица &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&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 style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; разреженная. Именно она подлежит оптимизации с использованием техник распараллеливания, поскольку она является вычислительным ядром алгоритма, а весь упомянутый процесс построения матрицы &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&amp;lt;/math&amp;gt; выполняется последовательно.&lt;br /&gt;
&lt;br /&gt;
Рассмотрим вторую часть алгоритма - поиск собственных значений сформированной матрицы &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&amp;lt;/math&amp;gt;.&amp;lt;br&amp;gt;&lt;br /&gt;
Далее, наглядно, в виде псевдокода, представлен, упомянутый в разделе 1.2, QR-алгоритм (аналогично можно рассмотреть и QL-алгоритм) со сдвигами Релэя, который весьма популярен на практике.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{align}&lt;br /&gt;
\mathbf{Input}: \;&amp;amp;tridiagonal\;\;matrix \;T\;with\;\;n\times n\;\;size\\&lt;br /&gt;
T^{(0)}&amp;amp;:=T\\&lt;br /&gt;
\mathbf{for}&amp;amp; \;\;m=n,...,2 \;\; \mathbf{do}\\&lt;br /&gt;
&amp;amp;k=0\\&lt;br /&gt;
&amp;amp; \mathbf{repeat}\\&lt;br /&gt;
&amp;amp; \quad \;\; k=k+1\\&lt;br /&gt;
&amp;amp; \quad \;\; \mu^{(k)}=T_{m,m}^{(k-1)}\\&lt;br /&gt;
&amp;amp; \quad \;\; Q^{(k)}R^{(k)}=T^{(k-1)}-\mu^{(k)}I\;\;using\;\;QR\;decomposition\\&lt;br /&gt;
&amp;amp; \quad \;\; T^{(k)}=R^{(k)}Q^{(k)}+\mu^{(k)}I\\&lt;br /&gt;
&amp;amp; \mathbf{until} \;\;\; |T_{m,m-1}^{(k)}| \;is\;\;small\;\;enough\\&lt;br /&gt;
&amp;amp; Save  \;\;T_{m,m}^{(k)} \;\;as\;\; converged\;\;eigenvalue\;of\;T\\ &lt;br /&gt;
&amp;amp; Remove \;\boldsymbol{n}\,th\;row\;and\;\boldsymbol{n}\,th\;column\;\;from \;T \\&lt;br /&gt;
&amp;amp; and\;take\;this\;new\;cropped\;matrix\;as\;new\;T^{(0)}\;with\;\;(n-1)\times (n-1)\;\;size\\&lt;br /&gt;
 \mathbf{end}&amp;amp;\; \mathbf{for}&lt;br /&gt;
\end{align}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Малость наддиагональных и поддиагональных элементов матрицы (фраза &#039;&#039;&amp;quot;small enough&amp;quot;&#039;&#039; в псевдокоде) подразумевает:&lt;br /&gt;
&amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt; |T_{m,m-1}^{(k)}| \leq \varepsilon\,|T_{m,m}^{(k)}| \quad\quad &amp;lt;/math&amp;gt; , где &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt; \varepsilon &amp;lt;/math&amp;gt; - заданная точность&amp;lt;br&amp;gt;&lt;br /&gt;
Также вместо сдвига Релэя, обозначенного в алгоритме через &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;\mu^{(k)}&amp;lt;/math&amp;gt;, часто на практике используется сдвиг по Уилкинсону, который даёт гарантированную сходимость внедиагональных элементов матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt; T^{(k)} &amp;lt;/math&amp;gt;, формируемой на каждом шаге, к нулю, при этом жертвуя монотонностью их убывания.&amp;lt;ref&amp;gt;Голуб Дж., Ван Лоун Ч. - Матричные вычисления//М.: Мир. - 1999 (c. 378, вторая половина страницы)&amp;lt;/ref&amp;gt;&amp;lt;ref&amp;gt;Парлетт Б. Симметричная проблема собственных значений. Численные методы.,: Мир, 1983. с. 169&amp;lt;/ref&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Подробнее с различными сдвигами и соответствующими оценками скоростей и количествами операций можно ознакомиться по указанной ссылке:&amp;lt;ref&amp;gt;Парлетт Б. Симметричная проблема собственных значений. Численные методы.,: Мир, 1983. с. 179-182&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;Для совершения QR-декомпозиции на каждом шаге может использоваться любой из алгоритмов по ссылке.&amp;lt;ref&amp;gt;https://en.wikipedia.org/wiki/QR_decomposition&amp;lt;/ref&amp;gt; Подробные описания этих алгоритмов также доступны на данном ресурсе algowiki-project.&amp;lt;br&amp;gt;&lt;br /&gt;
Так как мы оперируем не обычной матрицей и даже не Хессенберговой, а симметричной и трёхдиагональной, то скорость таких алгоритмов значительно возрастёт. Например, согласно данному ресурсу &amp;lt;ref&amp;gt;http://algorithm.narod.ru/ln/eigen/ETridiag.html&amp;lt;/ref&amp;gt;, для QL-алгоритма с неявными сдвигами:&amp;lt;br&amp;gt;&lt;br /&gt;
Для трёхдиагональной матрицы объем арифметических действий составляет &amp;lt;math&amp;gt; O(n)&amp;lt;/math&amp;gt; на одну итерацию вместо &amp;lt;math&amp;gt; O(n^3)&amp;lt;/math&amp;gt; для матрицы общего вида, а число итераций для нахождения первых собственных значений примерно равно 4 - 5. Но на этих итерациях также уменьшаются внедиагональные элементы правого нижнего угла. И, таким образом, дальнейшие собственные значения ищутся значительно быстрее. Среднее число итераций на каждое собственное значение обычно составляет 1.3 - 1.6.&amp;lt;br&amp;gt; &lt;br /&gt;
Аналогично QL, QR-разложение трёхдиагольной матрицы также требует &amp;lt;math&amp;gt; O(n)&amp;lt;/math&amp;gt; флопов&amp;lt;ref&amp;gt;Голуб Дж., Ван Лоун Ч. - Матричные вычисления//М.: Мир. - 1999 (c. 378, начало раздела 8.2.2)&amp;lt;/ref&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Подводя итог, во второй части алгоритма Ланцоша можно выделить следующие макрооперации:&lt;br /&gt;
* умножение матрицы на вещественное число;&lt;br /&gt;
* перемножение матриц;&lt;br /&gt;
* умножение и сравнение вещественных чисел;&lt;br /&gt;
* + набор других макроопераций в зависимости от выбора метода, с помощью которого будет совершаться сама QR или QL-декомпозиция (выше продемонстрированы, уже, как минимум, 3 разных способа).&lt;br /&gt;
Так же, важно заметить, что набор макропераций может быть несколько другим, если выбрать какой-либо иной современный метод поиска собственных чисел трёхдиагональной матрицы, не использующий QR и QL разложения(факторизацию). Два таких метода были упомянуты в пункте 1.2.&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
С целью полностью не дублировать раздел 1.2 данной статьи, где представлен наглядный и доступный для понимания псевдокод алгоритма, постараемся лишь коротко просуммировать и обобщить весь перечень последовательных действий в рассматриваемом алгоритме.&lt;br /&gt;
&lt;br /&gt;
В качестве входных данных имеем: вещественная симметричная матрица &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; размера &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;n\times n&amp;lt;/math&amp;gt;, известный вещественный вектор &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;b&amp;lt;/math&amp;gt; длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; и число &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;n&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Далее:&lt;br /&gt;
* Инициализируем вещественную константу &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;\beta_0&amp;lt;/math&amp;gt; и векторы &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;q_0&amp;lt;/math&amp;gt; и &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;q_1&amp;lt;/math&amp;gt;&lt;br /&gt;
* Итерационно для всех &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j=1,...,k&amp;lt;/math&amp;gt;:&lt;br /&gt;
** Вычисляем вспомогательный вектор &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt;, используя умножение матрицы на вектор&lt;br /&gt;
** Вычисляем, используя скалярное произведение векторов, значение &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;\alpha_j&amp;lt;/math&amp;gt; - элемент на главной диагонали трёхдиагональной матрицы &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&amp;lt;/math&amp;gt;&lt;br /&gt;
** Вычисляем по формуле новое значение и перезаписываем вектор &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt;&lt;br /&gt;
** Вычисляем значение &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;\beta_j&amp;lt;/math&amp;gt; - элементы непосредственно над и под главной диагональю той же матрицы &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&amp;lt;/math&amp;gt;&lt;br /&gt;
** Вычисляем, зная вектор &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt;,  очередной столбец матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;Q&amp;lt;/math&amp;gt;, он же вектор Ланцоша : &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;\,\,q_{j+1}&amp;lt;/math&amp;gt;&lt;br /&gt;
** Теперь, когда матрица &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&amp;lt;/math&amp;gt; сформирована на очередном шаге, находим её собственные значения и вектора любым доступным способом, о чём было подробно сказано в пункте 1.2&lt;br /&gt;
** Переходим на следующую итерацию: &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j&amp;lt;/math&amp;gt;++&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
Оценим количество операций и сложность последовательного алгоритма, изложенного в предыдущем разделе.&lt;br /&gt;
*Для вычисления вектора &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt; умножается матрица размера &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;n\times n&amp;lt;/math&amp;gt; на вектор длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt;, и потребуется &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n^2&amp;lt;/math&amp;gt; операций умножения и &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n^2&amp;lt;/math&amp;gt; операций сложения.&lt;br /&gt;
*Умножение векторов &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;q^T_j&amp;lt;/math&amp;gt; и &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt; длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; потребует &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; операций умножения и &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; операций сложения.&lt;br /&gt;
*При вычислении нового значения вектора &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt; поэлементное сложение двух векторов длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; требует &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; операций сложения.&lt;br /&gt;
*Умножение вектора длины &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; на вещественное число требует &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; операций умножения.&lt;br /&gt;
*Нахождение квадратичной нормы вектора &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt;  длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; требует &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; умножений и &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; сложений и ещё 1 операцию извлечения квадратного корня.&lt;br /&gt;
*Заключительное нахождение собственных значений и собственных векторов трёхдиагональной матрицы &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;T_j&amp;lt;/math&amp;gt; размера &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j\times j&amp;lt;/math&amp;gt; с помощью QR-алгоритма потребует в худшем случае &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(j^3)&amp;lt;/math&amp;gt; операций.&amp;lt;ref&amp;gt;http://num-anal.srcc.msu.ru/lib_na/int_ae/int_ae6.htm (пункт 6.2, &amp;quot;Скорость сходимости при этом всегда не хуже квадратичной и почти всегда лучше кубической.&amp;quot;)&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Посчитаем теперь суммарное количество простейших операций на одной итерации алгоритма (без учёта записей в память):&lt;br /&gt;
*&amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n^2+5\,n&amp;lt;/math&amp;gt; операций умножения/деления&lt;br /&gt;
*&amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n^2+4\,n&amp;lt;/math&amp;gt; операций сложения/вычитания&lt;br /&gt;
*1 операция извлечения квадратного корня&amp;lt;br&amp;gt;&lt;br /&gt;
Отдельно после всех итераций при &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j=k&amp;lt;/math&amp;gt; :&lt;br /&gt;
*&amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(k^3)&amp;lt;/math&amp;gt; операций для поиска собственных значений и собственных векторов трёхдиагональной матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_k&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Итого можно утверждать следующее:&lt;br /&gt;
&lt;br /&gt;
Последовательная сложность одной итерации рассматриваемого алгоритма:  &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(n ^ 2) &amp;lt;/math&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Суммарная сложность алгоритма (&amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;/math&amp;gt; итераций): &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(k\,n ^ 2) + O(k ^ 3)&amp;lt;/math&amp;gt; &amp;lt;ref&amp;gt;Здесь мы полагаем, что мы не вычисляем собственные значения и векторы матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_j&amp;lt;/math&amp;gt; на каждом промежуточном шаге, а лишь единожды затрачиваем &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;O(k ^ 3)&amp;lt;/math&amp;gt; действий в конце для нахождения &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;/math&amp;gt; собственных значений и векторов матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_k&amp;lt;/math&amp;gt;&amp;lt;/ref&amp;gt; &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
На практике же обычно рассматривается число &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;&amp;lt;n&amp;lt;/math&amp;gt;, поэтому второе слагаемое можно опустить.&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
На рис. 1 продемонстрирован граф одной итерации (при каком-либо произвольном значении итератора &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j&amp;lt;/math&amp;gt;) описанного алгоритма без отображения входных и выходных данных. Наглядно продемонстрированы связи между всеми действиями, и с помощью деления на &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; потоков показано, какие операции возможно выполнять параллельно на каждом шаге с целью оптимизации и экономии машинного времени. В результате, после параллельно выполненных операций &#039;&#039;&#039;Division&#039;&#039;&#039; на заключительном ярусе, на выходе имеем значение следующего вектора Ланцоша &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;q_{j+1}&amp;lt;/math&amp;gt;, после чего следует переход на следующую итерацию, и процесс повторяется.&lt;br /&gt;
&lt;br /&gt;
[[Файл:Levin_graph.png|600px|thumb|center|Рис. 1]] &amp;lt;br&amp;gt;&lt;br /&gt;
Обозначения на рисунке: &amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Simp&#039;&#039;&#039; (от англ. simple) - операции сложения и умножения вещественных чисел при вычислении произведения матрицы на вектор;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Vec mult&#039;&#039;&#039; (от англ. vectors multiplication) - операция скалярного умножения двух векторов;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Vec subtr&#039;&#039;&#039; (от англ. vectors subtraction, из-за использованных в операции вычитаний векторов) - операция умножения вектора на число (выполняется дважды) и формирование нового значения &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;z_{new}&amp;lt;/math&amp;gt; по формуле: &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;z_{new} = z - \alpha_j q_j - \beta_{j-1}q_{j-1} \;&amp;lt;/math&amp;gt;;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;||\cdot||&amp;lt;/math&amp;gt; - операция вычисления нормы вектора;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Division&#039;&#039;&#039; - операция деления вектора на вещественное число  &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;\beta_j&amp;lt;/math&amp;gt; &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Важно отметить, что упомянутые выше операции также легко поддаются оптимизации. Например, попарные умножения вещественных координат векторов при вычислении скалярного произведения также легко выполняются параллельно на &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; потоках, а затем можно применить суммирование методом сдваивания, о котором сказано в следующем разделе. Умножение или деление вектора на вещественное число являющееся, по определению, умножением или делением всех его координат на это число тоже может быть выполнено эффективнее, если мы используем &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; потоков, а не выполняем эти действия последовательно.&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
Параллельные операции возможны только внутри итераций, так как рассматриваемый алгоритм является итерационным, и сами итерации строго последовательны.&amp;lt;br&amp;gt;&lt;br /&gt;
Рассмотрим в этом разделе подробнее, какой выигрыш мы можем получить при распараллеливании операций внутри одной итерации согласно графу из предыдущего раздела.&lt;br /&gt;
&lt;br /&gt;
Умножение вещественной симметричной матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; размера &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;n\times n&amp;lt;/math&amp;gt; на вектор &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;b&amp;lt;/math&amp;gt; длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; требует последовательного выполнения &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; ярусов умножений и сложений. Сложение элементов вектора длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; на каждом шаге перемножения можно оптимизировать и выполнить за &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;\log_2 n&amp;lt;/math&amp;gt; действий, если применять метод сдваивания.&lt;br /&gt;
&lt;br /&gt;
Дальнейшие операции выполняются последовательно, а вычисление значений векторов происходит за один ярус операций сложения или умножения.&lt;br /&gt;
&lt;br /&gt;
Ресурс параллелизма алгоритма вычисления собственных значений построенной трёхдиагональной матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_k&amp;lt;/math&amp;gt; размера &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k\times k&amp;lt;/math&amp;gt; зависит от выбранного алгоритма (об этих алгоритмах подробнее было сказано в разделах 1.2 и 1.4). Будет очень затратно с точки зрения объёма материала пытаться рассмотреть пусть даже часть этих методов в этой статье, а так же тонкости их распараллеливания. Предлагаем читателям при желании самим ознакомиться с этими алгоритмами на данном ресурсе или прибегнув к иным источникам.&lt;br /&gt;
&lt;br /&gt;
При классификации по высоте ЯПФ, таким образом, алгоритм Ланцоша без переортогонализации относится к алгоритмам с &#039;&#039;логарифмической сложностью&#039;&#039;, и его сложность равна &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(\log_2 n)&amp;lt;/math&amp;gt; с важным замечанием, что это сложность только одной итерации, а максимум в алгоритме может быть выполнено последовательно &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;/math&amp;gt; таких однотипных итераций, если не будет осуществлён ранний выход из цикла. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Несмотря на то, что на графе в предыдущем разделе для лучшей визуализации и понимания было изображено &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; потоков (никаких допущений мы не делали и нарушений с точки зрения логики и математики нет, можно изобразить большее число потоков, просто часть времени некоторые из них могут бездействовать и не использоваться), на самом деле правильным и разумным будет реализовать начальное параллельное выполнение &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n^2&amp;lt;/math&amp;gt; операций умножения всех вещественных элементов матрицы &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;A&amp;lt;/math&amp;gt; на соответствующие элементы вектора &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;q_j&amp;lt;/math&amp;gt;, после чего применять тот же самый упомянутый метод сдваивания. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Поэтому при классификации по ширине ЯПФ его сложность будет &#039;&#039;квадратичной&#039;&#039; и равна &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(n^2)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
&#039;&#039;&#039;Входные данные алгоритма:&#039;&#039;&#039; вещественная симметричная &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; размера &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;n\times n&amp;lt;/math&amp;gt;, вещественный вектор &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;b&amp;lt;/math&amp;gt; длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt;, и одно целое число &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;k&amp;lt;/math&amp;gt;, означающее количество итераций.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём входных данных:&#039;&#039;&#039; &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;n^2 +n + 1 &amp;lt;/math&amp;gt;. Если учесть, что матрица симметричная и достаточно для её однозначного определения задать элементы на главной диагонали и элементы над или под ней, то можно сократить объём входных данных с целью экономии памяти до: &amp;lt;math&amp;gt;\ \frac{n^2-n}{2}+n+n+1 =\frac{n^2+3n}{2} + 1&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные алгоритма:&#039;&#039;&#039; вектор собственных значений &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;\Theta^k&amp;lt;/math&amp;gt; длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;/math&amp;gt;, матрица &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;S^k&amp;lt;/math&amp;gt; из соответствующих собственных векторов размера &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n\times k&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём выходных данных:&#039;&#039;&#039; &amp;lt;math&amp;gt;k\;(n + 1)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
В данном разделе перечислены без какой-либо хронологии или связи друг с другом наиболее важные и разнообразные свойства алгоритма, на которые стоит и полезно обратить внимание, а также которые выгодно отличают его от схожих алгоритмов, решающих ту же задачу.&amp;lt;br&amp;gt;&lt;br /&gt;
1) Отношение последовательной сложности алгоритма к параллельной,с учётом &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;/math&amp;gt; итераций, равно &amp;lt;math&amp;gt;\;\;\frac{kn^2}{k \log_2{n}}=\frac{n^2}{\log_2{n}}&amp;lt;/math&amp;gt;;&amp;lt;br&amp;gt;&lt;br /&gt;
2) Вычислительная мощность алгоритма, как отношение числа операций к суммарному объему входных и выходных данных, равна &amp;lt;math style=&amp;quot;vertical-align:-70%&amp;gt;\;\;\frac{k\,n^2}{0.5\,n^2+1.5\,n+k\,n+k+1}&amp;lt;/math&amp;gt; и &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;\approx 2\,k&amp;lt;/math&amp;gt;, так как на практике верно отношение &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;&amp;lt;n&amp;lt;/math&amp;gt; ;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
3) Для собственных значений формируемых матриц &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_j&amp;lt;/math&amp;gt; верно отношение (следствие теоремы Коши о перемежаемости): &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;\lambda_i(T_{k+1})\geq \lambda_i(T_{k})\geq \lambda_{i+1}(T_{k+1})\geq \lambda_{i+1}(T_{k})&amp;lt;/math&amp;gt; ;&amp;lt;ref&amp;gt;James W. Demmel - Вычислительная линейная алгебра. Теория и приложения //Мир. - 2001 (c. 383)&amp;lt;/ref&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
4) Крайние (наибольшие и наименьшие) собственные значения матриц &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_j&amp;lt;/math&amp;gt; сходятся к крайним собственным значениям матрицы &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;A&amp;lt;/math&amp;gt; первыми (это часто происходит уже на ранних шагах при &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j\approx 2\,\sqrt{n}&amp;lt;/math&amp;gt;&amp;lt;ref&amp;gt;http://num-anal.srcc.msu.ru/lib_na/int_ae/int_ae6.htm (пункт 6.5)&amp;lt;/ref&amp;gt;), а собственные значения в середине спектра - последними;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
5) Из-за ограниченной точности постепенно теряется ортогональность вектора Ланцоша &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;q_j&amp;lt;/math&amp;gt; к предыдущим векторам Ланцоша, поэтому необходимо примерно каждые 10-15 итераций проводить дорогостоящую операцию реортогонализации, но это уже будет иной алгоритм с очень малым различием в одной операции и в программном коде, реализующем его, соответственно; &amp;lt;ref&amp;gt;Sam Handler - The Lanczos Algorithm For Large-Scale Eigenvalue Problems (08.01.07), slide №8&amp;lt;/ref&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
6) Эффективность и быстрота выполнения алгоритма очень сильно зависит от скорости памяти (диска). Согласно тесту только &#039;&#039;6%&#039;&#039; времени работы программы приходится на вычисления, остальное время затрачивается на ожидание отклика диска;&amp;lt;ref&amp;gt;Sam Handler - The Lanczos Algorithm For Large-Scale Eigenvalue Problems (08.01.07), slide №10&amp;lt;/ref&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
7) Метод Ланцоша удобен тем, что не требует хранения исходной матрицы полным массивом: метод использует исходную матрицу только в операциях умножения матрицы на вектор, что позволяет эффективно использовать разреженность матрицы или регулярность структуры матрицы. Поэтому метод Ланцоша может быть использован для матриц таких больших порядков, когда методы вращений и отражений не могут быть применены.&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;
По заданию, во второй части требовалось описать только разделы 2.4 и 2.7, прошу не спрашивать с меня все разделы 2.1-2.6. Надеюсь на понимание, мне физически не хватает времени на это задание + 2 других в течение семестра, делаю всё, что в моих силах :)&lt;br /&gt;
&lt;br /&gt;
== Существующие реализации алгоритма ==&lt;br /&gt;
Несмотря на то, что алгоритм является далеко не самым популярным, алгоритмом, про который нельзя сказать, что он всегда «на слуху», на сегодняшний день существует множество реализаций на различных популярных языках.&amp;lt;br&amp;gt;&lt;br /&gt;
Перечислим далее некоторые из них, указывая язык программирования, лежащий в их основе, и некоторые важные характеристики, которые обсуждались в статье ранее:&lt;br /&gt;
*&#039;&#039;Code on netlib.org by Jane Cullum and Ralph Willoughby&#039;&#039; (&#039;&#039;&#039;Fortran 77&#039;&#039;&#039;; без реортогонализации векторов; без реализации распараллеливания)&amp;lt;ref&amp;gt;http://www.netlib.org/lanczos/leval&amp;lt;/ref&amp;gt;&lt;br /&gt;
*&#039;&#039;Lanczos algorithm on freesourcecode.net&#039;&#039; (&#039;&#039;&#039;Matlab&#039;&#039;&#039;; присутствует реортогонализация векторов; без реализации распараллеливания)&amp;lt;ref&amp;gt;http://freesourcecode.net/matlabprojects/61741/lanczos-algorithm--in-matlab&amp;lt;/ref&amp;gt;&lt;br /&gt;
*&#039;&#039;Lanczos for eigenvalues in Numerical Linear Algebra, Spring 2007&#039;&#039; (&#039;&#039;&#039;Matlab&#039;&#039;&#039;; частичная или полная реортогонализация - доступны оба варианта; без реализации распараллеливания)&amp;lt;ref&amp;gt;Ссылки на файлы lanso.m и lanfu.m можно найти на https://www.nada.kth.se/~ruhe/2D5219/labs2007.html&amp;lt;/ref&amp;gt;&lt;br /&gt;
*&#039;&#039;Planso&#039;&#039; (название происходит от parallel Lanso.f) &#039;&#039;code by Kesheng Wu and Horst D. Simon&#039;&#039; (&#039;&#039;&#039;Fortran 77&#039;&#039;&#039;; частичная реортогонализация векторов; использование MPI для коммуникаций)&amp;lt;ref&amp;gt;https://github.com/jiahao/planso.jl/tree/master/external/PLAN/plan К сожалению, ссылка в описании пакета на github, ведущая на сайт National Energy Research Scientific Computing Center (NERSC), с более подробной информацией о данной программе больше не активна и выдаёт результат &#039;&#039;Page not found&#039;&#039;&amp;lt;/ref&amp;gt; &lt;br /&gt;
* &#039;&#039;Lanczos.cpp in the Vienna Computing Library&#039;&#039;  (&#039;&#039;&#039;C++&#039;&#039;&#039;, частичная реортогонализация, без реализации распараллеливания) &amp;lt;ref&amp;gt;http://viennacl.sourceforge.net/doc/lanczos_8cpp_source.html&amp;lt;/ref&amp;gt;&lt;br /&gt;
* &#039;&#039;Parallel Eigen Values code using C++ AMP on microsoft msdn blog&#039;&#039; (&#039;&#039;&#039;C++&#039;&#039;&#039;; ? ; распараллеливание есть и реализовано через C++ AMP) &amp;lt;ref&amp;gt;https://blogs.msdn.microsoft.com/nativeconcurrency/2013/12/20/eigen-values/ Подробнее о C++ Accelerated Massive Parallelism можно почитать здесь: https://msdn.microsoft.com/ru-ru/library/hh265137(v=vs.140).aspx или здесь: http://professorweb.ru/my/csharp/optimization/level4/4_6.php &amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;br /&gt;
[[en:Description of algorithm properties and structure]]&lt;/div&gt;</summary>
		<author><name>AleksLevin</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:AleksLevin/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%9B%D0%B0%D0%BD%D1%86%D0%BE%D1%88%D0%B0_%D0%B2%D1%8B%D1%87%D0%B8%D1%81%D0%BB%D0%B5%D0%BD%D0%B8%D1%8F_%D1%81%D0%BE%D0%B1%D1%81%D1%82%D0%B2%D0%B5%D0%BD%D0%BD%D1%8B%D1%85_%D0%B7%D0%BD%D0%B0%D1%87%D0%B5%D0%BD%D0%B8%D0%B9_%D1%81%D0%B8%D0%BC%D0%BC%D0%B5%D1%82%D1%80%D0%B8%D1%87%D0%BD%D0%BE%D0%B9_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86%D1%8B_%D0%B4%D0%BB%D1%8F_%D1%82%D0%BE%D1%87%D0%BD%D0%BE%D0%B9_%D0%B0%D1%80%D0%B8%D1%84%D0%BC%D0%B5%D1%82%D0%B8%D0%BA%D0%B8_(%D0%B1%D0%B5%D0%B7_%D0%BF%D0%B5%D1%80%D0%B5%D0%BE%D1%80%D1%82%D0%BE%D0%B3%D0%BE%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D0%B8)&amp;diff=19950</id>
		<title>Участник:AleksLevin/Алгоритм Ланцоша вычисления собственных значений симметричной матрицы для точной арифметики (без переортогонализации)</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:AleksLevin/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%9B%D0%B0%D0%BD%D1%86%D0%BE%D1%88%D0%B0_%D0%B2%D1%8B%D1%87%D0%B8%D1%81%D0%BB%D0%B5%D0%BD%D0%B8%D1%8F_%D1%81%D0%BE%D0%B1%D1%81%D1%82%D0%B2%D0%B5%D0%BD%D0%BD%D1%8B%D1%85_%D0%B7%D0%BD%D0%B0%D1%87%D0%B5%D0%BD%D0%B8%D0%B9_%D1%81%D0%B8%D0%BC%D0%BC%D0%B5%D1%82%D1%80%D0%B8%D1%87%D0%BD%D0%BE%D0%B9_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86%D1%8B_%D0%B4%D0%BB%D1%8F_%D1%82%D0%BE%D1%87%D0%BD%D0%BE%D0%B9_%D0%B0%D1%80%D0%B8%D1%84%D0%BC%D0%B5%D1%82%D0%B8%D0%BA%D0%B8_(%D0%B1%D0%B5%D0%B7_%D0%BF%D0%B5%D1%80%D0%B5%D0%BE%D1%80%D1%82%D0%BE%D0%B3%D0%BE%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D0%B8)&amp;diff=19950"/>
		<updated>2016-12-02T19:28:10Z</updated>

		<summary type="html">&lt;p&gt;AleksLevin: /* Математическое описание алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Основные авторы описания: Левин А.Д.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{algorithm&lt;br /&gt;
| name              = Алгоритм Ланцоша для точной арифметики (без переортогонализации)&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(k\,n^2)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(k\log_2 n)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;\frac{n^2+3n}{2} + 1&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;k\;(n + 1)&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритмов =&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Данный алгоритм появился в 1950 г. и носит имя венгерского физика и математика Корнелия Ланцоша (венг. Lánczos Kornél). Алгоритм Ланцоша относится к итерационным методам вычисления собственных значений для матриц столь больших порядков &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt; n&amp;lt;/math&amp;gt;, что к ним нельзя применить прямые методы из-за ограничений по времени и памяти.&lt;br /&gt;
&lt;br /&gt;
Сам Ланцош указывал, что его метод предназначен для отыскания нескольких собственных векторов симметричных матриц, хотя к методу сразу было обращено внимание, как к способу приведения всей матрицы к трёхдиагональному виду. Двадцатью годами позже канадский математик Крис Пэж показал, что, несмотря на чувствительность к округлениям, алгоритм Ланцоша - эффективное средство вычисления некоторых &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; собственных чисел и соответствующих им собственных векторов. &amp;lt;ref&amp;gt;Парлетт Б. - Симметричная проблема собственных значений. Численные методы //М.: Мир. - 1983. (c. 276)&amp;lt;/ref&amp;gt;&lt;br /&gt;
Обычно число &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; берут в два раза больше, чем количество собственных значений матрицы, которые поставлена цель найти, и оно имеет порядок не более &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;10^2&amp;lt;/math&amp;gt;.&amp;lt;ref&amp;gt;Susan W. Bostic - Lanczos Eigensolution Method for High-Perfomance Computers, page 7&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Алгоритм Ланцоша для вычисления собственных значений симметричной матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; соединяет в себе метод Ланцоша для построения последовательности подпространств Крылова и ортонормированных векторов Ланцоша и процедуру Рэлея-Ритца получения оптимальных приближений собственных значений и соответствующих собственных векторов исходной матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt;.&amp;lt;ref&amp;gt;James W. Demmel - Вычислительная линейная алгебра. Теория и приложения //Мир. - 2001 (c. 381)&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
В данной статье рассматривается вариант алгоритма Ланцоша, в котором опущено влияние ошибок округления на вычислительный процесс, хотя на практике этому посвящается отдельное внимание и существуют различные методы решения данной проблемы, такие как частичная или полная переортогонализация. Этим модифицированным методам посвящены отдельные статьи на данном ресурсе.&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
Обозначения и формулы, используемые в данном разделе, взяты из литературы, указанной по ссылке.&amp;lt;ref&amp;gt;James W. Demmel - Вычислительная линейная алгебра. Теория и приложения //Мир. - 2001 (c. 313, &#039;&#039;&amp;lt;math&amp;gt; \S &amp;lt;/math&amp;gt; 6.6 Методы Крыловского подпространства&#039;&#039;)&amp;lt;/ref&amp;gt; &lt;br /&gt;
&lt;br /&gt;
Алгоритм Ланцоша для вычисления &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; собственных значений и собственных векторов вещественной симметричной матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A=A^T&amp;lt;/math&amp;gt; в точной арифметике: &amp;lt;ref&amp;gt;James W. Demmel - Вычислительная линейная алгебра. Теория и приложения //Мир. - 2001 (c. 381)&amp;lt;/ref&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{align}&lt;br /&gt;
q_1 = &amp;amp; \,\frac{b}{\|b\|_2},\; \beta_0 = 0,\; q_0 = 0\\&lt;br /&gt;
\mathbf{for} \; &amp;amp; j = 1 \; to \; k \,\; \mathbf{do} \\&lt;br /&gt;
&amp;amp; z = A\,q_j\\&lt;br /&gt;
&amp;amp; \alpha_j = q^T_j z\\&lt;br /&gt;
&amp;amp; z = z - \alpha_j q_j - \beta_{j-1}q_{j-1}\\&lt;br /&gt;
&amp;amp; \beta_j = \|z\|_2\\&lt;br /&gt;
&amp;amp; \mathbf{If} \; (\beta_j == 0) \; \mathbf{then}\; stop\; the\; algorithm \\ &lt;br /&gt;
&amp;amp; \;  q_{j+1} = \frac{z}{\beta_j} \\&lt;br /&gt;
&amp;amp; compute\; eigenvalues\; and \;eigenvectors\;of \;matrix \;\;T_j= Q^T_j A Q\;\;and\;estimate \;the\; errors\\&lt;br /&gt;
\mathbf{end} \; &amp;amp; \mathbf{for}&lt;br /&gt;
\end{align}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
В продемонстрированном выше алгоритме &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;b&amp;lt;/math&amp;gt; - заданный вещественный вектор. Также полагается известным алгоритм вычисления произведения матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; на вектор &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;x&amp;lt;/math&amp;gt;. &lt;br /&gt;
Введём матрицу Крылова, определяемую следующим соотношением: &amp;lt;math&amp;gt;K_j = [b,Ab,A^2b,...,A^{j-1}b]&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Далее, на практике, матрица &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;K&amp;lt;/math&amp;gt; заменяется матрицей &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;Q&amp;lt;/math&amp;gt;, такой, что при любом числе &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; линейные оболочки первых &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; столбцов в &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;K&amp;lt;/math&amp;gt; и &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;Q&amp;lt;/math&amp;gt; являются одним и тем же подпространством.&amp;lt;ref&amp;gt;James W. Demmel - Вычислительная линейная алгебра. Теория и приложения //Мир. - 2001 (c. 315)&amp;lt;/ref&amp;gt; &lt;br /&gt;
Тогда матрица &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;Q&amp;lt;/math&amp;gt;, в отличие от матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;K&amp;lt;/math&amp;gt;, хорошо обусловлена и легко обратима. В результате получаем матрицу &amp;lt;math&amp;gt;Q_j = [q_1, q_2, \dots, q_j]&amp;lt;/math&amp;gt; размерности &amp;lt;math&amp;gt;n\times j&amp;lt;/math&amp;gt;, столбцы которой ортогональны, являются базисом подпространства Крылова и называются векторами Ланцоша.&lt;br /&gt;
&lt;br /&gt;
В алгоритме Ланцоша вычислению подлежит столько первых столбцов в матрице &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;Q_j&amp;lt;/math&amp;gt;, сколько необходимо для получения требуемого приближения к решению &amp;lt;math&amp;gt;A\,x\,=b\,\,(A\,x=\lambda \, x)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Получение нулевого &amp;lt;math&amp;gt;\beta_j&amp;lt;/math&amp;gt; в итерационном процессе - событие, желательное в том смысле, что оно свидетельствует о том, что найдено некоторое подпространство, являющееся в точности инвариантным, а все собственные значения матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;T_j&amp;lt;/math&amp;gt; являются собственными значениями матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt;. На практике же нулевое и близкие к нулю значения получаются редко.&amp;lt;ref&amp;gt;Голуб Дж., Ван Лоун Ч. - Матричные вычисления//М.: Мир. - 1999 (c. 429)&amp;lt;/ref&amp;gt; &lt;br /&gt;
&lt;br /&gt;
Затем на каждом шаге цикла формируется симметричная трёхдиагональная матрица &amp;lt;math&amp;gt;T_j = Q^T_j A Q&amp;lt;/math&amp;gt;, к которой применяется процесс Рэлея-Ритца для поиска её собственных значений (на практике для поиска этих собственных значений можно использовать любой из специальных методов в параграфе книги по ссылке).&amp;lt;ref&amp;gt;Голуб Дж., Ван Лоун Ч. - Матричные вычисления//М.: Мир. - 1999 (&amp;lt;math&amp;gt;\S&amp;lt;/math&amp;gt; 8.4)&amp;lt;/ref&amp;gt;  &lt;br /&gt;
Эти собственные значения, они же числа Ритца, и полагаются приближёнными собственными значениями исходной матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt;.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Существует множество методов для отыскания собственных значений вещественной симметричной трехдиагональной матрицы. Большинство из них требует &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt; операций &amp;lt;ref&amp;gt;Парлетт Б. Симметричная проблема собственных значений. Численные методы.,: Мир, 1983. с. 179-182&amp;lt;/ref&amp;gt;, но существуют и быстрые алгоритмы, требующие лишь &amp;lt;math&amp;gt;O(n\ln n)&amp;lt;/math&amp;gt; операций.&amp;lt;ref&amp;gt;https://en.wikipedia.org/wiki/Tridiagonal_matrix#Eigenvalues  Раздел eigenvalues&amp;lt;/ref&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Одним из возможных способов отыскать собственные значения симметричной трехдиагональной матрицы - прямое вычисление корней характеристического полинома &amp;lt;math&amp;gt;p_n(\lambda)&amp;lt;/math&amp;gt; через метод деления пополам, где формируется последовательность Штурма и локализуются собственные числа, являющиеся корнями характеристического полинома. Нахождение всех &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; собственных значений матрицы этим способом требует &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;2n^2t&amp;lt;/math&amp;gt; умножений и вычитаний, где &amp;lt;math&amp;gt;t&amp;lt;/math&amp;gt; - число сделанных шагов с применением метода деления пополам.&amp;lt;ref&amp;gt;Уилкинсон Дж. X. Алгебраическая проблема собственныx значений. Изд-во &amp;quot;Наука&amp;quot;, 1970. - глава 5, с. 272-278&amp;lt;/ref&amp;gt; Соответствующие собственные вектора могут быть найдены посредством обратных итераций за &amp;lt;math&amp;gt; O(n) &amp;lt;/math&amp;gt; флопов. &amp;lt;ref&amp;gt;Голуб Дж., Ван Лоун Ч. - Матричные вычисления//М.: Мир. - 1999 (c. 394-395)&amp;lt;/ref&amp;gt; &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;На практике, если требуется только небольшая часть от всей совокупности собственных векторов и значений, и матрица имеет Хессенбергову или трёхдиагональную форму, очень эффективными будут методы факторизации, как, например, QR-алгоритм или QL-алгоритм со сдвигами (c целью ускорить алгоритм и сделать порядок сходимости квадратичным) или же без них.&amp;lt;ref&amp;gt;http://algorithm.narod.ru/ln/eigen/ETridiag.html&amp;lt;/ref&amp;gt; &amp;lt;br&amp;gt;&lt;br /&gt;
Весьма молодые и не менее актуальные конкуренты QR и QL алгоритмов, применяющиеся для поиска собственных значений:&lt;br /&gt;
*Методы divide-and-conquer (разделяй и властвуй), появившиеся в 1980-ых годах &amp;lt;ref&amp;gt;https://algowiki-project.org/w/ru/index.php?title=Метод_&amp;quot;Разделяй_и_властвуй&amp;quot;_Завольсков/Землянский&amp;amp;oldid=11026&amp;lt;/ref&amp;gt;&lt;br /&gt;
*Relatively robust representation методы, появившиеся в 1990-ых и позволяющие найти собственные числа симметричной матрицы порядка &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;n&amp;lt;/math&amp;gt; за &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt; операций&lt;br /&gt;
&lt;br /&gt;
Если требуется вычислить собственные векторы, то необходимо хранить вычисляемые векторы Ланцоша. Если работа при этом производится только с оперативной памятью, то при большом порядке исходной матрицы (а именно для таких матриц и предназначен метод Ланцоша) число шагов  &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;j&amp;lt;/math&amp;gt;, которые могут быть выполнены до того момента, как оперативная память будет исчерпана, будет очень незначительно, а следовательно, искомые собственные пары могут не успеть сойтись с требуемой точностью. В этом случае метод Ланцоша можно использовать итерационным образом: после выполнения заданного числа шагов процесс прерывается и, если еще не все требуемые пары Ритца сошлись с требуемой точностью, то формируется новый начальный вектор &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;q_1&amp;lt;/math&amp;gt;, являющийся линейной комбинацией векторов Ритца, еще не сошедшихся с заданной точностью, и процесс начинается заново.&amp;lt;ref&amp;gt;http://num-anal.srcc.msu.ru/lib_na/int_ae/int_ae6.htm (пункт 6.5)&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
Вычислительное ядро рассматриваемого алгоритма (наиболее ресурсно-затратная часть алгоритма) -  формирование на каждом шаге цикла промежуточного вектора &amp;lt;math&amp;gt;z&amp;lt;/math&amp;gt;, вычисляемого по формуле: &amp;lt;math&amp;gt;z = A\,q_j&amp;lt;/math&amp;gt;. Данная операция, по сравнению с другими операциями алгоритма, затратна и требовательна, как с точки зрения количества производимых операций, так и с точки зрения объема оперируемых данных. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Например, умножение матрицы размера &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;n\times n&amp;lt;/math&amp;gt; на вектор длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; требует: &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;n^2+(n-1)n = 2n^2-n&amp;lt;/math&amp;gt; операций умножения и сложения. В свою очередь аналогичная операция умножения матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;(n+1)\times (n+1)&amp;lt;/math&amp;gt; на вектор длины &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;(n+1)&amp;lt;/math&amp;gt; требует: &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;2n^2+3n+1&amp;lt;/math&amp;gt;  операций умножения и сложения. То есть повышение размерности задачи всего на 1 увеличивает число необходимых действий в этом шаге алгоритма на: &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;4n+1&amp;lt;/math&amp;gt;. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Так же, стоит помнить, что, согласно разделу 1.2, данную операцию умножения матрицы на вектор необходимо выполнить &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;k&amp;lt;/math&amp;gt; раз. Нетрудно понять, насколько возрастает и колоссален масштаб операций, если в задачах, где критична точность, размерности &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; могут иметь порядок &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;10^5&amp;lt;/math&amp;gt; или даже более.&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
Как уже было упомянуто в данной статье в описании алгоритма, рассматриваемый алгоритм состоит из двух последовательно выполненных алгоритмов: метод Ланцоша для построения последовательности подпространств Крылова и ортонормированных векторов Ланцоша и процедура Рэлея-Ритца получения оптимальных приближений собственных значений и соответствующих собственных векторов исходной матрицы.&lt;br /&gt;
&lt;br /&gt;
В первой части алгоритма, где итерационно строятся Крыловское подпространство и трёхдиагональная матрица &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&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 style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; разреженная. Именно она подлежит оптимизации с использованием техник распараллеливания, поскольку она является вычислительным ядром алгоритма, а весь упомянутый процесс построения матрицы &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&amp;lt;/math&amp;gt; выполняется последовательно.&lt;br /&gt;
&lt;br /&gt;
Рассмотрим вторую часть алгоритма - поиск собственных значений сформированной матрицы &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&amp;lt;/math&amp;gt;.&amp;lt;br&amp;gt;&lt;br /&gt;
Далее, наглядно, в виде псевдокода, представлен, упомянутый в разделе 1.2, QR-алгоритм (аналогично можно рассмотреть и QL-алгоритм) со сдвигами Релэя, который весьма популярен на практике.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{align}&lt;br /&gt;
\mathbf{Input}: \;&amp;amp;tridiagonal\;\;matrix \;T\;with\;\;n\times n\;\;size\\&lt;br /&gt;
T^{(0)}&amp;amp;:=T\\&lt;br /&gt;
\mathbf{for}&amp;amp; \;\;m=n,...,2 \;\; \mathbf{do}\\&lt;br /&gt;
&amp;amp;k=0\\&lt;br /&gt;
&amp;amp; \mathbf{repeat}\\&lt;br /&gt;
&amp;amp; \quad \;\; k=k+1\\&lt;br /&gt;
&amp;amp; \quad \;\; \mu^{(k)}=T_{m,m}^{(k-1)}\\&lt;br /&gt;
&amp;amp; \quad \;\; Q^{(k)}R^{(k)}=T^{(k-1)}-\mu^{(k)}I\;\;using\;\;QR\;decomposition\\&lt;br /&gt;
&amp;amp; \quad \;\; T^{(k)}=R^{(k)}Q^{(k)}+\mu^{(k)}I\\&lt;br /&gt;
&amp;amp; \mathbf{until} \;\;\; |T_{m,m-1}^{(k)}| \;is\;\;small\;\;enough\\&lt;br /&gt;
&amp;amp; Save  \;\;T_{m,m}^{(k)} \;\;as\;\; converged\;\;eigenvalue\;of\;T\\ &lt;br /&gt;
&amp;amp; Remove \;\boldsymbol{n}\,th\;row\;and\;\boldsymbol{n}\,th\;column\;\;from \;T \\&lt;br /&gt;
&amp;amp; and\;take\;this\;new\;cropped\;matrix\;as\;new\;T^{(0)}\;with\;\;(n-1)\times (n-1)\;\;size\\&lt;br /&gt;
 \mathbf{end}&amp;amp;\; \mathbf{for}&lt;br /&gt;
\end{align}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Малость наддиагональных и поддиагональных элементов матрицы (фраза &#039;&#039;&amp;quot;small enough&amp;quot;&#039;&#039; в псевдокоде) подразумевает:&lt;br /&gt;
&amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt; |T_{m,m-1}^{(k)}| \leq \varepsilon\,|T_{m,m}^{(k)}| \quad\quad &amp;lt;/math&amp;gt; , где &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt; \varepsilon &amp;lt;/math&amp;gt; - заданная точность&amp;lt;br&amp;gt;&lt;br /&gt;
Также вместо сдвига Релэя, обозначенного в алгоритме через &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;\mu^{(k)}&amp;lt;/math&amp;gt;, часто на практике используется сдвиг по Уилкинсону, который даёт гарантированную сходимость внедиагональных элементов матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt; T^{(k)} &amp;lt;/math&amp;gt;, формируемой на каждом шаге, к нулю, при этом жертвуя монотонностью их убывания.&amp;lt;ref&amp;gt;Голуб Дж., Ван Лоун Ч. - Матричные вычисления//М.: Мир. - 1999 (c. 378, вторая половина страницы)&amp;lt;/ref&amp;gt;&amp;lt;ref&amp;gt;Парлетт Б. Симметричная проблема собственных значений. Численные методы.,: Мир, 1983. с. 169&amp;lt;/ref&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Подробнее с различными сдвигами и соответствующими оценками скоростей и количествами операций можно ознакомиться по указанной ссылке:&amp;lt;ref&amp;gt;Парлетт Б. Симметричная проблема собственных значений. Численные методы.,: Мир, 1983. с. 179-182&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;Для совершения QR-декомпозиции на каждом шаге может использоваться любой из алгоритмов по ссылке.&amp;lt;ref&amp;gt;https://en.wikipedia.org/wiki/QR_decomposition&amp;lt;/ref&amp;gt; Подробные описания этих алгоритмов также доступны на данном ресурсе algowiki-project.&amp;lt;br&amp;gt;&lt;br /&gt;
Так как мы оперируем не обычной матрицей и даже не Хессенберговой, а симметричной и трёхдиагональной, то скорость таких алгоритмов значительно возрастёт. Например, согласно данному ресурсу &amp;lt;ref&amp;gt;http://algorithm.narod.ru/ln/eigen/ETridiag.html&amp;lt;/ref&amp;gt;, для QL-алгоритма с неявными сдвигами:&amp;lt;br&amp;gt;&lt;br /&gt;
Для трёхдиагональной матрицы объем арифметических действий составляет &amp;lt;math&amp;gt; O(n)&amp;lt;/math&amp;gt; на одну итерацию вместо &amp;lt;math&amp;gt; O(n^3)&amp;lt;/math&amp;gt; для матрицы общего вида, а число итераций для нахождения первых собственных значений примерно равно 4 - 5. Но на этих итерациях также уменьшаются внедиагональные элементы правого нижнего угла. И, таким образом, дальнейшие собственные значения ищутся значительно быстрее. Среднее число итераций на каждое собственное значение обычно составляет 1.3 - 1.6.&amp;lt;br&amp;gt; &lt;br /&gt;
Аналогично QL, QR-разложение трёхдиагольной матрицы также требует &amp;lt;math&amp;gt; O(n)&amp;lt;/math&amp;gt; флопов&amp;lt;ref&amp;gt;Голуб Дж., Ван Лоун Ч. - Матричные вычисления//М.: Мир. - 1999 (c. 378, начало раздела 8.2.2)&amp;lt;/ref&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Подводя итог, во второй части алгоритма Ланцоша можно выделить следующие макрооперации:&lt;br /&gt;
* умножение матрицы на вещественное число;&lt;br /&gt;
* перемножение матриц;&lt;br /&gt;
* умножение и сравнение вещественных чисел;&lt;br /&gt;
* + набор других макроопераций в зависимости от выбора метода, с помощью которого будет совершаться сама QR или QL-декомпозиция (выше продемонстрированы, уже, как минимум, 3 разных способа).&lt;br /&gt;
Так же, важно заметить, что набор макропераций может быть несколько другим, если выбрать какой-либо иной современный метод поиска собственных чисел трёхдиагональной матрицы, не использующий QR и QL разложения(факторизацию). Два таких метода были упомянуты в пункте 1.2.&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
С целью полностью не дублировать раздел 1.2 данной статьи, где представлен наглядный и доступный для понимания псевдокод алгоритма, постараемся лишь коротко просуммировать и обобщить весь перечень последовательных действий в рассматриваемом алгоритме.&lt;br /&gt;
&lt;br /&gt;
В качестве входных данных имеем: вещественная симметричная матрица &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; размера &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;n\times n&amp;lt;/math&amp;gt;, известный вещественный вектор &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;b&amp;lt;/math&amp;gt; длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; и число &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;n&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Далее:&lt;br /&gt;
* Инициализируем вещественную константу &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;\beta_0&amp;lt;/math&amp;gt; и векторы &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;q_0&amp;lt;/math&amp;gt; и &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;q_1&amp;lt;/math&amp;gt;&lt;br /&gt;
* Итерационно для всех &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j=1,...,k&amp;lt;/math&amp;gt;:&lt;br /&gt;
** Вычисляем вспомогательный вектор &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt;, используя умножение матрицы на вектор&lt;br /&gt;
** Вычисляем, используя скалярное произведение векторов, значение &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;\alpha_j&amp;lt;/math&amp;gt; - элемент на главной диагонали трёхдиагональной матрицы &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&amp;lt;/math&amp;gt;&lt;br /&gt;
** Вычисляем по формуле новое значение и перезаписываем вектор &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt;&lt;br /&gt;
** Вычисляем значение &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;\beta_j&amp;lt;/math&amp;gt; - элементы непосредственно над и под главной диагональю той же матрицы &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&amp;lt;/math&amp;gt;&lt;br /&gt;
** Вычисляем, зная вектор &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt;,  очередной столбец матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;Q&amp;lt;/math&amp;gt;, он же вектор Ланцоша : &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;\,\,q_{j+1}&amp;lt;/math&amp;gt;&lt;br /&gt;
** Теперь, когда матрица &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&amp;lt;/math&amp;gt; сформирована на очередном шаге, находим её собственные значения и вектора любым доступным способом, о чём было подробно сказано в пункте 1.2&lt;br /&gt;
** Переходим на следующую итерацию: &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j&amp;lt;/math&amp;gt;++&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
Оценим количество операций и сложность последовательного алгоритма, изложенного в предыдущем разделе.&lt;br /&gt;
*Для вычисления вектора &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt; умножается матрица размера &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;n\times n&amp;lt;/math&amp;gt; на вектор длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt;, и потребуется &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n^2&amp;lt;/math&amp;gt; операций умножения и &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n^2&amp;lt;/math&amp;gt; операций сложения.&lt;br /&gt;
*Умножение векторов &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;q^T_j&amp;lt;/math&amp;gt; и &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt; длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; потребует &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; операций умножения и &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; операций сложения.&lt;br /&gt;
*При вычислении нового значения вектора &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt; поэлементное сложение двух векторов длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; требует &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; операций сложения.&lt;br /&gt;
*Умножение вектора длины &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; на вещественное число требует &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; операций умножения.&lt;br /&gt;
*Нахождение квадратичной нормы вектора &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt;  длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; требует &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; умножений и &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; сложений и ещё 1 операцию извлечения квадратного корня.&lt;br /&gt;
*Заключительное нахождение собственных значений и собственных векторов трёхдиагональной матрицы &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;T_j&amp;lt;/math&amp;gt; размера &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j\times j&amp;lt;/math&amp;gt; с помощью QR-алгоритма потребует в худшем случае &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(j^3)&amp;lt;/math&amp;gt; операций.&amp;lt;ref&amp;gt;http://num-anal.srcc.msu.ru/lib_na/int_ae/int_ae6.htm (пункт 6.2, &amp;quot;Скорость сходимости при этом всегда не хуже квадратичной и почти всегда лучше кубической.&amp;quot;)&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Посчитаем теперь суммарное количество простейших операций на одной итерации алгоритма (без учёта записей в память):&lt;br /&gt;
*&amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n^2+5\,n&amp;lt;/math&amp;gt; операций умножения/деления&lt;br /&gt;
*&amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n^2+4\,n&amp;lt;/math&amp;gt; операций сложения/вычитания&lt;br /&gt;
*1 операция извлечения квадратного корня&amp;lt;br&amp;gt;&lt;br /&gt;
Отдельно после всех итераций при &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j=k&amp;lt;/math&amp;gt; :&lt;br /&gt;
*&amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(k^3)&amp;lt;/math&amp;gt; операций для поиска собственных значений и собственных векторов трёхдиагональной матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_k&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Итого можно утверждать следующее:&lt;br /&gt;
&lt;br /&gt;
Последовательная сложность одной итерации рассматриваемого алгоритма:  &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(n ^ 2) &amp;lt;/math&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Суммарная сложность алгоритма (&amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;/math&amp;gt; итераций): &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(k\,n ^ 2) + O(k ^ 3)&amp;lt;/math&amp;gt; &amp;lt;ref&amp;gt;Здесь мы полагаем, что мы не вычисляем собственные значения и векторы матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_j&amp;lt;/math&amp;gt; на каждом промежуточном шаге, а лишь единожды затрачиваем &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;O(k ^ 3)&amp;lt;/math&amp;gt; действий в конце для нахождения &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;/math&amp;gt; собственных значений и векторов матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_k&amp;lt;/math&amp;gt;&amp;lt;/ref&amp;gt; &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
На практике же обычно рассматривается число &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;&amp;lt;n&amp;lt;/math&amp;gt;, поэтому второе слагаемое можно опустить.&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
На рис. 1 продемонстрирован граф одной итерации (при каком-либо произвольном значении итератора &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j&amp;lt;/math&amp;gt;) описанного алгоритма без отображения входных и выходных данных. Наглядно продемонстрированы связи между всеми действиями, и с помощью деления на &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; потоков показано, какие операции возможно выполнять параллельно на каждом шаге с целью оптимизации и экономии машинного времени. В результате, после параллельно выполненных операций &#039;&#039;&#039;Division&#039;&#039;&#039; на заключительном ярусе, на выходе имеем значение следующего вектора Ланцоша &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;q_{j+1}&amp;lt;/math&amp;gt;, после чего следует переход на следующую итерацию, и процесс повторяется.&lt;br /&gt;
&lt;br /&gt;
[[Файл:Levin_graph.png|600px|thumb|center|Рис. 1]] &amp;lt;br&amp;gt;&lt;br /&gt;
Обозначения на рисунке: &amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Simp&#039;&#039;&#039; (от англ. simple) - операции сложения и умножения вещественных чисел при вычислении произведения матрицы на вектор;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Vec mult&#039;&#039;&#039; (от англ. vectors multiplication) - операция скалярного умножения двух векторов;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Vec subtr&#039;&#039;&#039; (от англ. vectors subtraction, из-за использованных в операции вычитаний векторов) - операция умножения вектора на число (выполняется дважды) и формирование нового значения &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;z_{new}&amp;lt;/math&amp;gt; по формуле: &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;z_{new} = z - \alpha_j q_j - \beta_{j-1}q_{j-1} \;&amp;lt;/math&amp;gt;;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;||\cdot||&amp;lt;/math&amp;gt; - операция вычисления нормы вектора;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Division&#039;&#039;&#039; - операция деления вектора на вещественное число  &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;\beta_j&amp;lt;/math&amp;gt; &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Важно отметить, что упомянутые выше операции также легко поддаются оптимизации. Например, попарные умножения вещественных координат векторов при вычислении скалярного произведения также легко выполняются параллельно на &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; потоках, а затем можно применить суммирование методом сдваивания, о котором сказано в следующем разделе. Умножение или деление вектора на вещественное число являющееся, по определению, умножением или делением всех его координат на это число тоже может быть выполнено эффективнее, если мы используем &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; потоков, а не выполняем эти действия последовательно.&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
Параллельные операции возможны только внутри итераций, так как рассматриваемый алгоритм является итерационным, и сами итерации строго последовательны.&amp;lt;br&amp;gt;&lt;br /&gt;
Рассмотрим в этом разделе подробнее, какой выигрыш мы можем получить при распараллеливании операций внутри одной итерации согласно графу из предыдущего раздела.&lt;br /&gt;
&lt;br /&gt;
Умножение вещественной симметричной матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; размера &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;n\times n&amp;lt;/math&amp;gt; на вектор &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;b&amp;lt;/math&amp;gt; длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; требует последовательного выполнения &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; ярусов умножений и сложений. Сложение элементов вектора длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; на каждом шаге перемножения можно оптимизировать и выполнить за &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;\log_2 n&amp;lt;/math&amp;gt; действий, если применять метод сдваивания.&lt;br /&gt;
&lt;br /&gt;
Дальнейшие операции выполняются последовательно, а вычисление значений векторов происходит за один ярус операций сложения или умножения.&lt;br /&gt;
&lt;br /&gt;
Ресурс параллелизма алгоритма вычисления собственных значений построенной трёхдиагональной матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_k&amp;lt;/math&amp;gt; размера &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k\times k&amp;lt;/math&amp;gt; зависит от выбранного алгоритма (об этих алгоритмах подробнее было сказано в разделах 1.2 и 1.4). Будет очень затратно с точки зрения объёма материала пытаться рассмотреть пусть даже часть этих методов в этой статье, а так же тонкости их распараллеливания. Предлагаем читателям при желании самим ознакомиться с этими алгоритмами на данном ресурсе или прибегнув к иным источникам.&lt;br /&gt;
&lt;br /&gt;
При классификации по высоте ЯПФ, таким образом, алгоритм Ланцоша без переортогонализации относится к алгоритмам с &#039;&#039;логарифмической сложностью&#039;&#039;, и его сложность равна &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(\log_2 n)&amp;lt;/math&amp;gt; с важным замечанием, что это сложность только одной итерации, а максимум в алгоритме может быть выполнено последовательно &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;/math&amp;gt; таких однотипных итераций, если не будет осуществлён ранний выход из цикла. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Несмотря на то, что на графе в предыдущем разделе для лучшей визуализации и понимания было изображено &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; потоков (никаких допущений мы не делали и нарушений с точки зрения логики и математики нет, можно изобразить большее число потоков, просто часть времени некоторые из них могут бездействовать и не использоваться), на самом деле правильным и разумным будет реализовать начальное параллельное выполнение &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n^2&amp;lt;/math&amp;gt; операций умножения всех вещественных элементов матрицы &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;A&amp;lt;/math&amp;gt; на соответствующие элементы вектора &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;q_j&amp;lt;/math&amp;gt;, после чего применять тот же самый упомянутый метод сдваивания. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Поэтому при классификации по ширине ЯПФ его сложность будет &#039;&#039;квадратичной&#039;&#039; и равна &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(n^2)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
&#039;&#039;&#039;Входные данные алгоритма:&#039;&#039;&#039; вещественная симметричная &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; размера &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;n\times n&amp;lt;/math&amp;gt;, вещественный вектор &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;b&amp;lt;/math&amp;gt; длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt;, и одно целое число &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;k&amp;lt;/math&amp;gt;, означающее количество итераций.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём входных данных:&#039;&#039;&#039; &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;n^2 +n + 1 &amp;lt;/math&amp;gt;. Если учесть, что матрица симметричная и достаточно для её однозначного определения задать элементы на главной диагонали и элементы над или под ней, то можно сократить объём входных данных с целью экономии памяти до: &amp;lt;math&amp;gt;\ \frac{n^2-n}{2}+n+n+1 =\frac{n^2+3n}{2} + 1&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные алгоритма:&#039;&#039;&#039; вектор собственных значений &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;\Theta^k&amp;lt;/math&amp;gt; длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;/math&amp;gt;, матрица &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;S^k&amp;lt;/math&amp;gt; из соответствующих собственных векторов размера &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n\times k&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём выходных данных:&#039;&#039;&#039; &amp;lt;math&amp;gt;k\;(n + 1)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
В данном разделе перечислены без какой-либо хронологии или связи друг с другом наиболее важные и разнообразные свойства алгоритма, на которые стоит и полезно обратить внимание, а также которые выгодно отличают его от схожих алгоритмов, решающих ту же задачу.&amp;lt;br&amp;gt;&lt;br /&gt;
1) Отношение последовательной сложности алгоритма к параллельной,с учётом &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;/math&amp;gt; итераций, равно &amp;lt;math&amp;gt;\;\;\frac{kn^2}{k \log_2{n}}=\frac{n^2}{\log_2{n}}&amp;lt;/math&amp;gt;;&amp;lt;br&amp;gt;&lt;br /&gt;
2) Вычислительная мощность алгоритма, как отношение числа операций к суммарному объему входных и выходных данных, равна &amp;lt;math style=&amp;quot;vertical-align:-70%&amp;gt;\;\;\frac{k\,n^2}{0.5\,n^2+1.5\,n+k\,n+k+1}&amp;lt;/math&amp;gt; и &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;\approx 2\,k&amp;lt;/math&amp;gt;, так как на практике верно отношение &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;&amp;lt;n&amp;lt;/math&amp;gt; ;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
3) Для собственных значений формируемых матриц &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_j&amp;lt;/math&amp;gt; верно отношение (следствие теоремы Коши о перемежаемости): &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;\lambda_i(T_{k+1})\geq \lambda_i(T_{k})\geq \lambda_{i+1}(T_{k+1})\geq \lambda_{i+1}(T_{k})&amp;lt;/math&amp;gt; ;&amp;lt;ref&amp;gt;James W. Demmel - Вычислительная линейная алгебра. Теория и приложения //Мир. - 2001 (c. 383)&amp;lt;/ref&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
4) Крайние (наибольшие и наименьшие) собственные значения матриц &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_j&amp;lt;/math&amp;gt; сходятся к крайним собственным значениям матрицы &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;A&amp;lt;/math&amp;gt; первыми (это часто происходит уже на ранних шагах при &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j\approx 2\,\sqrt{n}&amp;lt;/math&amp;gt;&amp;lt;ref&amp;gt;http://num-anal.srcc.msu.ru/lib_na/int_ae/int_ae6.htm (пункт 6.5)&amp;lt;/ref&amp;gt;), а собственные значения в середине спектра - последними;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
5) Из-за ограниченной точности постепенно теряется ортогональность вектора Ланцоша &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;q_j&amp;lt;/math&amp;gt; к предыдущим векторам Ланцоша, поэтому необходимо примерно каждые 10-15 итераций проводить дорогостоящую операцию реортогонализации, но это уже будет иной алгоритм с очень малым различием в одной операции и в программном коде, реализующем его, соответственно; &amp;lt;ref&amp;gt;Sam Handler - The Lanczos Algorithm For Large-Scale Eigenvalue Problems (08.01.07), slide №8&amp;lt;/ref&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
6) Эффективность и быстрота выполнения алгоритма очень сильно зависит от скорости памяти (диска). Согласно тесту только &#039;&#039;6%&#039;&#039; времени работы программы приходится на вычисления, остальное время затрачивается на ожидание отклика диска;&amp;lt;ref&amp;gt;Sam Handler - The Lanczos Algorithm For Large-Scale Eigenvalue Problems (08.01.07), slide №10&amp;lt;/ref&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
7) Метод Ланцоша удобен тем, что не требует хранения исходной матрицы полным массивом: метод использует исходную матрицу только в операциях умножения матрицы на вектор, что позволяет эффективно использовать разреженность матрицы или регулярность структуры матрицы. Поэтому метод Ланцоша может быть использован для матриц таких больших порядков, когда методы вращений и отражений не могут быть применены.&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;
По заданию, во второй части требовалось описать только разделы 2.4 и 2.7, прошу не спрашивать с меня все разделы 2.1-2.6. Надеюсь на понимание, мне физически не хватает времени на это задание + 2 других в течение семестра, делаю всё, что в моих силах :)&lt;br /&gt;
&lt;br /&gt;
== Существующие реализации алгоритма ==&lt;br /&gt;
Несмотря на то, что алгоритм является далеко не самым популярным, алгоритмом, про который нельзя сказать, что он всегда «на слуху», на сегодняшний день существует множество реализаций на различных популярных языках.&amp;lt;br&amp;gt;&lt;br /&gt;
Перечислим далее некоторые из них, указывая язык программирования, лежащий в их основе, и некоторые важные характеристики, которые обсуждались в статье ранее:&lt;br /&gt;
*&#039;&#039;Code on netlib.org by Jane Cullum and Ralph Willoughby&#039;&#039; (&#039;&#039;&#039;Fortran 77&#039;&#039;&#039;; без реортогонализации векторов; без реализации распараллеливания)&amp;lt;ref&amp;gt;http://www.netlib.org/lanczos/leval&amp;lt;/ref&amp;gt;&lt;br /&gt;
*&#039;&#039;Lanczos algorithm on freesourcecode.net&#039;&#039; (&#039;&#039;&#039;Matlab&#039;&#039;&#039;; присутствует реортогонализация векторов; без реализации распараллеливания)&amp;lt;ref&amp;gt;http://freesourcecode.net/matlabprojects/61741/lanczos-algorithm--in-matlab&amp;lt;/ref&amp;gt;&lt;br /&gt;
*&#039;&#039;Lanczos for eigenvalues in Numerical Linear Algebra, Spring 2007&#039;&#039; (&#039;&#039;&#039;Matlab&#039;&#039;&#039;; частичная или полная реортогонализация - доступны оба варианта; без реализации распараллеливания)&amp;lt;ref&amp;gt;Ссылки на файлы lanso.m и lanfu.m можно найти на https://www.nada.kth.se/~ruhe/2D5219/labs2007.html&amp;lt;/ref&amp;gt;&lt;br /&gt;
*&#039;&#039;Planso&#039;&#039; (название происходит от parallel Lanso.f) &#039;&#039;code by Kesheng Wu and Horst D. Simon&#039;&#039; (&#039;&#039;&#039;Fortran 77&#039;&#039;&#039;; частичная реортогонализация векторов; использование MPI для коммуникаций)&amp;lt;ref&amp;gt;https://github.com/jiahao/planso.jl/tree/master/external/PLAN/plan К сожалению, ссылка в описании пакета на github, ведущая на сайт National Energy Research Scientific Computing Center (NERSC), с более подробной информацией о данной программе больше не активна и выдаёт результат &#039;&#039;Page not found&#039;&#039;&amp;lt;/ref&amp;gt; &lt;br /&gt;
* &#039;&#039;Lanczos.cpp in the Vienna Computing Library&#039;&#039;  (&#039;&#039;&#039;C++&#039;&#039;&#039;, частичная реортогонализация, без реализации распараллеливания) &amp;lt;ref&amp;gt;http://viennacl.sourceforge.net/doc/lanczos_8cpp_source.html&amp;lt;/ref&amp;gt;&lt;br /&gt;
* &#039;&#039;Parallel Eigen Values code using C++ AMP on microsoft msdn blog&#039;&#039; (&#039;&#039;&#039;C++&#039;&#039;&#039;; ? ; распараллеливание есть и реализовано через C++ AMP) &amp;lt;ref&amp;gt;https://blogs.msdn.microsoft.com/nativeconcurrency/2013/12/20/eigen-values/ Подробнее о C++ Accelerated Massive Parallelism можно почитать здесь: https://msdn.microsoft.com/ru-ru/library/hh265137(v=vs.140).aspx или здесь: http://professorweb.ru/my/csharp/optimization/level4/4_6.php &amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;br /&gt;
[[en:Description of algorithm properties and structure]]&lt;/div&gt;</summary>
		<author><name>AleksLevin</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:AleksLevin/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%9B%D0%B0%D0%BD%D1%86%D0%BE%D1%88%D0%B0_%D0%B2%D1%8B%D1%87%D0%B8%D1%81%D0%BB%D0%B5%D0%BD%D0%B8%D1%8F_%D1%81%D0%BE%D0%B1%D1%81%D1%82%D0%B2%D0%B5%D0%BD%D0%BD%D1%8B%D1%85_%D0%B7%D0%BD%D0%B0%D1%87%D0%B5%D0%BD%D0%B8%D0%B9_%D1%81%D0%B8%D0%BC%D0%BC%D0%B5%D1%82%D1%80%D0%B8%D1%87%D0%BD%D0%BE%D0%B9_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86%D1%8B_%D0%B4%D0%BB%D1%8F_%D1%82%D0%BE%D1%87%D0%BD%D0%BE%D0%B9_%D0%B0%D1%80%D0%B8%D1%84%D0%BC%D0%B5%D1%82%D0%B8%D0%BA%D0%B8_(%D0%B1%D0%B5%D0%B7_%D0%BF%D0%B5%D1%80%D0%B5%D0%BE%D1%80%D1%82%D0%BE%D0%B3%D0%BE%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D0%B8)&amp;diff=19949</id>
		<title>Участник:AleksLevin/Алгоритм Ланцоша вычисления собственных значений симметричной матрицы для точной арифметики (без переортогонализации)</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:AleksLevin/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%9B%D0%B0%D0%BD%D1%86%D0%BE%D1%88%D0%B0_%D0%B2%D1%8B%D1%87%D0%B8%D1%81%D0%BB%D0%B5%D0%BD%D0%B8%D1%8F_%D1%81%D0%BE%D0%B1%D1%81%D1%82%D0%B2%D0%B5%D0%BD%D0%BD%D1%8B%D1%85_%D0%B7%D0%BD%D0%B0%D1%87%D0%B5%D0%BD%D0%B8%D0%B9_%D1%81%D0%B8%D0%BC%D0%BC%D0%B5%D1%82%D1%80%D0%B8%D1%87%D0%BD%D0%BE%D0%B9_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86%D1%8B_%D0%B4%D0%BB%D1%8F_%D1%82%D0%BE%D1%87%D0%BD%D0%BE%D0%B9_%D0%B0%D1%80%D0%B8%D1%84%D0%BC%D0%B5%D1%82%D0%B8%D0%BA%D0%B8_(%D0%B1%D0%B5%D0%B7_%D0%BF%D0%B5%D1%80%D0%B5%D0%BE%D1%80%D1%82%D0%BE%D0%B3%D0%BE%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D0%B8)&amp;diff=19949"/>
		<updated>2016-12-02T19:26:09Z</updated>

		<summary type="html">&lt;p&gt;AleksLevin: /* Математическое описание алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Основные авторы описания: Левин А.Д.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{algorithm&lt;br /&gt;
| name              = Алгоритм Ланцоша для точной арифметики (без переортогонализации)&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(k\,n^2)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(k\log_2 n)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;\frac{n^2+3n}{2} + 1&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;k\;(n + 1)&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритмов =&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Данный алгоритм появился в 1950 г. и носит имя венгерского физика и математика Корнелия Ланцоша (венг. Lánczos Kornél). Алгоритм Ланцоша относится к итерационным методам вычисления собственных значений для матриц столь больших порядков &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt; n&amp;lt;/math&amp;gt;, что к ним нельзя применить прямые методы из-за ограничений по времени и памяти.&lt;br /&gt;
&lt;br /&gt;
Сам Ланцош указывал, что его метод предназначен для отыскания нескольких собственных векторов симметричных матриц, хотя к методу сразу было обращено внимание, как к способу приведения всей матрицы к трёхдиагональному виду. Двадцатью годами позже канадский математик Крис Пэж показал, что, несмотря на чувствительность к округлениям, алгоритм Ланцоша - эффективное средство вычисления некоторых &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; собственных чисел и соответствующих им собственных векторов. &amp;lt;ref&amp;gt;Парлетт Б. - Симметричная проблема собственных значений. Численные методы //М.: Мир. - 1983. (c. 276)&amp;lt;/ref&amp;gt;&lt;br /&gt;
Обычно число &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; берут в два раза больше, чем количество собственных значений матрицы, которые поставлена цель найти, и оно имеет порядок не более &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;10^2&amp;lt;/math&amp;gt;.&amp;lt;ref&amp;gt;Susan W. Bostic - Lanczos Eigensolution Method for High-Perfomance Computers, page 7&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Алгоритм Ланцоша для вычисления собственных значений симметричной матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; соединяет в себе метод Ланцоша для построения последовательности подпространств Крылова и ортонормированных векторов Ланцоша и процедуру Рэлея-Ритца получения оптимальных приближений собственных значений и соответствующих собственных векторов исходной матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt;.&amp;lt;ref&amp;gt;James W. Demmel - Вычислительная линейная алгебра. Теория и приложения //Мир. - 2001 (c. 381)&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
В данной статье рассматривается вариант алгоритма Ланцоша, в котором опущено влияние ошибок округления на вычислительный процесс, хотя на практике этому посвящается отдельное внимание и существуют различные методы решения данной проблемы, такие как частичная или полная переортогонализация. Этим модифицированным методам посвящены отдельные статьи на данном ресурсе.&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
Обозначения и формулы, используемые в данном разделе, взяты из литературы, указанной по ссылке.&amp;lt;ref&amp;gt;James W. Demmel - Вычислительная линейная алгебра. Теория и приложения //Мир. - 2001 (c. 313, &#039;&#039;&amp;lt;math&amp;gt; \S &amp;lt;/math&amp;gt; 6.6 Методы Крыловского подпространства&#039;&#039;)&amp;lt;/ref&amp;gt; &lt;br /&gt;
&lt;br /&gt;
Алгоритм Ланцоша для вычисления &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; собственных значений и собственных векторов вещественной симметричной матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A=A^T&amp;lt;/math&amp;gt; в точной арифметике: &amp;lt;ref&amp;gt;James W. Demmel - Вычислительная линейная алгебра. Теория и приложения //Мир. - 2001 (c. 381)&amp;lt;/ref&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{align}&lt;br /&gt;
q_1 = &amp;amp; \,\frac{b}{\|b\|_2},\; \beta_0 = 0,\; q_0 = 0\\&lt;br /&gt;
\mathbf{for} \; &amp;amp; j = 1 \; to \; k \,\; \mathbf{do} \\&lt;br /&gt;
&amp;amp; z = A\,q_j\\&lt;br /&gt;
&amp;amp; \alpha_j = q^T_j z\\&lt;br /&gt;
&amp;amp; z = z - \alpha_j q_j - \beta_{j-1}q_{j-1}\\&lt;br /&gt;
&amp;amp; \beta_j = \|z\|_2\\&lt;br /&gt;
&amp;amp; \mathbf{If} \; (\beta_j == 0) \; \mathbf{then}\; stop\; the\; algorithm \\ &lt;br /&gt;
&amp;amp; \;  q_{j+1} = \frac{z}{\beta_j} \\&lt;br /&gt;
&amp;amp; compute\; eigenvalues\; and \;eigenvectors\;of \;matrix \;\;T_j= Q^T_j A Q\;\;and\;estimate \;the\; errors\\&lt;br /&gt;
\mathbf{end} \; &amp;amp; \mathbf{for}&lt;br /&gt;
\end{align}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
В продемонстрированном выше алгоритме &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;b&amp;lt;/math&amp;gt; - заданный вещественный вектор. Также полагается известным алгоритм вычисления произведения матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; на вектор &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;x&amp;lt;/math&amp;gt;. &lt;br /&gt;
Введём матрицу Крылова, определяемую следующим соотношением: &amp;lt;math&amp;gt;K_j = [b,Ab,A^2b,...,A^{j-1}b]&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Далее, на практике, матрица &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;K&amp;lt;/math&amp;gt; заменяется матрицей &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;Q&amp;lt;/math&amp;gt;, такой, что при любом числе &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; линейные оболочки первых &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; столбцов в &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;K&amp;lt;/math&amp;gt; и &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;Q&amp;lt;/math&amp;gt; являются одним и тем же подпространством.&amp;lt;ref&amp;gt;James W. Demmel - Вычислительная линейная алгебра. Теория и приложения //Мир. - 2001 (c. 315)&amp;lt;/ref&amp;gt; &lt;br /&gt;
Тогда матрица &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;Q&amp;lt;/math&amp;gt;, в отличие от матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;K&amp;lt;/math&amp;gt;, хорошо обусловлена и легко обратима. В результате получаем матрицу &amp;lt;math&amp;gt;Q_j = [q_1, q_2, \dots, q_j]&amp;lt;/math&amp;gt; размерности &amp;lt;math&amp;gt;n\times j&amp;lt;/math&amp;gt;, столбцы которой ортогональны, являются базисом подпространства Крылова и называются векторами Ланцоша.&lt;br /&gt;
&lt;br /&gt;
В алгоритме Ланцоша вычислению подлежит столько первых столбцов в матрице &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;Q_j&amp;lt;/math&amp;gt;, сколько необходимо для получения требуемого приближения к решению &amp;lt;math&amp;gt;A\,x\,=b\,\,(A\,x=\lambda \, x)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Получение нулевого &amp;lt;math&amp;gt;\beta_j&amp;lt;/math&amp;gt; в итерационном процессе - событие, желательное в том смысле, что оно свидетельствует о том, что найдено некоторое подпространство, являющееся в точности инвариантным, а все собственные значения матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;T_j&amp;lt;/math&amp;gt; являются собственными значениями матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt;. На практике же нулевое и близкие к нулю значения получаются редко.&amp;lt;ref&amp;gt;Голуб Дж., Ван Лоун Ч. - Матричные вычисления//М.: Мир. - 1999 (c. 429)&amp;lt;/ref&amp;gt; &lt;br /&gt;
&lt;br /&gt;
Затем на каждом шаге цикла формируется симметричная трёхдиагональная матрица &amp;lt;math&amp;gt;T_j = Q^T_j A Q&amp;lt;/math&amp;gt;, к которой применяется процесс Рэлея-Ритца для поиска её собственных значений (на практике для поиска этих собственных значений можно использовать любой из специальных методов в параграфе книги по ссылке).&amp;lt;ref&amp;gt;Голуб Дж., Ван Лоун Ч. - Матричные вычисления//М.: Мир. - 1999 (&amp;lt;math&amp;gt;\S&amp;lt;/math&amp;gt; 8.4)&amp;lt;/ref&amp;gt;  &lt;br /&gt;
Эти собственные значения, они же числа Ритца, и полагаются приближёнными собственными значениями исходной матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt;.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Существует множество методов для отыскания собственных значений вещественной симметричной трехдиагональной матрицы. Большинство из них требует &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt; операций &amp;lt;ref&amp;gt;Парлетт Б. Симметричная проблема собственных значений. Численные методы.,: Мир, 1983. с. 179-182&amp;lt;/ref&amp;gt;, но существуют и быстрые алгоритмы, требующие лишь &amp;lt;math&amp;gt;O(n\ln n)&amp;lt;/math&amp;gt; операций.&amp;lt;ref&amp;gt;https://en.wikipedia.org/wiki/Tridiagonal_matrix#Eigenvalues  Раздел eigenvalues&amp;lt;/ref&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Одним из возможных способов отыскать собственные значения симметричной трехдиагональной матрицы - прямое вычисление корней характеристического полинома &amp;lt;math&amp;gt;p_n(\lambda)&amp;lt;/math&amp;gt; через метод деления пополам, где формируется последовательность Штурма и локализуются собственные числа, являющиеся корнями характеристического полинома. Нахождение всех &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; собственных значений матрицы этим способом требует &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;2n^2t&amp;lt;/math&amp;gt; умножений и вычитаний, где &amp;lt;math&amp;gt;t&amp;lt;/math&amp;gt; - число сделанных шагов с применением метода деления пополам.&amp;lt;ref&amp;gt;Уилкинсон Дж. X. Алгебраическая проблема собственныx значений. Изд-во &amp;quot;Наука&amp;quot;, 1970. - глава 5, с. 272-278&amp;lt;/ref&amp;gt; Соответствующие собственные вектора могут быть найдены посредством обратных итераций за &amp;lt;math&amp;gt; O(n) &amp;lt;/math&amp;gt; флопов. &amp;lt;ref&amp;gt;Голуб Дж., Ван Лоун Ч. - Матричные вычисления//М.: Мир. - 1999 (c. 394-395)&amp;lt;/ref&amp;gt; &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;На практике, если требуется только небольшая часть от всей совокупности собственных векторов и значений, и матрица имеет Хессенбергову или трёхдиагональную форму, очень эффективными будут методы факторизации, как, например, QR-алгоритм или QL-алгоритм со сдвигами (c целью ускорить алгоритм и сделать порядок сходимости квадратичным) или же без них.&amp;lt;ref&amp;gt;http://algorithm.narod.ru/ln/eigen/ETridiag.html&amp;lt;/ref&amp;gt; &amp;lt;br&amp;gt;&lt;br /&gt;
Весьма молодые и не менее актуальные конкуренты QR и QL алгоритмов, применяющиеся для поиска собственных значений:&lt;br /&gt;
*Методы divide-and-conquer (разделяй и властвуй), появившиеся в 1980-ых годах &amp;lt;ref&amp;gt;https://algowiki-project.org/ru/Метод_&amp;quot;Разделяй_и_властвуй&amp;quot;_Завольсков/Землянский&amp;lt;/ref&amp;gt;&lt;br /&gt;
*Relatively robust representation методы, появившиеся в 1990-ых и позволяющие найти собственные числа симметричной матрицы порядка &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;n&amp;lt;/math&amp;gt; за &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt; операций&lt;br /&gt;
&lt;br /&gt;
Если требуется вычислить собственные векторы, то необходимо хранить вычисляемые векторы Ланцоша. Если работа при этом производится только с оперативной памятью, то при большом порядке исходной матрицы (а именно для таких матриц и предназначен метод Ланцоша) число шагов  &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;j&amp;lt;/math&amp;gt;, которые могут быть выполнены до того момента, как оперативная память будет исчерпана, будет очень незначительно, а следовательно, искомые собственные пары могут не успеть сойтись с требуемой точностью. В этом случае метод Ланцоша можно использовать итерационным образом: после выполнения заданного числа шагов процесс прерывается и, если еще не все требуемые пары Ритца сошлись с требуемой точностью, то формируется новый начальный вектор &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;q_1&amp;lt;/math&amp;gt;, являющийся линейной комбинацией векторов Ритца, еще не сошедшихся с заданной точностью, и процесс начинается заново.&amp;lt;ref&amp;gt;http://num-anal.srcc.msu.ru/lib_na/int_ae/int_ae6.htm (пункт 6.5)&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
Вычислительное ядро рассматриваемого алгоритма (наиболее ресурсно-затратная часть алгоритма) -  формирование на каждом шаге цикла промежуточного вектора &amp;lt;math&amp;gt;z&amp;lt;/math&amp;gt;, вычисляемого по формуле: &amp;lt;math&amp;gt;z = A\,q_j&amp;lt;/math&amp;gt;. Данная операция, по сравнению с другими операциями алгоритма, затратна и требовательна, как с точки зрения количества производимых операций, так и с точки зрения объема оперируемых данных. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Например, умножение матрицы размера &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;n\times n&amp;lt;/math&amp;gt; на вектор длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; требует: &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;n^2+(n-1)n = 2n^2-n&amp;lt;/math&amp;gt; операций умножения и сложения. В свою очередь аналогичная операция умножения матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;(n+1)\times (n+1)&amp;lt;/math&amp;gt; на вектор длины &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;(n+1)&amp;lt;/math&amp;gt; требует: &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;2n^2+3n+1&amp;lt;/math&amp;gt;  операций умножения и сложения. То есть повышение размерности задачи всего на 1 увеличивает число необходимых действий в этом шаге алгоритма на: &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;4n+1&amp;lt;/math&amp;gt;. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Так же, стоит помнить, что, согласно разделу 1.2, данную операцию умножения матрицы на вектор необходимо выполнить &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;k&amp;lt;/math&amp;gt; раз. Нетрудно понять, насколько возрастает и колоссален масштаб операций, если в задачах, где критична точность, размерности &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; могут иметь порядок &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;10^5&amp;lt;/math&amp;gt; или даже более.&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
Как уже было упомянуто в данной статье в описании алгоритма, рассматриваемый алгоритм состоит из двух последовательно выполненных алгоритмов: метод Ланцоша для построения последовательности подпространств Крылова и ортонормированных векторов Ланцоша и процедура Рэлея-Ритца получения оптимальных приближений собственных значений и соответствующих собственных векторов исходной матрицы.&lt;br /&gt;
&lt;br /&gt;
В первой части алгоритма, где итерационно строятся Крыловское подпространство и трёхдиагональная матрица &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&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 style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; разреженная. Именно она подлежит оптимизации с использованием техник распараллеливания, поскольку она является вычислительным ядром алгоритма, а весь упомянутый процесс построения матрицы &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&amp;lt;/math&amp;gt; выполняется последовательно.&lt;br /&gt;
&lt;br /&gt;
Рассмотрим вторую часть алгоритма - поиск собственных значений сформированной матрицы &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&amp;lt;/math&amp;gt;.&amp;lt;br&amp;gt;&lt;br /&gt;
Далее, наглядно, в виде псевдокода, представлен, упомянутый в разделе 1.2, QR-алгоритм (аналогично можно рассмотреть и QL-алгоритм) со сдвигами Релэя, который весьма популярен на практике.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{align}&lt;br /&gt;
\mathbf{Input}: \;&amp;amp;tridiagonal\;\;matrix \;T\;with\;\;n\times n\;\;size\\&lt;br /&gt;
T^{(0)}&amp;amp;:=T\\&lt;br /&gt;
\mathbf{for}&amp;amp; \;\;m=n,...,2 \;\; \mathbf{do}\\&lt;br /&gt;
&amp;amp;k=0\\&lt;br /&gt;
&amp;amp; \mathbf{repeat}\\&lt;br /&gt;
&amp;amp; \quad \;\; k=k+1\\&lt;br /&gt;
&amp;amp; \quad \;\; \mu^{(k)}=T_{m,m}^{(k-1)}\\&lt;br /&gt;
&amp;amp; \quad \;\; Q^{(k)}R^{(k)}=T^{(k-1)}-\mu^{(k)}I\;\;using\;\;QR\;decomposition\\&lt;br /&gt;
&amp;amp; \quad \;\; T^{(k)}=R^{(k)}Q^{(k)}+\mu^{(k)}I\\&lt;br /&gt;
&amp;amp; \mathbf{until} \;\;\; |T_{m,m-1}^{(k)}| \;is\;\;small\;\;enough\\&lt;br /&gt;
&amp;amp; Save  \;\;T_{m,m}^{(k)} \;\;as\;\; converged\;\;eigenvalue\;of\;T\\ &lt;br /&gt;
&amp;amp; Remove \;\boldsymbol{n}\,th\;row\;and\;\boldsymbol{n}\,th\;column\;\;from \;T \\&lt;br /&gt;
&amp;amp; and\;take\;this\;new\;cropped\;matrix\;as\;new\;T^{(0)}\;with\;\;(n-1)\times (n-1)\;\;size\\&lt;br /&gt;
 \mathbf{end}&amp;amp;\; \mathbf{for}&lt;br /&gt;
\end{align}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Малость наддиагональных и поддиагональных элементов матрицы (фраза &#039;&#039;&amp;quot;small enough&amp;quot;&#039;&#039; в псевдокоде) подразумевает:&lt;br /&gt;
&amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt; |T_{m,m-1}^{(k)}| \leq \varepsilon\,|T_{m,m}^{(k)}| \quad\quad &amp;lt;/math&amp;gt; , где &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt; \varepsilon &amp;lt;/math&amp;gt; - заданная точность&amp;lt;br&amp;gt;&lt;br /&gt;
Также вместо сдвига Релэя, обозначенного в алгоритме через &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;\mu^{(k)}&amp;lt;/math&amp;gt;, часто на практике используется сдвиг по Уилкинсону, который даёт гарантированную сходимость внедиагональных элементов матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt; T^{(k)} &amp;lt;/math&amp;gt;, формируемой на каждом шаге, к нулю, при этом жертвуя монотонностью их убывания.&amp;lt;ref&amp;gt;Голуб Дж., Ван Лоун Ч. - Матричные вычисления//М.: Мир. - 1999 (c. 378, вторая половина страницы)&amp;lt;/ref&amp;gt;&amp;lt;ref&amp;gt;Парлетт Б. Симметричная проблема собственных значений. Численные методы.,: Мир, 1983. с. 169&amp;lt;/ref&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Подробнее с различными сдвигами и соответствующими оценками скоростей и количествами операций можно ознакомиться по указанной ссылке:&amp;lt;ref&amp;gt;Парлетт Б. Симметричная проблема собственных значений. Численные методы.,: Мир, 1983. с. 179-182&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;Для совершения QR-декомпозиции на каждом шаге может использоваться любой из алгоритмов по ссылке.&amp;lt;ref&amp;gt;https://en.wikipedia.org/wiki/QR_decomposition&amp;lt;/ref&amp;gt; Подробные описания этих алгоритмов также доступны на данном ресурсе algowiki-project.&amp;lt;br&amp;gt;&lt;br /&gt;
Так как мы оперируем не обычной матрицей и даже не Хессенберговой, а симметричной и трёхдиагональной, то скорость таких алгоритмов значительно возрастёт. Например, согласно данному ресурсу &amp;lt;ref&amp;gt;http://algorithm.narod.ru/ln/eigen/ETridiag.html&amp;lt;/ref&amp;gt;, для QL-алгоритма с неявными сдвигами:&amp;lt;br&amp;gt;&lt;br /&gt;
Для трёхдиагональной матрицы объем арифметических действий составляет &amp;lt;math&amp;gt; O(n)&amp;lt;/math&amp;gt; на одну итерацию вместо &amp;lt;math&amp;gt; O(n^3)&amp;lt;/math&amp;gt; для матрицы общего вида, а число итераций для нахождения первых собственных значений примерно равно 4 - 5. Но на этих итерациях также уменьшаются внедиагональные элементы правого нижнего угла. И, таким образом, дальнейшие собственные значения ищутся значительно быстрее. Среднее число итераций на каждое собственное значение обычно составляет 1.3 - 1.6.&amp;lt;br&amp;gt; &lt;br /&gt;
Аналогично QL, QR-разложение трёхдиагольной матрицы также требует &amp;lt;math&amp;gt; O(n)&amp;lt;/math&amp;gt; флопов&amp;lt;ref&amp;gt;Голуб Дж., Ван Лоун Ч. - Матричные вычисления//М.: Мир. - 1999 (c. 378, начало раздела 8.2.2)&amp;lt;/ref&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Подводя итог, во второй части алгоритма Ланцоша можно выделить следующие макрооперации:&lt;br /&gt;
* умножение матрицы на вещественное число;&lt;br /&gt;
* перемножение матриц;&lt;br /&gt;
* умножение и сравнение вещественных чисел;&lt;br /&gt;
* + набор других макроопераций в зависимости от выбора метода, с помощью которого будет совершаться сама QR или QL-декомпозиция (выше продемонстрированы, уже, как минимум, 3 разных способа).&lt;br /&gt;
Так же, важно заметить, что набор макропераций может быть несколько другим, если выбрать какой-либо иной современный метод поиска собственных чисел трёхдиагональной матрицы, не использующий QR и QL разложения(факторизацию). Два таких метода были упомянуты в пункте 1.2.&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
С целью полностью не дублировать раздел 1.2 данной статьи, где представлен наглядный и доступный для понимания псевдокод алгоритма, постараемся лишь коротко просуммировать и обобщить весь перечень последовательных действий в рассматриваемом алгоритме.&lt;br /&gt;
&lt;br /&gt;
В качестве входных данных имеем: вещественная симметричная матрица &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; размера &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;n\times n&amp;lt;/math&amp;gt;, известный вещественный вектор &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;b&amp;lt;/math&amp;gt; длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; и число &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;n&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Далее:&lt;br /&gt;
* Инициализируем вещественную константу &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;\beta_0&amp;lt;/math&amp;gt; и векторы &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;q_0&amp;lt;/math&amp;gt; и &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;q_1&amp;lt;/math&amp;gt;&lt;br /&gt;
* Итерационно для всех &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j=1,...,k&amp;lt;/math&amp;gt;:&lt;br /&gt;
** Вычисляем вспомогательный вектор &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt;, используя умножение матрицы на вектор&lt;br /&gt;
** Вычисляем, используя скалярное произведение векторов, значение &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;\alpha_j&amp;lt;/math&amp;gt; - элемент на главной диагонали трёхдиагональной матрицы &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&amp;lt;/math&amp;gt;&lt;br /&gt;
** Вычисляем по формуле новое значение и перезаписываем вектор &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt;&lt;br /&gt;
** Вычисляем значение &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;\beta_j&amp;lt;/math&amp;gt; - элементы непосредственно над и под главной диагональю той же матрицы &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&amp;lt;/math&amp;gt;&lt;br /&gt;
** Вычисляем, зная вектор &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt;,  очередной столбец матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;Q&amp;lt;/math&amp;gt;, он же вектор Ланцоша : &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;\,\,q_{j+1}&amp;lt;/math&amp;gt;&lt;br /&gt;
** Теперь, когда матрица &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&amp;lt;/math&amp;gt; сформирована на очередном шаге, находим её собственные значения и вектора любым доступным способом, о чём было подробно сказано в пункте 1.2&lt;br /&gt;
** Переходим на следующую итерацию: &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j&amp;lt;/math&amp;gt;++&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
Оценим количество операций и сложность последовательного алгоритма, изложенного в предыдущем разделе.&lt;br /&gt;
*Для вычисления вектора &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt; умножается матрица размера &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;n\times n&amp;lt;/math&amp;gt; на вектор длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt;, и потребуется &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n^2&amp;lt;/math&amp;gt; операций умножения и &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n^2&amp;lt;/math&amp;gt; операций сложения.&lt;br /&gt;
*Умножение векторов &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;q^T_j&amp;lt;/math&amp;gt; и &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt; длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; потребует &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; операций умножения и &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; операций сложения.&lt;br /&gt;
*При вычислении нового значения вектора &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt; поэлементное сложение двух векторов длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; требует &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; операций сложения.&lt;br /&gt;
*Умножение вектора длины &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; на вещественное число требует &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; операций умножения.&lt;br /&gt;
*Нахождение квадратичной нормы вектора &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt;  длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; требует &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; умножений и &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; сложений и ещё 1 операцию извлечения квадратного корня.&lt;br /&gt;
*Заключительное нахождение собственных значений и собственных векторов трёхдиагональной матрицы &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;T_j&amp;lt;/math&amp;gt; размера &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j\times j&amp;lt;/math&amp;gt; с помощью QR-алгоритма потребует в худшем случае &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(j^3)&amp;lt;/math&amp;gt; операций.&amp;lt;ref&amp;gt;http://num-anal.srcc.msu.ru/lib_na/int_ae/int_ae6.htm (пункт 6.2, &amp;quot;Скорость сходимости при этом всегда не хуже квадратичной и почти всегда лучше кубической.&amp;quot;)&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Посчитаем теперь суммарное количество простейших операций на одной итерации алгоритма (без учёта записей в память):&lt;br /&gt;
*&amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n^2+5\,n&amp;lt;/math&amp;gt; операций умножения/деления&lt;br /&gt;
*&amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n^2+4\,n&amp;lt;/math&amp;gt; операций сложения/вычитания&lt;br /&gt;
*1 операция извлечения квадратного корня&amp;lt;br&amp;gt;&lt;br /&gt;
Отдельно после всех итераций при &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j=k&amp;lt;/math&amp;gt; :&lt;br /&gt;
*&amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(k^3)&amp;lt;/math&amp;gt; операций для поиска собственных значений и собственных векторов трёхдиагональной матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_k&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Итого можно утверждать следующее:&lt;br /&gt;
&lt;br /&gt;
Последовательная сложность одной итерации рассматриваемого алгоритма:  &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(n ^ 2) &amp;lt;/math&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Суммарная сложность алгоритма (&amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;/math&amp;gt; итераций): &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(k\,n ^ 2) + O(k ^ 3)&amp;lt;/math&amp;gt; &amp;lt;ref&amp;gt;Здесь мы полагаем, что мы не вычисляем собственные значения и векторы матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_j&amp;lt;/math&amp;gt; на каждом промежуточном шаге, а лишь единожды затрачиваем &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;O(k ^ 3)&amp;lt;/math&amp;gt; действий в конце для нахождения &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;/math&amp;gt; собственных значений и векторов матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_k&amp;lt;/math&amp;gt;&amp;lt;/ref&amp;gt; &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
На практике же обычно рассматривается число &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;&amp;lt;n&amp;lt;/math&amp;gt;, поэтому второе слагаемое можно опустить.&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
На рис. 1 продемонстрирован граф одной итерации (при каком-либо произвольном значении итератора &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j&amp;lt;/math&amp;gt;) описанного алгоритма без отображения входных и выходных данных. Наглядно продемонстрированы связи между всеми действиями, и с помощью деления на &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; потоков показано, какие операции возможно выполнять параллельно на каждом шаге с целью оптимизации и экономии машинного времени. В результате, после параллельно выполненных операций &#039;&#039;&#039;Division&#039;&#039;&#039; на заключительном ярусе, на выходе имеем значение следующего вектора Ланцоша &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;q_{j+1}&amp;lt;/math&amp;gt;, после чего следует переход на следующую итерацию, и процесс повторяется.&lt;br /&gt;
&lt;br /&gt;
[[Файл:Levin_graph.png|600px|thumb|center|Рис. 1]] &amp;lt;br&amp;gt;&lt;br /&gt;
Обозначения на рисунке: &amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Simp&#039;&#039;&#039; (от англ. simple) - операции сложения и умножения вещественных чисел при вычислении произведения матрицы на вектор;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Vec mult&#039;&#039;&#039; (от англ. vectors multiplication) - операция скалярного умножения двух векторов;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Vec subtr&#039;&#039;&#039; (от англ. vectors subtraction, из-за использованных в операции вычитаний векторов) - операция умножения вектора на число (выполняется дважды) и формирование нового значения &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;z_{new}&amp;lt;/math&amp;gt; по формуле: &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;z_{new} = z - \alpha_j q_j - \beta_{j-1}q_{j-1} \;&amp;lt;/math&amp;gt;;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;||\cdot||&amp;lt;/math&amp;gt; - операция вычисления нормы вектора;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Division&#039;&#039;&#039; - операция деления вектора на вещественное число  &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;\beta_j&amp;lt;/math&amp;gt; &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Важно отметить, что упомянутые выше операции также легко поддаются оптимизации. Например, попарные умножения вещественных координат векторов при вычислении скалярного произведения также легко выполняются параллельно на &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; потоках, а затем можно применить суммирование методом сдваивания, о котором сказано в следующем разделе. Умножение или деление вектора на вещественное число являющееся, по определению, умножением или делением всех его координат на это число тоже может быть выполнено эффективнее, если мы используем &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; потоков, а не выполняем эти действия последовательно.&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
Параллельные операции возможны только внутри итераций, так как рассматриваемый алгоритм является итерационным, и сами итерации строго последовательны.&amp;lt;br&amp;gt;&lt;br /&gt;
Рассмотрим в этом разделе подробнее, какой выигрыш мы можем получить при распараллеливании операций внутри одной итерации согласно графу из предыдущего раздела.&lt;br /&gt;
&lt;br /&gt;
Умножение вещественной симметричной матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; размера &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;n\times n&amp;lt;/math&amp;gt; на вектор &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;b&amp;lt;/math&amp;gt; длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; требует последовательного выполнения &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; ярусов умножений и сложений. Сложение элементов вектора длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; на каждом шаге перемножения можно оптимизировать и выполнить за &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;\log_2 n&amp;lt;/math&amp;gt; действий, если применять метод сдваивания.&lt;br /&gt;
&lt;br /&gt;
Дальнейшие операции выполняются последовательно, а вычисление значений векторов происходит за один ярус операций сложения или умножения.&lt;br /&gt;
&lt;br /&gt;
Ресурс параллелизма алгоритма вычисления собственных значений построенной трёхдиагональной матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_k&amp;lt;/math&amp;gt; размера &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k\times k&amp;lt;/math&amp;gt; зависит от выбранного алгоритма (об этих алгоритмах подробнее было сказано в разделах 1.2 и 1.4). Будет очень затратно с точки зрения объёма материала пытаться рассмотреть пусть даже часть этих методов в этой статье, а так же тонкости их распараллеливания. Предлагаем читателям при желании самим ознакомиться с этими алгоритмами на данном ресурсе или прибегнув к иным источникам.&lt;br /&gt;
&lt;br /&gt;
При классификации по высоте ЯПФ, таким образом, алгоритм Ланцоша без переортогонализации относится к алгоритмам с &#039;&#039;логарифмической сложностью&#039;&#039;, и его сложность равна &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(\log_2 n)&amp;lt;/math&amp;gt; с важным замечанием, что это сложность только одной итерации, а максимум в алгоритме может быть выполнено последовательно &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;/math&amp;gt; таких однотипных итераций, если не будет осуществлён ранний выход из цикла. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Несмотря на то, что на графе в предыдущем разделе для лучшей визуализации и понимания было изображено &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; потоков (никаких допущений мы не делали и нарушений с точки зрения логики и математики нет, можно изобразить большее число потоков, просто часть времени некоторые из них могут бездействовать и не использоваться), на самом деле правильным и разумным будет реализовать начальное параллельное выполнение &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n^2&amp;lt;/math&amp;gt; операций умножения всех вещественных элементов матрицы &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;A&amp;lt;/math&amp;gt; на соответствующие элементы вектора &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;q_j&amp;lt;/math&amp;gt;, после чего применять тот же самый упомянутый метод сдваивания. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Поэтому при классификации по ширине ЯПФ его сложность будет &#039;&#039;квадратичной&#039;&#039; и равна &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(n^2)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
&#039;&#039;&#039;Входные данные алгоритма:&#039;&#039;&#039; вещественная симметричная &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; размера &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;n\times n&amp;lt;/math&amp;gt;, вещественный вектор &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;b&amp;lt;/math&amp;gt; длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt;, и одно целое число &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;k&amp;lt;/math&amp;gt;, означающее количество итераций.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём входных данных:&#039;&#039;&#039; &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;n^2 +n + 1 &amp;lt;/math&amp;gt;. Если учесть, что матрица симметричная и достаточно для её однозначного определения задать элементы на главной диагонали и элементы над или под ней, то можно сократить объём входных данных с целью экономии памяти до: &amp;lt;math&amp;gt;\ \frac{n^2-n}{2}+n+n+1 =\frac{n^2+3n}{2} + 1&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные алгоритма:&#039;&#039;&#039; вектор собственных значений &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;\Theta^k&amp;lt;/math&amp;gt; длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;/math&amp;gt;, матрица &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;S^k&amp;lt;/math&amp;gt; из соответствующих собственных векторов размера &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n\times k&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём выходных данных:&#039;&#039;&#039; &amp;lt;math&amp;gt;k\;(n + 1)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
В данном разделе перечислены без какой-либо хронологии или связи друг с другом наиболее важные и разнообразные свойства алгоритма, на которые стоит и полезно обратить внимание, а также которые выгодно отличают его от схожих алгоритмов, решающих ту же задачу.&amp;lt;br&amp;gt;&lt;br /&gt;
1) Отношение последовательной сложности алгоритма к параллельной,с учётом &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;/math&amp;gt; итераций, равно &amp;lt;math&amp;gt;\;\;\frac{kn^2}{k \log_2{n}}=\frac{n^2}{\log_2{n}}&amp;lt;/math&amp;gt;;&amp;lt;br&amp;gt;&lt;br /&gt;
2) Вычислительная мощность алгоритма, как отношение числа операций к суммарному объему входных и выходных данных, равна &amp;lt;math style=&amp;quot;vertical-align:-70%&amp;gt;\;\;\frac{k\,n^2}{0.5\,n^2+1.5\,n+k\,n+k+1}&amp;lt;/math&amp;gt; и &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;\approx 2\,k&amp;lt;/math&amp;gt;, так как на практике верно отношение &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;&amp;lt;n&amp;lt;/math&amp;gt; ;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
3) Для собственных значений формируемых матриц &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_j&amp;lt;/math&amp;gt; верно отношение (следствие теоремы Коши о перемежаемости): &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;\lambda_i(T_{k+1})\geq \lambda_i(T_{k})\geq \lambda_{i+1}(T_{k+1})\geq \lambda_{i+1}(T_{k})&amp;lt;/math&amp;gt; ;&amp;lt;ref&amp;gt;James W. Demmel - Вычислительная линейная алгебра. Теория и приложения //Мир. - 2001 (c. 383)&amp;lt;/ref&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
4) Крайние (наибольшие и наименьшие) собственные значения матриц &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_j&amp;lt;/math&amp;gt; сходятся к крайним собственным значениям матрицы &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;A&amp;lt;/math&amp;gt; первыми (это часто происходит уже на ранних шагах при &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j\approx 2\,\sqrt{n}&amp;lt;/math&amp;gt;&amp;lt;ref&amp;gt;http://num-anal.srcc.msu.ru/lib_na/int_ae/int_ae6.htm (пункт 6.5)&amp;lt;/ref&amp;gt;), а собственные значения в середине спектра - последними;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
5) Из-за ограниченной точности постепенно теряется ортогональность вектора Ланцоша &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;q_j&amp;lt;/math&amp;gt; к предыдущим векторам Ланцоша, поэтому необходимо примерно каждые 10-15 итераций проводить дорогостоящую операцию реортогонализации, но это уже будет иной алгоритм с очень малым различием в одной операции и в программном коде, реализующем его, соответственно; &amp;lt;ref&amp;gt;Sam Handler - The Lanczos Algorithm For Large-Scale Eigenvalue Problems (08.01.07), slide №8&amp;lt;/ref&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
6) Эффективность и быстрота выполнения алгоритма очень сильно зависит от скорости памяти (диска). Согласно тесту только &#039;&#039;6%&#039;&#039; времени работы программы приходится на вычисления, остальное время затрачивается на ожидание отклика диска;&amp;lt;ref&amp;gt;Sam Handler - The Lanczos Algorithm For Large-Scale Eigenvalue Problems (08.01.07), slide №10&amp;lt;/ref&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
7) Метод Ланцоша удобен тем, что не требует хранения исходной матрицы полным массивом: метод использует исходную матрицу только в операциях умножения матрицы на вектор, что позволяет эффективно использовать разреженность матрицы или регулярность структуры матрицы. Поэтому метод Ланцоша может быть использован для матриц таких больших порядков, когда методы вращений и отражений не могут быть применены.&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;
По заданию, во второй части требовалось описать только разделы 2.4 и 2.7, прошу не спрашивать с меня все разделы 2.1-2.6. Надеюсь на понимание, мне физически не хватает времени на это задание + 2 других в течение семестра, делаю всё, что в моих силах :)&lt;br /&gt;
&lt;br /&gt;
== Существующие реализации алгоритма ==&lt;br /&gt;
Несмотря на то, что алгоритм является далеко не самым популярным, алгоритмом, про который нельзя сказать, что он всегда «на слуху», на сегодняшний день существует множество реализаций на различных популярных языках.&amp;lt;br&amp;gt;&lt;br /&gt;
Перечислим далее некоторые из них, указывая язык программирования, лежащий в их основе, и некоторые важные характеристики, которые обсуждались в статье ранее:&lt;br /&gt;
*&#039;&#039;Code on netlib.org by Jane Cullum and Ralph Willoughby&#039;&#039; (&#039;&#039;&#039;Fortran 77&#039;&#039;&#039;; без реортогонализации векторов; без реализации распараллеливания)&amp;lt;ref&amp;gt;http://www.netlib.org/lanczos/leval&amp;lt;/ref&amp;gt;&lt;br /&gt;
*&#039;&#039;Lanczos algorithm on freesourcecode.net&#039;&#039; (&#039;&#039;&#039;Matlab&#039;&#039;&#039;; присутствует реортогонализация векторов; без реализации распараллеливания)&amp;lt;ref&amp;gt;http://freesourcecode.net/matlabprojects/61741/lanczos-algorithm--in-matlab&amp;lt;/ref&amp;gt;&lt;br /&gt;
*&#039;&#039;Lanczos for eigenvalues in Numerical Linear Algebra, Spring 2007&#039;&#039; (&#039;&#039;&#039;Matlab&#039;&#039;&#039;; частичная или полная реортогонализация - доступны оба варианта; без реализации распараллеливания)&amp;lt;ref&amp;gt;Ссылки на файлы lanso.m и lanfu.m можно найти на https://www.nada.kth.se/~ruhe/2D5219/labs2007.html&amp;lt;/ref&amp;gt;&lt;br /&gt;
*&#039;&#039;Planso&#039;&#039; (название происходит от parallel Lanso.f) &#039;&#039;code by Kesheng Wu and Horst D. Simon&#039;&#039; (&#039;&#039;&#039;Fortran 77&#039;&#039;&#039;; частичная реортогонализация векторов; использование MPI для коммуникаций)&amp;lt;ref&amp;gt;https://github.com/jiahao/planso.jl/tree/master/external/PLAN/plan К сожалению, ссылка в описании пакета на github, ведущая на сайт National Energy Research Scientific Computing Center (NERSC), с более подробной информацией о данной программе больше не активна и выдаёт результат &#039;&#039;Page not found&#039;&#039;&amp;lt;/ref&amp;gt; &lt;br /&gt;
* &#039;&#039;Lanczos.cpp in the Vienna Computing Library&#039;&#039;  (&#039;&#039;&#039;C++&#039;&#039;&#039;, частичная реортогонализация, без реализации распараллеливания) &amp;lt;ref&amp;gt;http://viennacl.sourceforge.net/doc/lanczos_8cpp_source.html&amp;lt;/ref&amp;gt;&lt;br /&gt;
* &#039;&#039;Parallel Eigen Values code using C++ AMP on microsoft msdn blog&#039;&#039; (&#039;&#039;&#039;C++&#039;&#039;&#039;; ? ; распараллеливание есть и реализовано через C++ AMP) &amp;lt;ref&amp;gt;https://blogs.msdn.microsoft.com/nativeconcurrency/2013/12/20/eigen-values/ Подробнее о C++ Accelerated Massive Parallelism можно почитать здесь: https://msdn.microsoft.com/ru-ru/library/hh265137(v=vs.140).aspx или здесь: http://professorweb.ru/my/csharp/optimization/level4/4_6.php &amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;br /&gt;
[[en:Description of algorithm properties and structure]]&lt;/div&gt;</summary>
		<author><name>AleksLevin</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:AleksLevin/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%9B%D0%B0%D0%BD%D1%86%D0%BE%D1%88%D0%B0_%D0%B2%D1%8B%D1%87%D0%B8%D1%81%D0%BB%D0%B5%D0%BD%D0%B8%D1%8F_%D1%81%D0%BE%D0%B1%D1%81%D1%82%D0%B2%D0%B5%D0%BD%D0%BD%D1%8B%D1%85_%D0%B7%D0%BD%D0%B0%D1%87%D0%B5%D0%BD%D0%B8%D0%B9_%D1%81%D0%B8%D0%BC%D0%BC%D0%B5%D1%82%D1%80%D0%B8%D1%87%D0%BD%D0%BE%D0%B9_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86%D1%8B_%D0%B4%D0%BB%D1%8F_%D1%82%D0%BE%D1%87%D0%BD%D0%BE%D0%B9_%D0%B0%D1%80%D0%B8%D1%84%D0%BC%D0%B5%D1%82%D0%B8%D0%BA%D0%B8_(%D0%B1%D0%B5%D0%B7_%D0%BF%D0%B5%D1%80%D0%B5%D0%BE%D1%80%D1%82%D0%BE%D0%B3%D0%BE%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D0%B8)&amp;diff=19947</id>
		<title>Участник:AleksLevin/Алгоритм Ланцоша вычисления собственных значений симметричной матрицы для точной арифметики (без переортогонализации)</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:AleksLevin/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%9B%D0%B0%D0%BD%D1%86%D0%BE%D1%88%D0%B0_%D0%B2%D1%8B%D1%87%D0%B8%D1%81%D0%BB%D0%B5%D0%BD%D0%B8%D1%8F_%D1%81%D0%BE%D0%B1%D1%81%D1%82%D0%B2%D0%B5%D0%BD%D0%BD%D1%8B%D1%85_%D0%B7%D0%BD%D0%B0%D1%87%D0%B5%D0%BD%D0%B8%D0%B9_%D1%81%D0%B8%D0%BC%D0%BC%D0%B5%D1%82%D1%80%D0%B8%D1%87%D0%BD%D0%BE%D0%B9_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86%D1%8B_%D0%B4%D0%BB%D1%8F_%D1%82%D0%BE%D1%87%D0%BD%D0%BE%D0%B9_%D0%B0%D1%80%D0%B8%D1%84%D0%BC%D0%B5%D1%82%D0%B8%D0%BA%D0%B8_(%D0%B1%D0%B5%D0%B7_%D0%BF%D0%B5%D1%80%D0%B5%D0%BE%D1%80%D1%82%D0%BE%D0%B3%D0%BE%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D0%B8)&amp;diff=19947"/>
		<updated>2016-12-02T19:23:56Z</updated>

		<summary type="html">&lt;p&gt;AleksLevin: /* Макроструктура алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Основные авторы описания: Левин А.Д.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{algorithm&lt;br /&gt;
| name              = Алгоритм Ланцоша для точной арифметики (без переортогонализации)&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(k\,n^2)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(k\log_2 n)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;\frac{n^2+3n}{2} + 1&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;k\;(n + 1)&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритмов =&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Данный алгоритм появился в 1950 г. и носит имя венгерского физика и математика Корнелия Ланцоша (венг. Lánczos Kornél). Алгоритм Ланцоша относится к итерационным методам вычисления собственных значений для матриц столь больших порядков &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt; n&amp;lt;/math&amp;gt;, что к ним нельзя применить прямые методы из-за ограничений по времени и памяти.&lt;br /&gt;
&lt;br /&gt;
Сам Ланцош указывал, что его метод предназначен для отыскания нескольких собственных векторов симметричных матриц, хотя к методу сразу было обращено внимание, как к способу приведения всей матрицы к трёхдиагональному виду. Двадцатью годами позже канадский математик Крис Пэж показал, что, несмотря на чувствительность к округлениям, алгоритм Ланцоша - эффективное средство вычисления некоторых &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; собственных чисел и соответствующих им собственных векторов. &amp;lt;ref&amp;gt;Парлетт Б. - Симметричная проблема собственных значений. Численные методы //М.: Мир. - 1983. (c. 276)&amp;lt;/ref&amp;gt;&lt;br /&gt;
Обычно число &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; берут в два раза больше, чем количество собственных значений матрицы, которые поставлена цель найти, и оно имеет порядок не более &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;10^2&amp;lt;/math&amp;gt;.&amp;lt;ref&amp;gt;Susan W. Bostic - Lanczos Eigensolution Method for High-Perfomance Computers, page 7&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Алгоритм Ланцоша для вычисления собственных значений симметричной матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; соединяет в себе метод Ланцоша для построения последовательности подпространств Крылова и ортонормированных векторов Ланцоша и процедуру Рэлея-Ритца получения оптимальных приближений собственных значений и соответствующих собственных векторов исходной матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt;.&amp;lt;ref&amp;gt;James W. Demmel - Вычислительная линейная алгебра. Теория и приложения //Мир. - 2001 (c. 381)&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
В данной статье рассматривается вариант алгоритма Ланцоша, в котором опущено влияние ошибок округления на вычислительный процесс, хотя на практике этому посвящается отдельное внимание и существуют различные методы решения данной проблемы, такие как частичная или полная переортогонализация. Этим модифицированным методам посвящены отдельные статьи на данном ресурсе.&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
Обозначения и формулы, используемые в данном разделе, взяты из литературы, указанной по ссылке.&amp;lt;ref&amp;gt;James W. Demmel - Вычислительная линейная алгебра. Теория и приложения //Мир. - 2001 (c. 313, &#039;&#039;&amp;lt;math&amp;gt; \S &amp;lt;/math&amp;gt; 6.6 Методы Крыловского подпространства&#039;&#039;)&amp;lt;/ref&amp;gt; &lt;br /&gt;
&lt;br /&gt;
Алгоритм Ланцоша для вычисления &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; собственных значений и собственных векторов вещественной симметричной матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A=A^T&amp;lt;/math&amp;gt; в точной арифметике: &amp;lt;ref&amp;gt;James W. Demmel - Вычислительная линейная алгебра. Теория и приложения //Мир. - 2001 (c. 381)&amp;lt;/ref&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{align}&lt;br /&gt;
q_1 = &amp;amp; \,\frac{b}{\|b\|_2},\; \beta_0 = 0,\; q_0 = 0\\&lt;br /&gt;
\mathbf{for} \; &amp;amp; j = 1 \; to \; k \,\; \mathbf{do} \\&lt;br /&gt;
&amp;amp; z = A\,q_j\\&lt;br /&gt;
&amp;amp; \alpha_j = q^T_j z\\&lt;br /&gt;
&amp;amp; z = z - \alpha_j q_j - \beta_{j-1}q_{j-1}\\&lt;br /&gt;
&amp;amp; \beta_j = \|z\|_2\\&lt;br /&gt;
&amp;amp; \mathbf{If} \; (\beta_j == 0) \; \mathbf{then}\; stop\; the\; algorithm \\ &lt;br /&gt;
&amp;amp; \;  q_{j+1} = \frac{z}{\beta_j} \\&lt;br /&gt;
&amp;amp; compute\; eigenvalues\; and \;eigenvectors\;of \;matrix \;\;T_j= Q^T_j A Q\;\;and\;estimate \;the\; errors\\&lt;br /&gt;
\mathbf{end} \; &amp;amp; \mathbf{for}&lt;br /&gt;
\end{align}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
В продемонстрированном выше алгоритме &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;b&amp;lt;/math&amp;gt; - заданный вещественный вектор. Также полагается известным алгоритм вычисления произведения матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; на вектор &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;x&amp;lt;/math&amp;gt;. &lt;br /&gt;
Введём матрицу Крылова, определяемую следующим соотношением: &amp;lt;math&amp;gt;K_j = [b,Ab,A^2b,...,A^{j-1}b]&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Далее, на практике, матрица &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;K&amp;lt;/math&amp;gt; заменяется матрицей &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;Q&amp;lt;/math&amp;gt;, такой, что при любом числе &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; линейные оболочки первых &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; столбцов в &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;K&amp;lt;/math&amp;gt; и &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;Q&amp;lt;/math&amp;gt; являются одним и тем же подпространством.&amp;lt;ref&amp;gt;James W. Demmel - Вычислительная линейная алгебра. Теория и приложения //Мир. - 2001 (c. 315)&amp;lt;/ref&amp;gt; &lt;br /&gt;
Тогда матрица &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;Q&amp;lt;/math&amp;gt;, в отличие от матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;K&amp;lt;/math&amp;gt;, хорошо обусловлена и легко обратима. В результате получаем матрицу &amp;lt;math&amp;gt;Q_j = [q_1, q_2, \dots, q_j]&amp;lt;/math&amp;gt; размерности &amp;lt;math&amp;gt;n\times j&amp;lt;/math&amp;gt;, столбцы которой ортогональны, являются базисом подпространства Крылова и называются векторами Ланцоша.&lt;br /&gt;
&lt;br /&gt;
В алгоритме Ланцоша вычислению подлежит столько первых столбцов в матрице &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;Q_j&amp;lt;/math&amp;gt;, сколько необходимо для получения требуемого приближения к решению &amp;lt;math&amp;gt;A\,x\,=b\,\,(A\,x=\lambda \, x)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Получение нулевого &amp;lt;math&amp;gt;\beta_j&amp;lt;/math&amp;gt; в итерационном процессе - событие, желательное в том смысле, что оно свидетельствует о том, что найдено некоторое подпространство, являющееся в точности инвариантным, а все собственные значения матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;T_j&amp;lt;/math&amp;gt; являются собственными значениями матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt;. На практике же нулевое и близкие к нулю значения получаются редко.&amp;lt;ref&amp;gt;Голуб Дж., Ван Лоун Ч. - Матричные вычисления//М.: Мир. - 1999 (c. 429)&amp;lt;/ref&amp;gt; &lt;br /&gt;
&lt;br /&gt;
Затем на каждом шаге цикла формируется симметричная трёхдиагональная матрица &amp;lt;math&amp;gt;T_j = Q^T_j A Q&amp;lt;/math&amp;gt;, к которой применяется процесс Рэлея-Ритца для поиска её собственных значений (на практике для поиска этих собственных значений можно использовать любой из специальных методов в параграфе книги по ссылке).&amp;lt;ref&amp;gt;Голуб Дж., Ван Лоун Ч. - Матричные вычисления//М.: Мир. - 1999 (&amp;lt;math&amp;gt;\S&amp;lt;/math&amp;gt; 8.4)&amp;lt;/ref&amp;gt;  &lt;br /&gt;
Эти собственные значения, они же числа Ритца, и полагаются приближёнными собственными значениями исходной матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt;.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Существует множество методов для отыскания собственных значений вещественной симметричной трехдиагональной матрицы. Большинство из них требует &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt; операций &amp;lt;ref&amp;gt;Парлетт Б. Симметричная проблема собственных значений. Численные методы.,: Мир, 1983. с. 179-182&amp;lt;/ref&amp;gt;, но существуют и быстрые алгоритмы, требующие лишь &amp;lt;math&amp;gt;O(n\ln n)&amp;lt;/math&amp;gt; операций.&amp;lt;ref&amp;gt;https://en.wikipedia.org/wiki/Tridiagonal_matrix#Eigenvalues  Раздел eigenvalues&amp;lt;/ref&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Одним из возможных способов отыскать собственные значения симметричной трехдиагональной матрицы - прямое вычисление корней характеристического полинома &amp;lt;math&amp;gt;p_n(\lambda)&amp;lt;/math&amp;gt; через метод деления пополам, где формируется последовательность Штурма и локализуются собственные числа, являющиеся корнями характеристического полинома. Нахождение всех &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; собственных значений матрицы этим способом требует &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;2n^2t&amp;lt;/math&amp;gt; умножений и вычитаний, где &amp;lt;math&amp;gt;t&amp;lt;/math&amp;gt; - число сделанных шагов с применением метода деления пополам.&amp;lt;ref&amp;gt;Уилкинсон Дж. X. Алгебраическая проблема собственныx значений. Изд-во &amp;quot;Наука&amp;quot;, 1970. - глава 5, с. 272-278&amp;lt;/ref&amp;gt; Соответствующие собственные вектора могут быть найдены посредством обратных итераций за &amp;lt;math&amp;gt; O(n) &amp;lt;/math&amp;gt; флопов. &amp;lt;ref&amp;gt;Голуб Дж., Ван Лоун Ч. - Матричные вычисления//М.: Мир. - 1999 (c. 394-395)&amp;lt;/ref&amp;gt; &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;На практике, если требуется только небольшая часть от всей совокупности собственных векторов и значений, и матрица имеет Хессенбергову или трёхдиагональную форму, очень эффективными будут методы факторизации, как, например, QR-алгоритм или QL-алгоритм со сдвигами (c целью ускорить алгоритм и сделать порядок сходимости квадратичным) или же без них.&amp;lt;ref&amp;gt;http://algorithm.narod.ru/ln/eigen/ETridiag.html&amp;lt;/ref&amp;gt; &amp;lt;br&amp;gt;&lt;br /&gt;
Весьма молодые и не менее актуальные конкуренты QR и QL алгоритмов, применяющиеся для поиска собственных значений:&lt;br /&gt;
*Методы divide-and-conquer (разделяй и властвуй), появившиеся в 1980-ых годах &amp;lt;ref&amp;gt;https://algowiki-project.org/ru/Метод_&amp;quot;Разделяй_и_властвуй&amp;quot;_Завольсков/Землянский&amp;lt;/ref&amp;gt;&lt;br /&gt;
*Relatively robust representation methods, появившиеся в 1990-ых и позволяющие найти собственные числа симметричной матрицы порядка &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;n&amp;lt;/math&amp;gt; за &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt; операций&lt;br /&gt;
&lt;br /&gt;
Если требуется вычислить собственные векторы, то необходимо хранить вычисляемые векторы Ланцоша. Если работа при этом производится только с оперативной памятью, то при большом порядке исходной матрицы (а именно для таких матриц и предназначен метод Ланцоша) число шагов  &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;j&amp;lt;/math&amp;gt;, которые могут быть выполнены до того момента, как оперативная память будет исчерпана, будет очень незначительно, а следовательно, искомые собственные пары могут не успеть сойтись с требуемой точностью. В этом случае метод Ланцоша можно использовать итерационным образом: после выполнения заданного числа шагов процесс прерывается и, если еще не все требуемые пары Ритца сошлись с требуемой точностью, то формируется новый начальный вектор &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;q_1&amp;lt;/math&amp;gt;, являющийся линейной комбинацией векторов Ритца, еще не сошедшихся с заданной точностью, и процесс начинается заново.&amp;lt;ref&amp;gt;http://num-anal.srcc.msu.ru/lib_na/int_ae/int_ae6.htm (пункт 6.5)&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
Вычислительное ядро рассматриваемого алгоритма (наиболее ресурсно-затратная часть алгоритма) -  формирование на каждом шаге цикла промежуточного вектора &amp;lt;math&amp;gt;z&amp;lt;/math&amp;gt;, вычисляемого по формуле: &amp;lt;math&amp;gt;z = A\,q_j&amp;lt;/math&amp;gt;. Данная операция, по сравнению с другими операциями алгоритма, затратна и требовательна, как с точки зрения количества производимых операций, так и с точки зрения объема оперируемых данных. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Например, умножение матрицы размера &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;n\times n&amp;lt;/math&amp;gt; на вектор длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; требует: &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;n^2+(n-1)n = 2n^2-n&amp;lt;/math&amp;gt; операций умножения и сложения. В свою очередь аналогичная операция умножения матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;(n+1)\times (n+1)&amp;lt;/math&amp;gt; на вектор длины &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;(n+1)&amp;lt;/math&amp;gt; требует: &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;2n^2+3n+1&amp;lt;/math&amp;gt;  операций умножения и сложения. То есть повышение размерности задачи всего на 1 увеличивает число необходимых действий в этом шаге алгоритма на: &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;4n+1&amp;lt;/math&amp;gt;. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Так же, стоит помнить, что, согласно разделу 1.2, данную операцию умножения матрицы на вектор необходимо выполнить &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;k&amp;lt;/math&amp;gt; раз. Нетрудно понять, насколько возрастает и колоссален масштаб операций, если в задачах, где критична точность, размерности &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; могут иметь порядок &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;10^5&amp;lt;/math&amp;gt; или даже более.&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
Как уже было упомянуто в данной статье в описании алгоритма, рассматриваемый алгоритм состоит из двух последовательно выполненных алгоритмов: метод Ланцоша для построения последовательности подпространств Крылова и ортонормированных векторов Ланцоша и процедура Рэлея-Ритца получения оптимальных приближений собственных значений и соответствующих собственных векторов исходной матрицы.&lt;br /&gt;
&lt;br /&gt;
В первой части алгоритма, где итерационно строятся Крыловское подпространство и трёхдиагональная матрица &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&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 style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; разреженная. Именно она подлежит оптимизации с использованием техник распараллеливания, поскольку она является вычислительным ядром алгоритма, а весь упомянутый процесс построения матрицы &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&amp;lt;/math&amp;gt; выполняется последовательно.&lt;br /&gt;
&lt;br /&gt;
Рассмотрим вторую часть алгоритма - поиск собственных значений сформированной матрицы &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&amp;lt;/math&amp;gt;.&amp;lt;br&amp;gt;&lt;br /&gt;
Далее, наглядно, в виде псевдокода, представлен, упомянутый в разделе 1.2, QR-алгоритм (аналогично можно рассмотреть и QL-алгоритм) со сдвигами Релэя, который весьма популярен на практике.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{align}&lt;br /&gt;
\mathbf{Input}: \;&amp;amp;tridiagonal\;\;matrix \;T\;with\;\;n\times n\;\;size\\&lt;br /&gt;
T^{(0)}&amp;amp;:=T\\&lt;br /&gt;
\mathbf{for}&amp;amp; \;\;m=n,...,2 \;\; \mathbf{do}\\&lt;br /&gt;
&amp;amp;k=0\\&lt;br /&gt;
&amp;amp; \mathbf{repeat}\\&lt;br /&gt;
&amp;amp; \quad \;\; k=k+1\\&lt;br /&gt;
&amp;amp; \quad \;\; \mu^{(k)}=T_{m,m}^{(k-1)}\\&lt;br /&gt;
&amp;amp; \quad \;\; Q^{(k)}R^{(k)}=T^{(k-1)}-\mu^{(k)}I\;\;using\;\;QR\;decomposition\\&lt;br /&gt;
&amp;amp; \quad \;\; T^{(k)}=R^{(k)}Q^{(k)}+\mu^{(k)}I\\&lt;br /&gt;
&amp;amp; \mathbf{until} \;\;\; |T_{m,m-1}^{(k)}| \;is\;\;small\;\;enough\\&lt;br /&gt;
&amp;amp; Save  \;\;T_{m,m}^{(k)} \;\;as\;\; converged\;\;eigenvalue\;of\;T\\ &lt;br /&gt;
&amp;amp; Remove \;\boldsymbol{n}\,th\;row\;and\;\boldsymbol{n}\,th\;column\;\;from \;T \\&lt;br /&gt;
&amp;amp; and\;take\;this\;new\;cropped\;matrix\;as\;new\;T^{(0)}\;with\;\;(n-1)\times (n-1)\;\;size\\&lt;br /&gt;
 \mathbf{end}&amp;amp;\; \mathbf{for}&lt;br /&gt;
\end{align}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Малость наддиагональных и поддиагональных элементов матрицы (фраза &#039;&#039;&amp;quot;small enough&amp;quot;&#039;&#039; в псевдокоде) подразумевает:&lt;br /&gt;
&amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt; |T_{m,m-1}^{(k)}| \leq \varepsilon\,|T_{m,m}^{(k)}| \quad\quad &amp;lt;/math&amp;gt; , где &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt; \varepsilon &amp;lt;/math&amp;gt; - заданная точность&amp;lt;br&amp;gt;&lt;br /&gt;
Также вместо сдвига Релэя, обозначенного в алгоритме через &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;\mu^{(k)}&amp;lt;/math&amp;gt;, часто на практике используется сдвиг по Уилкинсону, который даёт гарантированную сходимость внедиагональных элементов матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt; T^{(k)} &amp;lt;/math&amp;gt;, формируемой на каждом шаге, к нулю, при этом жертвуя монотонностью их убывания.&amp;lt;ref&amp;gt;Голуб Дж., Ван Лоун Ч. - Матричные вычисления//М.: Мир. - 1999 (c. 378, вторая половина страницы)&amp;lt;/ref&amp;gt;&amp;lt;ref&amp;gt;Парлетт Б. Симметричная проблема собственных значений. Численные методы.,: Мир, 1983. с. 169&amp;lt;/ref&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Подробнее с различными сдвигами и соответствующими оценками скоростей и количествами операций можно ознакомиться по указанной ссылке:&amp;lt;ref&amp;gt;Парлетт Б. Симметричная проблема собственных значений. Численные методы.,: Мир, 1983. с. 179-182&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;Для совершения QR-декомпозиции на каждом шаге может использоваться любой из алгоритмов по ссылке.&amp;lt;ref&amp;gt;https://en.wikipedia.org/wiki/QR_decomposition&amp;lt;/ref&amp;gt; Подробные описания этих алгоритмов также доступны на данном ресурсе algowiki-project.&amp;lt;br&amp;gt;&lt;br /&gt;
Так как мы оперируем не обычной матрицей и даже не Хессенберговой, а симметричной и трёхдиагональной, то скорость таких алгоритмов значительно возрастёт. Например, согласно данному ресурсу &amp;lt;ref&amp;gt;http://algorithm.narod.ru/ln/eigen/ETridiag.html&amp;lt;/ref&amp;gt;, для QL-алгоритма с неявными сдвигами:&amp;lt;br&amp;gt;&lt;br /&gt;
Для трёхдиагональной матрицы объем арифметических действий составляет &amp;lt;math&amp;gt; O(n)&amp;lt;/math&amp;gt; на одну итерацию вместо &amp;lt;math&amp;gt; O(n^3)&amp;lt;/math&amp;gt; для матрицы общего вида, а число итераций для нахождения первых собственных значений примерно равно 4 - 5. Но на этих итерациях также уменьшаются внедиагональные элементы правого нижнего угла. И, таким образом, дальнейшие собственные значения ищутся значительно быстрее. Среднее число итераций на каждое собственное значение обычно составляет 1.3 - 1.6.&amp;lt;br&amp;gt; &lt;br /&gt;
Аналогично QL, QR-разложение трёхдиагольной матрицы также требует &amp;lt;math&amp;gt; O(n)&amp;lt;/math&amp;gt; флопов&amp;lt;ref&amp;gt;Голуб Дж., Ван Лоун Ч. - Матричные вычисления//М.: Мир. - 1999 (c. 378, начало раздела 8.2.2)&amp;lt;/ref&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Подводя итог, во второй части алгоритма Ланцоша можно выделить следующие макрооперации:&lt;br /&gt;
* умножение матрицы на вещественное число;&lt;br /&gt;
* перемножение матриц;&lt;br /&gt;
* умножение и сравнение вещественных чисел;&lt;br /&gt;
* + набор других макроопераций в зависимости от выбора метода, с помощью которого будет совершаться сама QR или QL-декомпозиция (выше продемонстрированы, уже, как минимум, 3 разных способа).&lt;br /&gt;
Так же, важно заметить, что набор макропераций может быть несколько другим, если выбрать какой-либо иной современный метод поиска собственных чисел трёхдиагональной матрицы, не использующий QR и QL разложения(факторизацию). Два таких метода были упомянуты в пункте 1.2.&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
С целью полностью не дублировать раздел 1.2 данной статьи, где представлен наглядный и доступный для понимания псевдокод алгоритма, постараемся лишь коротко просуммировать и обобщить весь перечень последовательных действий в рассматриваемом алгоритме.&lt;br /&gt;
&lt;br /&gt;
В качестве входных данных имеем: вещественная симметричная матрица &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; размера &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;n\times n&amp;lt;/math&amp;gt;, известный вещественный вектор &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;b&amp;lt;/math&amp;gt; длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; и число &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;n&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Далее:&lt;br /&gt;
* Инициализируем вещественную константу &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;\beta_0&amp;lt;/math&amp;gt; и векторы &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;q_0&amp;lt;/math&amp;gt; и &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;q_1&amp;lt;/math&amp;gt;&lt;br /&gt;
* Итерационно для всех &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j=1,...,k&amp;lt;/math&amp;gt;:&lt;br /&gt;
** Вычисляем вспомогательный вектор &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt;, используя умножение матрицы на вектор&lt;br /&gt;
** Вычисляем, используя скалярное произведение векторов, значение &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;\alpha_j&amp;lt;/math&amp;gt; - элемент на главной диагонали трёхдиагональной матрицы &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&amp;lt;/math&amp;gt;&lt;br /&gt;
** Вычисляем по формуле новое значение и перезаписываем вектор &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt;&lt;br /&gt;
** Вычисляем значение &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;\beta_j&amp;lt;/math&amp;gt; - элементы непосредственно над и под главной диагональю той же матрицы &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&amp;lt;/math&amp;gt;&lt;br /&gt;
** Вычисляем, зная вектор &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt;,  очередной столбец матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;Q&amp;lt;/math&amp;gt;, он же вектор Ланцоша : &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;\,\,q_{j+1}&amp;lt;/math&amp;gt;&lt;br /&gt;
** Теперь, когда матрица &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&amp;lt;/math&amp;gt; сформирована на очередном шаге, находим её собственные значения и вектора любым доступным способом, о чём было подробно сказано в пункте 1.2&lt;br /&gt;
** Переходим на следующую итерацию: &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j&amp;lt;/math&amp;gt;++&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
Оценим количество операций и сложность последовательного алгоритма, изложенного в предыдущем разделе.&lt;br /&gt;
*Для вычисления вектора &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt; умножается матрица размера &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;n\times n&amp;lt;/math&amp;gt; на вектор длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt;, и потребуется &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n^2&amp;lt;/math&amp;gt; операций умножения и &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n^2&amp;lt;/math&amp;gt; операций сложения.&lt;br /&gt;
*Умножение векторов &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;q^T_j&amp;lt;/math&amp;gt; и &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt; длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; потребует &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; операций умножения и &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; операций сложения.&lt;br /&gt;
*При вычислении нового значения вектора &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt; поэлементное сложение двух векторов длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; требует &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; операций сложения.&lt;br /&gt;
*Умножение вектора длины &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; на вещественное число требует &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; операций умножения.&lt;br /&gt;
*Нахождение квадратичной нормы вектора &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt;  длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; требует &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; умножений и &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; сложений и ещё 1 операцию извлечения квадратного корня.&lt;br /&gt;
*Заключительное нахождение собственных значений и собственных векторов трёхдиагональной матрицы &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;T_j&amp;lt;/math&amp;gt; размера &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j\times j&amp;lt;/math&amp;gt; с помощью QR-алгоритма потребует в худшем случае &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(j^3)&amp;lt;/math&amp;gt; операций.&amp;lt;ref&amp;gt;http://num-anal.srcc.msu.ru/lib_na/int_ae/int_ae6.htm (пункт 6.2, &amp;quot;Скорость сходимости при этом всегда не хуже квадратичной и почти всегда лучше кубической.&amp;quot;)&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Посчитаем теперь суммарное количество простейших операций на одной итерации алгоритма (без учёта записей в память):&lt;br /&gt;
*&amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n^2+5\,n&amp;lt;/math&amp;gt; операций умножения/деления&lt;br /&gt;
*&amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n^2+4\,n&amp;lt;/math&amp;gt; операций сложения/вычитания&lt;br /&gt;
*1 операция извлечения квадратного корня&amp;lt;br&amp;gt;&lt;br /&gt;
Отдельно после всех итераций при &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j=k&amp;lt;/math&amp;gt; :&lt;br /&gt;
*&amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(k^3)&amp;lt;/math&amp;gt; операций для поиска собственных значений и собственных векторов трёхдиагональной матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_k&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Итого можно утверждать следующее:&lt;br /&gt;
&lt;br /&gt;
Последовательная сложность одной итерации рассматриваемого алгоритма:  &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(n ^ 2) &amp;lt;/math&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Суммарная сложность алгоритма (&amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;/math&amp;gt; итераций): &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(k\,n ^ 2) + O(k ^ 3)&amp;lt;/math&amp;gt; &amp;lt;ref&amp;gt;Здесь мы полагаем, что мы не вычисляем собственные значения и векторы матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_j&amp;lt;/math&amp;gt; на каждом промежуточном шаге, а лишь единожды затрачиваем &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;O(k ^ 3)&amp;lt;/math&amp;gt; действий в конце для нахождения &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;/math&amp;gt; собственных значений и векторов матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_k&amp;lt;/math&amp;gt;&amp;lt;/ref&amp;gt; &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
На практике же обычно рассматривается число &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;&amp;lt;n&amp;lt;/math&amp;gt;, поэтому второе слагаемое можно опустить.&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
На рис. 1 продемонстрирован граф одной итерации (при каком-либо произвольном значении итератора &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j&amp;lt;/math&amp;gt;) описанного алгоритма без отображения входных и выходных данных. Наглядно продемонстрированы связи между всеми действиями, и с помощью деления на &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; потоков показано, какие операции возможно выполнять параллельно на каждом шаге с целью оптимизации и экономии машинного времени. В результате, после параллельно выполненных операций &#039;&#039;&#039;Division&#039;&#039;&#039; на заключительном ярусе, на выходе имеем значение следующего вектора Ланцоша &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;q_{j+1}&amp;lt;/math&amp;gt;, после чего следует переход на следующую итерацию, и процесс повторяется.&lt;br /&gt;
&lt;br /&gt;
[[Файл:Levin_graph.png|600px|thumb|center|Рис. 1]] &amp;lt;br&amp;gt;&lt;br /&gt;
Обозначения на рисунке: &amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Simp&#039;&#039;&#039; (от англ. simple) - операции сложения и умножения вещественных чисел при вычислении произведения матрицы на вектор;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Vec mult&#039;&#039;&#039; (от англ. vectors multiplication) - операция скалярного умножения двух векторов;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Vec subtr&#039;&#039;&#039; (от англ. vectors subtraction, из-за использованных в операции вычитаний векторов) - операция умножения вектора на число (выполняется дважды) и формирование нового значения &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;z_{new}&amp;lt;/math&amp;gt; по формуле: &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;z_{new} = z - \alpha_j q_j - \beta_{j-1}q_{j-1} \;&amp;lt;/math&amp;gt;;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;||\cdot||&amp;lt;/math&amp;gt; - операция вычисления нормы вектора;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Division&#039;&#039;&#039; - операция деления вектора на вещественное число  &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;\beta_j&amp;lt;/math&amp;gt; &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Важно отметить, что упомянутые выше операции также легко поддаются оптимизации. Например, попарные умножения вещественных координат векторов при вычислении скалярного произведения также легко выполняются параллельно на &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; потоках, а затем можно применить суммирование методом сдваивания, о котором сказано в следующем разделе. Умножение или деление вектора на вещественное число являющееся, по определению, умножением или делением всех его координат на это число тоже может быть выполнено эффективнее, если мы используем &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; потоков, а не выполняем эти действия последовательно.&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
Параллельные операции возможны только внутри итераций, так как рассматриваемый алгоритм является итерационным, и сами итерации строго последовательны.&amp;lt;br&amp;gt;&lt;br /&gt;
Рассмотрим в этом разделе подробнее, какой выигрыш мы можем получить при распараллеливании операций внутри одной итерации согласно графу из предыдущего раздела.&lt;br /&gt;
&lt;br /&gt;
Умножение вещественной симметричной матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; размера &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;n\times n&amp;lt;/math&amp;gt; на вектор &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;b&amp;lt;/math&amp;gt; длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; требует последовательного выполнения &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; ярусов умножений и сложений. Сложение элементов вектора длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; на каждом шаге перемножения можно оптимизировать и выполнить за &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;\log_2 n&amp;lt;/math&amp;gt; действий, если применять метод сдваивания.&lt;br /&gt;
&lt;br /&gt;
Дальнейшие операции выполняются последовательно, а вычисление значений векторов происходит за один ярус операций сложения или умножения.&lt;br /&gt;
&lt;br /&gt;
Ресурс параллелизма алгоритма вычисления собственных значений построенной трёхдиагональной матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_k&amp;lt;/math&amp;gt; размера &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k\times k&amp;lt;/math&amp;gt; зависит от выбранного алгоритма (об этих алгоритмах подробнее было сказано в разделах 1.2 и 1.4). Будет очень затратно с точки зрения объёма материала пытаться рассмотреть пусть даже часть этих методов в этой статье, а так же тонкости их распараллеливания. Предлагаем читателям при желании самим ознакомиться с этими алгоритмами на данном ресурсе или прибегнув к иным источникам.&lt;br /&gt;
&lt;br /&gt;
При классификации по высоте ЯПФ, таким образом, алгоритм Ланцоша без переортогонализации относится к алгоритмам с &#039;&#039;логарифмической сложностью&#039;&#039;, и его сложность равна &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(\log_2 n)&amp;lt;/math&amp;gt; с важным замечанием, что это сложность только одной итерации, а максимум в алгоритме может быть выполнено последовательно &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;/math&amp;gt; таких однотипных итераций, если не будет осуществлён ранний выход из цикла. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Несмотря на то, что на графе в предыдущем разделе для лучшей визуализации и понимания было изображено &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; потоков (никаких допущений мы не делали и нарушений с точки зрения логики и математики нет, можно изобразить большее число потоков, просто часть времени некоторые из них могут бездействовать и не использоваться), на самом деле правильным и разумным будет реализовать начальное параллельное выполнение &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n^2&amp;lt;/math&amp;gt; операций умножения всех вещественных элементов матрицы &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;A&amp;lt;/math&amp;gt; на соответствующие элементы вектора &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;q_j&amp;lt;/math&amp;gt;, после чего применять тот же самый упомянутый метод сдваивания. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Поэтому при классификации по ширине ЯПФ его сложность будет &#039;&#039;квадратичной&#039;&#039; и равна &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(n^2)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
&#039;&#039;&#039;Входные данные алгоритма:&#039;&#039;&#039; вещественная симметричная &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; размера &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;n\times n&amp;lt;/math&amp;gt;, вещественный вектор &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;b&amp;lt;/math&amp;gt; длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt;, и одно целое число &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;k&amp;lt;/math&amp;gt;, означающее количество итераций.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём входных данных:&#039;&#039;&#039; &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;n^2 +n + 1 &amp;lt;/math&amp;gt;. Если учесть, что матрица симметричная и достаточно для её однозначного определения задать элементы на главной диагонали и элементы над или под ней, то можно сократить объём входных данных с целью экономии памяти до: &amp;lt;math&amp;gt;\ \frac{n^2-n}{2}+n+n+1 =\frac{n^2+3n}{2} + 1&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные алгоритма:&#039;&#039;&#039; вектор собственных значений &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;\Theta^k&amp;lt;/math&amp;gt; длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;/math&amp;gt;, матрица &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;S^k&amp;lt;/math&amp;gt; из соответствующих собственных векторов размера &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n\times k&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём выходных данных:&#039;&#039;&#039; &amp;lt;math&amp;gt;k\;(n + 1)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
В данном разделе перечислены без какой-либо хронологии или связи друг с другом наиболее важные и разнообразные свойства алгоритма, на которые стоит и полезно обратить внимание, а также которые выгодно отличают его от схожих алгоритмов, решающих ту же задачу.&amp;lt;br&amp;gt;&lt;br /&gt;
1) Отношение последовательной сложности алгоритма к параллельной,с учётом &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;/math&amp;gt; итераций, равно &amp;lt;math&amp;gt;\;\;\frac{kn^2}{k \log_2{n}}=\frac{n^2}{\log_2{n}}&amp;lt;/math&amp;gt;;&amp;lt;br&amp;gt;&lt;br /&gt;
2) Вычислительная мощность алгоритма, как отношение числа операций к суммарному объему входных и выходных данных, равна &amp;lt;math style=&amp;quot;vertical-align:-70%&amp;gt;\;\;\frac{k\,n^2}{0.5\,n^2+1.5\,n+k\,n+k+1}&amp;lt;/math&amp;gt; и &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;\approx 2\,k&amp;lt;/math&amp;gt;, так как на практике верно отношение &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;&amp;lt;n&amp;lt;/math&amp;gt; ;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
3) Для собственных значений формируемых матриц &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_j&amp;lt;/math&amp;gt; верно отношение (следствие теоремы Коши о перемежаемости): &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;\lambda_i(T_{k+1})\geq \lambda_i(T_{k})\geq \lambda_{i+1}(T_{k+1})\geq \lambda_{i+1}(T_{k})&amp;lt;/math&amp;gt; ;&amp;lt;ref&amp;gt;James W. Demmel - Вычислительная линейная алгебра. Теория и приложения //Мир. - 2001 (c. 383)&amp;lt;/ref&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
4) Крайние (наибольшие и наименьшие) собственные значения матриц &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_j&amp;lt;/math&amp;gt; сходятся к крайним собственным значениям матрицы &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;A&amp;lt;/math&amp;gt; первыми (это часто происходит уже на ранних шагах при &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j\approx 2\,\sqrt{n}&amp;lt;/math&amp;gt;&amp;lt;ref&amp;gt;http://num-anal.srcc.msu.ru/lib_na/int_ae/int_ae6.htm (пункт 6.5)&amp;lt;/ref&amp;gt;), а собственные значения в середине спектра - последними;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
5) Из-за ограниченной точности постепенно теряется ортогональность вектора Ланцоша &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;q_j&amp;lt;/math&amp;gt; к предыдущим векторам Ланцоша, поэтому необходимо примерно каждые 10-15 итераций проводить дорогостоящую операцию реортогонализации, но это уже будет иной алгоритм с очень малым различием в одной операции и в программном коде, реализующем его, соответственно; &amp;lt;ref&amp;gt;Sam Handler - The Lanczos Algorithm For Large-Scale Eigenvalue Problems (08.01.07), slide №8&amp;lt;/ref&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
6) Эффективность и быстрота выполнения алгоритма очень сильно зависит от скорости памяти (диска). Согласно тесту только &#039;&#039;6%&#039;&#039; времени работы программы приходится на вычисления, остальное время затрачивается на ожидание отклика диска;&amp;lt;ref&amp;gt;Sam Handler - The Lanczos Algorithm For Large-Scale Eigenvalue Problems (08.01.07), slide №10&amp;lt;/ref&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
7) Метод Ланцоша удобен тем, что не требует хранения исходной матрицы полным массивом: метод использует исходную матрицу только в операциях умножения матрицы на вектор, что позволяет эффективно использовать разреженность матрицы или регулярность структуры матрицы. Поэтому метод Ланцоша может быть использован для матриц таких больших порядков, когда методы вращений и отражений не могут быть применены.&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;
По заданию, во второй части требовалось описать только разделы 2.4 и 2.7, прошу не спрашивать с меня все разделы 2.1-2.6. Надеюсь на понимание, мне физически не хватает времени на это задание + 2 других в течение семестра, делаю всё, что в моих силах :)&lt;br /&gt;
&lt;br /&gt;
== Существующие реализации алгоритма ==&lt;br /&gt;
Несмотря на то, что алгоритм является далеко не самым популярным, алгоритмом, про который нельзя сказать, что он всегда «на слуху», на сегодняшний день существует множество реализаций на различных популярных языках.&amp;lt;br&amp;gt;&lt;br /&gt;
Перечислим далее некоторые из них, указывая язык программирования, лежащий в их основе, и некоторые важные характеристики, которые обсуждались в статье ранее:&lt;br /&gt;
*&#039;&#039;Code on netlib.org by Jane Cullum and Ralph Willoughby&#039;&#039; (&#039;&#039;&#039;Fortran 77&#039;&#039;&#039;; без реортогонализации векторов; без реализации распараллеливания)&amp;lt;ref&amp;gt;http://www.netlib.org/lanczos/leval&amp;lt;/ref&amp;gt;&lt;br /&gt;
*&#039;&#039;Lanczos algorithm on freesourcecode.net&#039;&#039; (&#039;&#039;&#039;Matlab&#039;&#039;&#039;; присутствует реортогонализация векторов; без реализации распараллеливания)&amp;lt;ref&amp;gt;http://freesourcecode.net/matlabprojects/61741/lanczos-algorithm--in-matlab&amp;lt;/ref&amp;gt;&lt;br /&gt;
*&#039;&#039;Lanczos for eigenvalues in Numerical Linear Algebra, Spring 2007&#039;&#039; (&#039;&#039;&#039;Matlab&#039;&#039;&#039;; частичная или полная реортогонализация - доступны оба варианта; без реализации распараллеливания)&amp;lt;ref&amp;gt;Ссылки на файлы lanso.m и lanfu.m можно найти на https://www.nada.kth.se/~ruhe/2D5219/labs2007.html&amp;lt;/ref&amp;gt;&lt;br /&gt;
*&#039;&#039;Planso&#039;&#039; (название происходит от parallel Lanso.f) &#039;&#039;code by Kesheng Wu and Horst D. Simon&#039;&#039; (&#039;&#039;&#039;Fortran 77&#039;&#039;&#039;; частичная реортогонализация векторов; использование MPI для коммуникаций)&amp;lt;ref&amp;gt;https://github.com/jiahao/planso.jl/tree/master/external/PLAN/plan К сожалению, ссылка в описании пакета на github, ведущая на сайт National Energy Research Scientific Computing Center (NERSC), с более подробной информацией о данной программе больше не активна и выдаёт результат &#039;&#039;Page not found&#039;&#039;&amp;lt;/ref&amp;gt; &lt;br /&gt;
* &#039;&#039;Lanczos.cpp in the Vienna Computing Library&#039;&#039;  (&#039;&#039;&#039;C++&#039;&#039;&#039;, частичная реортогонализация, без реализации распараллеливания) &amp;lt;ref&amp;gt;http://viennacl.sourceforge.net/doc/lanczos_8cpp_source.html&amp;lt;/ref&amp;gt;&lt;br /&gt;
* &#039;&#039;Parallel Eigen Values code using C++ AMP on microsoft msdn blog&#039;&#039; (&#039;&#039;&#039;C++&#039;&#039;&#039;; ? ; распараллеливание есть и реализовано через C++ AMP) &amp;lt;ref&amp;gt;https://blogs.msdn.microsoft.com/nativeconcurrency/2013/12/20/eigen-values/ Подробнее о C++ Accelerated Massive Parallelism можно почитать здесь: https://msdn.microsoft.com/ru-ru/library/hh265137(v=vs.140).aspx или здесь: http://professorweb.ru/my/csharp/optimization/level4/4_6.php &amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;br /&gt;
[[en:Description of algorithm properties and structure]]&lt;/div&gt;</summary>
		<author><name>AleksLevin</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:AleksLevin/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%9B%D0%B0%D0%BD%D1%86%D0%BE%D1%88%D0%B0_%D0%B2%D1%8B%D1%87%D0%B8%D1%81%D0%BB%D0%B5%D0%BD%D0%B8%D1%8F_%D1%81%D0%BE%D0%B1%D1%81%D1%82%D0%B2%D0%B5%D0%BD%D0%BD%D1%8B%D1%85_%D0%B7%D0%BD%D0%B0%D1%87%D0%B5%D0%BD%D0%B8%D0%B9_%D1%81%D0%B8%D0%BC%D0%BC%D0%B5%D1%82%D1%80%D0%B8%D1%87%D0%BD%D0%BE%D0%B9_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86%D1%8B_%D0%B4%D0%BB%D1%8F_%D1%82%D0%BE%D1%87%D0%BD%D0%BE%D0%B9_%D0%B0%D1%80%D0%B8%D1%84%D0%BC%D0%B5%D1%82%D0%B8%D0%BA%D0%B8_(%D0%B1%D0%B5%D0%B7_%D0%BF%D0%B5%D1%80%D0%B5%D0%BE%D1%80%D1%82%D0%BE%D0%B3%D0%BE%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D0%B8)&amp;diff=19946</id>
		<title>Участник:AleksLevin/Алгоритм Ланцоша вычисления собственных значений симметричной матрицы для точной арифметики (без переортогонализации)</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:AleksLevin/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%9B%D0%B0%D0%BD%D1%86%D0%BE%D1%88%D0%B0_%D0%B2%D1%8B%D1%87%D0%B8%D1%81%D0%BB%D0%B5%D0%BD%D0%B8%D1%8F_%D1%81%D0%BE%D0%B1%D1%81%D1%82%D0%B2%D0%B5%D0%BD%D0%BD%D1%8B%D1%85_%D0%B7%D0%BD%D0%B0%D1%87%D0%B5%D0%BD%D0%B8%D0%B9_%D1%81%D0%B8%D0%BC%D0%BC%D0%B5%D1%82%D1%80%D0%B8%D1%87%D0%BD%D0%BE%D0%B9_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86%D1%8B_%D0%B4%D0%BB%D1%8F_%D1%82%D0%BE%D1%87%D0%BD%D0%BE%D0%B9_%D0%B0%D1%80%D0%B8%D1%84%D0%BC%D0%B5%D1%82%D0%B8%D0%BA%D0%B8_(%D0%B1%D0%B5%D0%B7_%D0%BF%D0%B5%D1%80%D0%B5%D0%BE%D1%80%D1%82%D0%BE%D0%B3%D0%BE%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D0%B8)&amp;diff=19946"/>
		<updated>2016-12-02T19:20:54Z</updated>

		<summary type="html">&lt;p&gt;AleksLevin: /* Макроструктура алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Основные авторы описания: Левин А.Д.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{algorithm&lt;br /&gt;
| name              = Алгоритм Ланцоша для точной арифметики (без переортогонализации)&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(k\,n^2)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(k\log_2 n)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;\frac{n^2+3n}{2} + 1&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;k\;(n + 1)&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритмов =&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Данный алгоритм появился в 1950 г. и носит имя венгерского физика и математика Корнелия Ланцоша (венг. Lánczos Kornél). Алгоритм Ланцоша относится к итерационным методам вычисления собственных значений для матриц столь больших порядков &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt; n&amp;lt;/math&amp;gt;, что к ним нельзя применить прямые методы из-за ограничений по времени и памяти.&lt;br /&gt;
&lt;br /&gt;
Сам Ланцош указывал, что его метод предназначен для отыскания нескольких собственных векторов симметричных матриц, хотя к методу сразу было обращено внимание, как к способу приведения всей матрицы к трёхдиагональному виду. Двадцатью годами позже канадский математик Крис Пэж показал, что, несмотря на чувствительность к округлениям, алгоритм Ланцоша - эффективное средство вычисления некоторых &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; собственных чисел и соответствующих им собственных векторов. &amp;lt;ref&amp;gt;Парлетт Б. - Симметричная проблема собственных значений. Численные методы //М.: Мир. - 1983. (c. 276)&amp;lt;/ref&amp;gt;&lt;br /&gt;
Обычно число &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; берут в два раза больше, чем количество собственных значений матрицы, которые поставлена цель найти, и оно имеет порядок не более &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;10^2&amp;lt;/math&amp;gt;.&amp;lt;ref&amp;gt;Susan W. Bostic - Lanczos Eigensolution Method for High-Perfomance Computers, page 7&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Алгоритм Ланцоша для вычисления собственных значений симметричной матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; соединяет в себе метод Ланцоша для построения последовательности подпространств Крылова и ортонормированных векторов Ланцоша и процедуру Рэлея-Ритца получения оптимальных приближений собственных значений и соответствующих собственных векторов исходной матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt;.&amp;lt;ref&amp;gt;James W. Demmel - Вычислительная линейная алгебра. Теория и приложения //Мир. - 2001 (c. 381)&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
В данной статье рассматривается вариант алгоритма Ланцоша, в котором опущено влияние ошибок округления на вычислительный процесс, хотя на практике этому посвящается отдельное внимание и существуют различные методы решения данной проблемы, такие как частичная или полная переортогонализация. Этим модифицированным методам посвящены отдельные статьи на данном ресурсе.&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
Обозначения и формулы, используемые в данном разделе, взяты из литературы, указанной по ссылке.&amp;lt;ref&amp;gt;James W. Demmel - Вычислительная линейная алгебра. Теория и приложения //Мир. - 2001 (c. 313, &#039;&#039;&amp;lt;math&amp;gt; \S &amp;lt;/math&amp;gt; 6.6 Методы Крыловского подпространства&#039;&#039;)&amp;lt;/ref&amp;gt; &lt;br /&gt;
&lt;br /&gt;
Алгоритм Ланцоша для вычисления &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; собственных значений и собственных векторов вещественной симметричной матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A=A^T&amp;lt;/math&amp;gt; в точной арифметике: &amp;lt;ref&amp;gt;James W. Demmel - Вычислительная линейная алгебра. Теория и приложения //Мир. - 2001 (c. 381)&amp;lt;/ref&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{align}&lt;br /&gt;
q_1 = &amp;amp; \,\frac{b}{\|b\|_2},\; \beta_0 = 0,\; q_0 = 0\\&lt;br /&gt;
\mathbf{for} \; &amp;amp; j = 1 \; to \; k \,\; \mathbf{do} \\&lt;br /&gt;
&amp;amp; z = A\,q_j\\&lt;br /&gt;
&amp;amp; \alpha_j = q^T_j z\\&lt;br /&gt;
&amp;amp; z = z - \alpha_j q_j - \beta_{j-1}q_{j-1}\\&lt;br /&gt;
&amp;amp; \beta_j = \|z\|_2\\&lt;br /&gt;
&amp;amp; \mathbf{If} \; (\beta_j == 0) \; \mathbf{then}\; stop\; the\; algorithm \\ &lt;br /&gt;
&amp;amp; \;  q_{j+1} = \frac{z}{\beta_j} \\&lt;br /&gt;
&amp;amp; compute\; eigenvalues\; and \;eigenvectors\;of \;matrix \;\;T_j= Q^T_j A Q\;\;and\;estimate \;the\; errors\\&lt;br /&gt;
\mathbf{end} \; &amp;amp; \mathbf{for}&lt;br /&gt;
\end{align}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
В продемонстрированном выше алгоритме &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;b&amp;lt;/math&amp;gt; - заданный вещественный вектор. Также полагается известным алгоритм вычисления произведения матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; на вектор &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;x&amp;lt;/math&amp;gt;. &lt;br /&gt;
Введём матрицу Крылова, определяемую следующим соотношением: &amp;lt;math&amp;gt;K_j = [b,Ab,A^2b,...,A^{j-1}b]&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Далее, на практике, матрица &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;K&amp;lt;/math&amp;gt; заменяется матрицей &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;Q&amp;lt;/math&amp;gt;, такой, что при любом числе &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; линейные оболочки первых &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; столбцов в &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;K&amp;lt;/math&amp;gt; и &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;Q&amp;lt;/math&amp;gt; являются одним и тем же подпространством.&amp;lt;ref&amp;gt;James W. Demmel - Вычислительная линейная алгебра. Теория и приложения //Мир. - 2001 (c. 315)&amp;lt;/ref&amp;gt; &lt;br /&gt;
Тогда матрица &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;Q&amp;lt;/math&amp;gt;, в отличие от матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;K&amp;lt;/math&amp;gt;, хорошо обусловлена и легко обратима. В результате получаем матрицу &amp;lt;math&amp;gt;Q_j = [q_1, q_2, \dots, q_j]&amp;lt;/math&amp;gt; размерности &amp;lt;math&amp;gt;n\times j&amp;lt;/math&amp;gt;, столбцы которой ортогональны, являются базисом подпространства Крылова и называются векторами Ланцоша.&lt;br /&gt;
&lt;br /&gt;
В алгоритме Ланцоша вычислению подлежит столько первых столбцов в матрице &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;Q_j&amp;lt;/math&amp;gt;, сколько необходимо для получения требуемого приближения к решению &amp;lt;math&amp;gt;A\,x\,=b\,\,(A\,x=\lambda \, x)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Получение нулевого &amp;lt;math&amp;gt;\beta_j&amp;lt;/math&amp;gt; в итерационном процессе - событие, желательное в том смысле, что оно свидетельствует о том, что найдено некоторое подпространство, являющееся в точности инвариантным, а все собственные значения матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;T_j&amp;lt;/math&amp;gt; являются собственными значениями матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt;. На практике же нулевое и близкие к нулю значения получаются редко.&amp;lt;ref&amp;gt;Голуб Дж., Ван Лоун Ч. - Матричные вычисления//М.: Мир. - 1999 (c. 429)&amp;lt;/ref&amp;gt; &lt;br /&gt;
&lt;br /&gt;
Затем на каждом шаге цикла формируется симметричная трёхдиагональная матрица &amp;lt;math&amp;gt;T_j = Q^T_j A Q&amp;lt;/math&amp;gt;, к которой применяется процесс Рэлея-Ритца для поиска её собственных значений (на практике для поиска этих собственных значений можно использовать любой из специальных методов в параграфе книги по ссылке).&amp;lt;ref&amp;gt;Голуб Дж., Ван Лоун Ч. - Матричные вычисления//М.: Мир. - 1999 (&amp;lt;math&amp;gt;\S&amp;lt;/math&amp;gt; 8.4)&amp;lt;/ref&amp;gt;  &lt;br /&gt;
Эти собственные значения, они же числа Ритца, и полагаются приближёнными собственными значениями исходной матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt;.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Существует множество методов для отыскания собственных значений вещественной симметричной трехдиагональной матрицы. Большинство из них требует &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt; операций &amp;lt;ref&amp;gt;Парлетт Б. Симметричная проблема собственных значений. Численные методы.,: Мир, 1983. с. 179-182&amp;lt;/ref&amp;gt;, но существуют и быстрые алгоритмы, требующие лишь &amp;lt;math&amp;gt;O(n\ln n)&amp;lt;/math&amp;gt; операций.&amp;lt;ref&amp;gt;https://en.wikipedia.org/wiki/Tridiagonal_matrix#Eigenvalues  Раздел eigenvalues&amp;lt;/ref&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Одним из возможных способов отыскать собственные значения симметричной трехдиагональной матрицы - прямое вычисление корней характеристического полинома &amp;lt;math&amp;gt;p_n(\lambda)&amp;lt;/math&amp;gt; через метод деления пополам, где формируется последовательность Штурма и локализуются собственные числа, являющиеся корнями характеристического полинома. Нахождение всех &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; собственных значений матрицы этим способом требует &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;2n^2t&amp;lt;/math&amp;gt; умножений и вычитаний, где &amp;lt;math&amp;gt;t&amp;lt;/math&amp;gt; - число сделанных шагов с применением метода деления пополам.&amp;lt;ref&amp;gt;Уилкинсон Дж. X. Алгебраическая проблема собственныx значений. Изд-во &amp;quot;Наука&amp;quot;, 1970. - глава 5, с. 272-278&amp;lt;/ref&amp;gt; Соответствующие собственные вектора могут быть найдены посредством обратных итераций за &amp;lt;math&amp;gt; O(n) &amp;lt;/math&amp;gt; флопов. &amp;lt;ref&amp;gt;Голуб Дж., Ван Лоун Ч. - Матричные вычисления//М.: Мир. - 1999 (c. 394-395)&amp;lt;/ref&amp;gt; &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;На практике, если требуется только небольшая часть от всей совокупности собственных векторов и значений, и матрица имеет Хессенбергову или трёхдиагональную форму, очень эффективными будут методы факторизации, как, например, QR-алгоритм или QL-алгоритм со сдвигами (c целью ускорить алгоритм и сделать порядок сходимости квадратичным) или же без них.&amp;lt;ref&amp;gt;http://algorithm.narod.ru/ln/eigen/ETridiag.html&amp;lt;/ref&amp;gt; &amp;lt;br&amp;gt;&lt;br /&gt;
Весьма молодые и не менее актуальные конкуренты QR и QL алгоритмов, применяющиеся для поиска собственных значений:&lt;br /&gt;
*Методы divide-and-conquer (разделяй и властвуй), появившиеся в 1980-ых годах &amp;lt;ref&amp;gt;https://algowiki-project.org/ru/Метод_&amp;quot;Разделяй_и_властвуй&amp;quot;_Завольсков/Землянский&amp;lt;/ref&amp;gt;&lt;br /&gt;
*Relatively robust representation methods, появившиеся в 1990-ых и позволяющие найти собственные числа симметричной матрицы порядка &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;n&amp;lt;/math&amp;gt; за &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt; операций&lt;br /&gt;
&lt;br /&gt;
Если требуется вычислить собственные векторы, то необходимо хранить вычисляемые векторы Ланцоша. Если работа при этом производится только с оперативной памятью, то при большом порядке исходной матрицы (а именно для таких матриц и предназначен метод Ланцоша) число шагов  &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;j&amp;lt;/math&amp;gt;, которые могут быть выполнены до того момента, как оперативная память будет исчерпана, будет очень незначительно, а следовательно, искомые собственные пары могут не успеть сойтись с требуемой точностью. В этом случае метод Ланцоша можно использовать итерационным образом: после выполнения заданного числа шагов процесс прерывается и, если еще не все требуемые пары Ритца сошлись с требуемой точностью, то формируется новый начальный вектор &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;q_1&amp;lt;/math&amp;gt;, являющийся линейной комбинацией векторов Ритца, еще не сошедшихся с заданной точностью, и процесс начинается заново.&amp;lt;ref&amp;gt;http://num-anal.srcc.msu.ru/lib_na/int_ae/int_ae6.htm (пункт 6.5)&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
Вычислительное ядро рассматриваемого алгоритма (наиболее ресурсно-затратная часть алгоритма) -  формирование на каждом шаге цикла промежуточного вектора &amp;lt;math&amp;gt;z&amp;lt;/math&amp;gt;, вычисляемого по формуле: &amp;lt;math&amp;gt;z = A\,q_j&amp;lt;/math&amp;gt;. Данная операция, по сравнению с другими операциями алгоритма, затратна и требовательна, как с точки зрения количества производимых операций, так и с точки зрения объема оперируемых данных. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Например, умножение матрицы размера &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;n\times n&amp;lt;/math&amp;gt; на вектор длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; требует: &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;n^2+(n-1)n = 2n^2-n&amp;lt;/math&amp;gt; операций умножения и сложения. В свою очередь аналогичная операция умножения матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;(n+1)\times (n+1)&amp;lt;/math&amp;gt; на вектор длины &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;(n+1)&amp;lt;/math&amp;gt; требует: &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;2n^2+3n+1&amp;lt;/math&amp;gt;  операций умножения и сложения. То есть повышение размерности задачи всего на 1 увеличивает число необходимых действий в этом шаге алгоритма на: &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;4n+1&amp;lt;/math&amp;gt;. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Так же, стоит помнить, что, согласно разделу 1.2, данную операцию умножения матрицы на вектор необходимо выполнить &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;k&amp;lt;/math&amp;gt; раз. Нетрудно понять, насколько возрастает и колоссален масштаб операций, если в задачах, где критична точность, размерности &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; могут иметь порядок &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;10^5&amp;lt;/math&amp;gt; или даже более.&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
Как уже было упомянуто в данной статье в описании алгоритма, рассматриваемый алгоритм состоит из двух последовательно выполненных алгоритмов: метод Ланцоша для построения последовательности подпространств Крылова и ортонормированных векторов Ланцоша и процедура Рэлея-Ритца получения оптимальных приближений собственных значений и соответствующих собственных векторов исходной матрицы.&lt;br /&gt;
&lt;br /&gt;
В первой части алгоритма, где итерационно строятся Крыловское подпространство и трёхдиагональная матрица &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&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 style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; разреженная. Именно она подлежит оптимизации с использованием техник распараллеливания, поскольку она является вычислительным ядром алгоритма, а весь упомянутый процесс построения матрицы &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&amp;lt;/math&amp;gt; выполняется последовательно.&lt;br /&gt;
&lt;br /&gt;
Рассмотрим вторую часть алгоритма - поиск собственных значений сформированной матрицы &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&amp;lt;/math&amp;gt;.&amp;lt;br&amp;gt;&lt;br /&gt;
Далее, наглядно, в виде псевдокода, представлен, упомянутый в разделе 1.2, QR-алгоритм (аналогично можно рассмотреть и QL-алгоритм) со сдвигами Релэя, который весьма популярен на практике.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{align}&lt;br /&gt;
\mathbf{Input}: \;&amp;amp;tridiagonal\;\;matrix \;T\;with\;\;n\times n\;\;size\\&lt;br /&gt;
T^{(0)}&amp;amp;:=T\\&lt;br /&gt;
\mathbf{for}&amp;amp; \;\;m=n,...,2 \;\; \mathbf{do}\\&lt;br /&gt;
&amp;amp;k=0\\&lt;br /&gt;
&amp;amp; \mathbf{repeat}\\&lt;br /&gt;
&amp;amp; \quad \;\; k=k+1\\&lt;br /&gt;
&amp;amp; \quad \;\; \mu^{(k)}=T_{m,m}^{(k-1)}\\&lt;br /&gt;
&amp;amp; \quad \;\; Q^{(k)}R^{(k)}=T^{(k-1)}-\mu^{(k)}I\;\;using\;\;QR\;decomposition\\&lt;br /&gt;
&amp;amp; \quad \;\; T^{(k)}=R^{(k)}Q^{(k)}+\mu^{(k)}I\\&lt;br /&gt;
&amp;amp; \mathbf{until} \;\;\; |T_{m,m-1}^{(k)}| \;is\;\;small\;\;enough\\&lt;br /&gt;
&amp;amp; Save  \;\;T_{m,m}^{(k)} \;\;as\;\; converged\;\;eigenvalue\;of\;T\\ &lt;br /&gt;
&amp;amp; Remove \;\boldsymbol{n}\,th\;row\;and\;\boldsymbol{n}\,th\;column\;\;from \;T \\&lt;br /&gt;
&amp;amp; and\;take\;this\;new\;cropped\;matrix\;as\;new\;T^{(0)}\;with\;\;(n-1)\times (n-1)\;\;size\\&lt;br /&gt;
 \mathbf{end}&amp;amp;\; \mathbf{for}&lt;br /&gt;
\end{align}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Малость наддиагональных и поддиагональных элементов матрицы (фраза &#039;&#039;&amp;quot;small enough&amp;quot;&#039;&#039; в псевдокоде) подразумевает:&lt;br /&gt;
&amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt; |T_{m,m-1}^{(k)}| \leq \varepsilon\,|T_{m,m}^{(k)}| \quad\quad &amp;lt;/math&amp;gt; , где &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt; \varepsilon &amp;lt;/math&amp;gt; - заданная точность&amp;lt;br&amp;gt;&lt;br /&gt;
Также вместо сдвига Релэя, обозначенного в алгоритме через &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;\mu^{(k)}&amp;lt;/math&amp;gt; часто на практике используется сдвиг по Уилкинсону, который даёт гарантированную сходимость внедиагональных элементов матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt; T^{(k)} &amp;lt;/math&amp;gt;, формируемой на каждом шаге, к нулю, при этом жертвуя монотонностью их убывания.&amp;lt;ref&amp;gt;Голуб Дж., Ван Лоун Ч. - Матричные вычисления//М.: Мир. - 1999 (c. 378, вторая половина страницы)&amp;lt;/ref&amp;gt;&amp;lt;ref&amp;gt;Парлетт Б. Симметричная проблема собственных значений. Численные методы.,: Мир, 1983. с. 169&amp;lt;/ref&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Подробнее с различными сдвигами и соответствующими оценками скоростей и количествами операций можно ознакомиться по указанной ссылке:&amp;lt;ref&amp;gt;Парлетт Б. Симметричная проблема собственных значений. Численные методы.,: Мир, 1983. с. 179-182&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;Для совершения QR-декомпозиции на каждом шаге может использоваться любой из алгоритмов по ссылке.&amp;lt;ref&amp;gt;https://en.wikipedia.org/wiki/QR_decomposition&amp;lt;/ref&amp;gt; Подробные описания этих алгоритмов также доступны на данном ресурсе algowiki-project.&amp;lt;br&amp;gt;&lt;br /&gt;
Так как мы оперируем не обычной матрицей и даже не Хессенберговой, а симметричной и трёхдиагональной, то скорость таких алгоритмов значительно возрастёт. Например, согласно данному ресурсу &amp;lt;ref&amp;gt;http://algorithm.narod.ru/ln/eigen/ETridiag.html&amp;lt;/ref&amp;gt;, для QL-алгоритма с неявными сдвигами:&amp;lt;br&amp;gt;&lt;br /&gt;
Для трёхдиагональной матрицы объем арифметических действий составляет &amp;lt;math&amp;gt; O(n)&amp;lt;/math&amp;gt; на одну итерацию вместо &amp;lt;math&amp;gt; O(n^3)&amp;lt;/math&amp;gt; для матрицы общего вида, а число итераций для нахождения первых собственных значений примерно равно 4 - 5. Но на этих итерациях также уменьшаются внедиагональные элементы правого нижнего угла. И, таким образом, дальнейшие собственные значения ищутся значительно быстрее. Среднее число итераций на каждое собственное значение обычно составляет 1.3 - 1.6.&amp;lt;br&amp;gt; &lt;br /&gt;
Аналогично QL, QR-разложение трёхдиагольной матрицы также требует &amp;lt;math&amp;gt; O(n)&amp;lt;/math&amp;gt; флопов&amp;lt;ref&amp;gt;Голуб Дж., Ван Лоун Ч. - Матричные вычисления//М.: Мир. - 1999 (c. 378, начало раздела 8.2.2)&amp;lt;/ref&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Подводя итог, во второй части алгоритма Ланцоша можно выделить следующие макрооперации:&lt;br /&gt;
* умножение матрицы на вещественное число;&lt;br /&gt;
* перемножение матриц;&lt;br /&gt;
* умножение и сравнение вещественных чисел;&lt;br /&gt;
* + набор других макроопераций в зависимости от выбора метода, с помощью которого будет совершаться сама QR или QL-декомпозиция (выше продемонстрированы, уже, как минимум, 3 разных способа).&lt;br /&gt;
Так же, важно заметить, что набор макропераций может быть несколько другим, если выбрать какой-либо иной современный метод поиска собственных чисел трёхдиагональной матрицы, не использующий QR и QL разложения(факторизацию). Два таких метода были упомянуты в пункте 1.2.&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
С целью полностью не дублировать раздел 1.2 данной статьи, где представлен наглядный и доступный для понимания псевдокод алгоритма, постараемся лишь коротко просуммировать и обобщить весь перечень последовательных действий в рассматриваемом алгоритме.&lt;br /&gt;
&lt;br /&gt;
В качестве входных данных имеем: вещественная симметричная матрица &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; размера &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;n\times n&amp;lt;/math&amp;gt;, известный вещественный вектор &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;b&amp;lt;/math&amp;gt; длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; и число &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;n&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Далее:&lt;br /&gt;
* Инициализируем вещественную константу &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;\beta_0&amp;lt;/math&amp;gt; и векторы &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;q_0&amp;lt;/math&amp;gt; и &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;q_1&amp;lt;/math&amp;gt;&lt;br /&gt;
* Итерационно для всех &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j=1,...,k&amp;lt;/math&amp;gt;:&lt;br /&gt;
** Вычисляем вспомогательный вектор &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt;, используя умножение матрицы на вектор&lt;br /&gt;
** Вычисляем, используя скалярное произведение векторов, значение &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;\alpha_j&amp;lt;/math&amp;gt; - элемент на главной диагонали трёхдиагональной матрицы &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&amp;lt;/math&amp;gt;&lt;br /&gt;
** Вычисляем по формуле новое значение и перезаписываем вектор &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt;&lt;br /&gt;
** Вычисляем значение &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;\beta_j&amp;lt;/math&amp;gt; - элементы непосредственно над и под главной диагональю той же матрицы &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&amp;lt;/math&amp;gt;&lt;br /&gt;
** Вычисляем, зная вектор &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt;,  очередной столбец матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;Q&amp;lt;/math&amp;gt;, он же вектор Ланцоша : &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;\,\,q_{j+1}&amp;lt;/math&amp;gt;&lt;br /&gt;
** Теперь, когда матрица &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&amp;lt;/math&amp;gt; сформирована на очередном шаге, находим её собственные значения и вектора любым доступным способом, о чём было подробно сказано в пункте 1.2&lt;br /&gt;
** Переходим на следующую итерацию: &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j&amp;lt;/math&amp;gt;++&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
Оценим количество операций и сложность последовательного алгоритма, изложенного в предыдущем разделе.&lt;br /&gt;
*Для вычисления вектора &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt; умножается матрица размера &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;n\times n&amp;lt;/math&amp;gt; на вектор длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt;, и потребуется &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n^2&amp;lt;/math&amp;gt; операций умножения и &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n^2&amp;lt;/math&amp;gt; операций сложения.&lt;br /&gt;
*Умножение векторов &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;q^T_j&amp;lt;/math&amp;gt; и &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt; длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; потребует &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; операций умножения и &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; операций сложения.&lt;br /&gt;
*При вычислении нового значения вектора &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt; поэлементное сложение двух векторов длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; требует &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; операций сложения.&lt;br /&gt;
*Умножение вектора длины &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; на вещественное число требует &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; операций умножения.&lt;br /&gt;
*Нахождение квадратичной нормы вектора &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt;  длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; требует &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; умножений и &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; сложений и ещё 1 операцию извлечения квадратного корня.&lt;br /&gt;
*Заключительное нахождение собственных значений и собственных векторов трёхдиагональной матрицы &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;T_j&amp;lt;/math&amp;gt; размера &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j\times j&amp;lt;/math&amp;gt; с помощью QR-алгоритма потребует в худшем случае &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(j^3)&amp;lt;/math&amp;gt; операций.&amp;lt;ref&amp;gt;http://num-anal.srcc.msu.ru/lib_na/int_ae/int_ae6.htm (пункт 6.2, &amp;quot;Скорость сходимости при этом всегда не хуже квадратичной и почти всегда лучше кубической.&amp;quot;)&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Посчитаем теперь суммарное количество простейших операций на одной итерации алгоритма (без учёта записей в память):&lt;br /&gt;
*&amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n^2+5\,n&amp;lt;/math&amp;gt; операций умножения/деления&lt;br /&gt;
*&amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n^2+4\,n&amp;lt;/math&amp;gt; операций сложения/вычитания&lt;br /&gt;
*1 операция извлечения квадратного корня&amp;lt;br&amp;gt;&lt;br /&gt;
Отдельно после всех итераций при &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j=k&amp;lt;/math&amp;gt; :&lt;br /&gt;
*&amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(k^3)&amp;lt;/math&amp;gt; операций для поиска собственных значений и собственных векторов трёхдиагональной матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_k&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Итого можно утверждать следующее:&lt;br /&gt;
&lt;br /&gt;
Последовательная сложность одной итерации рассматриваемого алгоритма:  &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(n ^ 2) &amp;lt;/math&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Суммарная сложность алгоритма (&amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;/math&amp;gt; итераций): &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(k\,n ^ 2) + O(k ^ 3)&amp;lt;/math&amp;gt; &amp;lt;ref&amp;gt;Здесь мы полагаем, что мы не вычисляем собственные значения и векторы матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_j&amp;lt;/math&amp;gt; на каждом промежуточном шаге, а лишь единожды затрачиваем &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;O(k ^ 3)&amp;lt;/math&amp;gt; действий в конце для нахождения &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;/math&amp;gt; собственных значений и векторов матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_k&amp;lt;/math&amp;gt;&amp;lt;/ref&amp;gt; &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
На практике же обычно рассматривается число &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;&amp;lt;n&amp;lt;/math&amp;gt;, поэтому второе слагаемое можно опустить.&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
На рис. 1 продемонстрирован граф одной итерации (при каком-либо произвольном значении итератора &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j&amp;lt;/math&amp;gt;) описанного алгоритма без отображения входных и выходных данных. Наглядно продемонстрированы связи между всеми действиями, и с помощью деления на &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; потоков показано, какие операции возможно выполнять параллельно на каждом шаге с целью оптимизации и экономии машинного времени. В результате, после параллельно выполненных операций &#039;&#039;&#039;Division&#039;&#039;&#039; на заключительном ярусе, на выходе имеем значение следующего вектора Ланцоша &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;q_{j+1}&amp;lt;/math&amp;gt;, после чего следует переход на следующую итерацию, и процесс повторяется.&lt;br /&gt;
&lt;br /&gt;
[[Файл:Levin_graph.png|600px|thumb|center|Рис. 1]] &amp;lt;br&amp;gt;&lt;br /&gt;
Обозначения на рисунке: &amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Simp&#039;&#039;&#039; (от англ. simple) - операции сложения и умножения вещественных чисел при вычислении произведения матрицы на вектор;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Vec mult&#039;&#039;&#039; (от англ. vectors multiplication) - операция скалярного умножения двух векторов;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Vec subtr&#039;&#039;&#039; (от англ. vectors subtraction, из-за использованных в операции вычитаний векторов) - операция умножения вектора на число (выполняется дважды) и формирование нового значения &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;z_{new}&amp;lt;/math&amp;gt; по формуле: &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;z_{new} = z - \alpha_j q_j - \beta_{j-1}q_{j-1} \;&amp;lt;/math&amp;gt;;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;||\cdot||&amp;lt;/math&amp;gt; - операция вычисления нормы вектора;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Division&#039;&#039;&#039; - операция деления вектора на вещественное число  &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;\beta_j&amp;lt;/math&amp;gt; &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Важно отметить, что упомянутые выше операции также легко поддаются оптимизации. Например, попарные умножения вещественных координат векторов при вычислении скалярного произведения также легко выполняются параллельно на &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; потоках, а затем можно применить суммирование методом сдваивания, о котором сказано в следующем разделе. Умножение или деление вектора на вещественное число являющееся, по определению, умножением или делением всех его координат на это число тоже может быть выполнено эффективнее, если мы используем &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; потоков, а не выполняем эти действия последовательно.&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
Параллельные операции возможны только внутри итераций, так как рассматриваемый алгоритм является итерационным, и сами итерации строго последовательны.&amp;lt;br&amp;gt;&lt;br /&gt;
Рассмотрим в этом разделе подробнее, какой выигрыш мы можем получить при распараллеливании операций внутри одной итерации согласно графу из предыдущего раздела.&lt;br /&gt;
&lt;br /&gt;
Умножение вещественной симметричной матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; размера &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;n\times n&amp;lt;/math&amp;gt; на вектор &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;b&amp;lt;/math&amp;gt; длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; требует последовательного выполнения &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; ярусов умножений и сложений. Сложение элементов вектора длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; на каждом шаге перемножения можно оптимизировать и выполнить за &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;\log_2 n&amp;lt;/math&amp;gt; действий, если применять метод сдваивания.&lt;br /&gt;
&lt;br /&gt;
Дальнейшие операции выполняются последовательно, а вычисление значений векторов происходит за один ярус операций сложения или умножения.&lt;br /&gt;
&lt;br /&gt;
Ресурс параллелизма алгоритма вычисления собственных значений построенной трёхдиагональной матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_k&amp;lt;/math&amp;gt; размера &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k\times k&amp;lt;/math&amp;gt; зависит от выбранного алгоритма (об этих алгоритмах подробнее было сказано в разделах 1.2 и 1.4). Будет очень затратно с точки зрения объёма материала пытаться рассмотреть пусть даже часть этих методов в этой статье, а так же тонкости их распараллеливания. Предлагаем читателям при желании самим ознакомиться с этими алгоритмами на данном ресурсе или прибегнув к иным источникам.&lt;br /&gt;
&lt;br /&gt;
При классификации по высоте ЯПФ, таким образом, алгоритм Ланцоша без переортогонализации относится к алгоритмам с &#039;&#039;логарифмической сложностью&#039;&#039;, и его сложность равна &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(\log_2 n)&amp;lt;/math&amp;gt; с важным замечанием, что это сложность только одной итерации, а максимум в алгоритме может быть выполнено последовательно &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;/math&amp;gt; таких однотипных итераций, если не будет осуществлён ранний выход из цикла. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Несмотря на то, что на графе в предыдущем разделе для лучшей визуализации и понимания было изображено &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; потоков (никаких допущений мы не делали и нарушений с точки зрения логики и математики нет, можно изобразить большее число потоков, просто часть времени некоторые из них могут бездействовать и не использоваться), на самом деле правильным и разумным будет реализовать начальное параллельное выполнение &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n^2&amp;lt;/math&amp;gt; операций умножения всех вещественных элементов матрицы &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;A&amp;lt;/math&amp;gt; на соответствующие элементы вектора &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;q_j&amp;lt;/math&amp;gt;, после чего применять тот же самый упомянутый метод сдваивания. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Поэтому при классификации по ширине ЯПФ его сложность будет &#039;&#039;квадратичной&#039;&#039; и равна &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(n^2)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
&#039;&#039;&#039;Входные данные алгоритма:&#039;&#039;&#039; вещественная симметричная &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; размера &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;n\times n&amp;lt;/math&amp;gt;, вещественный вектор &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;b&amp;lt;/math&amp;gt; длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt;, и одно целое число &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;k&amp;lt;/math&amp;gt;, означающее количество итераций.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём входных данных:&#039;&#039;&#039; &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;n^2 +n + 1 &amp;lt;/math&amp;gt;. Если учесть, что матрица симметричная и достаточно для её однозначного определения задать элементы на главной диагонали и элементы над или под ней, то можно сократить объём входных данных с целью экономии памяти до: &amp;lt;math&amp;gt;\ \frac{n^2-n}{2}+n+n+1 =\frac{n^2+3n}{2} + 1&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные алгоритма:&#039;&#039;&#039; вектор собственных значений &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;\Theta^k&amp;lt;/math&amp;gt; длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;/math&amp;gt;, матрица &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;S^k&amp;lt;/math&amp;gt; из соответствующих собственных векторов размера &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n\times k&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём выходных данных:&#039;&#039;&#039; &amp;lt;math&amp;gt;k\;(n + 1)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
В данном разделе перечислены без какой-либо хронологии или связи друг с другом наиболее важные и разнообразные свойства алгоритма, на которые стоит и полезно обратить внимание, а также которые выгодно отличают его от схожих алгоритмов, решающих ту же задачу.&amp;lt;br&amp;gt;&lt;br /&gt;
1) Отношение последовательной сложности алгоритма к параллельной,с учётом &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;/math&amp;gt; итераций, равно &amp;lt;math&amp;gt;\;\;\frac{kn^2}{k \log_2{n}}=\frac{n^2}{\log_2{n}}&amp;lt;/math&amp;gt;;&amp;lt;br&amp;gt;&lt;br /&gt;
2) Вычислительная мощность алгоритма, как отношение числа операций к суммарному объему входных и выходных данных, равна &amp;lt;math style=&amp;quot;vertical-align:-70%&amp;gt;\;\;\frac{k\,n^2}{0.5\,n^2+1.5\,n+k\,n+k+1}&amp;lt;/math&amp;gt; и &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;\approx 2\,k&amp;lt;/math&amp;gt;, так как на практике верно отношение &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;&amp;lt;n&amp;lt;/math&amp;gt; ;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
3) Для собственных значений формируемых матриц &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_j&amp;lt;/math&amp;gt; верно отношение (следствие теоремы Коши о перемежаемости): &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;\lambda_i(T_{k+1})\geq \lambda_i(T_{k})\geq \lambda_{i+1}(T_{k+1})\geq \lambda_{i+1}(T_{k})&amp;lt;/math&amp;gt; ;&amp;lt;ref&amp;gt;James W. Demmel - Вычислительная линейная алгебра. Теория и приложения //Мир. - 2001 (c. 383)&amp;lt;/ref&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
4) Крайние (наибольшие и наименьшие) собственные значения матриц &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_j&amp;lt;/math&amp;gt; сходятся к крайним собственным значениям матрицы &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;A&amp;lt;/math&amp;gt; первыми (это часто происходит уже на ранних шагах при &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j\approx 2\,\sqrt{n}&amp;lt;/math&amp;gt;&amp;lt;ref&amp;gt;http://num-anal.srcc.msu.ru/lib_na/int_ae/int_ae6.htm (пункт 6.5)&amp;lt;/ref&amp;gt;), а собственные значения в середине спектра - последними;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
5) Из-за ограниченной точности постепенно теряется ортогональность вектора Ланцоша &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;q_j&amp;lt;/math&amp;gt; к предыдущим векторам Ланцоша, поэтому необходимо примерно каждые 10-15 итераций проводить дорогостоящую операцию реортогонализации, но это уже будет иной алгоритм с очень малым различием в одной операции и в программном коде, реализующем его, соответственно; &amp;lt;ref&amp;gt;Sam Handler - The Lanczos Algorithm For Large-Scale Eigenvalue Problems (08.01.07), slide №8&amp;lt;/ref&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
6) Эффективность и быстрота выполнения алгоритма очень сильно зависит от скорости памяти (диска). Согласно тесту только &#039;&#039;6%&#039;&#039; времени работы программы приходится на вычисления, остальное время затрачивается на ожидание отклика диска;&amp;lt;ref&amp;gt;Sam Handler - The Lanczos Algorithm For Large-Scale Eigenvalue Problems (08.01.07), slide №10&amp;lt;/ref&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
7) Метод Ланцоша удобен тем, что не требует хранения исходной матрицы полным массивом: метод использует исходную матрицу только в операциях умножения матрицы на вектор, что позволяет эффективно использовать разреженность матрицы или регулярность структуры матрицы. Поэтому метод Ланцоша может быть использован для матриц таких больших порядков, когда методы вращений и отражений не могут быть применены.&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;
По заданию, во второй части требовалось описать только разделы 2.4 и 2.7, прошу не спрашивать с меня все разделы 2.1-2.6. Надеюсь на понимание, мне физически не хватает времени на это задание + 2 других в течение семестра, делаю всё, что в моих силах :)&lt;br /&gt;
&lt;br /&gt;
== Существующие реализации алгоритма ==&lt;br /&gt;
Несмотря на то, что алгоритм является далеко не самым популярным, алгоритмом, про который нельзя сказать, что он всегда «на слуху», на сегодняшний день существует множество реализаций на различных популярных языках.&amp;lt;br&amp;gt;&lt;br /&gt;
Перечислим далее некоторые из них, указывая язык программирования, лежащий в их основе, и некоторые важные характеристики, которые обсуждались в статье ранее:&lt;br /&gt;
*&#039;&#039;Code on netlib.org by Jane Cullum and Ralph Willoughby&#039;&#039; (&#039;&#039;&#039;Fortran 77&#039;&#039;&#039;; без реортогонализации векторов; без реализации распараллеливания)&amp;lt;ref&amp;gt;http://www.netlib.org/lanczos/leval&amp;lt;/ref&amp;gt;&lt;br /&gt;
*&#039;&#039;Lanczos algorithm on freesourcecode.net&#039;&#039; (&#039;&#039;&#039;Matlab&#039;&#039;&#039;; присутствует реортогонализация векторов; без реализации распараллеливания)&amp;lt;ref&amp;gt;http://freesourcecode.net/matlabprojects/61741/lanczos-algorithm--in-matlab&amp;lt;/ref&amp;gt;&lt;br /&gt;
*&#039;&#039;Lanczos for eigenvalues in Numerical Linear Algebra, Spring 2007&#039;&#039; (&#039;&#039;&#039;Matlab&#039;&#039;&#039;; частичная или полная реортогонализация - доступны оба варианта; без реализации распараллеливания)&amp;lt;ref&amp;gt;Ссылки на файлы lanso.m и lanfu.m можно найти на https://www.nada.kth.se/~ruhe/2D5219/labs2007.html&amp;lt;/ref&amp;gt;&lt;br /&gt;
*&#039;&#039;Planso&#039;&#039; (название происходит от parallel Lanso.f) &#039;&#039;code by Kesheng Wu and Horst D. Simon&#039;&#039; (&#039;&#039;&#039;Fortran 77&#039;&#039;&#039;; частичная реортогонализация векторов; использование MPI для коммуникаций)&amp;lt;ref&amp;gt;https://github.com/jiahao/planso.jl/tree/master/external/PLAN/plan К сожалению, ссылка в описании пакета на github, ведущая на сайт National Energy Research Scientific Computing Center (NERSC), с более подробной информацией о данной программе больше не активна и выдаёт результат &#039;&#039;Page not found&#039;&#039;&amp;lt;/ref&amp;gt; &lt;br /&gt;
* &#039;&#039;Lanczos.cpp in the Vienna Computing Library&#039;&#039;  (&#039;&#039;&#039;C++&#039;&#039;&#039;, частичная реортогонализация, без реализации распараллеливания) &amp;lt;ref&amp;gt;http://viennacl.sourceforge.net/doc/lanczos_8cpp_source.html&amp;lt;/ref&amp;gt;&lt;br /&gt;
* &#039;&#039;Parallel Eigen Values code using C++ AMP on microsoft msdn blog&#039;&#039; (&#039;&#039;&#039;C++&#039;&#039;&#039;; ? ; распараллеливание есть и реализовано через C++ AMP) &amp;lt;ref&amp;gt;https://blogs.msdn.microsoft.com/nativeconcurrency/2013/12/20/eigen-values/ Подробнее о C++ Accelerated Massive Parallelism можно почитать здесь: https://msdn.microsoft.com/ru-ru/library/hh265137(v=vs.140).aspx или здесь: http://professorweb.ru/my/csharp/optimization/level4/4_6.php &amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;br /&gt;
[[en:Description of algorithm properties and structure]]&lt;/div&gt;</summary>
		<author><name>AleksLevin</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:AleksLevin/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%9B%D0%B0%D0%BD%D1%86%D0%BE%D1%88%D0%B0_%D0%B2%D1%8B%D1%87%D0%B8%D1%81%D0%BB%D0%B5%D0%BD%D0%B8%D1%8F_%D1%81%D0%BE%D0%B1%D1%81%D1%82%D0%B2%D0%B5%D0%BD%D0%BD%D1%8B%D1%85_%D0%B7%D0%BD%D0%B0%D1%87%D0%B5%D0%BD%D0%B8%D0%B9_%D1%81%D0%B8%D0%BC%D0%BC%D0%B5%D1%82%D1%80%D0%B8%D1%87%D0%BD%D0%BE%D0%B9_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86%D1%8B_%D0%B4%D0%BB%D1%8F_%D1%82%D0%BE%D1%87%D0%BD%D0%BE%D0%B9_%D0%B0%D1%80%D0%B8%D1%84%D0%BC%D0%B5%D1%82%D0%B8%D0%BA%D0%B8_(%D0%B1%D0%B5%D0%B7_%D0%BF%D0%B5%D1%80%D0%B5%D0%BE%D1%80%D1%82%D0%BE%D0%B3%D0%BE%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D0%B8)&amp;diff=19945</id>
		<title>Участник:AleksLevin/Алгоритм Ланцоша вычисления собственных значений симметричной матрицы для точной арифметики (без переортогонализации)</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:AleksLevin/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%9B%D0%B0%D0%BD%D1%86%D0%BE%D1%88%D0%B0_%D0%B2%D1%8B%D1%87%D0%B8%D1%81%D0%BB%D0%B5%D0%BD%D0%B8%D1%8F_%D1%81%D0%BE%D0%B1%D1%81%D1%82%D0%B2%D0%B5%D0%BD%D0%BD%D1%8B%D1%85_%D0%B7%D0%BD%D0%B0%D1%87%D0%B5%D0%BD%D0%B8%D0%B9_%D1%81%D0%B8%D0%BC%D0%BC%D0%B5%D1%82%D1%80%D0%B8%D1%87%D0%BD%D0%BE%D0%B9_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86%D1%8B_%D0%B4%D0%BB%D1%8F_%D1%82%D0%BE%D1%87%D0%BD%D0%BE%D0%B9_%D0%B0%D1%80%D0%B8%D1%84%D0%BC%D0%B5%D1%82%D0%B8%D0%BA%D0%B8_(%D0%B1%D0%B5%D0%B7_%D0%BF%D0%B5%D1%80%D0%B5%D0%BE%D1%80%D1%82%D0%BE%D0%B3%D0%BE%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D0%B8)&amp;diff=19945"/>
		<updated>2016-12-02T19:18:22Z</updated>

		<summary type="html">&lt;p&gt;AleksLevin: /* Последовательная сложность алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Основные авторы описания: Левин А.Д.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{algorithm&lt;br /&gt;
| name              = Алгоритм Ланцоша для точной арифметики (без переортогонализации)&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(k\,n^2)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(k\log_2 n)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;\frac{n^2+3n}{2} + 1&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;k\;(n + 1)&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритмов =&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Данный алгоритм появился в 1950 г. и носит имя венгерского физика и математика Корнелия Ланцоша (венг. Lánczos Kornél). Алгоритм Ланцоша относится к итерационным методам вычисления собственных значений для матриц столь больших порядков &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt; n&amp;lt;/math&amp;gt;, что к ним нельзя применить прямые методы из-за ограничений по времени и памяти.&lt;br /&gt;
&lt;br /&gt;
Сам Ланцош указывал, что его метод предназначен для отыскания нескольких собственных векторов симметричных матриц, хотя к методу сразу было обращено внимание, как к способу приведения всей матрицы к трёхдиагональному виду. Двадцатью годами позже канадский математик Крис Пэж показал, что, несмотря на чувствительность к округлениям, алгоритм Ланцоша - эффективное средство вычисления некоторых &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; собственных чисел и соответствующих им собственных векторов. &amp;lt;ref&amp;gt;Парлетт Б. - Симметричная проблема собственных значений. Численные методы //М.: Мир. - 1983. (c. 276)&amp;lt;/ref&amp;gt;&lt;br /&gt;
Обычно число &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; берут в два раза больше, чем количество собственных значений матрицы, которые поставлена цель найти, и оно имеет порядок не более &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;10^2&amp;lt;/math&amp;gt;.&amp;lt;ref&amp;gt;Susan W. Bostic - Lanczos Eigensolution Method for High-Perfomance Computers, page 7&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Алгоритм Ланцоша для вычисления собственных значений симметричной матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; соединяет в себе метод Ланцоша для построения последовательности подпространств Крылова и ортонормированных векторов Ланцоша и процедуру Рэлея-Ритца получения оптимальных приближений собственных значений и соответствующих собственных векторов исходной матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt;.&amp;lt;ref&amp;gt;James W. Demmel - Вычислительная линейная алгебра. Теория и приложения //Мир. - 2001 (c. 381)&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
В данной статье рассматривается вариант алгоритма Ланцоша, в котором опущено влияние ошибок округления на вычислительный процесс, хотя на практике этому посвящается отдельное внимание и существуют различные методы решения данной проблемы, такие как частичная или полная переортогонализация. Этим модифицированным методам посвящены отдельные статьи на данном ресурсе.&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
Обозначения и формулы, используемые в данном разделе, взяты из литературы, указанной по ссылке.&amp;lt;ref&amp;gt;James W. Demmel - Вычислительная линейная алгебра. Теория и приложения //Мир. - 2001 (c. 313, &#039;&#039;&amp;lt;math&amp;gt; \S &amp;lt;/math&amp;gt; 6.6 Методы Крыловского подпространства&#039;&#039;)&amp;lt;/ref&amp;gt; &lt;br /&gt;
&lt;br /&gt;
Алгоритм Ланцоша для вычисления &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; собственных значений и собственных векторов вещественной симметричной матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A=A^T&amp;lt;/math&amp;gt; в точной арифметике: &amp;lt;ref&amp;gt;James W. Demmel - Вычислительная линейная алгебра. Теория и приложения //Мир. - 2001 (c. 381)&amp;lt;/ref&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{align}&lt;br /&gt;
q_1 = &amp;amp; \,\frac{b}{\|b\|_2},\; \beta_0 = 0,\; q_0 = 0\\&lt;br /&gt;
\mathbf{for} \; &amp;amp; j = 1 \; to \; k \,\; \mathbf{do} \\&lt;br /&gt;
&amp;amp; z = A\,q_j\\&lt;br /&gt;
&amp;amp; \alpha_j = q^T_j z\\&lt;br /&gt;
&amp;amp; z = z - \alpha_j q_j - \beta_{j-1}q_{j-1}\\&lt;br /&gt;
&amp;amp; \beta_j = \|z\|_2\\&lt;br /&gt;
&amp;amp; \mathbf{If} \; (\beta_j == 0) \; \mathbf{then}\; stop\; the\; algorithm \\ &lt;br /&gt;
&amp;amp; \;  q_{j+1} = \frac{z}{\beta_j} \\&lt;br /&gt;
&amp;amp; compute\; eigenvalues\; and \;eigenvectors\;of \;matrix \;\;T_j= Q^T_j A Q\;\;and\;estimate \;the\; errors\\&lt;br /&gt;
\mathbf{end} \; &amp;amp; \mathbf{for}&lt;br /&gt;
\end{align}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
В продемонстрированном выше алгоритме &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;b&amp;lt;/math&amp;gt; - заданный вещественный вектор. Также полагается известным алгоритм вычисления произведения матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; на вектор &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;x&amp;lt;/math&amp;gt;. &lt;br /&gt;
Введём матрицу Крылова, определяемую следующим соотношением: &amp;lt;math&amp;gt;K_j = [b,Ab,A^2b,...,A^{j-1}b]&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Далее, на практике, матрица &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;K&amp;lt;/math&amp;gt; заменяется матрицей &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;Q&amp;lt;/math&amp;gt;, такой, что при любом числе &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; линейные оболочки первых &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; столбцов в &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;K&amp;lt;/math&amp;gt; и &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;Q&amp;lt;/math&amp;gt; являются одним и тем же подпространством.&amp;lt;ref&amp;gt;James W. Demmel - Вычислительная линейная алгебра. Теория и приложения //Мир. - 2001 (c. 315)&amp;lt;/ref&amp;gt; &lt;br /&gt;
Тогда матрица &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;Q&amp;lt;/math&amp;gt;, в отличие от матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;K&amp;lt;/math&amp;gt;, хорошо обусловлена и легко обратима. В результате получаем матрицу &amp;lt;math&amp;gt;Q_j = [q_1, q_2, \dots, q_j]&amp;lt;/math&amp;gt; размерности &amp;lt;math&amp;gt;n\times j&amp;lt;/math&amp;gt;, столбцы которой ортогональны, являются базисом подпространства Крылова и называются векторами Ланцоша.&lt;br /&gt;
&lt;br /&gt;
В алгоритме Ланцоша вычислению подлежит столько первых столбцов в матрице &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;Q_j&amp;lt;/math&amp;gt;, сколько необходимо для получения требуемого приближения к решению &amp;lt;math&amp;gt;A\,x\,=b\,\,(A\,x=\lambda \, x)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Получение нулевого &amp;lt;math&amp;gt;\beta_j&amp;lt;/math&amp;gt; в итерационном процессе - событие, желательное в том смысле, что оно свидетельствует о том, что найдено некоторое подпространство, являющееся в точности инвариантным, а все собственные значения матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;T_j&amp;lt;/math&amp;gt; являются собственными значениями матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt;. На практике же нулевое и близкие к нулю значения получаются редко.&amp;lt;ref&amp;gt;Голуб Дж., Ван Лоун Ч. - Матричные вычисления//М.: Мир. - 1999 (c. 429)&amp;lt;/ref&amp;gt; &lt;br /&gt;
&lt;br /&gt;
Затем на каждом шаге цикла формируется симметричная трёхдиагональная матрица &amp;lt;math&amp;gt;T_j = Q^T_j A Q&amp;lt;/math&amp;gt;, к которой применяется процесс Рэлея-Ритца для поиска её собственных значений (на практике для поиска этих собственных значений можно использовать любой из специальных методов в параграфе книги по ссылке).&amp;lt;ref&amp;gt;Голуб Дж., Ван Лоун Ч. - Матричные вычисления//М.: Мир. - 1999 (&amp;lt;math&amp;gt;\S&amp;lt;/math&amp;gt; 8.4)&amp;lt;/ref&amp;gt;  &lt;br /&gt;
Эти собственные значения, они же числа Ритца, и полагаются приближёнными собственными значениями исходной матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt;.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Существует множество методов для отыскания собственных значений вещественной симметричной трехдиагональной матрицы. Большинство из них требует &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt; операций &amp;lt;ref&amp;gt;Парлетт Б. Симметричная проблема собственных значений. Численные методы.,: Мир, 1983. с. 179-182&amp;lt;/ref&amp;gt;, но существуют и быстрые алгоритмы, требующие лишь &amp;lt;math&amp;gt;O(n\ln n)&amp;lt;/math&amp;gt; операций.&amp;lt;ref&amp;gt;https://en.wikipedia.org/wiki/Tridiagonal_matrix#Eigenvalues  Раздел eigenvalues&amp;lt;/ref&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Одним из возможных способов отыскать собственные значения симметричной трехдиагональной матрицы - прямое вычисление корней характеристического полинома &amp;lt;math&amp;gt;p_n(\lambda)&amp;lt;/math&amp;gt; через метод деления пополам, где формируется последовательность Штурма и локализуются собственные числа, являющиеся корнями характеристического полинома. Нахождение всех &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; собственных значений матрицы этим способом требует &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;2n^2t&amp;lt;/math&amp;gt; умножений и вычитаний, где &amp;lt;math&amp;gt;t&amp;lt;/math&amp;gt; - число сделанных шагов с применением метода деления пополам.&amp;lt;ref&amp;gt;Уилкинсон Дж. X. Алгебраическая проблема собственныx значений. Изд-во &amp;quot;Наука&amp;quot;, 1970. - глава 5, с. 272-278&amp;lt;/ref&amp;gt; Соответствующие собственные вектора могут быть найдены посредством обратных итераций за &amp;lt;math&amp;gt; O(n) &amp;lt;/math&amp;gt; флопов. &amp;lt;ref&amp;gt;Голуб Дж., Ван Лоун Ч. - Матричные вычисления//М.: Мир. - 1999 (c. 394-395)&amp;lt;/ref&amp;gt; &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;На практике, если требуется только небольшая часть от всей совокупности собственных векторов и значений, и матрица имеет Хессенбергову или трёхдиагональную форму, очень эффективными будут методы факторизации, как, например, QR-алгоритм или QL-алгоритм со сдвигами (c целью ускорить алгоритм и сделать порядок сходимости квадратичным) или же без них.&amp;lt;ref&amp;gt;http://algorithm.narod.ru/ln/eigen/ETridiag.html&amp;lt;/ref&amp;gt; &amp;lt;br&amp;gt;&lt;br /&gt;
Весьма молодые и не менее актуальные конкуренты QR и QL алгоритмов, применяющиеся для поиска собственных значений:&lt;br /&gt;
*Методы divide-and-conquer (разделяй и властвуй), появившиеся в 1980-ых годах &amp;lt;ref&amp;gt;https://algowiki-project.org/ru/Метод_&amp;quot;Разделяй_и_властвуй&amp;quot;_Завольсков/Землянский&amp;lt;/ref&amp;gt;&lt;br /&gt;
*Relatively robust representation methods, появившиеся в 1990-ых и позволяющие найти собственные числа симметричной матрицы порядка &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;n&amp;lt;/math&amp;gt; за &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt; операций&lt;br /&gt;
&lt;br /&gt;
Если требуется вычислить собственные векторы, то необходимо хранить вычисляемые векторы Ланцоша. Если работа при этом производится только с оперативной памятью, то при большом порядке исходной матрицы (а именно для таких матриц и предназначен метод Ланцоша) число шагов  &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;j&amp;lt;/math&amp;gt;, которые могут быть выполнены до того момента, как оперативная память будет исчерпана, будет очень незначительно, а следовательно, искомые собственные пары могут не успеть сойтись с требуемой точностью. В этом случае метод Ланцоша можно использовать итерационным образом: после выполнения заданного числа шагов процесс прерывается и, если еще не все требуемые пары Ритца сошлись с требуемой точностью, то формируется новый начальный вектор &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;q_1&amp;lt;/math&amp;gt;, являющийся линейной комбинацией векторов Ритца, еще не сошедшихся с заданной точностью, и процесс начинается заново.&amp;lt;ref&amp;gt;http://num-anal.srcc.msu.ru/lib_na/int_ae/int_ae6.htm (пункт 6.5)&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
Вычислительное ядро рассматриваемого алгоритма (наиболее ресурсно-затратная часть алгоритма) -  формирование на каждом шаге цикла промежуточного вектора &amp;lt;math&amp;gt;z&amp;lt;/math&amp;gt;, вычисляемого по формуле: &amp;lt;math&amp;gt;z = A\,q_j&amp;lt;/math&amp;gt;. Данная операция, по сравнению с другими операциями алгоритма, затратна и требовательна, как с точки зрения количества производимых операций, так и с точки зрения объема оперируемых данных. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Например, умножение матрицы размера &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;n\times n&amp;lt;/math&amp;gt; на вектор длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; требует: &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;n^2+(n-1)n = 2n^2-n&amp;lt;/math&amp;gt; операций умножения и сложения. В свою очередь аналогичная операция умножения матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;(n+1)\times (n+1)&amp;lt;/math&amp;gt; на вектор длины &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;(n+1)&amp;lt;/math&amp;gt; требует: &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;2n^2+3n+1&amp;lt;/math&amp;gt;  операций умножения и сложения. То есть повышение размерности задачи всего на 1 увеличивает число необходимых действий в этом шаге алгоритма на: &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;4n+1&amp;lt;/math&amp;gt;. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Так же, стоит помнить, что, согласно разделу 1.2, данную операцию умножения матрицы на вектор необходимо выполнить &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;k&amp;lt;/math&amp;gt; раз. Нетрудно понять, насколько возрастает и колоссален масштаб операций, если в задачах, где критична точность, размерности &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; могут иметь порядок &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;10^5&amp;lt;/math&amp;gt; или даже более.&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
Как уже было упомянуто в данной статье в описании алгоритма, рассматриваемый алгоритм состоит из двух последовательно выполненных алгоритмов: метод Ланцоша для построения последовательности подпространств Крылова и ортонормированных векторов Ланцоша и процедура Рэлея-Ритца получения оптимальных приближений собственных значений и соответствующих собственных векторов исходной матрицы.&lt;br /&gt;
&lt;br /&gt;
В первой части алгоритма, где итерационно строятся Крыловское подпространство и трёхдиагональная матрица &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&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 style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; разреженная. Именно она подлежит оптимизации с использованием техник распараллеливания, поскольку она является вычислительным ядром алгоритма, а весь упомянутый процесс построения матрицы &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&amp;lt;/math&amp;gt; выполняется последовательно.&lt;br /&gt;
&lt;br /&gt;
Рассмотрим вторую часть алгоритма - поиск собственных значений сформированной матрицы &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&amp;lt;/math&amp;gt;.&amp;lt;br&amp;gt;&lt;br /&gt;
Далее, наглядно, в виде псевдокода, представлен, упомянутый в разделе 1.2, QR-алгоритм (аналогично можно рассмотреть и QL-алгоритм) со сдвигами Релэя, который весьма популярен на практике.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{align}&lt;br /&gt;
\mathbf{Input}: \;&amp;amp;tridiagonal\;\;matrix \;T\;with\;\;n\times n\;\;size\\&lt;br /&gt;
T^{(0)}&amp;amp;:=T\\&lt;br /&gt;
\mathbf{for}&amp;amp; \;\;m=n,...,2 \;\; \mathbf{do}\\&lt;br /&gt;
&amp;amp;k=0\\&lt;br /&gt;
&amp;amp; \mathbf{repeat}\\&lt;br /&gt;
&amp;amp; \quad \;\; k=k+1\\&lt;br /&gt;
&amp;amp; \quad \;\; \mu^{(k)}=T_{m,m}^{(k-1)}\\&lt;br /&gt;
&amp;amp; \quad \;\; Q^{(k)}R^{(k)}=T^{(k-1)}-\mu^{(k)}I\;\;using\;\;QR\;decomposition\\&lt;br /&gt;
&amp;amp; \quad \;\; T^{(k)}=R^{(k)}Q^{(k)}+\mu^{(k)}I\\&lt;br /&gt;
&amp;amp; \mathbf{until} \;\;\; |T_{m,m-1}^{(k)}| \;is\;\;small\;\;enough\\&lt;br /&gt;
&amp;amp; Save  \;\;T_{m,m}^{(k)} \;\;as\;\; converged\;\;eigenvalue\;of\;T\\ &lt;br /&gt;
&amp;amp; Remove \;\boldsymbol{n}\,th\;row\;and\;\boldsymbol{n}\,th\;column\;\;from \;T \\&lt;br /&gt;
&amp;amp; and\;take\;this\;new\;cropped\;matrix\;as\;new\;T^{(0)}\;with\;\;(n-1)\times (n-1)\;\;size\\&lt;br /&gt;
 \mathbf{end}&amp;amp;\; \mathbf{for}&lt;br /&gt;
\end{align}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Малость наддиагональных и поддиагональных элементов матрицы (фраза &#039;&#039;&amp;quot;small enough&amp;quot;&#039;&#039; в псевдокоде) подразумевает:&lt;br /&gt;
&amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt; |T_{m,m-1}^{(k)}| \leq \varepsilon\,|T_{m,m}^{(k)}| \quad\quad &amp;lt;/math&amp;gt; , где &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt; \varepsilon &amp;lt;/math&amp;gt; - заданная точность&amp;lt;br&amp;gt;&lt;br /&gt;
Также вместо сдвига Релэя, обозначенного в алгоритме через &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;\mu^{(k)}&amp;lt;/math&amp;gt; часто на практике используется сдвиг по Уилкинсону, который даёт гарантированную сходимость внедиагональных элементов матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt; T^{(k)} &amp;lt;/math&amp;gt;, формируемой на каждом шаге, к нулю, при этом жертвуя монотонностью их убывания.&amp;lt;ref&amp;gt;Голуб Дж., Ван Лоун Ч. - Матричные вычисления//М.: Мир. - 1999 (c. 378, вторая половина страницы)&amp;lt;/ref&amp;gt;&amp;lt;ref&amp;gt;Парлетт Б. Симметричная проблема собственных значений. Численные методы.,: Мир, 1983. с. 169&amp;lt;/ref&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Подробнее с различными сдвигами и соответствующими оценками скоростей и количествами операций можно ознакомиться по указанной ссылке:&amp;lt;ref&amp;gt;Парлетт Б. Симметричная проблема собственных значений. Численные методы.,: Мир, 1983. с. 179-182&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;Для совершения QR-декомпозиции на каждом шаге может использоваться любой из алгоритмов по ссылке.&amp;lt;ref&amp;gt;https://en.wikipedia.org/wiki/QR_decomposition&amp;lt;/ref&amp;gt; Подробные описания этих алгоритмов также доступны на данном ресурсе algowiki-project.&amp;lt;br&amp;gt;&lt;br /&gt;
Так как мы оперируем не обычной матрицей и даже не Хессенберговой, а симметричной и трёхдиагональной, то скорость таких алгоритмов значительно возрастёт. Например, согласно данному ресурсу &amp;lt;ref&amp;gt;http://algorithm.narod.ru/ln/eigen/ETridiag.html&amp;lt;/ref&amp;gt;, для QL-алгоритма с неявными сдвигами:&amp;lt;br&amp;gt;&lt;br /&gt;
Для трёхдиагональной матрицы объем арифметических действий составляет &amp;lt;math&amp;gt; O(n)&amp;lt;/math&amp;gt; на одну итерацию вместо &amp;lt;math&amp;gt; O(n^3)&amp;lt;/math&amp;gt; для матрицы общего вида, а число итераций для нахождения первых собственных значений примерно равно 4 - 5. Но на этих итерациях также уменьшаются внедиагональные элементы правого нижнего угла. И, таким образом, дальнейшие собственные значения ищутся значительно быстрее. Среднее число итераций на каждое собственное значение обычно составляет 1.3 - 1.6.&amp;lt;br&amp;gt; &lt;br /&gt;
Аналогично QL, QR-разложение трёхдиагольной матрицы также требует &amp;lt;math&amp;gt; O(n)&amp;lt;/math&amp;gt; флопов&amp;lt;ref&amp;gt;Голуб Дж., Ван Лоун Ч. - Матричные вычисления//М.: Мир. - 1999 (c. 378, начало раздела 8.2.2)&amp;lt;/ref&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Подводя итог, во второй части алгоритма Ланцоша можно выделить следующие макрооперации:&lt;br /&gt;
* умножение матрицы на вещественное число;&lt;br /&gt;
* перемножение матриц;&lt;br /&gt;
* умножение и сравнение вещественных чисел;&lt;br /&gt;
* + набор других макроопераций в зависимости от выбора метода, с помощью которого будет совершаться сама QR или QL-декомпозиция (выше продемонстрированы, уже, как минимум, 3 разных способа).&lt;br /&gt;
Так же, важно заметить, что набор макропераций может быть несколько другим, если выбрать какой-либо иной современный метод поиска собственных чисел трёхдиагональной матрицы, не использующий QR и QL разложения(факторизацию). Два таких метода были упомянуты в пункте 1.2.&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
С целью полностью не дублировать раздел 1.2 данной статьи, где представлен наглядный и доступный для понимания псевдокод алгоритма, постараемся лишь коротко просуммировать и обобщить весь перечень последовательных действий в рассматриваемом алгоритме.&lt;br /&gt;
&lt;br /&gt;
В качестве входных данных имеем: вещественная симметричная матрица &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; размера &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;n\times n&amp;lt;/math&amp;gt;, известный вещественный вектор &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;b&amp;lt;/math&amp;gt; длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; и число &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;n&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Далее:&lt;br /&gt;
* Инициализируем вещественную константу &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;\beta_0&amp;lt;/math&amp;gt; и векторы &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;q_0&amp;lt;/math&amp;gt; и &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;q_1&amp;lt;/math&amp;gt;&lt;br /&gt;
* Итерационно для всех &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j=1,...,k&amp;lt;/math&amp;gt;:&lt;br /&gt;
** Вычисляем вспомогательный вектор &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt;, используя умножение матрицы на вектор&lt;br /&gt;
** Вычисляем, используя скалярное произведение векторов, значение &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;\alpha_j&amp;lt;/math&amp;gt; - элемент на главной диагонали трёхдиагональной матрицы &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&amp;lt;/math&amp;gt;&lt;br /&gt;
** Вычисляем по формуле новое значение и перезаписываем вектор &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt;&lt;br /&gt;
** Вычисляем значение &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;\beta_j&amp;lt;/math&amp;gt; - элементы непосредственно над и под главной диагональю той же матрицы &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&amp;lt;/math&amp;gt;&lt;br /&gt;
** Вычисляем, зная вектор &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt;,  очередной столбец матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;Q&amp;lt;/math&amp;gt;, он же вектор Ланцоша : &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;\,\,q_{j+1}&amp;lt;/math&amp;gt;&lt;br /&gt;
** Теперь, когда матрица &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&amp;lt;/math&amp;gt; сформирована на очередном шаге, находим её собственные значения и вектора любым доступным способом, о чём было подробно сказано в пункте 1.2&lt;br /&gt;
** Переходим на следующую итерацию: &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j&amp;lt;/math&amp;gt;++&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
Оценим количество операций и сложность последовательного алгоритма, изложенного в предыдущем разделе.&lt;br /&gt;
*Для вычисления вектора &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt; умножается матрица размера &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;n\times n&amp;lt;/math&amp;gt; на вектор длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt;, и потребуется &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n^2&amp;lt;/math&amp;gt; операций умножения и &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n^2&amp;lt;/math&amp;gt; операций сложения.&lt;br /&gt;
*Умножение векторов &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;q^T_j&amp;lt;/math&amp;gt; и &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt; длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; потребует &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; операций умножения и &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; операций сложения.&lt;br /&gt;
*При вычислении нового значения вектора &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt; поэлементное сложение двух векторов длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; требует &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; операций сложения.&lt;br /&gt;
*Умножение вектора длины &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; на вещественное число требует &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; операций умножения.&lt;br /&gt;
*Нахождение квадратичной нормы вектора &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt;  длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; требует &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; умножений и &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; сложений и ещё 1 операцию извлечения квадратного корня.&lt;br /&gt;
*Заключительное нахождение собственных значений и собственных векторов трёхдиагональной матрицы &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;T_j&amp;lt;/math&amp;gt; размера &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j\times j&amp;lt;/math&amp;gt; с помощью QR-алгоритма потребует в худшем случае &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(j^3)&amp;lt;/math&amp;gt; операций.&amp;lt;ref&amp;gt;http://num-anal.srcc.msu.ru/lib_na/int_ae/int_ae6.htm (пункт 6.2, &amp;quot;Скорость сходимости при этом всегда не хуже квадратичной и почти всегда лучше кубической.&amp;quot;)&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Посчитаем теперь суммарное количество простейших операций на одной итерации алгоритма (без учёта записей в память):&lt;br /&gt;
*&amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n^2+5\,n&amp;lt;/math&amp;gt; операций умножения/деления&lt;br /&gt;
*&amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n^2+4\,n&amp;lt;/math&amp;gt; операций сложения/вычитания&lt;br /&gt;
*1 операция извлечения квадратного корня&amp;lt;br&amp;gt;&lt;br /&gt;
Отдельно после всех итераций при &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j=k&amp;lt;/math&amp;gt; :&lt;br /&gt;
*&amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(k^3)&amp;lt;/math&amp;gt; операций для поиска собственных значений и собственных векторов трёхдиагональной матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_k&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Итого можно утверждать следующее:&lt;br /&gt;
&lt;br /&gt;
Последовательная сложность одной итерации рассматриваемого алгоритма:  &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(n ^ 2) &amp;lt;/math&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Суммарная сложность алгоритма (&amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;/math&amp;gt; итераций): &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(k\,n ^ 2) + O(k ^ 3)&amp;lt;/math&amp;gt; &amp;lt;ref&amp;gt;Здесь мы полагаем, что мы не вычисляем собственные значения и векторы матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_j&amp;lt;/math&amp;gt; на каждом промежуточном шаге, а лишь единожды затрачиваем &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;O(k ^ 3)&amp;lt;/math&amp;gt; действий в конце для нахождения &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;/math&amp;gt; собственных значений и векторов матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_k&amp;lt;/math&amp;gt;&amp;lt;/ref&amp;gt; &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
На практике же обычно рассматривается число &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;&amp;lt;n&amp;lt;/math&amp;gt;, поэтому второе слагаемое можно опустить.&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
На рис. 1 продемонстрирован граф одной итерации (при каком-либо произвольном значении итератора &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j&amp;lt;/math&amp;gt;) описанного алгоритма без отображения входных и выходных данных. Наглядно продемонстрированы связи между всеми действиями, и с помощью деления на &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; потоков показано, какие операции возможно выполнять параллельно на каждом шаге с целью оптимизации и экономии машинного времени. В результате, после параллельно выполненных операций &#039;&#039;&#039;Division&#039;&#039;&#039; на заключительном ярусе, на выходе имеем значение следующего вектора Ланцоша &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;q_{j+1}&amp;lt;/math&amp;gt;, после чего следует переход на следующую итерацию, и процесс повторяется.&lt;br /&gt;
&lt;br /&gt;
[[Файл:Levin_graph.png|600px|thumb|center|Рис. 1]] &amp;lt;br&amp;gt;&lt;br /&gt;
Обозначения на рисунке: &amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Simp&#039;&#039;&#039; (от англ. simple) - операции сложения и умножения вещественных чисел при вычислении произведения матрицы на вектор;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Vec mult&#039;&#039;&#039; (от англ. vectors multiplication) - операция скалярного умножения двух векторов;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Vec subtr&#039;&#039;&#039; (от англ. vectors subtraction, из-за использованных в операции вычитаний векторов) - операция умножения вектора на число (выполняется дважды) и формирование нового значения &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;z_{new}&amp;lt;/math&amp;gt; по формуле: &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;z_{new} = z - \alpha_j q_j - \beta_{j-1}q_{j-1} \;&amp;lt;/math&amp;gt;;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;||\cdot||&amp;lt;/math&amp;gt; - операция вычисления нормы вектора;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Division&#039;&#039;&#039; - операция деления вектора на вещественное число  &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;\beta_j&amp;lt;/math&amp;gt; &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Важно отметить, что упомянутые выше операции также легко поддаются оптимизации. Например, попарные умножения вещественных координат векторов при вычислении скалярного произведения также легко выполняются параллельно на &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; потоках, а затем можно применить суммирование методом сдваивания, о котором сказано в следующем разделе. Умножение или деление вектора на вещественное число являющееся, по определению, умножением или делением всех его координат на это число тоже может быть выполнено эффективнее, если мы используем &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; потоков, а не выполняем эти действия последовательно.&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
Параллельные операции возможны только внутри итераций, так как рассматриваемый алгоритм является итерационным, и сами итерации строго последовательны.&amp;lt;br&amp;gt;&lt;br /&gt;
Рассмотрим в этом разделе подробнее, какой выигрыш мы можем получить при распараллеливании операций внутри одной итерации согласно графу из предыдущего раздела.&lt;br /&gt;
&lt;br /&gt;
Умножение вещественной симметричной матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; размера &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;n\times n&amp;lt;/math&amp;gt; на вектор &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;b&amp;lt;/math&amp;gt; длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; требует последовательного выполнения &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; ярусов умножений и сложений. Сложение элементов вектора длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; на каждом шаге перемножения можно оптимизировать и выполнить за &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;\log_2 n&amp;lt;/math&amp;gt; действий, если применять метод сдваивания.&lt;br /&gt;
&lt;br /&gt;
Дальнейшие операции выполняются последовательно, а вычисление значений векторов происходит за один ярус операций сложения или умножения.&lt;br /&gt;
&lt;br /&gt;
Ресурс параллелизма алгоритма вычисления собственных значений построенной трёхдиагональной матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_k&amp;lt;/math&amp;gt; размера &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k\times k&amp;lt;/math&amp;gt; зависит от выбранного алгоритма (об этих алгоритмах подробнее было сказано в разделах 1.2 и 1.4). Будет очень затратно с точки зрения объёма материала пытаться рассмотреть пусть даже часть этих методов в этой статье, а так же тонкости их распараллеливания. Предлагаем читателям при желании самим ознакомиться с этими алгоритмами на данном ресурсе или прибегнув к иным источникам.&lt;br /&gt;
&lt;br /&gt;
При классификации по высоте ЯПФ, таким образом, алгоритм Ланцоша без переортогонализации относится к алгоритмам с &#039;&#039;логарифмической сложностью&#039;&#039;, и его сложность равна &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(\log_2 n)&amp;lt;/math&amp;gt; с важным замечанием, что это сложность только одной итерации, а максимум в алгоритме может быть выполнено последовательно &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;/math&amp;gt; таких однотипных итераций, если не будет осуществлён ранний выход из цикла. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Несмотря на то, что на графе в предыдущем разделе для лучшей визуализации и понимания было изображено &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; потоков (никаких допущений мы не делали и нарушений с точки зрения логики и математики нет, можно изобразить большее число потоков, просто часть времени некоторые из них могут бездействовать и не использоваться), на самом деле правильным и разумным будет реализовать начальное параллельное выполнение &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n^2&amp;lt;/math&amp;gt; операций умножения всех вещественных элементов матрицы &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;A&amp;lt;/math&amp;gt; на соответствующие элементы вектора &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;q_j&amp;lt;/math&amp;gt;, после чего применять тот же самый упомянутый метод сдваивания. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Поэтому при классификации по ширине ЯПФ его сложность будет &#039;&#039;квадратичной&#039;&#039; и равна &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(n^2)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
&#039;&#039;&#039;Входные данные алгоритма:&#039;&#039;&#039; вещественная симметричная &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; размера &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;n\times n&amp;lt;/math&amp;gt;, вещественный вектор &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;b&amp;lt;/math&amp;gt; длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt;, и одно целое число &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;k&amp;lt;/math&amp;gt;, означающее количество итераций.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём входных данных:&#039;&#039;&#039; &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;n^2 +n + 1 &amp;lt;/math&amp;gt;. Если учесть, что матрица симметричная и достаточно для её однозначного определения задать элементы на главной диагонали и элементы над или под ней, то можно сократить объём входных данных с целью экономии памяти до: &amp;lt;math&amp;gt;\ \frac{n^2-n}{2}+n+n+1 =\frac{n^2+3n}{2} + 1&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные алгоритма:&#039;&#039;&#039; вектор собственных значений &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;\Theta^k&amp;lt;/math&amp;gt; длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;/math&amp;gt;, матрица &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;S^k&amp;lt;/math&amp;gt; из соответствующих собственных векторов размера &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n\times k&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём выходных данных:&#039;&#039;&#039; &amp;lt;math&amp;gt;k\;(n + 1)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
В данном разделе перечислены без какой-либо хронологии или связи друг с другом наиболее важные и разнообразные свойства алгоритма, на которые стоит и полезно обратить внимание, а также которые выгодно отличают его от схожих алгоритмов, решающих ту же задачу.&amp;lt;br&amp;gt;&lt;br /&gt;
1) Отношение последовательной сложности алгоритма к параллельной,с учётом &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;/math&amp;gt; итераций, равно &amp;lt;math&amp;gt;\;\;\frac{kn^2}{k \log_2{n}}=\frac{n^2}{\log_2{n}}&amp;lt;/math&amp;gt;;&amp;lt;br&amp;gt;&lt;br /&gt;
2) Вычислительная мощность алгоритма, как отношение числа операций к суммарному объему входных и выходных данных, равна &amp;lt;math style=&amp;quot;vertical-align:-70%&amp;gt;\;\;\frac{k\,n^2}{0.5\,n^2+1.5\,n+k\,n+k+1}&amp;lt;/math&amp;gt; и &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;\approx 2\,k&amp;lt;/math&amp;gt;, так как на практике верно отношение &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;&amp;lt;n&amp;lt;/math&amp;gt; ;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
3) Для собственных значений формируемых матриц &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_j&amp;lt;/math&amp;gt; верно отношение (следствие теоремы Коши о перемежаемости): &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;\lambda_i(T_{k+1})\geq \lambda_i(T_{k})\geq \lambda_{i+1}(T_{k+1})\geq \lambda_{i+1}(T_{k})&amp;lt;/math&amp;gt; ;&amp;lt;ref&amp;gt;James W. Demmel - Вычислительная линейная алгебра. Теория и приложения //Мир. - 2001 (c. 383)&amp;lt;/ref&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
4) Крайние (наибольшие и наименьшие) собственные значения матриц &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_j&amp;lt;/math&amp;gt; сходятся к крайним собственным значениям матрицы &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;A&amp;lt;/math&amp;gt; первыми (это часто происходит уже на ранних шагах при &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j\approx 2\,\sqrt{n}&amp;lt;/math&amp;gt;&amp;lt;ref&amp;gt;http://num-anal.srcc.msu.ru/lib_na/int_ae/int_ae6.htm (пункт 6.5)&amp;lt;/ref&amp;gt;), а собственные значения в середине спектра - последними;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
5) Из-за ограниченной точности постепенно теряется ортогональность вектора Ланцоша &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;q_j&amp;lt;/math&amp;gt; к предыдущим векторам Ланцоша, поэтому необходимо примерно каждые 10-15 итераций проводить дорогостоящую операцию реортогонализации, но это уже будет иной алгоритм с очень малым различием в одной операции и в программном коде, реализующем его, соответственно; &amp;lt;ref&amp;gt;Sam Handler - The Lanczos Algorithm For Large-Scale Eigenvalue Problems (08.01.07), slide №8&amp;lt;/ref&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
6) Эффективность и быстрота выполнения алгоритма очень сильно зависит от скорости памяти (диска). Согласно тесту только &#039;&#039;6%&#039;&#039; времени работы программы приходится на вычисления, остальное время затрачивается на ожидание отклика диска;&amp;lt;ref&amp;gt;Sam Handler - The Lanczos Algorithm For Large-Scale Eigenvalue Problems (08.01.07), slide №10&amp;lt;/ref&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
7) Метод Ланцоша удобен тем, что не требует хранения исходной матрицы полным массивом: метод использует исходную матрицу только в операциях умножения матрицы на вектор, что позволяет эффективно использовать разреженность матрицы или регулярность структуры матрицы. Поэтому метод Ланцоша может быть использован для матриц таких больших порядков, когда методы вращений и отражений не могут быть применены.&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;
По заданию, во второй части требовалось описать только разделы 2.4 и 2.7, прошу не спрашивать с меня все разделы 2.1-2.6. Надеюсь на понимание, мне физически не хватает времени на это задание + 2 других в течение семестра, делаю всё, что в моих силах :)&lt;br /&gt;
&lt;br /&gt;
== Существующие реализации алгоритма ==&lt;br /&gt;
Несмотря на то, что алгоритм является далеко не самым популярным, алгоритмом, про который нельзя сказать, что он всегда «на слуху», на сегодняшний день существует множество реализаций на различных популярных языках.&amp;lt;br&amp;gt;&lt;br /&gt;
Перечислим далее некоторые из них, указывая язык программирования, лежащий в их основе, и некоторые важные характеристики, которые обсуждались в статье ранее:&lt;br /&gt;
*&#039;&#039;Code on netlib.org by Jane Cullum and Ralph Willoughby&#039;&#039; (&#039;&#039;&#039;Fortran 77&#039;&#039;&#039;; без реортогонализации векторов; без реализации распараллеливания)&amp;lt;ref&amp;gt;http://www.netlib.org/lanczos/leval&amp;lt;/ref&amp;gt;&lt;br /&gt;
*&#039;&#039;Lanczos algorithm on freesourcecode.net&#039;&#039; (&#039;&#039;&#039;Matlab&#039;&#039;&#039;; присутствует реортогонализация векторов; без реализации распараллеливания)&amp;lt;ref&amp;gt;http://freesourcecode.net/matlabprojects/61741/lanczos-algorithm--in-matlab&amp;lt;/ref&amp;gt;&lt;br /&gt;
*&#039;&#039;Lanczos for eigenvalues in Numerical Linear Algebra, Spring 2007&#039;&#039; (&#039;&#039;&#039;Matlab&#039;&#039;&#039;; частичная или полная реортогонализация - доступны оба варианта; без реализации распараллеливания)&amp;lt;ref&amp;gt;Ссылки на файлы lanso.m и lanfu.m можно найти на https://www.nada.kth.se/~ruhe/2D5219/labs2007.html&amp;lt;/ref&amp;gt;&lt;br /&gt;
*&#039;&#039;Planso&#039;&#039; (название происходит от parallel Lanso.f) &#039;&#039;code by Kesheng Wu and Horst D. Simon&#039;&#039; (&#039;&#039;&#039;Fortran 77&#039;&#039;&#039;; частичная реортогонализация векторов; использование MPI для коммуникаций)&amp;lt;ref&amp;gt;https://github.com/jiahao/planso.jl/tree/master/external/PLAN/plan К сожалению, ссылка в описании пакета на github, ведущая на сайт National Energy Research Scientific Computing Center (NERSC), с более подробной информацией о данной программе больше не активна и выдаёт результат &#039;&#039;Page not found&#039;&#039;&amp;lt;/ref&amp;gt; &lt;br /&gt;
* &#039;&#039;Lanczos.cpp in the Vienna Computing Library&#039;&#039;  (&#039;&#039;&#039;C++&#039;&#039;&#039;, частичная реортогонализация, без реализации распараллеливания) &amp;lt;ref&amp;gt;http://viennacl.sourceforge.net/doc/lanczos_8cpp_source.html&amp;lt;/ref&amp;gt;&lt;br /&gt;
* &#039;&#039;Parallel Eigen Values code using C++ AMP on microsoft msdn blog&#039;&#039; (&#039;&#039;&#039;C++&#039;&#039;&#039;; ? ; распараллеливание есть и реализовано через C++ AMP) &amp;lt;ref&amp;gt;https://blogs.msdn.microsoft.com/nativeconcurrency/2013/12/20/eigen-values/ Подробнее о C++ Accelerated Massive Parallelism можно почитать здесь: https://msdn.microsoft.com/ru-ru/library/hh265137(v=vs.140).aspx или здесь: http://professorweb.ru/my/csharp/optimization/level4/4_6.php &amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;br /&gt;
[[en:Description of algorithm properties and structure]]&lt;/div&gt;</summary>
		<author><name>AleksLevin</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:AleksLevin&amp;diff=19944</id>
		<title>Участник:AleksLevin</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:AleksLevin&amp;diff=19944"/>
		<updated>2016-12-02T19:15:08Z</updated>

		<summary type="html">&lt;p&gt;AleksLevin: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;магистр ВМК МГУ, 604 группа, кафедра вычислительных методов.&lt;br /&gt;
Личная почта для всех вопросов и предложений: &#039;&#039;alev343@gmail.com&#039;&#039;&lt;/div&gt;</summary>
		<author><name>AleksLevin</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:AleksLevin&amp;diff=19943</id>
		<title>Участник:AleksLevin</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:AleksLevin&amp;diff=19943"/>
		<updated>2016-12-02T19:14:42Z</updated>

		<summary type="html">&lt;p&gt;AleksLevin: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;магистр ВМК МГУ, 604 группа, кафедра вычислительных методов&lt;br /&gt;
личная почта для всех вопросов и предложений: alev343@gmail.com&lt;/div&gt;</summary>
		<author><name>AleksLevin</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:AleksLevin/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%9B%D0%B0%D0%BD%D1%86%D0%BE%D1%88%D0%B0_%D0%B2%D1%8B%D1%87%D0%B8%D1%81%D0%BB%D0%B5%D0%BD%D0%B8%D1%8F_%D1%81%D0%BE%D0%B1%D1%81%D1%82%D0%B2%D0%B5%D0%BD%D0%BD%D1%8B%D1%85_%D0%B7%D0%BD%D0%B0%D1%87%D0%B5%D0%BD%D0%B8%D0%B9_%D1%81%D0%B8%D0%BC%D0%BC%D0%B5%D1%82%D1%80%D0%B8%D1%87%D0%BD%D0%BE%D0%B9_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86%D1%8B_%D0%B4%D0%BB%D1%8F_%D1%82%D0%BE%D1%87%D0%BD%D0%BE%D0%B9_%D0%B0%D1%80%D0%B8%D1%84%D0%BC%D0%B5%D1%82%D0%B8%D0%BA%D0%B8_(%D0%B1%D0%B5%D0%B7_%D0%BF%D0%B5%D1%80%D0%B5%D0%BE%D1%80%D1%82%D0%BE%D0%B3%D0%BE%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D0%B8)&amp;diff=19941</id>
		<title>Участник:AleksLevin/Алгоритм Ланцоша вычисления собственных значений симметричной матрицы для точной арифметики (без переортогонализации)</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:AleksLevin/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%9B%D0%B0%D0%BD%D1%86%D0%BE%D1%88%D0%B0_%D0%B2%D1%8B%D1%87%D0%B8%D1%81%D0%BB%D0%B5%D0%BD%D0%B8%D1%8F_%D1%81%D0%BE%D0%B1%D1%81%D1%82%D0%B2%D0%B5%D0%BD%D0%BD%D1%8B%D1%85_%D0%B7%D0%BD%D0%B0%D1%87%D0%B5%D0%BD%D0%B8%D0%B9_%D1%81%D0%B8%D0%BC%D0%BC%D0%B5%D1%82%D1%80%D0%B8%D1%87%D0%BD%D0%BE%D0%B9_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86%D1%8B_%D0%B4%D0%BB%D1%8F_%D1%82%D0%BE%D1%87%D0%BD%D0%BE%D0%B9_%D0%B0%D1%80%D0%B8%D1%84%D0%BC%D0%B5%D1%82%D0%B8%D0%BA%D0%B8_(%D0%B1%D0%B5%D0%B7_%D0%BF%D0%B5%D1%80%D0%B5%D0%BE%D1%80%D1%82%D0%BE%D0%B3%D0%BE%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D0%B8)&amp;diff=19941"/>
		<updated>2016-12-02T19:12:24Z</updated>

		<summary type="html">&lt;p&gt;AleksLevin: /* Математическое описание алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Основные авторы описания: Левин А.Д.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{algorithm&lt;br /&gt;
| name              = Алгоритм Ланцоша для точной арифметики (без переортогонализации)&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(k\,n^2)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(k\log_2 n)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;\frac{n^2+3n}{2} + 1&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;k\;(n + 1)&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритмов =&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Данный алгоритм появился в 1950 г. и носит имя венгерского физика и математика Корнелия Ланцоша (венг. Lánczos Kornél). Алгоритм Ланцоша относится к итерационным методам вычисления собственных значений для матриц столь больших порядков &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt; n&amp;lt;/math&amp;gt;, что к ним нельзя применить прямые методы из-за ограничений по времени и памяти.&lt;br /&gt;
&lt;br /&gt;
Сам Ланцош указывал, что его метод предназначен для отыскания нескольких собственных векторов симметричных матриц, хотя к методу сразу было обращено внимание, как к способу приведения всей матрицы к трёхдиагональному виду. Двадцатью годами позже канадский математик Крис Пэж показал, что, несмотря на чувствительность к округлениям, алгоритм Ланцоша - эффективное средство вычисления некоторых &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; собственных чисел и соответствующих им собственных векторов. &amp;lt;ref&amp;gt;Парлетт Б. - Симметричная проблема собственных значений. Численные методы //М.: Мир. - 1983. (c. 276)&amp;lt;/ref&amp;gt;&lt;br /&gt;
Обычно число &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; берут в два раза больше, чем количество собственных значений матрицы, которые поставлена цель найти, и оно имеет порядок не более &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;10^2&amp;lt;/math&amp;gt;.&amp;lt;ref&amp;gt;Susan W. Bostic - Lanczos Eigensolution Method for High-Perfomance Computers, page 7&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Алгоритм Ланцоша для вычисления собственных значений симметричной матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; соединяет в себе метод Ланцоша для построения последовательности подпространств Крылова и ортонормированных векторов Ланцоша и процедуру Рэлея-Ритца получения оптимальных приближений собственных значений и соответствующих собственных векторов исходной матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt;.&amp;lt;ref&amp;gt;James W. Demmel - Вычислительная линейная алгебра. Теория и приложения //Мир. - 2001 (c. 381)&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
В данной статье рассматривается вариант алгоритма Ланцоша, в котором опущено влияние ошибок округления на вычислительный процесс, хотя на практике этому посвящается отдельное внимание и существуют различные методы решения данной проблемы, такие как частичная или полная переортогонализация. Этим модифицированным методам посвящены отдельные статьи на данном ресурсе.&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
Обозначения и формулы, используемые в данном разделе, взяты из литературы, указанной по ссылке.&amp;lt;ref&amp;gt;James W. Demmel - Вычислительная линейная алгебра. Теория и приложения //Мир. - 2001 (c. 313, &#039;&#039;&amp;lt;math&amp;gt; \S &amp;lt;/math&amp;gt; 6.6 Методы Крыловского подпространства&#039;&#039;)&amp;lt;/ref&amp;gt; &lt;br /&gt;
&lt;br /&gt;
Алгоритм Ланцоша для вычисления &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; собственных значений и собственных векторов вещественной симметричной матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A=A^T&amp;lt;/math&amp;gt; в точной арифметике: &amp;lt;ref&amp;gt;James W. Demmel - Вычислительная линейная алгебра. Теория и приложения //Мир. - 2001 (c. 381)&amp;lt;/ref&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{align}&lt;br /&gt;
q_1 = &amp;amp; \,\frac{b}{\|b\|_2},\; \beta_0 = 0,\; q_0 = 0\\&lt;br /&gt;
\mathbf{for} \; &amp;amp; j = 1 \; to \; k \,\; \mathbf{do} \\&lt;br /&gt;
&amp;amp; z = A\,q_j\\&lt;br /&gt;
&amp;amp; \alpha_j = q^T_j z\\&lt;br /&gt;
&amp;amp; z = z - \alpha_j q_j - \beta_{j-1}q_{j-1}\\&lt;br /&gt;
&amp;amp; \beta_j = \|z\|_2\\&lt;br /&gt;
&amp;amp; \mathbf{If} \; (\beta_j == 0) \; \mathbf{then}\; stop\; the\; algorithm \\ &lt;br /&gt;
&amp;amp; \;  q_{j+1} = \frac{z}{\beta_j} \\&lt;br /&gt;
&amp;amp; compute\; eigenvalues\; and \;eigenvectors\;of \;matrix \;\;T_j= Q^T_j A Q\;\;and\;estimate \;the\; errors\\&lt;br /&gt;
\mathbf{end} \; &amp;amp; \mathbf{for}&lt;br /&gt;
\end{align}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
В продемонстрированном выше алгоритме &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;b&amp;lt;/math&amp;gt; - заданный вещественный вектор. Также полагается известным алгоритм вычисления произведения матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; на вектор &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;x&amp;lt;/math&amp;gt;. &lt;br /&gt;
Введём матрицу Крылова, определяемую следующим соотношением: &amp;lt;math&amp;gt;K_j = [b,Ab,A^2b,...,A^{j-1}b]&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Далее, на практике, матрица &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;K&amp;lt;/math&amp;gt; заменяется матрицей &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;Q&amp;lt;/math&amp;gt;, такой, что при любом числе &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; линейные оболочки первых &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; столбцов в &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;K&amp;lt;/math&amp;gt; и &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;Q&amp;lt;/math&amp;gt; являются одним и тем же подпространством.&amp;lt;ref&amp;gt;James W. Demmel - Вычислительная линейная алгебра. Теория и приложения //Мир. - 2001 (c. 315)&amp;lt;/ref&amp;gt; &lt;br /&gt;
Тогда матрица &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;Q&amp;lt;/math&amp;gt;, в отличие от матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;K&amp;lt;/math&amp;gt;, хорошо обусловлена и легко обратима. В результате получаем матрицу &amp;lt;math&amp;gt;Q_j = [q_1, q_2, \dots, q_j]&amp;lt;/math&amp;gt; размерности &amp;lt;math&amp;gt;n\times j&amp;lt;/math&amp;gt;, столбцы которой ортогональны, являются базисом подпространства Крылова и называются векторами Ланцоша.&lt;br /&gt;
&lt;br /&gt;
В алгоритме Ланцоша вычислению подлежит столько первых столбцов в матрице &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;Q_j&amp;lt;/math&amp;gt;, сколько необходимо для получения требуемого приближения к решению &amp;lt;math&amp;gt;A\,x\,=b\,\,(A\,x=\lambda \, x)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Получение нулевого &amp;lt;math&amp;gt;\beta_j&amp;lt;/math&amp;gt; в итерационном процессе - событие, желательное в том смысле, что оно свидетельствует о том, что найдено некоторое подпространство, являющееся в точности инвариантным, а все собственные значения матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;T_j&amp;lt;/math&amp;gt; являются собственными значениями матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt;. На практике же нулевое и близкие к нулю значения получаются редко.&amp;lt;ref&amp;gt;Голуб Дж., Ван Лоун Ч. - Матричные вычисления//М.: Мир. - 1999 (c. 429)&amp;lt;/ref&amp;gt; &lt;br /&gt;
&lt;br /&gt;
Затем на каждом шаге цикла формируется симметричная трёхдиагональная матрица &amp;lt;math&amp;gt;T_j = Q^T_j A Q&amp;lt;/math&amp;gt;, к которой применяется процесс Рэлея-Ритца для поиска её собственных значений (на практике для поиска этих собственных значений можно использовать любой из специальных методов в параграфе книги по ссылке).&amp;lt;ref&amp;gt;Голуб Дж., Ван Лоун Ч. - Матричные вычисления//М.: Мир. - 1999 (&amp;lt;math&amp;gt;\S&amp;lt;/math&amp;gt; 8.4)&amp;lt;/ref&amp;gt;  &lt;br /&gt;
Эти собственные значения, они же числа Ритца, и полагаются приближёнными собственными значениями исходной матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt;.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Существует множество методов для отыскания собственных значений вещественной симметричной трехдиагональной матрицы. Большинство из них требует &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt; операций &amp;lt;ref&amp;gt;Парлетт Б. Симметричная проблема собственных значений. Численные методы.,: Мир, 1983. с. 179-182&amp;lt;/ref&amp;gt;, но существуют и быстрые алгоритмы, требующие лишь &amp;lt;math&amp;gt;O(n\ln n)&amp;lt;/math&amp;gt; операций.&amp;lt;ref&amp;gt;https://en.wikipedia.org/wiki/Tridiagonal_matrix#Eigenvalues  Раздел eigenvalues&amp;lt;/ref&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Одним из возможных способов отыскать собственные значения симметричной трехдиагональной матрицы - прямое вычисление корней характеристического полинома &amp;lt;math&amp;gt;p_n(\lambda)&amp;lt;/math&amp;gt; через метод деления пополам, где формируется последовательность Штурма и локализуются собственные числа, являющиеся корнями характеристического полинома. Нахождение всех &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; собственных значений матрицы этим способом требует &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;2n^2t&amp;lt;/math&amp;gt; умножений и вычитаний, где &amp;lt;math&amp;gt;t&amp;lt;/math&amp;gt; - число сделанных шагов с применением метода деления пополам.&amp;lt;ref&amp;gt;Уилкинсон Дж. X. Алгебраическая проблема собственныx значений. Изд-во &amp;quot;Наука&amp;quot;, 1970. - глава 5, с. 272-278&amp;lt;/ref&amp;gt; Соответствующие собственные вектора могут быть найдены посредством обратных итераций за &amp;lt;math&amp;gt; O(n) &amp;lt;/math&amp;gt; флопов. &amp;lt;ref&amp;gt;Голуб Дж., Ван Лоун Ч. - Матричные вычисления//М.: Мир. - 1999 (c. 394-395)&amp;lt;/ref&amp;gt; &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;На практике, если требуется только небольшая часть от всей совокупности собственных векторов и значений, и матрица имеет Хессенбергову или трёхдиагональную форму, очень эффективными будут методы факторизации, как, например, QR-алгоритм или QL-алгоритм со сдвигами (c целью ускорить алгоритм и сделать порядок сходимости квадратичным) или же без них.&amp;lt;ref&amp;gt;http://algorithm.narod.ru/ln/eigen/ETridiag.html&amp;lt;/ref&amp;gt; &amp;lt;br&amp;gt;&lt;br /&gt;
Весьма молодые и не менее актуальные конкуренты QR и QL алгоритмов, применяющиеся для поиска собственных значений:&lt;br /&gt;
*Методы divide-and-conquer (разделяй и властвуй), появившиеся в 1980-ых годах &amp;lt;ref&amp;gt;https://algowiki-project.org/ru/Метод_&amp;quot;Разделяй_и_властвуй&amp;quot;_Завольсков/Землянский&amp;lt;/ref&amp;gt;&lt;br /&gt;
*Relatively robust representation methods, появившиеся в 1990-ых и позволяющие найти собственные числа симметричной матрицы порядка &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;n&amp;lt;/math&amp;gt; за &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt; операций&lt;br /&gt;
&lt;br /&gt;
Если требуется вычислить собственные векторы, то необходимо хранить вычисляемые векторы Ланцоша. Если работа при этом производится только с оперативной памятью, то при большом порядке исходной матрицы (а именно для таких матриц и предназначен метод Ланцоша) число шагов  &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;j&amp;lt;/math&amp;gt;, которые могут быть выполнены до того момента, как оперативная память будет исчерпана, будет очень незначительно, а следовательно, искомые собственные пары могут не успеть сойтись с требуемой точностью. В этом случае метод Ланцоша можно использовать итерационным образом: после выполнения заданного числа шагов процесс прерывается и, если еще не все требуемые пары Ритца сошлись с требуемой точностью, то формируется новый начальный вектор &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;q_1&amp;lt;/math&amp;gt;, являющийся линейной комбинацией векторов Ритца, еще не сошедшихся с заданной точностью, и процесс начинается заново.&amp;lt;ref&amp;gt;http://num-anal.srcc.msu.ru/lib_na/int_ae/int_ae6.htm (пункт 6.5)&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
Вычислительное ядро рассматриваемого алгоритма (наиболее ресурсно-затратная часть алгоритма) -  формирование на каждом шаге цикла промежуточного вектора &amp;lt;math&amp;gt;z&amp;lt;/math&amp;gt;, вычисляемого по формуле: &amp;lt;math&amp;gt;z = A\,q_j&amp;lt;/math&amp;gt;. Данная операция, по сравнению с другими операциями алгоритма, затратна и требовательна, как с точки зрения количества производимых операций, так и с точки зрения объема оперируемых данных. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Например, умножение матрицы размера &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;n\times n&amp;lt;/math&amp;gt; на вектор длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; требует: &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;n^2+(n-1)n = 2n^2-n&amp;lt;/math&amp;gt; операций умножения и сложения. В свою очередь аналогичная операция умножения матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;(n+1)\times (n+1)&amp;lt;/math&amp;gt; на вектор длины &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;(n+1)&amp;lt;/math&amp;gt; требует: &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;2n^2+3n+1&amp;lt;/math&amp;gt;  операций умножения и сложения. То есть повышение размерности задачи всего на 1 увеличивает число необходимых действий в этом шаге алгоритма на: &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;4n+1&amp;lt;/math&amp;gt;. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Так же, стоит помнить, что, согласно разделу 1.2, данную операцию умножения матрицы на вектор необходимо выполнить &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;k&amp;lt;/math&amp;gt; раз. Нетрудно понять, насколько возрастает и колоссален масштаб операций, если в задачах, где критична точность, размерности &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; могут иметь порядок &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;10^5&amp;lt;/math&amp;gt; или даже более.&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
Как уже было упомянуто в данной статье в описании алгоритма, рассматриваемый алгоритм состоит из двух последовательно выполненных алгоритмов: метод Ланцоша для построения последовательности подпространств Крылова и ортонормированных векторов Ланцоша и процедура Рэлея-Ритца получения оптимальных приближений собственных значений и соответствующих собственных векторов исходной матрицы.&lt;br /&gt;
&lt;br /&gt;
В первой части алгоритма, где итерационно строятся Крыловское подпространство и трёхдиагональная матрица &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&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 style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; разреженная. Именно она подлежит оптимизации с использованием техник распараллеливания, поскольку она является вычислительным ядром алгоритма, а весь упомянутый процесс построения матрицы &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&amp;lt;/math&amp;gt; выполняется последовательно.&lt;br /&gt;
&lt;br /&gt;
Рассмотрим вторую часть алгоритма - поиск собственных значений сформированной матрицы &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&amp;lt;/math&amp;gt;.&amp;lt;br&amp;gt;&lt;br /&gt;
Далее, наглядно, в виде псевдокода, представлен, упомянутый в разделе 1.2, QR-алгоритм (аналогично можно рассмотреть и QL-алгоритм) со сдвигами Релэя, который весьма популярен на практике.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{align}&lt;br /&gt;
\mathbf{Input}: \;&amp;amp;tridiagonal\;\;matrix \;T\;with\;\;n\times n\;\;size\\&lt;br /&gt;
T^{(0)}&amp;amp;:=T\\&lt;br /&gt;
\mathbf{for}&amp;amp; \;\;m=n,...,2 \;\; \mathbf{do}\\&lt;br /&gt;
&amp;amp;k=0\\&lt;br /&gt;
&amp;amp; \mathbf{repeat}\\&lt;br /&gt;
&amp;amp; \quad \;\; k=k+1\\&lt;br /&gt;
&amp;amp; \quad \;\; \mu^{(k)}=T_{m,m}^{(k-1)}\\&lt;br /&gt;
&amp;amp; \quad \;\; Q^{(k)}R^{(k)}=T^{(k-1)}-\mu^{(k)}I\;\;using\;\;QR\;decomposition\\&lt;br /&gt;
&amp;amp; \quad \;\; T^{(k)}=R^{(k)}Q^{(k)}+\mu^{(k)}I\\&lt;br /&gt;
&amp;amp; \mathbf{until} \;\;\; |T_{m,m-1}^{(k)}| \;is\;\;small\;\;enough\\&lt;br /&gt;
&amp;amp; Save  \;\;T_{m,m}^{(k)} \;\;as\;\; converged\;\;eigenvalue\;of\;T\\ &lt;br /&gt;
&amp;amp; Remove \;\boldsymbol{n}\,th\;row\;and\;\boldsymbol{n}\,th\;column\;\;from \;T \\&lt;br /&gt;
&amp;amp; and\;take\;this\;new\;cropped\;matrix\;as\;new\;T^{(0)}\;with\;\;(n-1)\times (n-1)\;\;size\\&lt;br /&gt;
 \mathbf{end}&amp;amp;\; \mathbf{for}&lt;br /&gt;
\end{align}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Малость наддиагональных и поддиагональных элементов матрицы (фраза &#039;&#039;&amp;quot;small enough&amp;quot;&#039;&#039; в псевдокоде) подразумевает:&lt;br /&gt;
&amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt; |T_{m,m-1}^{(k)}| \leq \varepsilon\,|T_{m,m}^{(k)}| \quad\quad &amp;lt;/math&amp;gt; , где &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt; \varepsilon &amp;lt;/math&amp;gt; - заданная точность&amp;lt;br&amp;gt;&lt;br /&gt;
Также вместо сдвига Релэя, обозначенного в алгоритме через &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;\mu^{(k)}&amp;lt;/math&amp;gt; часто на практике используется сдвиг по Уилкинсону, который даёт гарантированную сходимость внедиагональных элементов матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt; T^{(k)} &amp;lt;/math&amp;gt;, формируемой на каждом шаге, к нулю, при этом жертвуя монотонностью их убывания.&amp;lt;ref&amp;gt;Голуб Дж., Ван Лоун Ч. - Матричные вычисления//М.: Мир. - 1999 (c. 378, вторая половина страницы)&amp;lt;/ref&amp;gt;&amp;lt;ref&amp;gt;Парлетт Б. Симметричная проблема собственных значений. Численные методы.,: Мир, 1983. с. 169&amp;lt;/ref&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Подробнее с различными сдвигами и соответствующими оценками скоростей и количествами операций можно ознакомиться по указанной ссылке:&amp;lt;ref&amp;gt;Парлетт Б. Симметричная проблема собственных значений. Численные методы.,: Мир, 1983. с. 179-182&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;Для совершения QR-декомпозиции на каждом шаге может использоваться любой из алгоритмов по ссылке.&amp;lt;ref&amp;gt;https://en.wikipedia.org/wiki/QR_decomposition&amp;lt;/ref&amp;gt; Подробные описания этих алгоритмов также доступны на данном ресурсе algowiki-project.&amp;lt;br&amp;gt;&lt;br /&gt;
Так как мы оперируем не обычной матрицей и даже не Хессенберговой, а симметричной и трёхдиагональной, то скорость таких алгоритмов значительно возрастёт. Например, согласно данному ресурсу &amp;lt;ref&amp;gt;http://algorithm.narod.ru/ln/eigen/ETridiag.html&amp;lt;/ref&amp;gt;, для QL-алгоритма с неявными сдвигами:&amp;lt;br&amp;gt;&lt;br /&gt;
Для трёхдиагональной матрицы объем арифметических действий составляет &amp;lt;math&amp;gt; O(n)&amp;lt;/math&amp;gt; на одну итерацию вместо &amp;lt;math&amp;gt; O(n^3)&amp;lt;/math&amp;gt; для матрицы общего вида, а число итераций для нахождения первых собственных значений примерно равно 4 - 5. Но на этих итерациях также уменьшаются внедиагональные элементы правого нижнего угла. И, таким образом, дальнейшие собственные значения ищутся значительно быстрее. Среднее число итераций на каждое собственное значение обычно составляет 1.3 - 1.6.&amp;lt;br&amp;gt; &lt;br /&gt;
Аналогично QL, QR-разложение трёхдиагольной матрицы также требует &amp;lt;math&amp;gt; O(n)&amp;lt;/math&amp;gt; флопов&amp;lt;ref&amp;gt;Голуб Дж., Ван Лоун Ч. - Матричные вычисления//М.: Мир. - 1999 (c. 378, начало раздела 8.2.2)&amp;lt;/ref&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Подводя итог, во второй части алгоритма Ланцоша можно выделить следующие макрооперации:&lt;br /&gt;
* умножение матрицы на вещественное число;&lt;br /&gt;
* перемножение матриц;&lt;br /&gt;
* умножение и сравнение вещественных чисел;&lt;br /&gt;
* + набор других макроопераций в зависимости от выбора метода, с помощью которого будет совершаться сама QR или QL-декомпозиция (выше продемонстрированы, уже, как минимум, 3 разных способа).&lt;br /&gt;
Так же, важно заметить, что набор макропераций может быть несколько другим, если выбрать какой-либо иной современный метод поиска собственных чисел трёхдиагональной матрицы, не использующий QR и QL разложения(факторизацию). Два таких метода были упомянуты в пункте 1.2.&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
С целью полностью не дублировать раздел 1.2 данной статьи, где представлен наглядный и доступный для понимания псевдокод алгоритма, постараемся лишь коротко просуммировать и обобщить весь перечень последовательных действий в рассматриваемом алгоритме.&lt;br /&gt;
&lt;br /&gt;
В качестве входных данных имеем: вещественная симметричная матрица &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; размера &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;n\times n&amp;lt;/math&amp;gt;, известный вещественный вектор &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;b&amp;lt;/math&amp;gt; длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; и число &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;n&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Далее:&lt;br /&gt;
* Инициализируем вещественную константу &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;\beta_0&amp;lt;/math&amp;gt; и векторы &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;q_0&amp;lt;/math&amp;gt; и &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;q_1&amp;lt;/math&amp;gt;&lt;br /&gt;
* Итерационно для всех &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j=1,...,k&amp;lt;/math&amp;gt;:&lt;br /&gt;
** Вычисляем вспомогательный вектор &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt;, используя умножение матрицы на вектор&lt;br /&gt;
** Вычисляем, используя скалярное произведение векторов, значение &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;\alpha_j&amp;lt;/math&amp;gt; - элемент на главной диагонали трёхдиагональной матрицы &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&amp;lt;/math&amp;gt;&lt;br /&gt;
** Вычисляем по формуле новое значение и перезаписываем вектор &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt;&lt;br /&gt;
** Вычисляем значение &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;\beta_j&amp;lt;/math&amp;gt; - элементы непосредственно над и под главной диагональю той же матрицы &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&amp;lt;/math&amp;gt;&lt;br /&gt;
** Вычисляем, зная вектор &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt;,  очередной столбец матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;Q&amp;lt;/math&amp;gt;, он же вектор Ланцоша : &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;\,\,q_{j+1}&amp;lt;/math&amp;gt;&lt;br /&gt;
** Теперь, когда матрица &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&amp;lt;/math&amp;gt; сформирована на очередном шаге, находим её собственные значения и вектора любым доступным способом, о чём было подробно сказано в пункте 1.2&lt;br /&gt;
** Переходим на следующую итерацию: &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j&amp;lt;/math&amp;gt;++&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
Оценим количество операций и сложность последовательного алгоритма, изложенного в предыдущем разделе.&lt;br /&gt;
*Для вычисления вектора &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt; умножается матрица размера &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;n\times n&amp;lt;/math&amp;gt; на вектор длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt;, и потребуется &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n^2&amp;lt;/math&amp;gt; операций умножения и &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n^2&amp;lt;/math&amp;gt; операций сложения.&lt;br /&gt;
*Умножение векторов &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;q^T_j&amp;lt;/math&amp;gt; и &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt; длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; потребует &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; операций умножения и &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; операций сложения.&lt;br /&gt;
*При вычислении нового значения вектора &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt; поэлементное сложение двух векторов длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; требует &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; операций сложения.&lt;br /&gt;
*Умножение вектора длины &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; на вещественное число требует &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; операций умножения.&lt;br /&gt;
*Нахождение квадратичной нормы вектора &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt;  длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; требует &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; умножений и &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; сложений и ещё 1 операцию извлечения квадратного корня.&lt;br /&gt;
*Заключительное нахождение собственных значений и собственных векторов трёхдиагональной матрицы &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;T_j&amp;lt;/math&amp;gt; размера &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j\times j&amp;lt;/math&amp;gt; с помощью QR-алгоритма потребует в худшем случае &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(j^3)&amp;lt;/math&amp;gt; операций.&amp;lt;ref&amp;gt;http://num-anal.srcc.msu.ru/lib_na/int_ae/int_ae6.htm (пункт 6.2, &amp;quot;Скорость сходимости при этом всегда не хуже квадратичной и почти всегда лучше кубической.&amp;quot;)&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Посчитаем теперь суммарное количество простейших операций на одной итерации алгоритма (без учёта записей в память):&lt;br /&gt;
*&amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n^2+5\,n&amp;lt;/math&amp;gt; операций умножения/деления&lt;br /&gt;
*&amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n^2+4\,n&amp;lt;/math&amp;gt; операций сложения/вычитания&lt;br /&gt;
*1 операция извлечения квадратного корня&amp;lt;br&amp;gt;&lt;br /&gt;
Отдельно после всех итераций при &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j=k&amp;lt;/math&amp;gt; :&lt;br /&gt;
*&amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(k^3)&amp;lt;/math&amp;gt; операций для поиска собственных значений и собственных векторов трёхдиагональной матрицы &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;T_k&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Итого можно утверждать следующее:&lt;br /&gt;
&lt;br /&gt;
Последовательная сложность одной итерации рассматриваемого алгоритма:  &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(n ^ 2) &amp;lt;/math&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Суммарная сложность алгоритма (&amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;/math&amp;gt; итераций): &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(k\,n ^ 2) + O(k ^ 3)&amp;lt;/math&amp;gt; &amp;lt;ref&amp;gt;Здесь мы полагаем, что мы не вычисляем собственные значения и векторы матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_j&amp;lt;/math&amp;gt; на каждом промежуточном шаге, а лишь единожды затрачиваем &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;O(k ^ 3)&amp;lt;/math&amp;gt; действий в конце для нахождения &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;/math&amp;gt; собственных значений и векторов матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_k&amp;lt;/math&amp;gt;&amp;lt;/ref&amp;gt; &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
На практике же обычно рассматривается число &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;&amp;lt;n&amp;lt;/math&amp;gt;, поэтому второе слагаемое можно опустить.&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
На рис. 1 продемонстрирован граф одной итерации (при каком-либо произвольном значении итератора &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j&amp;lt;/math&amp;gt;) описанного алгоритма без отображения входных и выходных данных. Наглядно продемонстрированы связи между всеми действиями, и с помощью деления на &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; потоков показано, какие операции возможно выполнять параллельно на каждом шаге с целью оптимизации и экономии машинного времени. В результате, после параллельно выполненных операций &#039;&#039;&#039;Division&#039;&#039;&#039; на заключительном ярусе, на выходе имеем значение следующего вектора Ланцоша &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;q_{j+1}&amp;lt;/math&amp;gt;, после чего следует переход на следующую итерацию, и процесс повторяется.&lt;br /&gt;
&lt;br /&gt;
[[Файл:Levin_graph.png|600px|thumb|center|Рис. 1]] &amp;lt;br&amp;gt;&lt;br /&gt;
Обозначения на рисунке: &amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Simp&#039;&#039;&#039; (от англ. simple) - операции сложения и умножения вещественных чисел при вычислении произведения матрицы на вектор;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Vec mult&#039;&#039;&#039; (от англ. vectors multiplication) - операция скалярного умножения двух векторов;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Vec subtr&#039;&#039;&#039; (от англ. vectors subtraction, из-за использованных в операции вычитаний векторов) - операция умножения вектора на число (выполняется дважды) и формирование нового значения &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;z_{new}&amp;lt;/math&amp;gt; по формуле: &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;z_{new} = z - \alpha_j q_j - \beta_{j-1}q_{j-1} \;&amp;lt;/math&amp;gt;;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;||\cdot||&amp;lt;/math&amp;gt; - операция вычисления нормы вектора;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Division&#039;&#039;&#039; - операция деления вектора на вещественное число  &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;\beta_j&amp;lt;/math&amp;gt; &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Важно отметить, что упомянутые выше операции также легко поддаются оптимизации. Например, попарные умножения вещественных координат векторов при вычислении скалярного произведения также легко выполняются параллельно на &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; потоках, а затем можно применить суммирование методом сдваивания, о котором сказано в следующем разделе. Умножение или деление вектора на вещественное число являющееся, по определению, умножением или делением всех его координат на это число тоже может быть выполнено эффективнее, если мы используем &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; потоков, а не выполняем эти действия последовательно.&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
Параллельные операции возможны только внутри итераций, так как рассматриваемый алгоритм является итерационным, и сами итерации строго последовательны.&amp;lt;br&amp;gt;&lt;br /&gt;
Рассмотрим в этом разделе подробнее, какой выигрыш мы можем получить при распараллеливании операций внутри одной итерации согласно графу из предыдущего раздела.&lt;br /&gt;
&lt;br /&gt;
Умножение вещественной симметричной матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; размера &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;n\times n&amp;lt;/math&amp;gt; на вектор &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;b&amp;lt;/math&amp;gt; длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; требует последовательного выполнения &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; ярусов умножений и сложений. Сложение элементов вектора длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; на каждом шаге перемножения можно оптимизировать и выполнить за &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;\log_2 n&amp;lt;/math&amp;gt; действий, если применять метод сдваивания.&lt;br /&gt;
&lt;br /&gt;
Дальнейшие операции выполняются последовательно, а вычисление значений векторов происходит за один ярус операций сложения или умножения.&lt;br /&gt;
&lt;br /&gt;
Ресурс параллелизма алгоритма вычисления собственных значений построенной трёхдиагональной матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_k&amp;lt;/math&amp;gt; размера &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k\times k&amp;lt;/math&amp;gt; зависит от выбранного алгоритма (об этих алгоритмах подробнее было сказано в разделах 1.2 и 1.4). Будет очень затратно с точки зрения объёма материала пытаться рассмотреть пусть даже часть этих методов в этой статье, а так же тонкости их распараллеливания. Предлагаем читателям при желании самим ознакомиться с этими алгоритмами на данном ресурсе или прибегнув к иным источникам.&lt;br /&gt;
&lt;br /&gt;
При классификации по высоте ЯПФ, таким образом, алгоритм Ланцоша без переортогонализации относится к алгоритмам с &#039;&#039;логарифмической сложностью&#039;&#039;, и его сложность равна &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(\log_2 n)&amp;lt;/math&amp;gt; с важным замечанием, что это сложность только одной итерации, а максимум в алгоритме может быть выполнено последовательно &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;/math&amp;gt; таких однотипных итераций, если не будет осуществлён ранний выход из цикла. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Несмотря на то, что на графе в предыдущем разделе для лучшей визуализации и понимания было изображено &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; потоков (никаких допущений мы не делали и нарушений с точки зрения логики и математики нет, можно изобразить большее число потоков, просто часть времени некоторые из них могут бездействовать и не использоваться), на самом деле правильным и разумным будет реализовать начальное параллельное выполнение &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n^2&amp;lt;/math&amp;gt; операций умножения всех вещественных элементов матрицы &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;A&amp;lt;/math&amp;gt; на соответствующие элементы вектора &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;q_j&amp;lt;/math&amp;gt;, после чего применять тот же самый упомянутый метод сдваивания. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Поэтому при классификации по ширине ЯПФ его сложность будет &#039;&#039;квадратичной&#039;&#039; и равна &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(n^2)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
&#039;&#039;&#039;Входные данные алгоритма:&#039;&#039;&#039; вещественная симметричная &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; размера &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;n\times n&amp;lt;/math&amp;gt;, вещественный вектор &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;b&amp;lt;/math&amp;gt; длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt;, и одно целое число &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;k&amp;lt;/math&amp;gt;, означающее количество итераций.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём входных данных:&#039;&#039;&#039; &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;n^2 +n + 1 &amp;lt;/math&amp;gt;. Если учесть, что матрица симметричная и достаточно для её однозначного определения задать элементы на главной диагонали и элементы над или под ней, то можно сократить объём входных данных с целью экономии памяти до: &amp;lt;math&amp;gt;\ \frac{n^2-n}{2}+n+n+1 =\frac{n^2+3n}{2} + 1&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные алгоритма:&#039;&#039;&#039; вектор собственных значений &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;\Theta^k&amp;lt;/math&amp;gt; длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;/math&amp;gt;, матрица &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;S^k&amp;lt;/math&amp;gt; из соответствующих собственных векторов размера &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n\times k&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём выходных данных:&#039;&#039;&#039; &amp;lt;math&amp;gt;k\;(n + 1)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
В данном разделе перечислены без какой-либо хронологии или связи друг с другом наиболее важные и разнообразные свойства алгоритма, на которые стоит и полезно обратить внимание, а также которые выгодно отличают его от схожих алгоритмов, решающих ту же задачу.&amp;lt;br&amp;gt;&lt;br /&gt;
1) Отношение последовательной сложности алгоритма к параллельной,с учётом &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;/math&amp;gt; итераций, равно &amp;lt;math&amp;gt;\;\;\frac{kn^2}{k \log_2{n}}=\frac{n^2}{\log_2{n}}&amp;lt;/math&amp;gt;;&amp;lt;br&amp;gt;&lt;br /&gt;
2) Вычислительная мощность алгоритма, как отношение числа операций к суммарному объему входных и выходных данных, равна &amp;lt;math style=&amp;quot;vertical-align:-70%&amp;gt;\;\;\frac{k\,n^2}{0.5\,n^2+1.5\,n+k\,n+k+1}&amp;lt;/math&amp;gt; и &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;\approx 2\,k&amp;lt;/math&amp;gt;, так как на практике верно отношение &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;&amp;lt;n&amp;lt;/math&amp;gt; ;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
3) Для собственных значений формируемых матриц &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_j&amp;lt;/math&amp;gt; верно отношение (следствие теоремы Коши о перемежаемости): &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;\lambda_i(T_{k+1})\geq \lambda_i(T_{k})\geq \lambda_{i+1}(T_{k+1})\geq \lambda_{i+1}(T_{k})&amp;lt;/math&amp;gt; ;&amp;lt;ref&amp;gt;James W. Demmel - Вычислительная линейная алгебра. Теория и приложения //Мир. - 2001 (c. 383)&amp;lt;/ref&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
4) Крайние (наибольшие и наименьшие) собственные значения матриц &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_j&amp;lt;/math&amp;gt; сходятся к крайним собственным значениям матрицы &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;A&amp;lt;/math&amp;gt; первыми (это часто происходит уже на ранних шагах при &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j\approx 2\,\sqrt{n}&amp;lt;/math&amp;gt;&amp;lt;ref&amp;gt;http://num-anal.srcc.msu.ru/lib_na/int_ae/int_ae6.htm (пункт 6.5)&amp;lt;/ref&amp;gt;), а собственные значения в середине спектра - последними;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
5) Из-за ограниченной точности постепенно теряется ортогональность вектора Ланцоша &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;q_j&amp;lt;/math&amp;gt; к предыдущим векторам Ланцоша, поэтому необходимо примерно каждые 10-15 итераций проводить дорогостоящую операцию реортогонализации, но это уже будет иной алгоритм с очень малым различием в одной операции и в программном коде, реализующем его, соответственно; &amp;lt;ref&amp;gt;Sam Handler - The Lanczos Algorithm For Large-Scale Eigenvalue Problems (08.01.07), slide №8&amp;lt;/ref&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
6) Эффективность и быстрота выполнения алгоритма очень сильно зависит от скорости памяти (диска). Согласно тесту только &#039;&#039;6%&#039;&#039; времени работы программы приходится на вычисления, остальное время затрачивается на ожидание отклика диска;&amp;lt;ref&amp;gt;Sam Handler - The Lanczos Algorithm For Large-Scale Eigenvalue Problems (08.01.07), slide №10&amp;lt;/ref&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
7) Метод Ланцоша удобен тем, что не требует хранения исходной матрицы полным массивом: метод использует исходную матрицу только в операциях умножения матрицы на вектор, что позволяет эффективно использовать разреженность матрицы или регулярность структуры матрицы. Поэтому метод Ланцоша может быть использован для матриц таких больших порядков, когда методы вращений и отражений не могут быть применены.&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;
По заданию, во второй части требовалось описать только разделы 2.4 и 2.7, прошу не спрашивать с меня все разделы 2.1-2.6. Надеюсь на понимание, мне физически не хватает времени на это задание + 2 других в течение семестра, делаю всё, что в моих силах :)&lt;br /&gt;
&lt;br /&gt;
== Существующие реализации алгоритма ==&lt;br /&gt;
Несмотря на то, что алгоритм является далеко не самым популярным, алгоритмом, про который нельзя сказать, что он всегда «на слуху», на сегодняшний день существует множество реализаций на различных популярных языках.&amp;lt;br&amp;gt;&lt;br /&gt;
Перечислим далее некоторые из них, указывая язык программирования, лежащий в их основе, и некоторые важные характеристики, которые обсуждались в статье ранее:&lt;br /&gt;
*&#039;&#039;Code on netlib.org by Jane Cullum and Ralph Willoughby&#039;&#039; (&#039;&#039;&#039;Fortran 77&#039;&#039;&#039;; без реортогонализации векторов; без реализации распараллеливания)&amp;lt;ref&amp;gt;http://www.netlib.org/lanczos/leval&amp;lt;/ref&amp;gt;&lt;br /&gt;
*&#039;&#039;Lanczos algorithm on freesourcecode.net&#039;&#039; (&#039;&#039;&#039;Matlab&#039;&#039;&#039;; присутствует реортогонализация векторов; без реализации распараллеливания)&amp;lt;ref&amp;gt;http://freesourcecode.net/matlabprojects/61741/lanczos-algorithm--in-matlab&amp;lt;/ref&amp;gt;&lt;br /&gt;
*&#039;&#039;Lanczos for eigenvalues in Numerical Linear Algebra, Spring 2007&#039;&#039; (&#039;&#039;&#039;Matlab&#039;&#039;&#039;; частичная или полная реортогонализация - доступны оба варианта; без реализации распараллеливания)&amp;lt;ref&amp;gt;Ссылки на файлы lanso.m и lanfu.m можно найти на https://www.nada.kth.se/~ruhe/2D5219/labs2007.html&amp;lt;/ref&amp;gt;&lt;br /&gt;
*&#039;&#039;Planso&#039;&#039; (название происходит от parallel Lanso.f) &#039;&#039;code by Kesheng Wu and Horst D. Simon&#039;&#039; (&#039;&#039;&#039;Fortran 77&#039;&#039;&#039;; частичная реортогонализация векторов; использование MPI для коммуникаций)&amp;lt;ref&amp;gt;https://github.com/jiahao/planso.jl/tree/master/external/PLAN/plan К сожалению, ссылка в описании пакета на github, ведущая на сайт National Energy Research Scientific Computing Center (NERSC), с более подробной информацией о данной программе больше не активна и выдаёт результат &#039;&#039;Page not found&#039;&#039;&amp;lt;/ref&amp;gt; &lt;br /&gt;
* &#039;&#039;Lanczos.cpp in the Vienna Computing Library&#039;&#039;  (&#039;&#039;&#039;C++&#039;&#039;&#039;, частичная реортогонализация, без реализации распараллеливания) &amp;lt;ref&amp;gt;http://viennacl.sourceforge.net/doc/lanczos_8cpp_source.html&amp;lt;/ref&amp;gt;&lt;br /&gt;
* &#039;&#039;Parallel Eigen Values code using C++ AMP on microsoft msdn blog&#039;&#039; (&#039;&#039;&#039;C++&#039;&#039;&#039;; ? ; распараллеливание есть и реализовано через C++ AMP) &amp;lt;ref&amp;gt;https://blogs.msdn.microsoft.com/nativeconcurrency/2013/12/20/eigen-values/ Подробнее о C++ Accelerated Massive Parallelism можно почитать здесь: https://msdn.microsoft.com/ru-ru/library/hh265137(v=vs.140).aspx или здесь: http://professorweb.ru/my/csharp/optimization/level4/4_6.php &amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;br /&gt;
[[en:Description of algorithm properties and structure]]&lt;/div&gt;</summary>
		<author><name>AleksLevin</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:AleksLevin/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%9B%D0%B0%D0%BD%D1%86%D0%BE%D1%88%D0%B0_%D0%B2%D1%8B%D1%87%D0%B8%D1%81%D0%BB%D0%B5%D0%BD%D0%B8%D1%8F_%D1%81%D0%BE%D0%B1%D1%81%D1%82%D0%B2%D0%B5%D0%BD%D0%BD%D1%8B%D1%85_%D0%B7%D0%BD%D0%B0%D1%87%D0%B5%D0%BD%D0%B8%D0%B9_%D1%81%D0%B8%D0%BC%D0%BC%D0%B5%D1%82%D1%80%D0%B8%D1%87%D0%BD%D0%BE%D0%B9_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86%D1%8B_%D0%B4%D0%BB%D1%8F_%D1%82%D0%BE%D1%87%D0%BD%D0%BE%D0%B9_%D0%B0%D1%80%D0%B8%D1%84%D0%BC%D0%B5%D1%82%D0%B8%D0%BA%D0%B8_(%D0%B1%D0%B5%D0%B7_%D0%BF%D0%B5%D1%80%D0%B5%D0%BE%D1%80%D1%82%D0%BE%D0%B3%D0%BE%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D0%B8)&amp;diff=19940</id>
		<title>Участник:AleksLevin/Алгоритм Ланцоша вычисления собственных значений симметричной матрицы для точной арифметики (без переортогонализации)</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:AleksLevin/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%9B%D0%B0%D0%BD%D1%86%D0%BE%D1%88%D0%B0_%D0%B2%D1%8B%D1%87%D0%B8%D1%81%D0%BB%D0%B5%D0%BD%D0%B8%D1%8F_%D1%81%D0%BE%D0%B1%D1%81%D1%82%D0%B2%D0%B5%D0%BD%D0%BD%D1%8B%D1%85_%D0%B7%D0%BD%D0%B0%D1%87%D0%B5%D0%BD%D0%B8%D0%B9_%D1%81%D0%B8%D0%BC%D0%BC%D0%B5%D1%82%D1%80%D0%B8%D1%87%D0%BD%D0%BE%D0%B9_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86%D1%8B_%D0%B4%D0%BB%D1%8F_%D1%82%D0%BE%D1%87%D0%BD%D0%BE%D0%B9_%D0%B0%D1%80%D0%B8%D1%84%D0%BC%D0%B5%D1%82%D0%B8%D0%BA%D0%B8_(%D0%B1%D0%B5%D0%B7_%D0%BF%D0%B5%D1%80%D0%B5%D0%BE%D1%80%D1%82%D0%BE%D0%B3%D0%BE%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D0%B8)&amp;diff=19940"/>
		<updated>2016-12-02T19:11:27Z</updated>

		<summary type="html">&lt;p&gt;AleksLevin: /* Макроструктура алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Основные авторы описания: Левин А.Д.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{algorithm&lt;br /&gt;
| name              = Алгоритм Ланцоша для точной арифметики (без переортогонализации)&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(k\,n^2)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(k\log_2 n)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;\frac{n^2+3n}{2} + 1&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;k\;(n + 1)&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритмов =&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Данный алгоритм появился в 1950 г. и носит имя венгерского физика и математика Корнелия Ланцоша (венг. Lánczos Kornél). Алгоритм Ланцоша относится к итерационным методам вычисления собственных значений для матриц столь больших порядков &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt; n&amp;lt;/math&amp;gt;, что к ним нельзя применить прямые методы из-за ограничений по времени и памяти.&lt;br /&gt;
&lt;br /&gt;
Сам Ланцош указывал, что его метод предназначен для отыскания нескольких собственных векторов симметричных матриц, хотя к методу сразу было обращено внимание, как к способу приведения всей матрицы к трёхдиагональному виду. Двадцатью годами позже канадский математик Крис Пэж показал, что, несмотря на чувствительность к округлениям, алгоритм Ланцоша - эффективное средство вычисления некоторых &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; собственных чисел и соответствующих им собственных векторов. &amp;lt;ref&amp;gt;Парлетт Б. - Симметричная проблема собственных значений. Численные методы //М.: Мир. - 1983. (c. 276)&amp;lt;/ref&amp;gt;&lt;br /&gt;
Обычно число &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; берут в два раза больше, чем количество собственных значений матрицы, которые поставлена цель найти, и оно имеет порядок не более &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;10^2&amp;lt;/math&amp;gt;.&amp;lt;ref&amp;gt;Susan W. Bostic - Lanczos Eigensolution Method for High-Perfomance Computers, page 7&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Алгоритм Ланцоша для вычисления собственных значений симметричной матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; соединяет в себе метод Ланцоша для построения последовательности подпространств Крылова и ортонормированных векторов Ланцоша и процедуру Рэлея-Ритца получения оптимальных приближений собственных значений и соответствующих собственных векторов исходной матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt;.&amp;lt;ref&amp;gt;James W. Demmel - Вычислительная линейная алгебра. Теория и приложения //Мир. - 2001 (c. 381)&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
В данной статье рассматривается вариант алгоритма Ланцоша, в котором опущено влияние ошибок округления на вычислительный процесс, хотя на практике этому посвящается отдельное внимание и существуют различные методы решения данной проблемы, такие как частичная или полная переортогонализация. Этим модифицированным методам посвящены отдельные статьи на данном ресурсе.&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
Обозначения и формулы, используемые в данном разделе, взяты из литературы, указанной по ссылке.&amp;lt;ref&amp;gt;James W. Demmel - Вычислительная линейная алгебра. Теория и приложения //Мир. - 2001 (c. 313, &#039;&#039;&amp;lt;math&amp;gt; \S &amp;lt;/math&amp;gt; 6.6 Методы Крыловского подпространства&#039;&#039;)&amp;lt;/ref&amp;gt; &lt;br /&gt;
&lt;br /&gt;
Алгоритм Ланцоша для вычисления &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; собственных значений и собственных векторов вещественной симметричной матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A=A^T&amp;lt;/math&amp;gt; в точной арифметике: &amp;lt;ref&amp;gt;James W. Demmel - Вычислительная линейная алгебра. Теория и приложения //Мир. - 2001 (c. 381)&amp;lt;/ref&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{align}&lt;br /&gt;
q_1 = &amp;amp; \,\frac{b}{\|b\|_2},\; \beta_0 = 0,\; q_0 = 0\\&lt;br /&gt;
\mathbf{for} \; &amp;amp; j = 1 \; to \; k \,\; \mathbf{do} \\&lt;br /&gt;
&amp;amp; z = A\,q_j\\&lt;br /&gt;
&amp;amp; \alpha_j = q^T_j z\\&lt;br /&gt;
&amp;amp; z = z - \alpha_j q_j - \beta_{j-1}q_{j-1}\\&lt;br /&gt;
&amp;amp; \beta_j = \|z\|_2\\&lt;br /&gt;
&amp;amp; \mathbf{If} \; (\beta_j == 0) \; \mathbf{then}\; stop\; the\; algorithm \\ &lt;br /&gt;
&amp;amp; \;  q_{j+1} = \frac{z}{\beta_j} \\&lt;br /&gt;
&amp;amp; compute\; eigenvalues\; and \;eigenvectors\;of \;matrix \;\;T_j= Q^T_j A Q\;\;and\;estimate \;the\; errors\\&lt;br /&gt;
\mathbf{end} \; &amp;amp; \mathbf{for}&lt;br /&gt;
\end{align}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
В продемонстрированном выше алгоритме &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;b&amp;lt;/math&amp;gt; - заданный вещественный вектор. Также полагается известным алгоритм вычисления произведения матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; на вектор &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;x&amp;lt;/math&amp;gt;. &lt;br /&gt;
Введём матрицу Крылова, определяемую следующим соотношением: &amp;lt;math&amp;gt;K_j = [b,Ab,A^2b,...,A^{j-1}b]&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Далее, на практике, матрица &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;K&amp;lt;/math&amp;gt; заменяется матрицей &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;Q&amp;lt;/math&amp;gt;, такой, что при любом числе &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; линейные оболочки первых &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; столбцов в &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;K&amp;lt;/math&amp;gt; и &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;Q&amp;lt;/math&amp;gt; являются одним и тем же подпространством.&amp;lt;ref&amp;gt;James W. Demmel - Вычислительная линейная алгебра. Теория и приложения //Мир. - 2001 (c. 315)&amp;lt;/ref&amp;gt; &lt;br /&gt;
Тогда матрица &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;Q&amp;lt;/math&amp;gt;, в отличие от матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;K&amp;lt;/math&amp;gt;, хорошо обусловлена и легко обратима. В результате получаем матрицу &amp;lt;math&amp;gt;Q_j = [q_1, q_2, \dots, q_j]&amp;lt;/math&amp;gt; размерности &amp;lt;math&amp;gt;n\times j&amp;lt;/math&amp;gt;, столбцы которой ортогональны, являются базисом подпространства Крылова и называются векторами Ланцоша.&lt;br /&gt;
&lt;br /&gt;
В алгоритме Ланцоша вычислению подлежит столько первых столбцов в матрице &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;Q_j&amp;lt;/math&amp;gt;, сколько необходимо для получения требуемого приближения к решению &amp;lt;math&amp;gt;A\,x\,=b\,\,(A\,x=\lambda \, x)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Получение нулевого &amp;lt;math&amp;gt;\beta_j&amp;lt;/math&amp;gt; в итерационном процессе - событие, желательное в том смысле, что оно свидетельствует о том, что найдено некоторое подпространство, являющееся в точности инвариантным, а все собственные значения матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;T_j&amp;lt;/math&amp;gt; являются собственными значениями матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt;. На практике же нулевое и близкие к нулю значения получаются редко.&amp;lt;ref&amp;gt;Голуб Дж., Ван Лоун Ч. - Матричные вычисления//М.: Мир. - 1999 (c. 429)&amp;lt;/ref&amp;gt; &lt;br /&gt;
&lt;br /&gt;
Затем на каждом шаге цикла формируется симметричная трёхдиагональная матрица &amp;lt;math&amp;gt;T_j = Q^T_j A Q&amp;lt;/math&amp;gt;, к которой применяется процесс Рэлея-Ритца для поиска её собственных значений (на практике для поиска этих собственных значений можно использовать любой из специальных методов в параграфе книги по ссылке).&amp;lt;ref&amp;gt;Голуб Дж., Ван Лоун Ч. - Матричные вычисления//М.: Мир. - 1999 (&amp;lt;math&amp;gt;\S&amp;lt;/math&amp;gt; 8.4)&amp;lt;/ref&amp;gt;  &lt;br /&gt;
Эти собственные значения, они же числа Ритца, и полагаются приближёнными собственными значениями исходной матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt;.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Существует множество методов для отыскания собственных значений вещественной симметричной трехдиагональной матрицы. Большинство из них требует &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt; операций &amp;lt;ref&amp;gt;Парлетт Б. Симметричная проблема собственных значений. Численные методы.,: Мир, 1983. с. 179-182&amp;lt;/ref&amp;gt;, но существуют и быстрые алгоритмы, требующие лишь &amp;lt;math&amp;gt;O(n\ln n)&amp;lt;/math&amp;gt; операций.&amp;lt;ref&amp;gt;https://en.wikipedia.org/wiki/Tridiagonal_matrix#Eigenvalues  Раздел eigenvalues&amp;lt;/ref&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Одним из возможных способов отыскать собственные значения симметричной трехдиагональной матрицы - прямое вычисление корней характеристического полинома &amp;lt;math&amp;gt;p_n(\lambda)&amp;lt;/math&amp;gt; через метод деления пополам, где формируется последовательность Штурма и локализуются собственные числа, являющиеся корнями характеристического полинома. Нахождение всех &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; собственных значений матрицы этим способом требует &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;2n^2t&amp;lt;/math&amp;gt; умножений и вычитаний, где &amp;lt;math&amp;gt;t&amp;lt;/math&amp;gt; - число сделанных шагов с применением метода деления пополам.&amp;lt;ref&amp;gt;Уилкинсон Дж. X. Алгебраическая проблема собственныx значений. Изд-во &amp;quot;Наука&amp;quot;, 1970. - глава 5, с. 272-278&amp;lt;/ref&amp;gt; Соответствующие собственные вектора могут быть найдены посредством обратных итераций за &amp;lt;math&amp;gt; O(n) &amp;lt;/math&amp;gt; флопов. &amp;lt;ref&amp;gt;Голуб Дж., Ван Лоун Ч. - Матричные вычисления//М.: Мир. - 1999 (c. 394-395)&amp;lt;/ref&amp;gt; &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;На практике, если требуется только небольшая часть от всей совокупности собственных векторов и значений, и матрица имеет Хессенбергову или трёхдиагональную форму, очень эффективными будут методы факторизации, как, например, QR-алгоритм или QL-алгоритм со сдвигами (c целью ускорить алгоритм и сделать порядок сходимости квадратичным) или же без них.&amp;lt;ref&amp;gt;http://algorithm.narod.ru/ln/eigen/ETridiag.html&amp;lt;/ref&amp;gt; &amp;lt;br&amp;gt;&lt;br /&gt;
Весьма молодые и не менее актуальные конкуренты QR и QL алгоритмов:&lt;br /&gt;
*Методы divide-and-conquer (разделяй и властвуй), появившиеся в 1980-ых годах &amp;lt;ref&amp;gt;https://algowiki-project.org/ru/Метод_&amp;quot;Разделяй_и_властвуй&amp;quot;_Завольсков/Землянский&amp;lt;/ref&amp;gt;&lt;br /&gt;
*Relatively robust representation methods, появившиеся в 1990-ых и позволяющие найти собственные числа симметричной матрицы порядка &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;n&amp;lt;/math&amp;gt; за &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt; операций&lt;br /&gt;
&lt;br /&gt;
Если требуется вычислить собственные векторы, то необходимо хранить вычисляемые векторы Ланцоша. Если работа при этом производится только с оперативной памятью, то при большом порядке исходной матрицы (а именно для таких матриц и предназначен метод Ланцоша) число шагов  &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;j&amp;lt;/math&amp;gt;, которые могут быть выполнены до того момента, как оперативная память будет исчерпана, будет очень незначительно, а следовательно, искомые собственные пары могут не успеть сойтись с требуемой точностью. В этом случае метод Ланцоша можно использовать итерационным образом: после выполнения заданного числа шагов процесс прерывается и, если еще не все требуемые пары Ритца сошлись с требуемой точностью, то формируется новый начальный вектор &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;q_1&amp;lt;/math&amp;gt;, являющийся линейной комбинацией векторов Ритца, еще не сошедшихся с заданной точностью, и процесс начинается заново.&amp;lt;ref&amp;gt;http://num-anal.srcc.msu.ru/lib_na/int_ae/int_ae6.htm (пункт 6.5)&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
Вычислительное ядро рассматриваемого алгоритма (наиболее ресурсно-затратная часть алгоритма) -  формирование на каждом шаге цикла промежуточного вектора &amp;lt;math&amp;gt;z&amp;lt;/math&amp;gt;, вычисляемого по формуле: &amp;lt;math&amp;gt;z = A\,q_j&amp;lt;/math&amp;gt;. Данная операция, по сравнению с другими операциями алгоритма, затратна и требовательна, как с точки зрения количества производимых операций, так и с точки зрения объема оперируемых данных. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Например, умножение матрицы размера &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;n\times n&amp;lt;/math&amp;gt; на вектор длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; требует: &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;n^2+(n-1)n = 2n^2-n&amp;lt;/math&amp;gt; операций умножения и сложения. В свою очередь аналогичная операция умножения матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;(n+1)\times (n+1)&amp;lt;/math&amp;gt; на вектор длины &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;(n+1)&amp;lt;/math&amp;gt; требует: &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;2n^2+3n+1&amp;lt;/math&amp;gt;  операций умножения и сложения. То есть повышение размерности задачи всего на 1 увеличивает число необходимых действий в этом шаге алгоритма на: &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;4n+1&amp;lt;/math&amp;gt;. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Так же, стоит помнить, что, согласно разделу 1.2, данную операцию умножения матрицы на вектор необходимо выполнить &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;k&amp;lt;/math&amp;gt; раз. Нетрудно понять, насколько возрастает и колоссален масштаб операций, если в задачах, где критична точность, размерности &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; могут иметь порядок &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;10^5&amp;lt;/math&amp;gt; или даже более.&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
Как уже было упомянуто в данной статье в описании алгоритма, рассматриваемый алгоритм состоит из двух последовательно выполненных алгоритмов: метод Ланцоша для построения последовательности подпространств Крылова и ортонормированных векторов Ланцоша и процедура Рэлея-Ритца получения оптимальных приближений собственных значений и соответствующих собственных векторов исходной матрицы.&lt;br /&gt;
&lt;br /&gt;
В первой части алгоритма, где итерационно строятся Крыловское подпространство и трёхдиагональная матрица &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&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 style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; разреженная. Именно она подлежит оптимизации с использованием техник распараллеливания, поскольку она является вычислительным ядром алгоритма, а весь упомянутый процесс построения матрицы &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&amp;lt;/math&amp;gt; выполняется последовательно.&lt;br /&gt;
&lt;br /&gt;
Рассмотрим вторую часть алгоритма - поиск собственных значений сформированной матрицы &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&amp;lt;/math&amp;gt;.&amp;lt;br&amp;gt;&lt;br /&gt;
Далее, наглядно, в виде псевдокода, представлен, упомянутый в разделе 1.2, QR-алгоритм (аналогично можно рассмотреть и QL-алгоритм) со сдвигами Релэя, который весьма популярен на практике.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{align}&lt;br /&gt;
\mathbf{Input}: \;&amp;amp;tridiagonal\;\;matrix \;T\;with\;\;n\times n\;\;size\\&lt;br /&gt;
T^{(0)}&amp;amp;:=T\\&lt;br /&gt;
\mathbf{for}&amp;amp; \;\;m=n,...,2 \;\; \mathbf{do}\\&lt;br /&gt;
&amp;amp;k=0\\&lt;br /&gt;
&amp;amp; \mathbf{repeat}\\&lt;br /&gt;
&amp;amp; \quad \;\; k=k+1\\&lt;br /&gt;
&amp;amp; \quad \;\; \mu^{(k)}=T_{m,m}^{(k-1)}\\&lt;br /&gt;
&amp;amp; \quad \;\; Q^{(k)}R^{(k)}=T^{(k-1)}-\mu^{(k)}I\;\;using\;\;QR\;decomposition\\&lt;br /&gt;
&amp;amp; \quad \;\; T^{(k)}=R^{(k)}Q^{(k)}+\mu^{(k)}I\\&lt;br /&gt;
&amp;amp; \mathbf{until} \;\;\; |T_{m,m-1}^{(k)}| \;is\;\;small\;\;enough\\&lt;br /&gt;
&amp;amp; Save  \;\;T_{m,m}^{(k)} \;\;as\;\; converged\;\;eigenvalue\;of\;T\\ &lt;br /&gt;
&amp;amp; Remove \;\boldsymbol{n}\,th\;row\;and\;\boldsymbol{n}\,th\;column\;\;from \;T \\&lt;br /&gt;
&amp;amp; and\;take\;this\;new\;cropped\;matrix\;as\;new\;T^{(0)}\;with\;\;(n-1)\times (n-1)\;\;size\\&lt;br /&gt;
 \mathbf{end}&amp;amp;\; \mathbf{for}&lt;br /&gt;
\end{align}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Малость наддиагональных и поддиагональных элементов матрицы (фраза &#039;&#039;&amp;quot;small enough&amp;quot;&#039;&#039; в псевдокоде) подразумевает:&lt;br /&gt;
&amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt; |T_{m,m-1}^{(k)}| \leq \varepsilon\,|T_{m,m}^{(k)}| \quad\quad &amp;lt;/math&amp;gt; , где &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt; \varepsilon &amp;lt;/math&amp;gt; - заданная точность&amp;lt;br&amp;gt;&lt;br /&gt;
Также вместо сдвига Релэя, обозначенного в алгоритме через &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;\mu^{(k)}&amp;lt;/math&amp;gt; часто на практике используется сдвиг по Уилкинсону, который даёт гарантированную сходимость внедиагональных элементов матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt; T^{(k)} &amp;lt;/math&amp;gt;, формируемой на каждом шаге, к нулю, при этом жертвуя монотонностью их убывания.&amp;lt;ref&amp;gt;Голуб Дж., Ван Лоун Ч. - Матричные вычисления//М.: Мир. - 1999 (c. 378, вторая половина страницы)&amp;lt;/ref&amp;gt;&amp;lt;ref&amp;gt;Парлетт Б. Симметричная проблема собственных значений. Численные методы.,: Мир, 1983. с. 169&amp;lt;/ref&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Подробнее с различными сдвигами и соответствующими оценками скоростей и количествами операций можно ознакомиться по указанной ссылке:&amp;lt;ref&amp;gt;Парлетт Б. Симметричная проблема собственных значений. Численные методы.,: Мир, 1983. с. 179-182&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;Для совершения QR-декомпозиции на каждом шаге может использоваться любой из алгоритмов по ссылке.&amp;lt;ref&amp;gt;https://en.wikipedia.org/wiki/QR_decomposition&amp;lt;/ref&amp;gt; Подробные описания этих алгоритмов также доступны на данном ресурсе algowiki-project.&amp;lt;br&amp;gt;&lt;br /&gt;
Так как мы оперируем не обычной матрицей и даже не Хессенберговой, а симметричной и трёхдиагональной, то скорость таких алгоритмов значительно возрастёт. Например, согласно данному ресурсу &amp;lt;ref&amp;gt;http://algorithm.narod.ru/ln/eigen/ETridiag.html&amp;lt;/ref&amp;gt;, для QL-алгоритма с неявными сдвигами:&amp;lt;br&amp;gt;&lt;br /&gt;
Для трёхдиагональной матрицы объем арифметических действий составляет &amp;lt;math&amp;gt; O(n)&amp;lt;/math&amp;gt; на одну итерацию вместо &amp;lt;math&amp;gt; O(n^3)&amp;lt;/math&amp;gt; для матрицы общего вида, а число итераций для нахождения первых собственных значений примерно равно 4 - 5. Но на этих итерациях также уменьшаются внедиагональные элементы правого нижнего угла. И, таким образом, дальнейшие собственные значения ищутся значительно быстрее. Среднее число итераций на каждое собственное значение обычно составляет 1.3 - 1.6.&amp;lt;br&amp;gt; &lt;br /&gt;
Аналогично QL, QR-разложение трёхдиагольной матрицы также требует &amp;lt;math&amp;gt; O(n)&amp;lt;/math&amp;gt; флопов&amp;lt;ref&amp;gt;Голуб Дж., Ван Лоун Ч. - Матричные вычисления//М.: Мир. - 1999 (c. 378, начало раздела 8.2.2)&amp;lt;/ref&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Подводя итог, во второй части алгоритма Ланцоша можно выделить следующие макрооперации:&lt;br /&gt;
* умножение матрицы на вещественное число;&lt;br /&gt;
* перемножение матриц;&lt;br /&gt;
* умножение и сравнение вещественных чисел;&lt;br /&gt;
* + набор других макроопераций в зависимости от выбора метода, с помощью которого будет совершаться сама QR или QL-декомпозиция (выше продемонстрированы, уже, как минимум, 3 разных способа).&lt;br /&gt;
Так же, важно заметить, что набор макропераций может быть несколько другим, если выбрать какой-либо иной современный метод поиска собственных чисел трёхдиагональной матрицы, не использующий QR и QL разложения(факторизацию). Два таких метода были упомянуты в пункте 1.2.&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
С целью полностью не дублировать раздел 1.2 данной статьи, где представлен наглядный и доступный для понимания псевдокод алгоритма, постараемся лишь коротко просуммировать и обобщить весь перечень последовательных действий в рассматриваемом алгоритме.&lt;br /&gt;
&lt;br /&gt;
В качестве входных данных имеем: вещественная симметричная матрица &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; размера &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;n\times n&amp;lt;/math&amp;gt;, известный вещественный вектор &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;b&amp;lt;/math&amp;gt; длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; и число &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;n&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Далее:&lt;br /&gt;
* Инициализируем вещественную константу &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;\beta_0&amp;lt;/math&amp;gt; и векторы &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;q_0&amp;lt;/math&amp;gt; и &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;q_1&amp;lt;/math&amp;gt;&lt;br /&gt;
* Итерационно для всех &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j=1,...,k&amp;lt;/math&amp;gt;:&lt;br /&gt;
** Вычисляем вспомогательный вектор &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt;, используя умножение матрицы на вектор&lt;br /&gt;
** Вычисляем, используя скалярное произведение векторов, значение &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;\alpha_j&amp;lt;/math&amp;gt; - элемент на главной диагонали трёхдиагональной матрицы &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&amp;lt;/math&amp;gt;&lt;br /&gt;
** Вычисляем по формуле новое значение и перезаписываем вектор &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt;&lt;br /&gt;
** Вычисляем значение &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;\beta_j&amp;lt;/math&amp;gt; - элементы непосредственно над и под главной диагональю той же матрицы &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&amp;lt;/math&amp;gt;&lt;br /&gt;
** Вычисляем, зная вектор &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt;,  очередной столбец матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;Q&amp;lt;/math&amp;gt;, он же вектор Ланцоша : &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;\,\,q_{j+1}&amp;lt;/math&amp;gt;&lt;br /&gt;
** Теперь, когда матрица &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&amp;lt;/math&amp;gt; сформирована на очередном шаге, находим её собственные значения и вектора любым доступным способом, о чём было подробно сказано в пункте 1.2&lt;br /&gt;
** Переходим на следующую итерацию: &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j&amp;lt;/math&amp;gt;++&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
Оценим количество операций и сложность последовательного алгоритма, изложенного в предыдущем разделе.&lt;br /&gt;
*Для вычисления вектора &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt; умножается матрица размера &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;n\times n&amp;lt;/math&amp;gt; на вектор длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt;, и потребуется &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n^2&amp;lt;/math&amp;gt; операций умножения и &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n^2&amp;lt;/math&amp;gt; операций сложения.&lt;br /&gt;
*Умножение векторов &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;q^T_j&amp;lt;/math&amp;gt; и &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt; длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; потребует &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; операций умножения и &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; операций сложения.&lt;br /&gt;
*При вычислении нового значения вектора &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt; поэлементное сложение двух векторов длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; требует &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; операций сложения.&lt;br /&gt;
*Умножение вектора длины &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; на вещественное число требует &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; операций умножения.&lt;br /&gt;
*Нахождение квадратичной нормы вектора &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt;  длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; требует &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; умножений и &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; сложений и ещё 1 операцию извлечения квадратного корня.&lt;br /&gt;
*Заключительное нахождение собственных значений и собственных векторов трёхдиагональной матрицы &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;T_j&amp;lt;/math&amp;gt; размера &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j\times j&amp;lt;/math&amp;gt; с помощью QR-алгоритма потребует в худшем случае &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(j^3)&amp;lt;/math&amp;gt; операций.&amp;lt;ref&amp;gt;http://num-anal.srcc.msu.ru/lib_na/int_ae/int_ae6.htm (пункт 6.2, &amp;quot;Скорость сходимости при этом всегда не хуже квадратичной и почти всегда лучше кубической.&amp;quot;)&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Посчитаем теперь суммарное количество простейших операций на одной итерации алгоритма (без учёта записей в память):&lt;br /&gt;
*&amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n^2+5\,n&amp;lt;/math&amp;gt; операций умножения/деления&lt;br /&gt;
*&amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n^2+4\,n&amp;lt;/math&amp;gt; операций сложения/вычитания&lt;br /&gt;
*1 операция извлечения квадратного корня&amp;lt;br&amp;gt;&lt;br /&gt;
Отдельно после всех итераций при &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j=k&amp;lt;/math&amp;gt; :&lt;br /&gt;
*&amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(k^3)&amp;lt;/math&amp;gt; операций для поиска собственных значений и собственных векторов трёхдиагональной матрицы &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;T_k&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Итого можно утверждать следующее:&lt;br /&gt;
&lt;br /&gt;
Последовательная сложность одной итерации рассматриваемого алгоритма:  &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(n ^ 2) &amp;lt;/math&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Суммарная сложность алгоритма (&amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;/math&amp;gt; итераций): &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(k\,n ^ 2) + O(k ^ 3)&amp;lt;/math&amp;gt; &amp;lt;ref&amp;gt;Здесь мы полагаем, что мы не вычисляем собственные значения и векторы матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_j&amp;lt;/math&amp;gt; на каждом промежуточном шаге, а лишь единожды затрачиваем &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;O(k ^ 3)&amp;lt;/math&amp;gt; действий в конце для нахождения &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;/math&amp;gt; собственных значений и векторов матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_k&amp;lt;/math&amp;gt;&amp;lt;/ref&amp;gt; &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
На практике же обычно рассматривается число &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;&amp;lt;n&amp;lt;/math&amp;gt;, поэтому второе слагаемое можно опустить.&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
На рис. 1 продемонстрирован граф одной итерации (при каком-либо произвольном значении итератора &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j&amp;lt;/math&amp;gt;) описанного алгоритма без отображения входных и выходных данных. Наглядно продемонстрированы связи между всеми действиями, и с помощью деления на &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; потоков показано, какие операции возможно выполнять параллельно на каждом шаге с целью оптимизации и экономии машинного времени. В результате, после параллельно выполненных операций &#039;&#039;&#039;Division&#039;&#039;&#039; на заключительном ярусе, на выходе имеем значение следующего вектора Ланцоша &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;q_{j+1}&amp;lt;/math&amp;gt;, после чего следует переход на следующую итерацию, и процесс повторяется.&lt;br /&gt;
&lt;br /&gt;
[[Файл:Levin_graph.png|600px|thumb|center|Рис. 1]] &amp;lt;br&amp;gt;&lt;br /&gt;
Обозначения на рисунке: &amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Simp&#039;&#039;&#039; (от англ. simple) - операции сложения и умножения вещественных чисел при вычислении произведения матрицы на вектор;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Vec mult&#039;&#039;&#039; (от англ. vectors multiplication) - операция скалярного умножения двух векторов;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Vec subtr&#039;&#039;&#039; (от англ. vectors subtraction, из-за использованных в операции вычитаний векторов) - операция умножения вектора на число (выполняется дважды) и формирование нового значения &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;z_{new}&amp;lt;/math&amp;gt; по формуле: &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;z_{new} = z - \alpha_j q_j - \beta_{j-1}q_{j-1} \;&amp;lt;/math&amp;gt;;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;||\cdot||&amp;lt;/math&amp;gt; - операция вычисления нормы вектора;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Division&#039;&#039;&#039; - операция деления вектора на вещественное число  &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;\beta_j&amp;lt;/math&amp;gt; &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Важно отметить, что упомянутые выше операции также легко поддаются оптимизации. Например, попарные умножения вещественных координат векторов при вычислении скалярного произведения также легко выполняются параллельно на &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; потоках, а затем можно применить суммирование методом сдваивания, о котором сказано в следующем разделе. Умножение или деление вектора на вещественное число являющееся, по определению, умножением или делением всех его координат на это число тоже может быть выполнено эффективнее, если мы используем &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; потоков, а не выполняем эти действия последовательно.&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
Параллельные операции возможны только внутри итераций, так как рассматриваемый алгоритм является итерационным, и сами итерации строго последовательны.&amp;lt;br&amp;gt;&lt;br /&gt;
Рассмотрим в этом разделе подробнее, какой выигрыш мы можем получить при распараллеливании операций внутри одной итерации согласно графу из предыдущего раздела.&lt;br /&gt;
&lt;br /&gt;
Умножение вещественной симметричной матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; размера &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;n\times n&amp;lt;/math&amp;gt; на вектор &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;b&amp;lt;/math&amp;gt; длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; требует последовательного выполнения &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; ярусов умножений и сложений. Сложение элементов вектора длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; на каждом шаге перемножения можно оптимизировать и выполнить за &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;\log_2 n&amp;lt;/math&amp;gt; действий, если применять метод сдваивания.&lt;br /&gt;
&lt;br /&gt;
Дальнейшие операции выполняются последовательно, а вычисление значений векторов происходит за один ярус операций сложения или умножения.&lt;br /&gt;
&lt;br /&gt;
Ресурс параллелизма алгоритма вычисления собственных значений построенной трёхдиагональной матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_k&amp;lt;/math&amp;gt; размера &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k\times k&amp;lt;/math&amp;gt; зависит от выбранного алгоритма (об этих алгоритмах подробнее было сказано в разделах 1.2 и 1.4). Будет очень затратно с точки зрения объёма материала пытаться рассмотреть пусть даже часть этих методов в этой статье, а так же тонкости их распараллеливания. Предлагаем читателям при желании самим ознакомиться с этими алгоритмами на данном ресурсе или прибегнув к иным источникам.&lt;br /&gt;
&lt;br /&gt;
При классификации по высоте ЯПФ, таким образом, алгоритм Ланцоша без переортогонализации относится к алгоритмам с &#039;&#039;логарифмической сложностью&#039;&#039;, и его сложность равна &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(\log_2 n)&amp;lt;/math&amp;gt; с важным замечанием, что это сложность только одной итерации, а максимум в алгоритме может быть выполнено последовательно &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;/math&amp;gt; таких однотипных итераций, если не будет осуществлён ранний выход из цикла. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Несмотря на то, что на графе в предыдущем разделе для лучшей визуализации и понимания было изображено &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; потоков (никаких допущений мы не делали и нарушений с точки зрения логики и математики нет, можно изобразить большее число потоков, просто часть времени некоторые из них могут бездействовать и не использоваться), на самом деле правильным и разумным будет реализовать начальное параллельное выполнение &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n^2&amp;lt;/math&amp;gt; операций умножения всех вещественных элементов матрицы &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;A&amp;lt;/math&amp;gt; на соответствующие элементы вектора &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;q_j&amp;lt;/math&amp;gt;, после чего применять тот же самый упомянутый метод сдваивания. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Поэтому при классификации по ширине ЯПФ его сложность будет &#039;&#039;квадратичной&#039;&#039; и равна &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(n^2)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
&#039;&#039;&#039;Входные данные алгоритма:&#039;&#039;&#039; вещественная симметричная &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; размера &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;n\times n&amp;lt;/math&amp;gt;, вещественный вектор &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;b&amp;lt;/math&amp;gt; длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt;, и одно целое число &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;k&amp;lt;/math&amp;gt;, означающее количество итераций.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём входных данных:&#039;&#039;&#039; &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;n^2 +n + 1 &amp;lt;/math&amp;gt;. Если учесть, что матрица симметричная и достаточно для её однозначного определения задать элементы на главной диагонали и элементы над или под ней, то можно сократить объём входных данных с целью экономии памяти до: &amp;lt;math&amp;gt;\ \frac{n^2-n}{2}+n+n+1 =\frac{n^2+3n}{2} + 1&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные алгоритма:&#039;&#039;&#039; вектор собственных значений &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;\Theta^k&amp;lt;/math&amp;gt; длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;/math&amp;gt;, матрица &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;S^k&amp;lt;/math&amp;gt; из соответствующих собственных векторов размера &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n\times k&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём выходных данных:&#039;&#039;&#039; &amp;lt;math&amp;gt;k\;(n + 1)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
В данном разделе перечислены без какой-либо хронологии или связи друг с другом наиболее важные и разнообразные свойства алгоритма, на которые стоит и полезно обратить внимание, а также которые выгодно отличают его от схожих алгоритмов, решающих ту же задачу.&amp;lt;br&amp;gt;&lt;br /&gt;
1) Отношение последовательной сложности алгоритма к параллельной,с учётом &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;/math&amp;gt; итераций, равно &amp;lt;math&amp;gt;\;\;\frac{kn^2}{k \log_2{n}}=\frac{n^2}{\log_2{n}}&amp;lt;/math&amp;gt;;&amp;lt;br&amp;gt;&lt;br /&gt;
2) Вычислительная мощность алгоритма, как отношение числа операций к суммарному объему входных и выходных данных, равна &amp;lt;math style=&amp;quot;vertical-align:-70%&amp;gt;\;\;\frac{k\,n^2}{0.5\,n^2+1.5\,n+k\,n+k+1}&amp;lt;/math&amp;gt; и &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;\approx 2\,k&amp;lt;/math&amp;gt;, так как на практике верно отношение &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;&amp;lt;n&amp;lt;/math&amp;gt; ;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
3) Для собственных значений формируемых матриц &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_j&amp;lt;/math&amp;gt; верно отношение (следствие теоремы Коши о перемежаемости): &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;\lambda_i(T_{k+1})\geq \lambda_i(T_{k})\geq \lambda_{i+1}(T_{k+1})\geq \lambda_{i+1}(T_{k})&amp;lt;/math&amp;gt; ;&amp;lt;ref&amp;gt;James W. Demmel - Вычислительная линейная алгебра. Теория и приложения //Мир. - 2001 (c. 383)&amp;lt;/ref&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
4) Крайние (наибольшие и наименьшие) собственные значения матриц &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_j&amp;lt;/math&amp;gt; сходятся к крайним собственным значениям матрицы &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;A&amp;lt;/math&amp;gt; первыми (это часто происходит уже на ранних шагах при &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j\approx 2\,\sqrt{n}&amp;lt;/math&amp;gt;&amp;lt;ref&amp;gt;http://num-anal.srcc.msu.ru/lib_na/int_ae/int_ae6.htm (пункт 6.5)&amp;lt;/ref&amp;gt;), а собственные значения в середине спектра - последними;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
5) Из-за ограниченной точности постепенно теряется ортогональность вектора Ланцоша &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;q_j&amp;lt;/math&amp;gt; к предыдущим векторам Ланцоша, поэтому необходимо примерно каждые 10-15 итераций проводить дорогостоящую операцию реортогонализации, но это уже будет иной алгоритм с очень малым различием в одной операции и в программном коде, реализующем его, соответственно; &amp;lt;ref&amp;gt;Sam Handler - The Lanczos Algorithm For Large-Scale Eigenvalue Problems (08.01.07), slide №8&amp;lt;/ref&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
6) Эффективность и быстрота выполнения алгоритма очень сильно зависит от скорости памяти (диска). Согласно тесту только &#039;&#039;6%&#039;&#039; времени работы программы приходится на вычисления, остальное время затрачивается на ожидание отклика диска;&amp;lt;ref&amp;gt;Sam Handler - The Lanczos Algorithm For Large-Scale Eigenvalue Problems (08.01.07), slide №10&amp;lt;/ref&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
7) Метод Ланцоша удобен тем, что не требует хранения исходной матрицы полным массивом: метод использует исходную матрицу только в операциях умножения матрицы на вектор, что позволяет эффективно использовать разреженность матрицы или регулярность структуры матрицы. Поэтому метод Ланцоша может быть использован для матриц таких больших порядков, когда методы вращений и отражений не могут быть применены.&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;
По заданию, во второй части требовалось описать только разделы 2.4 и 2.7, прошу не спрашивать с меня все разделы 2.1-2.6. Надеюсь на понимание, мне физически не хватает времени на это задание + 2 других в течение семестра, делаю всё, что в моих силах :)&lt;br /&gt;
&lt;br /&gt;
== Существующие реализации алгоритма ==&lt;br /&gt;
Несмотря на то, что алгоритм является далеко не самым популярным, алгоритмом, про который нельзя сказать, что он всегда «на слуху», на сегодняшний день существует множество реализаций на различных популярных языках.&amp;lt;br&amp;gt;&lt;br /&gt;
Перечислим далее некоторые из них, указывая язык программирования, лежащий в их основе, и некоторые важные характеристики, которые обсуждались в статье ранее:&lt;br /&gt;
*&#039;&#039;Code on netlib.org by Jane Cullum and Ralph Willoughby&#039;&#039; (&#039;&#039;&#039;Fortran 77&#039;&#039;&#039;; без реортогонализации векторов; без реализации распараллеливания)&amp;lt;ref&amp;gt;http://www.netlib.org/lanczos/leval&amp;lt;/ref&amp;gt;&lt;br /&gt;
*&#039;&#039;Lanczos algorithm on freesourcecode.net&#039;&#039; (&#039;&#039;&#039;Matlab&#039;&#039;&#039;; присутствует реортогонализация векторов; без реализации распараллеливания)&amp;lt;ref&amp;gt;http://freesourcecode.net/matlabprojects/61741/lanczos-algorithm--in-matlab&amp;lt;/ref&amp;gt;&lt;br /&gt;
*&#039;&#039;Lanczos for eigenvalues in Numerical Linear Algebra, Spring 2007&#039;&#039; (&#039;&#039;&#039;Matlab&#039;&#039;&#039;; частичная или полная реортогонализация - доступны оба варианта; без реализации распараллеливания)&amp;lt;ref&amp;gt;Ссылки на файлы lanso.m и lanfu.m можно найти на https://www.nada.kth.se/~ruhe/2D5219/labs2007.html&amp;lt;/ref&amp;gt;&lt;br /&gt;
*&#039;&#039;Planso&#039;&#039; (название происходит от parallel Lanso.f) &#039;&#039;code by Kesheng Wu and Horst D. Simon&#039;&#039; (&#039;&#039;&#039;Fortran 77&#039;&#039;&#039;; частичная реортогонализация векторов; использование MPI для коммуникаций)&amp;lt;ref&amp;gt;https://github.com/jiahao/planso.jl/tree/master/external/PLAN/plan К сожалению, ссылка в описании пакета на github, ведущая на сайт National Energy Research Scientific Computing Center (NERSC), с более подробной информацией о данной программе больше не активна и выдаёт результат &#039;&#039;Page not found&#039;&#039;&amp;lt;/ref&amp;gt; &lt;br /&gt;
* &#039;&#039;Lanczos.cpp in the Vienna Computing Library&#039;&#039;  (&#039;&#039;&#039;C++&#039;&#039;&#039;, частичная реортогонализация, без реализации распараллеливания) &amp;lt;ref&amp;gt;http://viennacl.sourceforge.net/doc/lanczos_8cpp_source.html&amp;lt;/ref&amp;gt;&lt;br /&gt;
* &#039;&#039;Parallel Eigen Values code using C++ AMP on microsoft msdn blog&#039;&#039; (&#039;&#039;&#039;C++&#039;&#039;&#039;; ? ; распараллеливание есть и реализовано через C++ AMP) &amp;lt;ref&amp;gt;https://blogs.msdn.microsoft.com/nativeconcurrency/2013/12/20/eigen-values/ Подробнее о C++ Accelerated Massive Parallelism можно почитать здесь: https://msdn.microsoft.com/ru-ru/library/hh265137(v=vs.140).aspx или здесь: http://professorweb.ru/my/csharp/optimization/level4/4_6.php &amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;br /&gt;
[[en:Description of algorithm properties and structure]]&lt;/div&gt;</summary>
		<author><name>AleksLevin</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:AleksLevin/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%9B%D0%B0%D0%BD%D1%86%D0%BE%D1%88%D0%B0_%D0%B2%D1%8B%D1%87%D0%B8%D1%81%D0%BB%D0%B5%D0%BD%D0%B8%D1%8F_%D1%81%D0%BE%D0%B1%D1%81%D1%82%D0%B2%D0%B5%D0%BD%D0%BD%D1%8B%D1%85_%D0%B7%D0%BD%D0%B0%D1%87%D0%B5%D0%BD%D0%B8%D0%B9_%D1%81%D0%B8%D0%BC%D0%BC%D0%B5%D1%82%D1%80%D0%B8%D1%87%D0%BD%D0%BE%D0%B9_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86%D1%8B_%D0%B4%D0%BB%D1%8F_%D1%82%D0%BE%D1%87%D0%BD%D0%BE%D0%B9_%D0%B0%D1%80%D0%B8%D1%84%D0%BC%D0%B5%D1%82%D0%B8%D0%BA%D0%B8_(%D0%B1%D0%B5%D0%B7_%D0%BF%D0%B5%D1%80%D0%B5%D0%BE%D1%80%D1%82%D0%BE%D0%B3%D0%BE%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D0%B8)&amp;diff=19939</id>
		<title>Участник:AleksLevin/Алгоритм Ланцоша вычисления собственных значений симметричной матрицы для точной арифметики (без переортогонализации)</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:AleksLevin/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%9B%D0%B0%D0%BD%D1%86%D0%BE%D1%88%D0%B0_%D0%B2%D1%8B%D1%87%D0%B8%D1%81%D0%BB%D0%B5%D0%BD%D0%B8%D1%8F_%D1%81%D0%BE%D0%B1%D1%81%D1%82%D0%B2%D0%B5%D0%BD%D0%BD%D1%8B%D1%85_%D0%B7%D0%BD%D0%B0%D1%87%D0%B5%D0%BD%D0%B8%D0%B9_%D1%81%D0%B8%D0%BC%D0%BC%D0%B5%D1%82%D1%80%D0%B8%D1%87%D0%BD%D0%BE%D0%B9_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86%D1%8B_%D0%B4%D0%BB%D1%8F_%D1%82%D0%BE%D1%87%D0%BD%D0%BE%D0%B9_%D0%B0%D1%80%D0%B8%D1%84%D0%BC%D0%B5%D1%82%D0%B8%D0%BA%D0%B8_(%D0%B1%D0%B5%D0%B7_%D0%BF%D0%B5%D1%80%D0%B5%D0%BE%D1%80%D1%82%D0%BE%D0%B3%D0%BE%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D0%B8)&amp;diff=19939"/>
		<updated>2016-12-02T18:56:28Z</updated>

		<summary type="html">&lt;p&gt;AleksLevin: /* Макроструктура алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Основные авторы описания: Левин А.Д.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{algorithm&lt;br /&gt;
| name              = Алгоритм Ланцоша для точной арифметики (без переортогонализации)&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(k\,n^2)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(k\log_2 n)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;\frac{n^2+3n}{2} + 1&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;k\;(n + 1)&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритмов =&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Данный алгоритм появился в 1950 г. и носит имя венгерского физика и математика Корнелия Ланцоша (венг. Lánczos Kornél). Алгоритм Ланцоша относится к итерационным методам вычисления собственных значений для матриц столь больших порядков &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt; n&amp;lt;/math&amp;gt;, что к ним нельзя применить прямые методы из-за ограничений по времени и памяти.&lt;br /&gt;
&lt;br /&gt;
Сам Ланцош указывал, что его метод предназначен для отыскания нескольких собственных векторов симметричных матриц, хотя к методу сразу было обращено внимание, как к способу приведения всей матрицы к трёхдиагональному виду. Двадцатью годами позже канадский математик Крис Пэж показал, что, несмотря на чувствительность к округлениям, алгоритм Ланцоша - эффективное средство вычисления некоторых &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; собственных чисел и соответствующих им собственных векторов. &amp;lt;ref&amp;gt;Парлетт Б. - Симметричная проблема собственных значений. Численные методы //М.: Мир. - 1983. (c. 276)&amp;lt;/ref&amp;gt;&lt;br /&gt;
Обычно число &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; берут в два раза больше, чем количество собственных значений матрицы, которые поставлена цель найти, и оно имеет порядок не более &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;10^2&amp;lt;/math&amp;gt;.&amp;lt;ref&amp;gt;Susan W. Bostic - Lanczos Eigensolution Method for High-Perfomance Computers, page 7&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Алгоритм Ланцоша для вычисления собственных значений симметричной матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; соединяет в себе метод Ланцоша для построения последовательности подпространств Крылова и ортонормированных векторов Ланцоша и процедуру Рэлея-Ритца получения оптимальных приближений собственных значений и соответствующих собственных векторов исходной матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt;.&amp;lt;ref&amp;gt;James W. Demmel - Вычислительная линейная алгебра. Теория и приложения //Мир. - 2001 (c. 381)&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
В данной статье рассматривается вариант алгоритма Ланцоша, в котором опущено влияние ошибок округления на вычислительный процесс, хотя на практике этому посвящается отдельное внимание и существуют различные методы решения данной проблемы, такие как частичная или полная переортогонализация. Этим модифицированным методам посвящены отдельные статьи на данном ресурсе.&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
Обозначения и формулы, используемые в данном разделе, взяты из литературы, указанной по ссылке.&amp;lt;ref&amp;gt;James W. Demmel - Вычислительная линейная алгебра. Теория и приложения //Мир. - 2001 (c. 313, &#039;&#039;&amp;lt;math&amp;gt; \S &amp;lt;/math&amp;gt; 6.6 Методы Крыловского подпространства&#039;&#039;)&amp;lt;/ref&amp;gt; &lt;br /&gt;
&lt;br /&gt;
Алгоритм Ланцоша для вычисления &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; собственных значений и собственных векторов вещественной симметричной матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A=A^T&amp;lt;/math&amp;gt; в точной арифметике: &amp;lt;ref&amp;gt;James W. Demmel - Вычислительная линейная алгебра. Теория и приложения //Мир. - 2001 (c. 381)&amp;lt;/ref&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{align}&lt;br /&gt;
q_1 = &amp;amp; \,\frac{b}{\|b\|_2},\; \beta_0 = 0,\; q_0 = 0\\&lt;br /&gt;
\mathbf{for} \; &amp;amp; j = 1 \; to \; k \,\; \mathbf{do} \\&lt;br /&gt;
&amp;amp; z = A\,q_j\\&lt;br /&gt;
&amp;amp; \alpha_j = q^T_j z\\&lt;br /&gt;
&amp;amp; z = z - \alpha_j q_j - \beta_{j-1}q_{j-1}\\&lt;br /&gt;
&amp;amp; \beta_j = \|z\|_2\\&lt;br /&gt;
&amp;amp; \mathbf{If} \; (\beta_j == 0) \; \mathbf{then}\; stop\; the\; algorithm \\ &lt;br /&gt;
&amp;amp; \;  q_{j+1} = \frac{z}{\beta_j} \\&lt;br /&gt;
&amp;amp; compute\; eigenvalues\; and \;eigenvectors\;of \;matrix \;\;T_j= Q^T_j A Q\;\;and\;estimate \;the\; errors\\&lt;br /&gt;
\mathbf{end} \; &amp;amp; \mathbf{for}&lt;br /&gt;
\end{align}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
В продемонстрированном выше алгоритме &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;b&amp;lt;/math&amp;gt; - заданный вещественный вектор. Также полагается известным алгоритм вычисления произведения матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; на вектор &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;x&amp;lt;/math&amp;gt;. &lt;br /&gt;
Введём матрицу Крылова, определяемую следующим соотношением: &amp;lt;math&amp;gt;K_j = [b,Ab,A^2b,...,A^{j-1}b]&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Далее, на практике, матрица &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;K&amp;lt;/math&amp;gt; заменяется матрицей &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;Q&amp;lt;/math&amp;gt;, такой, что при любом числе &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; линейные оболочки первых &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; столбцов в &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;K&amp;lt;/math&amp;gt; и &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;Q&amp;lt;/math&amp;gt; являются одним и тем же подпространством.&amp;lt;ref&amp;gt;James W. Demmel - Вычислительная линейная алгебра. Теория и приложения //Мир. - 2001 (c. 315)&amp;lt;/ref&amp;gt; &lt;br /&gt;
Тогда матрица &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;Q&amp;lt;/math&amp;gt;, в отличие от матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;K&amp;lt;/math&amp;gt;, хорошо обусловлена и легко обратима. В результате получаем матрицу &amp;lt;math&amp;gt;Q_j = [q_1, q_2, \dots, q_j]&amp;lt;/math&amp;gt; размерности &amp;lt;math&amp;gt;n\times j&amp;lt;/math&amp;gt;, столбцы которой ортогональны, являются базисом подпространства Крылова и называются векторами Ланцоша.&lt;br /&gt;
&lt;br /&gt;
В алгоритме Ланцоша вычислению подлежит столько первых столбцов в матрице &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;Q_j&amp;lt;/math&amp;gt;, сколько необходимо для получения требуемого приближения к решению &amp;lt;math&amp;gt;A\,x\,=b\,\,(A\,x=\lambda \, x)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Получение нулевого &amp;lt;math&amp;gt;\beta_j&amp;lt;/math&amp;gt; в итерационном процессе - событие, желательное в том смысле, что оно свидетельствует о том, что найдено некоторое подпространство, являющееся в точности инвариантным, а все собственные значения матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;T_j&amp;lt;/math&amp;gt; являются собственными значениями матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt;. На практике же нулевое и близкие к нулю значения получаются редко.&amp;lt;ref&amp;gt;Голуб Дж., Ван Лоун Ч. - Матричные вычисления//М.: Мир. - 1999 (c. 429)&amp;lt;/ref&amp;gt; &lt;br /&gt;
&lt;br /&gt;
Затем на каждом шаге цикла формируется симметричная трёхдиагональная матрица &amp;lt;math&amp;gt;T_j = Q^T_j A Q&amp;lt;/math&amp;gt;, к которой применяется процесс Рэлея-Ритца для поиска её собственных значений (на практике для поиска этих собственных значений можно использовать любой из специальных методов в параграфе книги по ссылке).&amp;lt;ref&amp;gt;Голуб Дж., Ван Лоун Ч. - Матричные вычисления//М.: Мир. - 1999 (&amp;lt;math&amp;gt;\S&amp;lt;/math&amp;gt; 8.4)&amp;lt;/ref&amp;gt;  &lt;br /&gt;
Эти собственные значения, они же числа Ритца, и полагаются приближёнными собственными значениями исходной матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt;.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Существует множество методов для отыскания собственных значений вещественной симметричной трехдиагональной матрицы. Большинство из них требует &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt; операций &amp;lt;ref&amp;gt;Парлетт Б. Симметричная проблема собственных значений. Численные методы.,: Мир, 1983. с. 179-182&amp;lt;/ref&amp;gt;, но существуют и быстрые алгоритмы, требующие лишь &amp;lt;math&amp;gt;O(n\ln n)&amp;lt;/math&amp;gt; операций.&amp;lt;ref&amp;gt;https://en.wikipedia.org/wiki/Tridiagonal_matrix#Eigenvalues  Раздел eigenvalues&amp;lt;/ref&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Одним из возможных способов отыскать собственные значения симметричной трехдиагональной матрицы - прямое вычисление корней характеристического полинома &amp;lt;math&amp;gt;p_n(\lambda)&amp;lt;/math&amp;gt; через метод деления пополам, где формируется последовательность Штурма и локализуются собственные числа, являющиеся корнями характеристического полинома. Нахождение всех &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; собственных значений матрицы этим способом требует &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;2n^2t&amp;lt;/math&amp;gt; умножений и вычитаний, где &amp;lt;math&amp;gt;t&amp;lt;/math&amp;gt; - число сделанных шагов с применением метода деления пополам.&amp;lt;ref&amp;gt;Уилкинсон Дж. X. Алгебраическая проблема собственныx значений. Изд-во &amp;quot;Наука&amp;quot;, 1970. - глава 5, с. 272-278&amp;lt;/ref&amp;gt; Соответствующие собственные вектора могут быть найдены посредством обратных итераций за &amp;lt;math&amp;gt; O(n) &amp;lt;/math&amp;gt; флопов. &amp;lt;ref&amp;gt;Голуб Дж., Ван Лоун Ч. - Матричные вычисления//М.: Мир. - 1999 (c. 394-395)&amp;lt;/ref&amp;gt; &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;На практике, если требуется только небольшая часть от всей совокупности собственных векторов и значений, и матрица имеет Хессенбергову или трёхдиагональную форму, очень эффективными будут методы факторизации, как, например, QR-алгоритм или QL-алгоритм со сдвигами (c целью ускорить алгоритм и сделать порядок сходимости квадратичным) или же без них.&amp;lt;ref&amp;gt;http://algorithm.narod.ru/ln/eigen/ETridiag.html&amp;lt;/ref&amp;gt; &amp;lt;br&amp;gt;&lt;br /&gt;
Весьма молодые и не менее актуальные конкуренты QR и QL алгоритмов:&lt;br /&gt;
*Методы divide-and-conquer (разделяй и властвуй), появившиеся в 1980-ых годах &amp;lt;ref&amp;gt;https://algowiki-project.org/ru/Метод_&amp;quot;Разделяй_и_властвуй&amp;quot;_Завольсков/Землянский&amp;lt;/ref&amp;gt;&lt;br /&gt;
*Relatively robust representation methods, появившиеся в 1990-ых и позволяющие найти собственные числа симметричной матрицы порядка &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;n&amp;lt;/math&amp;gt; за &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt; операций&lt;br /&gt;
&lt;br /&gt;
Если требуется вычислить собственные векторы, то необходимо хранить вычисляемые векторы Ланцоша. Если работа при этом производится только с оперативной памятью, то при большом порядке исходной матрицы (а именно для таких матриц и предназначен метод Ланцоша) число шагов  &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;j&amp;lt;/math&amp;gt;, которые могут быть выполнены до того момента, как оперативная память будет исчерпана, будет очень незначительно, а следовательно, искомые собственные пары могут не успеть сойтись с требуемой точностью. В этом случае метод Ланцоша можно использовать итерационным образом: после выполнения заданного числа шагов процесс прерывается и, если еще не все требуемые пары Ритца сошлись с требуемой точностью, то формируется новый начальный вектор &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;q_1&amp;lt;/math&amp;gt;, являющийся линейной комбинацией векторов Ритца, еще не сошедшихся с заданной точностью, и процесс начинается заново.&amp;lt;ref&amp;gt;http://num-anal.srcc.msu.ru/lib_na/int_ae/int_ae6.htm (пункт 6.5)&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
Вычислительное ядро рассматриваемого алгоритма (наиболее ресурсно-затратная часть алгоритма) -  формирование на каждом шаге цикла промежуточного вектора &amp;lt;math&amp;gt;z&amp;lt;/math&amp;gt;, вычисляемого по формуле: &amp;lt;math&amp;gt;z = A\,q_j&amp;lt;/math&amp;gt;. Данная операция, по сравнению с другими операциями алгоритма, затратна и требовательна, как с точки зрения количества производимых операций, так и с точки зрения объема оперируемых данных. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Например, умножение матрицы размера &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;n\times n&amp;lt;/math&amp;gt; на вектор длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; требует: &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;n^2+(n-1)n = 2n^2-n&amp;lt;/math&amp;gt; операций умножения и сложения. В свою очередь аналогичная операция умножения матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;(n+1)\times (n+1)&amp;lt;/math&amp;gt; на вектор длины &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;(n+1)&amp;lt;/math&amp;gt; требует: &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;2n^2+3n+1&amp;lt;/math&amp;gt;  операций умножения и сложения. То есть повышение размерности задачи всего на 1 увеличивает число необходимых действий в этом шаге алгоритма на: &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;4n+1&amp;lt;/math&amp;gt;. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Так же, стоит помнить, что, согласно разделу 1.2, данную операцию умножения матрицы на вектор необходимо выполнить &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;k&amp;lt;/math&amp;gt; раз. Нетрудно понять, насколько возрастает и колоссален масштаб операций, если в задачах, где критична точность, размерности &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; могут иметь порядок &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;10^5&amp;lt;/math&amp;gt; или даже более.&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
Как уже было упомянуто в данной статье в описании алгоритма, рассматриваемый алгоритм состоит из двух последовательно выполненных алгоритмов: метод Ланцоша для построения последовательности подпространств Крылова и ортонормированных векторов Ланцоша и процедура Рэлея-Ритца получения оптимальных приближений собственных значений и соответствующих собственных векторов исходной матрицы.&lt;br /&gt;
&lt;br /&gt;
В первой части алгоритма, где итерационно строятся Крыловское подпространство и трёхдиагональная матрица &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&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 style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; разреженная. Именно она подлежит оптимизации с использованием техник распараллеливания, поскольку она является вычислительным ядром алгоритма, а весь упомянутый процесс построения матрицы &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&amp;lt;/math&amp;gt; выполняется последовательно.&lt;br /&gt;
&lt;br /&gt;
Рассмотрим вторую часть алгоритма - поиск собственных значений сформированной матрицы &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&amp;lt;/math&amp;gt;.&amp;lt;br&amp;gt;&lt;br /&gt;
Далее, наглядно, в виде псевдокода, представлен, упомянутый в разделе 1.2, QR-алгоритм (аналогично в качестве примера можно взять и QL-алгоритм) со сдвигами Релэя, который весьма популярен на практике.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{align}&lt;br /&gt;
\mathbf{Input}: \;&amp;amp;tridiagonal\;\;matrix \;T\;with\;\;n\times n\;\;size\\&lt;br /&gt;
T^{(0)}&amp;amp;:=T\\&lt;br /&gt;
\mathbf{for}&amp;amp; \;\;m=n,...,2 \;\; \mathbf{do}\\&lt;br /&gt;
&amp;amp;k=0\\&lt;br /&gt;
&amp;amp; \mathbf{repeat}\\&lt;br /&gt;
&amp;amp; \quad \;\; k=k+1\\&lt;br /&gt;
&amp;amp; \quad \;\; \mu^{(k)}=T_{m,m}^{(k-1)}\\&lt;br /&gt;
&amp;amp; \quad \;\; Q^{(k)}R^{(k)}=T^{(k-1)}-\mu^{(k)}I\;\;using\;\;QR\;decomposition\\&lt;br /&gt;
&amp;amp; \quad \;\; T^{(k)}=R^{(k)}Q^{(k)}+\mu^{(k)}I\\&lt;br /&gt;
&amp;amp; \mathbf{until} \;\;\; |T_{m,m-1}^{(k)}| \;is\;\;small\;\;enough\\&lt;br /&gt;
&amp;amp; Save  \;\;T_{m,m}^{(k)} \;\;as\;\; converged\;\;eigenvalue\;of\;T\\ &lt;br /&gt;
&amp;amp; Remove \;\boldsymbol{n}\,th\;row\;and\;\boldsymbol{n}\,th\;column\;\;from \;T \\&lt;br /&gt;
&amp;amp; and\;take\;this\;new\;cropped\;matrix\;as\;new\;T^{(0)}\;with\;\;(n-1)\times (n-1)\;\;size\\&lt;br /&gt;
 \mathbf{end}&amp;amp;\; \mathbf{for}&lt;br /&gt;
\end{align}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Малость наддиагональных и поддиагональных элементов матрицы (фраза &#039;&#039;&amp;quot;small enough&amp;quot;&#039;&#039; в псевдокоде) подразумевает:&lt;br /&gt;
&amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt; |T_{m,m-1}^{(k)}| \leq \varepsilon\,|T_{m,m}^{(k)}| \quad\quad &amp;lt;/math&amp;gt; , где &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt; \varepsilon &amp;lt;/math&amp;gt; - заданная точность&amp;lt;br&amp;gt;&lt;br /&gt;
Также вместо сдвига Релэя, обозначенного в алгоритме через &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;\mu^{(k)}&amp;lt;/math&amp;gt; часто на практике используется сдвиг по Уилкинсону, который даёт гарантированную сходимость внедиагональных элементов матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt; T^{(k)} &amp;lt;/math&amp;gt;, формируемой на каждом шаге, к нулю, при этом жертвуя монотонностью их убывания.&amp;lt;ref&amp;gt;Голуб Дж., Ван Лоун Ч. - Матричные вычисления//М.: Мир. - 1999 (c. 378)&amp;lt;/ref&amp;gt;&amp;lt;ref&amp;gt;Парлетт Б. Симметричная проблема собственных значений. Численные методы.,: Мир, 1983. с. 169&amp;lt;/ref&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Подробнее с различными сдвигами и соответствующими оценками скоростей и количествами операций можно ознакомиться по указанной ссылке:&amp;lt;ref&amp;gt;Парлетт Б. Симметричная проблема собственных значений. Численные методы.,: Мир, 1983. с. 179-182&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;Для совершения QR-декомпозиции на каждом шаге может использоваться любой из алгоритмов по ссылке.&amp;lt;ref&amp;gt;https://en.wikipedia.org/wiki/QR_decomposition&amp;lt;/ref&amp;gt; Подробные описания этих алгоритмов также доступны на данном ресурсе algowiki-project.&amp;lt;br&amp;gt;&lt;br /&gt;
Так как мы оперируем не обычной матрицей и даже не Хессенберговой, а симметричной и трёхдиагональной, то скорость таких алгоритмов значительно возрастёт. Например, согласно данному ресурсу &amp;lt;ref&amp;gt;http://algorithm.narod.ru/ln/eigen/ETridiag.html&amp;lt;/ref&amp;gt;, для QL-алгоритма с неявными сдвигами:&lt;br /&gt;
Для трехдиагональной матрицы объем арифметических действий составляет &amp;lt;math&amp;gt; O(n)&amp;lt;/math&amp;gt; на итерацию вместо &amp;lt;math&amp;gt; O(n^3)&amp;lt;/math&amp;gt; для матрицы общего вида, а число итераций для нахождения первых собственных значений примерно равно 4 - 5. Но на этих итерациях также уменьшаются внедиагональные элементы правого нижнего угла. И, таким образом, дальнейшие собственные значения ищутся значительно быстрее. Среднее число итераций на каждое собственное значение обычно составляет 1.3 - 1.6. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Итого во второй части алгоритма Ланцоша можно выделить следующие макрооперации:&lt;br /&gt;
* умножение матрицы на вещественное число;&lt;br /&gt;
* перемножение матриц;&lt;br /&gt;
* умножение и сравнение вещественных чисел;&lt;br /&gt;
* + набор других макроопераций в зависимости от выбора метода, с помощью которого будет совершаться сама QR или QL-декомпозиция (по указанной ссылке продемонстрированы, уже, как минимум, 3 разных способа).&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
С целью полностью не дублировать раздел 1.2 данной статьи, где представлен наглядный и доступный для понимания псевдокод алгоритма, постараемся лишь коротко просуммировать и обобщить весь перечень последовательных действий в рассматриваемом алгоритме.&lt;br /&gt;
&lt;br /&gt;
В качестве входных данных имеем: вещественная симметричная матрица &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; размера &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;n\times n&amp;lt;/math&amp;gt;, известный вещественный вектор &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;b&amp;lt;/math&amp;gt; длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; и число &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;n&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Далее:&lt;br /&gt;
* Инициализируем вещественную константу &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;\beta_0&amp;lt;/math&amp;gt; и векторы &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;q_0&amp;lt;/math&amp;gt; и &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;q_1&amp;lt;/math&amp;gt;&lt;br /&gt;
* Итерационно для всех &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j=1,...,k&amp;lt;/math&amp;gt;:&lt;br /&gt;
** Вычисляем вспомогательный вектор &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt;, используя умножение матрицы на вектор&lt;br /&gt;
** Вычисляем, используя скалярное произведение векторов, значение &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;\alpha_j&amp;lt;/math&amp;gt; - элемент на главной диагонали трёхдиагональной матрицы &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&amp;lt;/math&amp;gt;&lt;br /&gt;
** Вычисляем по формуле новое значение и перезаписываем вектор &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt;&lt;br /&gt;
** Вычисляем значение &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;\beta_j&amp;lt;/math&amp;gt; - элементы непосредственно над и под главной диагональю той же матрицы &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&amp;lt;/math&amp;gt;&lt;br /&gt;
** Вычисляем, зная вектор &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt;,  очередной столбец матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;Q&amp;lt;/math&amp;gt;, он же вектор Ланцоша : &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;\,\,q_{j+1}&amp;lt;/math&amp;gt;&lt;br /&gt;
** Теперь, когда матрица &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&amp;lt;/math&amp;gt; сформирована на очередном шаге, находим её собственные значения и вектора любым доступным способом, о чём было подробно сказано в пункте 1.2&lt;br /&gt;
** Переходим на следующую итерацию: &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j&amp;lt;/math&amp;gt;++&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
Оценим количество операций и сложность последовательного алгоритма, изложенного в предыдущем разделе.&lt;br /&gt;
*Для вычисления вектора &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt; умножается матрица размера &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;n\times n&amp;lt;/math&amp;gt; на вектор длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt;, и потребуется &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n^2&amp;lt;/math&amp;gt; операций умножения и &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n^2&amp;lt;/math&amp;gt; операций сложения.&lt;br /&gt;
*Умножение векторов &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;q^T_j&amp;lt;/math&amp;gt; и &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt; длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; потребует &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; операций умножения и &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; операций сложения.&lt;br /&gt;
*При вычислении нового значения вектора &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt; поэлементное сложение двух векторов длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; требует &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; операций сложения.&lt;br /&gt;
*Умножение вектора длины &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; на вещественное число требует &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; операций умножения.&lt;br /&gt;
*Нахождение квадратичной нормы вектора &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt;  длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; требует &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; умножений и &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; сложений и ещё 1 операцию извлечения квадратного корня.&lt;br /&gt;
*Заключительное нахождение собственных значений и собственных векторов трёхдиагональной матрицы &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;T_j&amp;lt;/math&amp;gt; размера &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j\times j&amp;lt;/math&amp;gt; с помощью QR-алгоритма потребует в худшем случае &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(j^3)&amp;lt;/math&amp;gt; операций.&amp;lt;ref&amp;gt;http://num-anal.srcc.msu.ru/lib_na/int_ae/int_ae6.htm (пункт 6.2, &amp;quot;Скорость сходимости при этом всегда не хуже квадратичной и почти всегда лучше кубической.&amp;quot;)&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Посчитаем теперь суммарное количество простейших операций на одной итерации алгоритма (без учёта записей в память):&lt;br /&gt;
*&amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n^2+5\,n&amp;lt;/math&amp;gt; операций умножения/деления&lt;br /&gt;
*&amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n^2+4\,n&amp;lt;/math&amp;gt; операций сложения/вычитания&lt;br /&gt;
*1 операция извлечения квадратного корня&amp;lt;br&amp;gt;&lt;br /&gt;
Отдельно после всех итераций при &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j=k&amp;lt;/math&amp;gt; :&lt;br /&gt;
*&amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(k^3)&amp;lt;/math&amp;gt; операций для поиска собственных значений и собственных векторов трёхдиагональной матрицы &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;T_k&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Итого можно утверждать следующее:&lt;br /&gt;
&lt;br /&gt;
Последовательная сложность одной итерации рассматриваемого алгоритма:  &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(n ^ 2) &amp;lt;/math&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Суммарная сложность алгоритма (&amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;/math&amp;gt; итераций): &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(k\,n ^ 2) + O(k ^ 3)&amp;lt;/math&amp;gt; &amp;lt;ref&amp;gt;Здесь мы полагаем, что мы не вычисляем собственные значения и векторы матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_j&amp;lt;/math&amp;gt; на каждом промежуточном шаге, а лишь единожды затрачиваем &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;O(k ^ 3)&amp;lt;/math&amp;gt; действий в конце для нахождения &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;/math&amp;gt; собственных значений и векторов матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_k&amp;lt;/math&amp;gt;&amp;lt;/ref&amp;gt; &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
На практике же обычно рассматривается число &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;&amp;lt;n&amp;lt;/math&amp;gt;, поэтому второе слагаемое можно опустить.&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
На рис. 1 продемонстрирован граф одной итерации (при каком-либо произвольном значении итератора &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j&amp;lt;/math&amp;gt;) описанного алгоритма без отображения входных и выходных данных. Наглядно продемонстрированы связи между всеми действиями, и с помощью деления на &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; потоков показано, какие операции возможно выполнять параллельно на каждом шаге с целью оптимизации и экономии машинного времени. В результате, после параллельно выполненных операций &#039;&#039;&#039;Division&#039;&#039;&#039; на заключительном ярусе, на выходе имеем значение следующего вектора Ланцоша &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;q_{j+1}&amp;lt;/math&amp;gt;, после чего следует переход на следующую итерацию, и процесс повторяется.&lt;br /&gt;
&lt;br /&gt;
[[Файл:Levin_graph.png|600px|thumb|center|Рис. 1]] &amp;lt;br&amp;gt;&lt;br /&gt;
Обозначения на рисунке: &amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Simp&#039;&#039;&#039; (от англ. simple) - операции сложения и умножения вещественных чисел при вычислении произведения матрицы на вектор;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Vec mult&#039;&#039;&#039; (от англ. vectors multiplication) - операция скалярного умножения двух векторов;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Vec subtr&#039;&#039;&#039; (от англ. vectors subtraction, из-за использованных в операции вычитаний векторов) - операция умножения вектора на число (выполняется дважды) и формирование нового значения &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;z_{new}&amp;lt;/math&amp;gt; по формуле: &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;z_{new} = z - \alpha_j q_j - \beta_{j-1}q_{j-1} \;&amp;lt;/math&amp;gt;;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;||\cdot||&amp;lt;/math&amp;gt; - операция вычисления нормы вектора;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Division&#039;&#039;&#039; - операция деления вектора на вещественное число  &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;\beta_j&amp;lt;/math&amp;gt; &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Важно отметить, что упомянутые выше операции также легко поддаются оптимизации. Например, попарные умножения вещественных координат векторов при вычислении скалярного произведения также легко выполняются параллельно на &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; потоках, а затем можно применить суммирование методом сдваивания, о котором сказано в следующем разделе. Умножение или деление вектора на вещественное число являющееся, по определению, умножением или делением всех его координат на это число тоже может быть выполнено эффективнее, если мы используем &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; потоков, а не выполняем эти действия последовательно.&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
Параллельные операции возможны только внутри итераций, так как рассматриваемый алгоритм является итерационным, и сами итерации строго последовательны.&amp;lt;br&amp;gt;&lt;br /&gt;
Рассмотрим в этом разделе подробнее, какой выигрыш мы можем получить при распараллеливании операций внутри одной итерации согласно графу из предыдущего раздела.&lt;br /&gt;
&lt;br /&gt;
Умножение вещественной симметричной матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; размера &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;n\times n&amp;lt;/math&amp;gt; на вектор &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;b&amp;lt;/math&amp;gt; длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; требует последовательного выполнения &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; ярусов умножений и сложений. Сложение элементов вектора длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; на каждом шаге перемножения можно оптимизировать и выполнить за &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;\log_2 n&amp;lt;/math&amp;gt; действий, если применять метод сдваивания.&lt;br /&gt;
&lt;br /&gt;
Дальнейшие операции выполняются последовательно, а вычисление значений векторов происходит за один ярус операций сложения или умножения.&lt;br /&gt;
&lt;br /&gt;
Ресурс параллелизма алгоритма вычисления собственных значений построенной трёхдиагональной матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_k&amp;lt;/math&amp;gt; размера &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k\times k&amp;lt;/math&amp;gt; зависит от выбранного алгоритма (об этих алгоритмах подробнее было сказано в разделах 1.2 и 1.4). Будет очень затратно с точки зрения объёма материала пытаться рассмотреть пусть даже часть этих методов в этой статье, а так же тонкости их распараллеливания. Предлагаем читателям при желании самим ознакомиться с этими алгоритмами на данном ресурсе или прибегнув к иным источникам.&lt;br /&gt;
&lt;br /&gt;
При классификации по высоте ЯПФ, таким образом, алгоритм Ланцоша без переортогонализации относится к алгоритмам с &#039;&#039;логарифмической сложностью&#039;&#039;, и его сложность равна &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(\log_2 n)&amp;lt;/math&amp;gt; с важным замечанием, что это сложность только одной итерации, а максимум в алгоритме может быть выполнено последовательно &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;/math&amp;gt; таких однотипных итераций, если не будет осуществлён ранний выход из цикла. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Несмотря на то, что на графе в предыдущем разделе для лучшей визуализации и понимания было изображено &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; потоков (никаких допущений мы не делали и нарушений с точки зрения логики и математики нет, можно изобразить большее число потоков, просто часть времени некоторые из них могут бездействовать и не использоваться), на самом деле правильным и разумным будет реализовать начальное параллельное выполнение &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n^2&amp;lt;/math&amp;gt; операций умножения всех вещественных элементов матрицы &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;A&amp;lt;/math&amp;gt; на соответствующие элементы вектора &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;q_j&amp;lt;/math&amp;gt;, после чего применять тот же самый упомянутый метод сдваивания. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Поэтому при классификации по ширине ЯПФ его сложность будет &#039;&#039;квадратичной&#039;&#039; и равна &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(n^2)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
&#039;&#039;&#039;Входные данные алгоритма:&#039;&#039;&#039; вещественная симметричная &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; размера &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;n\times n&amp;lt;/math&amp;gt;, вещественный вектор &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;b&amp;lt;/math&amp;gt; длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt;, и одно целое число &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;k&amp;lt;/math&amp;gt;, означающее количество итераций.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём входных данных:&#039;&#039;&#039; &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;n^2 +n + 1 &amp;lt;/math&amp;gt;. Если учесть, что матрица симметричная и достаточно для её однозначного определения задать элементы на главной диагонали и элементы над или под ней, то можно сократить объём входных данных с целью экономии памяти до: &amp;lt;math&amp;gt;\ \frac{n^2-n}{2}+n+n+1 =\frac{n^2+3n}{2} + 1&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные алгоритма:&#039;&#039;&#039; вектор собственных значений &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;\Theta^k&amp;lt;/math&amp;gt; длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;/math&amp;gt;, матрица &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;S^k&amp;lt;/math&amp;gt; из соответствующих собственных векторов размера &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n\times k&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём выходных данных:&#039;&#039;&#039; &amp;lt;math&amp;gt;k\;(n + 1)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
В данном разделе перечислены без какой-либо хронологии или связи друг с другом наиболее важные и разнообразные свойства алгоритма, на которые стоит и полезно обратить внимание, а также которые выгодно отличают его от схожих алгоритмов, решающих ту же задачу.&amp;lt;br&amp;gt;&lt;br /&gt;
1) Отношение последовательной сложности алгоритма к параллельной,с учётом &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;/math&amp;gt; итераций, равно &amp;lt;math&amp;gt;\;\;\frac{kn^2}{k \log_2{n}}=\frac{n^2}{\log_2{n}}&amp;lt;/math&amp;gt;;&amp;lt;br&amp;gt;&lt;br /&gt;
2) Вычислительная мощность алгоритма, как отношение числа операций к суммарному объему входных и выходных данных, равна &amp;lt;math style=&amp;quot;vertical-align:-70%&amp;gt;\;\;\frac{k\,n^2}{0.5\,n^2+1.5\,n+k\,n+k+1}&amp;lt;/math&amp;gt; и &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;\approx 2\,k&amp;lt;/math&amp;gt;, так как на практике верно отношение &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;&amp;lt;n&amp;lt;/math&amp;gt; ;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
3) Для собственных значений формируемых матриц &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_j&amp;lt;/math&amp;gt; верно отношение (следствие теоремы Коши о перемежаемости): &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;\lambda_i(T_{k+1})\geq \lambda_i(T_{k})\geq \lambda_{i+1}(T_{k+1})\geq \lambda_{i+1}(T_{k})&amp;lt;/math&amp;gt; ;&amp;lt;ref&amp;gt;James W. Demmel - Вычислительная линейная алгебра. Теория и приложения //Мир. - 2001 (c. 383)&amp;lt;/ref&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
4) Крайние (наибольшие и наименьшие) собственные значения матриц &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_j&amp;lt;/math&amp;gt; сходятся к крайним собственным значениям матрицы &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;A&amp;lt;/math&amp;gt; первыми (это часто происходит уже на ранних шагах при &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j\approx 2\,\sqrt{n}&amp;lt;/math&amp;gt;&amp;lt;ref&amp;gt;http://num-anal.srcc.msu.ru/lib_na/int_ae/int_ae6.htm (пункт 6.5)&amp;lt;/ref&amp;gt;), а собственные значения в середине спектра - последними;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
5) Из-за ограниченной точности постепенно теряется ортогональность вектора Ланцоша &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;q_j&amp;lt;/math&amp;gt; к предыдущим векторам Ланцоша, поэтому необходимо примерно каждые 10-15 итераций проводить дорогостоящую операцию реортогонализации, но это уже будет иной алгоритм с очень малым различием в одной операции и в программном коде, реализующем его, соответственно; &amp;lt;ref&amp;gt;Sam Handler - The Lanczos Algorithm For Large-Scale Eigenvalue Problems (08.01.07), slide №8&amp;lt;/ref&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
6) Эффективность и быстрота выполнения алгоритма очень сильно зависит от скорости памяти (диска). Согласно тесту только &#039;&#039;6%&#039;&#039; времени работы программы приходится на вычисления, остальное время затрачивается на ожидание отклика диска;&amp;lt;ref&amp;gt;Sam Handler - The Lanczos Algorithm For Large-Scale Eigenvalue Problems (08.01.07), slide №10&amp;lt;/ref&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
7) Метод Ланцоша удобен тем, что не требует хранения исходной матрицы полным массивом: метод использует исходную матрицу только в операциях умножения матрицы на вектор, что позволяет эффективно использовать разреженность матрицы или регулярность структуры матрицы. Поэтому метод Ланцоша может быть использован для матриц таких больших порядков, когда методы вращений и отражений не могут быть применены.&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;
По заданию, во второй части требовалось описать только разделы 2.4 и 2.7, прошу не спрашивать с меня все разделы 2.1-2.6. Надеюсь на понимание, мне физически не хватает времени на это задание + 2 других в течение семестра, делаю всё, что в моих силах :)&lt;br /&gt;
&lt;br /&gt;
== Существующие реализации алгоритма ==&lt;br /&gt;
Несмотря на то, что алгоритм является далеко не самым популярным, алгоритмом, про который нельзя сказать, что он всегда «на слуху», на сегодняшний день существует множество реализаций на различных популярных языках.&amp;lt;br&amp;gt;&lt;br /&gt;
Перечислим далее некоторые из них, указывая язык программирования, лежащий в их основе, и некоторые важные характеристики, которые обсуждались в статье ранее:&lt;br /&gt;
*&#039;&#039;Code on netlib.org by Jane Cullum and Ralph Willoughby&#039;&#039; (&#039;&#039;&#039;Fortran 77&#039;&#039;&#039;; без реортогонализации векторов; без реализации распараллеливания)&amp;lt;ref&amp;gt;http://www.netlib.org/lanczos/leval&amp;lt;/ref&amp;gt;&lt;br /&gt;
*&#039;&#039;Lanczos algorithm on freesourcecode.net&#039;&#039; (&#039;&#039;&#039;Matlab&#039;&#039;&#039;; присутствует реортогонализация векторов; без реализации распараллеливания)&amp;lt;ref&amp;gt;http://freesourcecode.net/matlabprojects/61741/lanczos-algorithm--in-matlab&amp;lt;/ref&amp;gt;&lt;br /&gt;
*&#039;&#039;Lanczos for eigenvalues in Numerical Linear Algebra, Spring 2007&#039;&#039; (&#039;&#039;&#039;Matlab&#039;&#039;&#039;; частичная или полная реортогонализация - доступны оба варианта; без реализации распараллеливания)&amp;lt;ref&amp;gt;Ссылки на файлы lanso.m и lanfu.m можно найти на https://www.nada.kth.se/~ruhe/2D5219/labs2007.html&amp;lt;/ref&amp;gt;&lt;br /&gt;
*&#039;&#039;Planso&#039;&#039; (название происходит от parallel Lanso.f) &#039;&#039;code by Kesheng Wu and Horst D. Simon&#039;&#039; (&#039;&#039;&#039;Fortran 77&#039;&#039;&#039;; частичная реортогонализация векторов; использование MPI для коммуникаций)&amp;lt;ref&amp;gt;https://github.com/jiahao/planso.jl/tree/master/external/PLAN/plan К сожалению, ссылка в описании пакета на github, ведущая на сайт National Energy Research Scientific Computing Center (NERSC), с более подробной информацией о данной программе больше не активна и выдаёт результат &#039;&#039;Page not found&#039;&#039;&amp;lt;/ref&amp;gt; &lt;br /&gt;
* &#039;&#039;Lanczos.cpp in the Vienna Computing Library&#039;&#039;  (&#039;&#039;&#039;C++&#039;&#039;&#039;, частичная реортогонализация, без реализации распараллеливания) &amp;lt;ref&amp;gt;http://viennacl.sourceforge.net/doc/lanczos_8cpp_source.html&amp;lt;/ref&amp;gt;&lt;br /&gt;
* &#039;&#039;Parallel Eigen Values code using C++ AMP on microsoft msdn blog&#039;&#039; (&#039;&#039;&#039;C++&#039;&#039;&#039;; ? ; распараллеливание есть и реализовано через C++ AMP) &amp;lt;ref&amp;gt;https://blogs.msdn.microsoft.com/nativeconcurrency/2013/12/20/eigen-values/ Подробнее о C++ Accelerated Massive Parallelism можно почитать здесь: https://msdn.microsoft.com/ru-ru/library/hh265137(v=vs.140).aspx или здесь: http://professorweb.ru/my/csharp/optimization/level4/4_6.php &amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;br /&gt;
[[en:Description of algorithm properties and structure]]&lt;/div&gt;</summary>
		<author><name>AleksLevin</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:AleksLevin/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%9B%D0%B0%D0%BD%D1%86%D0%BE%D1%88%D0%B0_%D0%B2%D1%8B%D1%87%D0%B8%D1%81%D0%BB%D0%B5%D0%BD%D0%B8%D1%8F_%D1%81%D0%BE%D0%B1%D1%81%D1%82%D0%B2%D0%B5%D0%BD%D0%BD%D1%8B%D1%85_%D0%B7%D0%BD%D0%B0%D1%87%D0%B5%D0%BD%D0%B8%D0%B9_%D1%81%D0%B8%D0%BC%D0%BC%D0%B5%D1%82%D1%80%D0%B8%D1%87%D0%BD%D0%BE%D0%B9_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86%D1%8B_%D0%B4%D0%BB%D1%8F_%D1%82%D0%BE%D1%87%D0%BD%D0%BE%D0%B9_%D0%B0%D1%80%D0%B8%D1%84%D0%BC%D0%B5%D1%82%D0%B8%D0%BA%D0%B8_(%D0%B1%D0%B5%D0%B7_%D0%BF%D0%B5%D1%80%D0%B5%D0%BE%D1%80%D1%82%D0%BE%D0%B3%D0%BE%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D0%B8)&amp;diff=19938</id>
		<title>Участник:AleksLevin/Алгоритм Ланцоша вычисления собственных значений симметричной матрицы для точной арифметики (без переортогонализации)</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:AleksLevin/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%9B%D0%B0%D0%BD%D1%86%D0%BE%D1%88%D0%B0_%D0%B2%D1%8B%D1%87%D0%B8%D1%81%D0%BB%D0%B5%D0%BD%D0%B8%D1%8F_%D1%81%D0%BE%D0%B1%D1%81%D1%82%D0%B2%D0%B5%D0%BD%D0%BD%D1%8B%D1%85_%D0%B7%D0%BD%D0%B0%D1%87%D0%B5%D0%BD%D0%B8%D0%B9_%D1%81%D0%B8%D0%BC%D0%BC%D0%B5%D1%82%D1%80%D0%B8%D1%87%D0%BD%D0%BE%D0%B9_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86%D1%8B_%D0%B4%D0%BB%D1%8F_%D1%82%D0%BE%D1%87%D0%BD%D0%BE%D0%B9_%D0%B0%D1%80%D0%B8%D1%84%D0%BC%D0%B5%D1%82%D0%B8%D0%BA%D0%B8_(%D0%B1%D0%B5%D0%B7_%D0%BF%D0%B5%D1%80%D0%B5%D0%BE%D1%80%D1%82%D0%BE%D0%B3%D0%BE%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D0%B8)&amp;diff=19938"/>
		<updated>2016-12-02T18:49:24Z</updated>

		<summary type="html">&lt;p&gt;AleksLevin: /* Макроструктура алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Основные авторы описания: Левин А.Д.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{algorithm&lt;br /&gt;
| name              = Алгоритм Ланцоша для точной арифметики (без переортогонализации)&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(k\,n^2)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(k\log_2 n)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;\frac{n^2+3n}{2} + 1&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;k\;(n + 1)&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритмов =&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Данный алгоритм появился в 1950 г. и носит имя венгерского физика и математика Корнелия Ланцоша (венг. Lánczos Kornél). Алгоритм Ланцоша относится к итерационным методам вычисления собственных значений для матриц столь больших порядков &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt; n&amp;lt;/math&amp;gt;, что к ним нельзя применить прямые методы из-за ограничений по времени и памяти.&lt;br /&gt;
&lt;br /&gt;
Сам Ланцош указывал, что его метод предназначен для отыскания нескольких собственных векторов симметричных матриц, хотя к методу сразу было обращено внимание, как к способу приведения всей матрицы к трёхдиагональному виду. Двадцатью годами позже канадский математик Крис Пэж показал, что, несмотря на чувствительность к округлениям, алгоритм Ланцоша - эффективное средство вычисления некоторых &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; собственных чисел и соответствующих им собственных векторов. &amp;lt;ref&amp;gt;Парлетт Б. - Симметричная проблема собственных значений. Численные методы //М.: Мир. - 1983. (c. 276)&amp;lt;/ref&amp;gt;&lt;br /&gt;
Обычно число &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; берут в два раза больше, чем количество собственных значений матрицы, которые поставлена цель найти, и оно имеет порядок не более &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;10^2&amp;lt;/math&amp;gt;.&amp;lt;ref&amp;gt;Susan W. Bostic - Lanczos Eigensolution Method for High-Perfomance Computers, page 7&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Алгоритм Ланцоша для вычисления собственных значений симметричной матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; соединяет в себе метод Ланцоша для построения последовательности подпространств Крылова и ортонормированных векторов Ланцоша и процедуру Рэлея-Ритца получения оптимальных приближений собственных значений и соответствующих собственных векторов исходной матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt;.&amp;lt;ref&amp;gt;James W. Demmel - Вычислительная линейная алгебра. Теория и приложения //Мир. - 2001 (c. 381)&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
В данной статье рассматривается вариант алгоритма Ланцоша, в котором опущено влияние ошибок округления на вычислительный процесс, хотя на практике этому посвящается отдельное внимание и существуют различные методы решения данной проблемы, такие как частичная или полная переортогонализация. Этим модифицированным методам посвящены отдельные статьи на данном ресурсе.&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
Обозначения и формулы, используемые в данном разделе, взяты из литературы, указанной по ссылке.&amp;lt;ref&amp;gt;James W. Demmel - Вычислительная линейная алгебра. Теория и приложения //Мир. - 2001 (c. 313, &#039;&#039;&amp;lt;math&amp;gt; \S &amp;lt;/math&amp;gt; 6.6 Методы Крыловского подпространства&#039;&#039;)&amp;lt;/ref&amp;gt; &lt;br /&gt;
&lt;br /&gt;
Алгоритм Ланцоша для вычисления &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; собственных значений и собственных векторов вещественной симметричной матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A=A^T&amp;lt;/math&amp;gt; в точной арифметике: &amp;lt;ref&amp;gt;James W. Demmel - Вычислительная линейная алгебра. Теория и приложения //Мир. - 2001 (c. 381)&amp;lt;/ref&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{align}&lt;br /&gt;
q_1 = &amp;amp; \,\frac{b}{\|b\|_2},\; \beta_0 = 0,\; q_0 = 0\\&lt;br /&gt;
\mathbf{for} \; &amp;amp; j = 1 \; to \; k \,\; \mathbf{do} \\&lt;br /&gt;
&amp;amp; z = A\,q_j\\&lt;br /&gt;
&amp;amp; \alpha_j = q^T_j z\\&lt;br /&gt;
&amp;amp; z = z - \alpha_j q_j - \beta_{j-1}q_{j-1}\\&lt;br /&gt;
&amp;amp; \beta_j = \|z\|_2\\&lt;br /&gt;
&amp;amp; \mathbf{If} \; (\beta_j == 0) \; \mathbf{then}\; stop\; the\; algorithm \\ &lt;br /&gt;
&amp;amp; \;  q_{j+1} = \frac{z}{\beta_j} \\&lt;br /&gt;
&amp;amp; compute\; eigenvalues\; and \;eigenvectors\;of \;matrix \;\;T_j= Q^T_j A Q\;\;and\;estimate \;the\; errors\\&lt;br /&gt;
\mathbf{end} \; &amp;amp; \mathbf{for}&lt;br /&gt;
\end{align}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
В продемонстрированном выше алгоритме &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;b&amp;lt;/math&amp;gt; - заданный вещественный вектор. Также полагается известным алгоритм вычисления произведения матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; на вектор &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;x&amp;lt;/math&amp;gt;. &lt;br /&gt;
Введём матрицу Крылова, определяемую следующим соотношением: &amp;lt;math&amp;gt;K_j = [b,Ab,A^2b,...,A^{j-1}b]&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Далее, на практике, матрица &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;K&amp;lt;/math&amp;gt; заменяется матрицей &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;Q&amp;lt;/math&amp;gt;, такой, что при любом числе &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; линейные оболочки первых &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;k&amp;lt;/math&amp;gt; столбцов в &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;K&amp;lt;/math&amp;gt; и &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;Q&amp;lt;/math&amp;gt; являются одним и тем же подпространством.&amp;lt;ref&amp;gt;James W. Demmel - Вычислительная линейная алгебра. Теория и приложения //Мир. - 2001 (c. 315)&amp;lt;/ref&amp;gt; &lt;br /&gt;
Тогда матрица &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;Q&amp;lt;/math&amp;gt;, в отличие от матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;K&amp;lt;/math&amp;gt;, хорошо обусловлена и легко обратима. В результате получаем матрицу &amp;lt;math&amp;gt;Q_j = [q_1, q_2, \dots, q_j]&amp;lt;/math&amp;gt; размерности &amp;lt;math&amp;gt;n\times j&amp;lt;/math&amp;gt;, столбцы которой ортогональны, являются базисом подпространства Крылова и называются векторами Ланцоша.&lt;br /&gt;
&lt;br /&gt;
В алгоритме Ланцоша вычислению подлежит столько первых столбцов в матрице &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;Q_j&amp;lt;/math&amp;gt;, сколько необходимо для получения требуемого приближения к решению &amp;lt;math&amp;gt;A\,x\,=b\,\,(A\,x=\lambda \, x)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Получение нулевого &amp;lt;math&amp;gt;\beta_j&amp;lt;/math&amp;gt; в итерационном процессе - событие, желательное в том смысле, что оно свидетельствует о том, что найдено некоторое подпространство, являющееся в точности инвариантным, а все собственные значения матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;T_j&amp;lt;/math&amp;gt; являются собственными значениями матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt;. На практике же нулевое и близкие к нулю значения получаются редко.&amp;lt;ref&amp;gt;Голуб Дж., Ван Лоун Ч. - Матричные вычисления//М.: Мир. - 1999 (c. 429)&amp;lt;/ref&amp;gt; &lt;br /&gt;
&lt;br /&gt;
Затем на каждом шаге цикла формируется симметричная трёхдиагональная матрица &amp;lt;math&amp;gt;T_j = Q^T_j A Q&amp;lt;/math&amp;gt;, к которой применяется процесс Рэлея-Ритца для поиска её собственных значений (на практике для поиска этих собственных значений можно использовать любой из специальных методов в параграфе книги по ссылке).&amp;lt;ref&amp;gt;Голуб Дж., Ван Лоун Ч. - Матричные вычисления//М.: Мир. - 1999 (&amp;lt;math&amp;gt;\S&amp;lt;/math&amp;gt; 8.4)&amp;lt;/ref&amp;gt;  &lt;br /&gt;
Эти собственные значения, они же числа Ритца, и полагаются приближёнными собственными значениями исходной матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt;.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Существует множество методов для отыскания собственных значений вещественной симметричной трехдиагональной матрицы. Большинство из них требует &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt; операций &amp;lt;ref&amp;gt;Парлетт Б. Симметричная проблема собственных значений. Численные методы.,: Мир, 1983. с. 179-182&amp;lt;/ref&amp;gt;, но существуют и быстрые алгоритмы, требующие лишь &amp;lt;math&amp;gt;O(n\ln n)&amp;lt;/math&amp;gt; операций.&amp;lt;ref&amp;gt;https://en.wikipedia.org/wiki/Tridiagonal_matrix#Eigenvalues  Раздел eigenvalues&amp;lt;/ref&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Одним из возможных способов отыскать собственные значения симметричной трехдиагональной матрицы - прямое вычисление корней характеристического полинома &amp;lt;math&amp;gt;p_n(\lambda)&amp;lt;/math&amp;gt; через метод деления пополам, где формируется последовательность Штурма и локализуются собственные числа, являющиеся корнями характеристического полинома. Нахождение всех &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; собственных значений матрицы этим способом требует &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;2n^2t&amp;lt;/math&amp;gt; умножений и вычитаний, где &amp;lt;math&amp;gt;t&amp;lt;/math&amp;gt; - число сделанных шагов с применением метода деления пополам.&amp;lt;ref&amp;gt;Уилкинсон Дж. X. Алгебраическая проблема собственныx значений. Изд-во &amp;quot;Наука&amp;quot;, 1970. - глава 5, с. 272-278&amp;lt;/ref&amp;gt; Соответствующие собственные вектора могут быть найдены посредством обратных итераций за &amp;lt;math&amp;gt; O(n) &amp;lt;/math&amp;gt; флопов. &amp;lt;ref&amp;gt;Голуб Дж., Ван Лоун Ч. - Матричные вычисления//М.: Мир. - 1999 (c. 394-395)&amp;lt;/ref&amp;gt; &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;На практике, если требуется только небольшая часть от всей совокупности собственных векторов и значений, и матрица имеет Хессенбергову или трёхдиагональную форму, очень эффективными будут методы факторизации, как, например, QR-алгоритм или QL-алгоритм со сдвигами (c целью ускорить алгоритм и сделать порядок сходимости квадратичным) или же без них.&amp;lt;ref&amp;gt;http://algorithm.narod.ru/ln/eigen/ETridiag.html&amp;lt;/ref&amp;gt; &amp;lt;br&amp;gt;&lt;br /&gt;
Весьма молодые и не менее актуальные конкуренты QR и QL алгоритмов:&lt;br /&gt;
*Методы divide-and-conquer (разделяй и властвуй), появившиеся в 1980-ых годах &amp;lt;ref&amp;gt;https://algowiki-project.org/ru/Метод_&amp;quot;Разделяй_и_властвуй&amp;quot;_Завольсков/Землянский&amp;lt;/ref&amp;gt;&lt;br /&gt;
*Relatively robust representation methods, появившиеся в 1990-ых и позволяющие найти собственные числа симметричной матрицы порядка &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;n&amp;lt;/math&amp;gt; за &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt; операций&lt;br /&gt;
&lt;br /&gt;
Если требуется вычислить собственные векторы, то необходимо хранить вычисляемые векторы Ланцоша. Если работа при этом производится только с оперативной памятью, то при большом порядке исходной матрицы (а именно для таких матриц и предназначен метод Ланцоша) число шагов  &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;j&amp;lt;/math&amp;gt;, которые могут быть выполнены до того момента, как оперативная память будет исчерпана, будет очень незначительно, а следовательно, искомые собственные пары могут не успеть сойтись с требуемой точностью. В этом случае метод Ланцоша можно использовать итерационным образом: после выполнения заданного числа шагов процесс прерывается и, если еще не все требуемые пары Ритца сошлись с требуемой точностью, то формируется новый начальный вектор &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;q_1&amp;lt;/math&amp;gt;, являющийся линейной комбинацией векторов Ритца, еще не сошедшихся с заданной точностью, и процесс начинается заново.&amp;lt;ref&amp;gt;http://num-anal.srcc.msu.ru/lib_na/int_ae/int_ae6.htm (пункт 6.5)&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
Вычислительное ядро рассматриваемого алгоритма (наиболее ресурсно-затратная часть алгоритма) -  формирование на каждом шаге цикла промежуточного вектора &amp;lt;math&amp;gt;z&amp;lt;/math&amp;gt;, вычисляемого по формуле: &amp;lt;math&amp;gt;z = A\,q_j&amp;lt;/math&amp;gt;. Данная операция, по сравнению с другими операциями алгоритма, затратна и требовательна, как с точки зрения количества производимых операций, так и с точки зрения объема оперируемых данных. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Например, умножение матрицы размера &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;n\times n&amp;lt;/math&amp;gt; на вектор длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; требует: &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;n^2+(n-1)n = 2n^2-n&amp;lt;/math&amp;gt; операций умножения и сложения. В свою очередь аналогичная операция умножения матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;(n+1)\times (n+1)&amp;lt;/math&amp;gt; на вектор длины &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;(n+1)&amp;lt;/math&amp;gt; требует: &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;2n^2+3n+1&amp;lt;/math&amp;gt;  операций умножения и сложения. То есть повышение размерности задачи всего на 1 увеличивает число необходимых действий в этом шаге алгоритма на: &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;4n+1&amp;lt;/math&amp;gt;. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Так же, стоит помнить, что, согласно разделу 1.2, данную операцию умножения матрицы на вектор необходимо выполнить &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;k&amp;lt;/math&amp;gt; раз. Нетрудно понять, насколько возрастает и колоссален масштаб операций, если в задачах, где критична точность, размерности &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; могут иметь порядок &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;10^5&amp;lt;/math&amp;gt; или даже более.&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
Как уже было упомянуто в данной статье в описании алгоритма, рассматриваемый алгоритм состоит из двух последовательно выполненных алгоритмов: метод Ланцоша для построения последовательности подпространств Крылова и ортонормированных векторов Ланцоша и процедура Рэлея-Ритца получения оптимальных приближений собственных значений и соответствующих собственных векторов исходной матрицы.&lt;br /&gt;
&lt;br /&gt;
В первой части алгоритма, где итерационно строятся Крыловское подпространство и трёхдиагональная матрица &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&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 style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; разреженная. Именно она подлежит оптимизации с использованием техник распараллеливания, поскольку она является вычислительным ядром алгоритма, а весь упомянутый процесс построения матрицы &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&amp;lt;/math&amp;gt; выполняется последовательно.&lt;br /&gt;
&lt;br /&gt;
Рассмотрим вторую часть алгоритма - поиск собственных значений сформированной матрицы &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&amp;lt;/math&amp;gt;.&amp;lt;br&amp;gt;&lt;br /&gt;
Далее, наглядно, в виде псевдокода, представлен, упомянутый в разделе 1.2, QR-алгоритм (аналогично в качестве примера можно взять и QL-алгоритм) со сдвигами Релэя, который весьма популярен на практике.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{align}&lt;br /&gt;
\mathbf{Input}: \;&amp;amp;tridiagonal\;\;matrix \;T\;with\;\;n\times n\;\;size\\&lt;br /&gt;
T^{(0)}&amp;amp;:=T\\&lt;br /&gt;
\mathbf{for}&amp;amp; \;\;m=n,...,2 \;\; \mathbf{do}\\&lt;br /&gt;
&amp;amp;k=0\\&lt;br /&gt;
&amp;amp; \mathbf{repeat}\\&lt;br /&gt;
&amp;amp; \quad \;\; k=k+1\\&lt;br /&gt;
&amp;amp; \quad \;\; \mu^{(k)}=T_{m,m}^{(k-1)}\\&lt;br /&gt;
&amp;amp; \quad \;\; Q^{(k)}R^{(k)}=T^{(k-1)}-\mu^{(k)}I\;\;using\;\;QR\;decomposition\\&lt;br /&gt;
&amp;amp; \quad \;\; T^{(k)}=R^{(k)}Q^{(k)}+\mu^{(k)}I\\&lt;br /&gt;
&amp;amp; \mathbf{until} \;\;\; |T_{m,m-1}^{(k)}| \;is\;\;small\;\;enough\\&lt;br /&gt;
&amp;amp; Save  \;\;T_{m,m}^{(k)} \;\;as\;\; converged\;\;eigenvalue\;of\;T\\ &lt;br /&gt;
&amp;amp; Remove \;\boldsymbol{n}\,th\;row\;and\;\boldsymbol{n}\,th\;column\;\;from \;T \\&lt;br /&gt;
&amp;amp; and\;take\;this\;new\;cropped\;matrix\;as\;new\;T^{(0)}\;with\;\;(n-1)\times (n-1)\;\;size\\&lt;br /&gt;
 \mathbf{end}&amp;amp;\; \mathbf{for}&lt;br /&gt;
\end{align}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Малость наддиагональных и поддиагональных элементов матрицы (фраза &#039;&#039;&amp;quot;small enough&amp;quot;&#039;&#039; в псевдокоде) подразумевает:&lt;br /&gt;
&amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt; |T_{m,m-1}^{(k)}| \leq \varepsilon\,|T_{m,m}^{(k)}| \quad\quad &amp;lt;/math&amp;gt; , где &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt; \varepsilon &amp;lt;/math&amp;gt; - заданная точность&amp;lt;br&amp;gt;&lt;br /&gt;
Также вместо сдвига Релэя, обозначенного в алгоритме через &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;\mu^{(k)}&amp;lt;/math&amp;gt; часто на практике используется сдвиг по Уилкинсону, который даёт гарантированную сходимость внедиагональных элементов матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt; T^{(k)} &amp;lt;/math&amp;gt;, формируемой на каждом шаге, к нулю, при этом жертвуя монотонностью их убывания.&amp;lt;ref&amp;gt;Голуб Дж., Ван Лоун Ч. - Матричные вычисления//М.: Мир. - 1999 (c. 378)&amp;lt;/ref&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Подробнее с различными сдвигами и соответствующими оценками скоростей и количествами операций можно ознакомиться по указанной ссылке:&amp;lt;ref&amp;gt;Парлетт Б. Симметричная проблема собственных значений. Численные методы.,: Мир, 1983. с. 179-182&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;Для совершения QR-декомпозиции на каждом шаге может использоваться любой из алгоритмов по ссылке.&amp;lt;ref&amp;gt;https://en.wikipedia.org/wiki/QR_decomposition&amp;lt;/ref&amp;gt; Подробные описания к этим алгоритмам также доступны на данном ресурсе algowiki.&amp;lt;br&amp;gt;&lt;br /&gt;
Но так как мы оперируем не с обычной матрицей и даже не с Хессенберговой, а с симметричной и трёхдиагональной, то скорость таких алгоритмов значительно возрастёт. Например, согласно данному ресурсу &amp;lt;ref&amp;gt;http://algorithm.narod.ru/ln/eigen/ETridiag.html&amp;lt;/ref&amp;gt;, для QL-алгоритма с неявными сдвигами:&lt;br /&gt;
Для трехдиагональной матрицы объем арифметических действий составляет &amp;lt;math&amp;gt; O(n)&amp;lt;/math&amp;gt; на итерацию вместо &amp;lt;math&amp;gt; O(n^3)&amp;lt;/math&amp;gt; для матрицы общего вида, а число итераций для нахождения первых собственных значений примерно равно 4 - 5. Но на этих итерациях также уменьшаются внедиагональные элементы правого нижнего угла. И, таким образом, дальнейшие собственные значения ищутся значительно быстрее. Среднее число итераций на каждое собственное значение обычно составляет 1.3 - 1.6. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Итого во второй части алгоритма Ланцоша можно выделить следующие макрооперации:&lt;br /&gt;
* умножение матрицы на вещественное число;&lt;br /&gt;
* перемножение матриц;&lt;br /&gt;
* умножение и сравнение вещественных чисел;&lt;br /&gt;
* + набор других макроопераций в зависимости от выбора метода, с помощью которого будет совершаться сама QR или QL-декомпозиция (по указанной ссылке продемонстрированы, уже, как минимум, 3 разных способа).&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
С целью полностью не дублировать раздел 1.2 данной статьи, где представлен наглядный и доступный для понимания псевдокод алгоритма, постараемся лишь коротко просуммировать и обобщить весь перечень последовательных действий в рассматриваемом алгоритме.&lt;br /&gt;
&lt;br /&gt;
В качестве входных данных имеем: вещественная симметричная матрица &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; размера &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;n\times n&amp;lt;/math&amp;gt;, известный вещественный вектор &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;b&amp;lt;/math&amp;gt; длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; и число &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;n&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Далее:&lt;br /&gt;
* Инициализируем вещественную константу &amp;lt;math style=&amp;quot;vertical-align:-20%;&amp;gt;\beta_0&amp;lt;/math&amp;gt; и векторы &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;q_0&amp;lt;/math&amp;gt; и &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;q_1&amp;lt;/math&amp;gt;&lt;br /&gt;
* Итерационно для всех &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j=1,...,k&amp;lt;/math&amp;gt;:&lt;br /&gt;
** Вычисляем вспомогательный вектор &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt;, используя умножение матрицы на вектор&lt;br /&gt;
** Вычисляем, используя скалярное произведение векторов, значение &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;\alpha_j&amp;lt;/math&amp;gt; - элемент на главной диагонали трёхдиагональной матрицы &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&amp;lt;/math&amp;gt;&lt;br /&gt;
** Вычисляем по формуле новое значение и перезаписываем вектор &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt;&lt;br /&gt;
** Вычисляем значение &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;\beta_j&amp;lt;/math&amp;gt; - элементы непосредственно над и под главной диагональю той же матрицы &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&amp;lt;/math&amp;gt;&lt;br /&gt;
** Вычисляем, зная вектор &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt;,  очередной столбец матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;Q&amp;lt;/math&amp;gt;, он же вектор Ланцоша : &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;\,\,q_{j+1}&amp;lt;/math&amp;gt;&lt;br /&gt;
** Теперь, когда матрица &amp;lt;math style=&amp;quot;vertical-align:-30%;&amp;gt;T_j&amp;lt;/math&amp;gt; сформирована на очередном шаге, находим её собственные значения и вектора любым доступным способом, о чём было подробно сказано в пункте 1.2&lt;br /&gt;
** Переходим на следующую итерацию: &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j&amp;lt;/math&amp;gt;++&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
Оценим количество операций и сложность последовательного алгоритма, изложенного в предыдущем разделе.&lt;br /&gt;
*Для вычисления вектора &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt; умножается матрица размера &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;n\times n&amp;lt;/math&amp;gt; на вектор длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt;, и потребуется &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n^2&amp;lt;/math&amp;gt; операций умножения и &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n^2&amp;lt;/math&amp;gt; операций сложения.&lt;br /&gt;
*Умножение векторов &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;q^T_j&amp;lt;/math&amp;gt; и &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt; длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; потребует &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; операций умножения и &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; операций сложения.&lt;br /&gt;
*При вычислении нового значения вектора &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt; поэлементное сложение двух векторов длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; требует &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; операций сложения.&lt;br /&gt;
*Умножение вектора длины &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; на вещественное число требует &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; операций умножения.&lt;br /&gt;
*Нахождение квадратичной нормы вектора &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;z&amp;lt;/math&amp;gt;  длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; требует &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; умножений и &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; сложений и ещё 1 операцию извлечения квадратного корня.&lt;br /&gt;
*Заключительное нахождение собственных значений и собственных векторов трёхдиагональной матрицы &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;T_j&amp;lt;/math&amp;gt; размера &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j\times j&amp;lt;/math&amp;gt; с помощью QR-алгоритма потребует в худшем случае &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(j^3)&amp;lt;/math&amp;gt; операций.&amp;lt;ref&amp;gt;http://num-anal.srcc.msu.ru/lib_na/int_ae/int_ae6.htm (пункт 6.2, &amp;quot;Скорость сходимости при этом всегда не хуже квадратичной и почти всегда лучше кубической.&amp;quot;)&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Посчитаем теперь суммарное количество простейших операций на одной итерации алгоритма (без учёта записей в память):&lt;br /&gt;
*&amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n^2+5\,n&amp;lt;/math&amp;gt; операций умножения/деления&lt;br /&gt;
*&amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n^2+4\,n&amp;lt;/math&amp;gt; операций сложения/вычитания&lt;br /&gt;
*1 операция извлечения квадратного корня&amp;lt;br&amp;gt;&lt;br /&gt;
Отдельно после всех итераций при &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j=k&amp;lt;/math&amp;gt; :&lt;br /&gt;
*&amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(k^3)&amp;lt;/math&amp;gt; операций для поиска собственных значений и собственных векторов трёхдиагональной матрицы &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;T_k&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Итого можно утверждать следующее:&lt;br /&gt;
&lt;br /&gt;
Последовательная сложность одной итерации рассматриваемого алгоритма:  &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(n ^ 2) &amp;lt;/math&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Суммарная сложность алгоритма (&amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;/math&amp;gt; итераций): &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(k\,n ^ 2) + O(k ^ 3)&amp;lt;/math&amp;gt; &amp;lt;ref&amp;gt;Здесь мы полагаем, что мы не вычисляем собственные значения и векторы матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_j&amp;lt;/math&amp;gt; на каждом промежуточном шаге, а лишь единожды затрачиваем &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;O(k ^ 3)&amp;lt;/math&amp;gt; действий в конце для нахождения &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;/math&amp;gt; собственных значений и векторов матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_k&amp;lt;/math&amp;gt;&amp;lt;/ref&amp;gt; &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
На практике же обычно рассматривается число &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;&amp;lt;n&amp;lt;/math&amp;gt;, поэтому второе слагаемое можно опустить.&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
На рис. 1 продемонстрирован граф одной итерации (при каком-либо произвольном значении итератора &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j&amp;lt;/math&amp;gt;) описанного алгоритма без отображения входных и выходных данных. Наглядно продемонстрированы связи между всеми действиями, и с помощью деления на &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; потоков показано, какие операции возможно выполнять параллельно на каждом шаге с целью оптимизации и экономии машинного времени. В результате, после параллельно выполненных операций &#039;&#039;&#039;Division&#039;&#039;&#039; на заключительном ярусе, на выходе имеем значение следующего вектора Ланцоша &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;q_{j+1}&amp;lt;/math&amp;gt;, после чего следует переход на следующую итерацию, и процесс повторяется.&lt;br /&gt;
&lt;br /&gt;
[[Файл:Levin_graph.png|600px|thumb|center|Рис. 1]] &amp;lt;br&amp;gt;&lt;br /&gt;
Обозначения на рисунке: &amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Simp&#039;&#039;&#039; (от англ. simple) - операции сложения и умножения вещественных чисел при вычислении произведения матрицы на вектор;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Vec mult&#039;&#039;&#039; (от англ. vectors multiplication) - операция скалярного умножения двух векторов;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Vec subtr&#039;&#039;&#039; (от англ. vectors subtraction, из-за использованных в операции вычитаний векторов) - операция умножения вектора на число (выполняется дважды) и формирование нового значения &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;z_{new}&amp;lt;/math&amp;gt; по формуле: &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;z_{new} = z - \alpha_j q_j - \beta_{j-1}q_{j-1} \;&amp;lt;/math&amp;gt;;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;||\cdot||&amp;lt;/math&amp;gt; - операция вычисления нормы вектора;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Division&#039;&#039;&#039; - операция деления вектора на вещественное число  &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;\beta_j&amp;lt;/math&amp;gt; &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Важно отметить, что упомянутые выше операции также легко поддаются оптимизации. Например, попарные умножения вещественных координат векторов при вычислении скалярного произведения также легко выполняются параллельно на &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; потоках, а затем можно применить суммирование методом сдваивания, о котором сказано в следующем разделе. Умножение или деление вектора на вещественное число являющееся, по определению, умножением или делением всех его координат на это число тоже может быть выполнено эффективнее, если мы используем &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; потоков, а не выполняем эти действия последовательно.&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
Параллельные операции возможны только внутри итераций, так как рассматриваемый алгоритм является итерационным, и сами итерации строго последовательны.&amp;lt;br&amp;gt;&lt;br /&gt;
Рассмотрим в этом разделе подробнее, какой выигрыш мы можем получить при распараллеливании операций внутри одной итерации согласно графу из предыдущего раздела.&lt;br /&gt;
&lt;br /&gt;
Умножение вещественной симметричной матрицы &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; размера &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;n\times n&amp;lt;/math&amp;gt; на вектор &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;b&amp;lt;/math&amp;gt; длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; требует последовательного выполнения &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; ярусов умножений и сложений. Сложение элементов вектора длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; на каждом шаге перемножения можно оптимизировать и выполнить за &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;\log_2 n&amp;lt;/math&amp;gt; действий, если применять метод сдваивания.&lt;br /&gt;
&lt;br /&gt;
Дальнейшие операции выполняются последовательно, а вычисление значений векторов происходит за один ярус операций сложения или умножения.&lt;br /&gt;
&lt;br /&gt;
Ресурс параллелизма алгоритма вычисления собственных значений построенной трёхдиагональной матрицы &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_k&amp;lt;/math&amp;gt; размера &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k\times k&amp;lt;/math&amp;gt; зависит от выбранного алгоритма (об этих алгоритмах подробнее было сказано в разделах 1.2 и 1.4). Будет очень затратно с точки зрения объёма материала пытаться рассмотреть пусть даже часть этих методов в этой статье, а так же тонкости их распараллеливания. Предлагаем читателям при желании самим ознакомиться с этими алгоритмами на данном ресурсе или прибегнув к иным источникам.&lt;br /&gt;
&lt;br /&gt;
При классификации по высоте ЯПФ, таким образом, алгоритм Ланцоша без переортогонализации относится к алгоритмам с &#039;&#039;логарифмической сложностью&#039;&#039;, и его сложность равна &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(\log_2 n)&amp;lt;/math&amp;gt; с важным замечанием, что это сложность только одной итерации, а максимум в алгоритме может быть выполнено последовательно &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;/math&amp;gt; таких однотипных итераций, если не будет осуществлён ранний выход из цикла. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Несмотря на то, что на графе в предыдущем разделе для лучшей визуализации и понимания было изображено &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt; потоков (никаких допущений мы не делали и нарушений с точки зрения логики и математики нет, можно изобразить большее число потоков, просто часть времени некоторые из них могут бездействовать и не использоваться), на самом деле правильным и разумным будет реализовать начальное параллельное выполнение &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n^2&amp;lt;/math&amp;gt; операций умножения всех вещественных элементов матрицы &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;A&amp;lt;/math&amp;gt; на соответствующие элементы вектора &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;q_j&amp;lt;/math&amp;gt;, после чего применять тот же самый упомянутый метод сдваивания. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Поэтому при классификации по ширине ЯПФ его сложность будет &#039;&#039;квадратичной&#039;&#039; и равна &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;O(n^2)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
&#039;&#039;&#039;Входные данные алгоритма:&#039;&#039;&#039; вещественная симметричная &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;A&amp;lt;/math&amp;gt; размера &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;n\times n&amp;lt;/math&amp;gt;, вещественный вектор &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;b&amp;lt;/math&amp;gt; длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n&amp;lt;/math&amp;gt;, и одно целое число &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;k&amp;lt;/math&amp;gt;, означающее количество итераций.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём входных данных:&#039;&#039;&#039; &amp;lt;math style=&amp;quot;vertical-align:-10%;&amp;gt;n^2 +n + 1 &amp;lt;/math&amp;gt;. Если учесть, что матрица симметричная и достаточно для её однозначного определения задать элементы на главной диагонали и элементы над или под ней, то можно сократить объём входных данных с целью экономии памяти до: &amp;lt;math&amp;gt;\ \frac{n^2-n}{2}+n+n+1 =\frac{n^2+3n}{2} + 1&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные алгоритма:&#039;&#039;&#039; вектор собственных значений &amp;lt;math style=&amp;quot;vertical-align:0%;&amp;gt;\Theta^k&amp;lt;/math&amp;gt; длины &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;/math&amp;gt;, матрица &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;S^k&amp;lt;/math&amp;gt; из соответствующих собственных векторов размера &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;n\times k&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём выходных данных:&#039;&#039;&#039; &amp;lt;math&amp;gt;k\;(n + 1)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
В данном разделе перечислены без какой-либо хронологии или связи друг с другом наиболее важные и разнообразные свойства алгоритма, на которые стоит и полезно обратить внимание, а также которые выгодно отличают его от схожих алгоритмов, решающих ту же задачу.&amp;lt;br&amp;gt;&lt;br /&gt;
1) Отношение последовательной сложности алгоритма к параллельной,с учётом &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;/math&amp;gt; итераций, равно &amp;lt;math&amp;gt;\;\;\frac{kn^2}{k \log_2{n}}=\frac{n^2}{\log_2{n}}&amp;lt;/math&amp;gt;;&amp;lt;br&amp;gt;&lt;br /&gt;
2) Вычислительная мощность алгоритма, как отношение числа операций к суммарному объему входных и выходных данных, равна &amp;lt;math style=&amp;quot;vertical-align:-70%&amp;gt;\;\;\frac{k\,n^2}{0.5\,n^2+1.5\,n+k\,n+k+1}&amp;lt;/math&amp;gt; и &amp;lt;math style=&amp;quot;vertical-align:-10%&amp;gt;\approx 2\,k&amp;lt;/math&amp;gt;, так как на практике верно отношение &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;k&amp;lt;&amp;lt;n&amp;lt;/math&amp;gt; ;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
3) Для собственных значений формируемых матриц &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_j&amp;lt;/math&amp;gt; верно отношение (следствие теоремы Коши о перемежаемости): &amp;lt;math style=&amp;quot;vertical-align:-30%&amp;gt;\lambda_i(T_{k+1})\geq \lambda_i(T_{k})\geq \lambda_{i+1}(T_{k+1})\geq \lambda_{i+1}(T_{k})&amp;lt;/math&amp;gt; ;&amp;lt;ref&amp;gt;James W. Demmel - Вычислительная линейная алгебра. Теория и приложения //Мир. - 2001 (c. 383)&amp;lt;/ref&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
4) Крайние (наибольшие и наименьшие) собственные значения матриц &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;T_j&amp;lt;/math&amp;gt; сходятся к крайним собственным значениям матрицы &amp;lt;math style=&amp;quot;vertical-align:0%&amp;gt;A&amp;lt;/math&amp;gt; первыми (это часто происходит уже на ранних шагах при &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;j\approx 2\,\sqrt{n}&amp;lt;/math&amp;gt;&amp;lt;ref&amp;gt;http://num-anal.srcc.msu.ru/lib_na/int_ae/int_ae6.htm (пункт 6.5)&amp;lt;/ref&amp;gt;), а собственные значения в середине спектра - последними;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
5) Из-за ограниченной точности постепенно теряется ортогональность вектора Ланцоша &amp;lt;math style=&amp;quot;vertical-align:-20%&amp;gt;q_j&amp;lt;/math&amp;gt; к предыдущим векторам Ланцоша, поэтому необходимо примерно каждые 10-15 итераций проводить дорогостоящую операцию реортогонализации, но это уже будет иной алгоритм с очень малым различием в одной операции и в программном коде, реализующем его, соответственно; &amp;lt;ref&amp;gt;Sam Handler - The Lanczos Algorithm For Large-Scale Eigenvalue Problems (08.01.07), slide №8&amp;lt;/ref&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
6) Эффективность и быстрота выполнения алгоритма очень сильно зависит от скорости памяти (диска). Согласно тесту только &#039;&#039;6%&#039;&#039; времени работы программы приходится на вычисления, остальное время затрачивается на ожидание отклика диска;&amp;lt;ref&amp;gt;Sam Handler - The Lanczos Algorithm For Large-Scale Eigenvalue Problems (08.01.07), slide №10&amp;lt;/ref&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
7) Метод Ланцоша удобен тем, что не требует хранения исходной матрицы полным массивом: метод использует исходную матрицу только в операциях умножения матрицы на вектор, что позволяет эффективно использовать разреженность матрицы или регулярность структуры матрицы. Поэтому метод Ланцоша может быть использован для матриц таких больших порядков, когда методы вращений и отражений не могут быть применены.&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;
По заданию, во второй части требовалось описать только разделы 2.4 и 2.7, прошу не спрашивать с меня все разделы 2.1-2.6. Надеюсь на понимание, мне физически не хватает времени на это задание + 2 других в течение семестра, делаю всё, что в моих силах :)&lt;br /&gt;
&lt;br /&gt;
== Существующие реализации алгоритма ==&lt;br /&gt;
Несмотря на то, что алгоритм является далеко не самым популярным, алгоритмом, про который нельзя сказать, что он всегда «на слуху», на сегодняшний день существует множество реализаций на различных популярных языках.&amp;lt;br&amp;gt;&lt;br /&gt;
Перечислим далее некоторые из них, указывая язык программирования, лежащий в их основе, и некоторые важные характеристики, которые обсуждались в статье ранее:&lt;br /&gt;
*&#039;&#039;Code on netlib.org by Jane Cullum and Ralph Willoughby&#039;&#039; (&#039;&#039;&#039;Fortran 77&#039;&#039;&#039;; без реортогонализации векторов; без реализации распараллеливания)&amp;lt;ref&amp;gt;http://www.netlib.org/lanczos/leval&amp;lt;/ref&amp;gt;&lt;br /&gt;
*&#039;&#039;Lanczos algorithm on freesourcecode.net&#039;&#039; (&#039;&#039;&#039;Matlab&#039;&#039;&#039;; присутствует реортогонализация векторов; без реализации распараллеливания)&amp;lt;ref&amp;gt;http://freesourcecode.net/matlabprojects/61741/lanczos-algorithm--in-matlab&amp;lt;/ref&amp;gt;&lt;br /&gt;
*&#039;&#039;Lanczos for eigenvalues in Numerical Linear Algebra, Spring 2007&#039;&#039; (&#039;&#039;&#039;Matlab&#039;&#039;&#039;; частичная или полная реортогонализация - доступны оба варианта; без реализации распараллеливания)&amp;lt;ref&amp;gt;Ссылки на файлы lanso.m и lanfu.m можно найти на https://www.nada.kth.se/~ruhe/2D5219/labs2007.html&amp;lt;/ref&amp;gt;&lt;br /&gt;
*&#039;&#039;Planso&#039;&#039; (название происходит от parallel Lanso.f) &#039;&#039;code by Kesheng Wu and Horst D. Simon&#039;&#039; (&#039;&#039;&#039;Fortran 77&#039;&#039;&#039;; частичная реортогонализация векторов; использование MPI для коммуникаций)&amp;lt;ref&amp;gt;https://github.com/jiahao/planso.jl/tree/master/external/PLAN/plan К сожалению, ссылка в описании пакета на github, ведущая на сайт National Energy Research Scientific Computing Center (NERSC), с более подробной информацией о данной программе больше не активна и выдаёт результат &#039;&#039;Page not found&#039;&#039;&amp;lt;/ref&amp;gt; &lt;br /&gt;
* &#039;&#039;Lanczos.cpp in the Vienna Computing Library&#039;&#039;  (&#039;&#039;&#039;C++&#039;&#039;&#039;, частичная реортогонализация, без реализации распараллеливания) &amp;lt;ref&amp;gt;http://viennacl.sourceforge.net/doc/lanczos_8cpp_source.html&amp;lt;/ref&amp;gt;&lt;br /&gt;
* &#039;&#039;Parallel Eigen Values code using C++ AMP on microsoft msdn blog&#039;&#039; (&#039;&#039;&#039;C++&#039;&#039;&#039;; ? ; распараллеливание есть и реализовано через C++ AMP) &amp;lt;ref&amp;gt;https://blogs.msdn.microsoft.com/nativeconcurrency/2013/12/20/eigen-values/ Подробнее о C++ Accelerated Massive Parallelism можно почитать здесь: https://msdn.microsoft.com/ru-ru/library/hh265137(v=vs.140).aspx или здесь: http://professorweb.ru/my/csharp/optimization/level4/4_6.php &amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;br /&gt;
[[en:Description of algorithm properties and structure]]&lt;/div&gt;</summary>
		<author><name>AleksLevin</name></author>
	</entry>
</feed>