<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="ru">
	<id>http://digida.mgpu.ru/index.php?action=history&amp;feed=atom&amp;title=%D0%9F%D0%BE%D0%B8%D1%81%D0%BA_%D0%BF%D0%BE_%D0%BA%D1%80%D0%B0%D1%8F%D0%BC</id>
	<title>Поиск по краям - История изменений</title>
	<link rel="self" type="application/atom+xml" href="http://digida.mgpu.ru/index.php?action=history&amp;feed=atom&amp;title=%D0%9F%D0%BE%D0%B8%D1%81%D0%BA_%D0%BF%D0%BE_%D0%BA%D1%80%D0%B0%D1%8F%D0%BC"/>
	<link rel="alternate" type="text/html" href="http://digida.mgpu.ru/index.php?title=%D0%9F%D0%BE%D0%B8%D1%81%D0%BA_%D0%BF%D0%BE_%D0%BA%D1%80%D0%B0%D1%8F%D0%BC&amp;action=history"/>
	<updated>2026-04-26T11:44:09Z</updated>
	<subtitle>История изменений этой страницы в вики</subtitle>
	<generator>MediaWiki 1.44.0</generator>
	<entry>
		<id>http://digida.mgpu.ru/index.php?title=%D0%9F%D0%BE%D0%B8%D1%81%D0%BA_%D0%BF%D0%BE_%D0%BA%D1%80%D0%B0%D1%8F%D0%BC&amp;diff=4687&amp;oldid=prev</id>
		<title>Patarakin: 1 версия импортирована</title>
		<link rel="alternate" type="text/html" href="http://digida.mgpu.ru/index.php?title=%D0%9F%D0%BE%D0%B8%D1%81%D0%BA_%D0%BF%D0%BE_%D0%BA%D1%80%D0%B0%D1%8F%D0%BC&amp;diff=4687&amp;oldid=prev"/>
		<updated>2022-10-19T17:55:04Z</updated>

		<summary type="html">&lt;p&gt;1 версия импортирована&lt;/p&gt;
&lt;table style=&quot;background-color: #fff; color: #202122;&quot; data-mw=&quot;interface&quot;&gt;
				&lt;col class=&quot;diff-marker&quot; /&gt;
				&lt;col class=&quot;diff-content&quot; /&gt;
				&lt;col class=&quot;diff-marker&quot; /&gt;
				&lt;col class=&quot;diff-content&quot; /&gt;
				&lt;tr class=&quot;diff-title&quot; lang=&quot;ru&quot;&gt;
				&lt;td colspan=&quot;2&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;← Предыдущая версия&lt;/td&gt;
				&lt;td colspan=&quot;2&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;Версия от 20:55, 19 октября 2022&lt;/td&gt;
				&lt;/tr&gt;&lt;tr&gt;&lt;td colspan=&quot;4&quot; class=&quot;diff-notice&quot; lang=&quot;ru&quot;&gt;&lt;div class=&quot;mw-diff-empty&quot;&gt;(нет различий)&lt;/div&gt;
&lt;/td&gt;&lt;/tr&gt;
&lt;!-- diff cache key digida:diff:1.41:old-4686:rev-4687 --&gt;
&lt;/table&gt;</summary>
		<author><name>Patarakin</name></author>
	</entry>
	<entry>
		<id>http://digida.mgpu.ru/index.php?title=%D0%9F%D0%BE%D0%B8%D1%81%D0%BA_%D0%BF%D0%BE_%D0%BA%D1%80%D0%B0%D1%8F%D0%BC&amp;diff=4686&amp;oldid=prev</id>
		<title>ru_wikipedia&gt;MagnusFit: Перевод из Английской Википедии</title>
		<link rel="alternate" type="text/html" href="http://digida.mgpu.ru/index.php?title=%D0%9F%D0%BE%D0%B8%D1%81%D0%BA_%D0%BF%D0%BE_%D0%BA%D1%80%D0%B0%D1%8F%D0%BC&amp;diff=4686&amp;oldid=prev"/>
		<updated>2021-09-19T19:11:06Z</updated>

		<summary type="html">&lt;p&gt;Перевод из Английской Википедии&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Новая страница&lt;/b&gt;&lt;/p&gt;&lt;div&gt;В [[Информатика|информатике]] &amp;#039;&amp;#039;&amp;#039;поиск по краям&amp;#039;&amp;#039;&amp;#039; ([[Английский язык|англ.]] &amp;#039;&amp;#039;&amp;#039;fringe search&amp;#039;&amp;#039;&amp;#039;) — это {{нп5|Поиск по графу|алгоритм поиска по графу|uk|Пошук по графу}}, который находит путь с наименьшей стоимостью от заданного начального [[Вершина (теория графов)|узла]] до одного &amp;#039;&amp;#039;целевого узла&amp;#039;&amp;#039;.&lt;br /&gt;
&lt;br /&gt;
По сути, поиск по краям — это золотая середина между [[A*|алгоритмом поиска A*]] и вариантом {{нп5|Итеративное углубление A*|итеративного углубления A*||&lt;br /&gt;
Iterative deepening A*}} (&amp;#039;&amp;#039;&amp;#039;IDA*&amp;#039;&amp;#039;&amp;#039;&amp;lt;ref&amp;gt;&amp;#039;&amp;#039;&amp;#039;IDA*&amp;#039;&amp;#039;&amp;#039; — сокращение [[Английский язык|английского]] словосочетания &amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039;I&amp;#039;&amp;#039;&amp;#039;terative &amp;#039;&amp;#039;&amp;#039;D&amp;#039;&amp;#039;&amp;#039;eepening &amp;#039;&amp;#039;&amp;#039;A*&amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039; ([[Русский язык|рус.]] &amp;#039;&amp;#039;Итеративное углубление A*&amp;#039;&amp;#039;)&amp;lt;/ref&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
Если &amp;#039;&amp;#039;g&amp;#039;&amp;#039;(&amp;#039;&amp;#039;x&amp;#039;&amp;#039;) — стоимость пути поиска от первого узла до текущего, а &amp;#039;&amp;#039;h&amp;#039;&amp;#039;(&amp;#039;&amp;#039;x&amp;#039;&amp;#039;) — [[эвристический алгоритм|эвристика]] оценки стоимости от текущего узла до цели, тогда {{math|1=&amp;#039;&amp;#039;ƒ&amp;#039;&amp;#039;(&amp;#039;&amp;#039;x&amp;#039;&amp;#039;) = &amp;#039;&amp;#039;g&amp;#039;&amp;#039;(&amp;#039;&amp;#039;x&amp;#039;&amp;#039;) + &amp;#039;&amp;#039;h&amp;#039;&amp;#039;(&amp;#039;&amp;#039;x&amp;#039;&amp;#039;)}} — фактическая стоимость пути к цели. Рассмотрим &amp;#039;&amp;#039;&amp;#039;IDA*&amp;#039;&amp;#039;&amp;#039;, который выполняет [[Рекурсивная функция|рекурсивный]] слева направо [[поиск в глубину]] от корневого узла, останавливая рекурсию, как только цель будет найдена или узлы достигнут максимального значения &amp;#039;&amp;#039;ƒ&amp;#039;&amp;#039;. Если цель не найдена на первой итерации &amp;#039;&amp;#039;ƒ&amp;#039;&amp;#039;, итерация затем увеличивается, и алгоритм выполняет поиск снова. То есть, он повторяется на итерациях.&lt;br /&gt;
&lt;br /&gt;
У &amp;#039;&amp;#039;&amp;#039;IDA*&amp;#039;&amp;#039;&amp;#039; есть три основных недостатка. Во-первых, &amp;#039;&amp;#039;&amp;#039;IDA*&amp;#039;&amp;#039;&amp;#039; будет повторять состояния при наличии нескольких (иногда неоптимальных) путей к целевому узлу - это часто решается путём сохранения кеша посещённых состояний. Изменённый таким образом &amp;#039;&amp;#039;&amp;#039;IDA*&amp;#039;&amp;#039;&amp;#039; обозначается как &amp;#039;&amp;#039;&amp;#039;IDA*&amp;#039;&amp;#039;&amp;#039; с расширенной памятью (&amp;#039;&amp;#039;&amp;#039;ME-IDA*&amp;#039;&amp;#039;&amp;#039;&amp;lt;ref&amp;gt;&amp;#039;&amp;#039;&amp;#039;ME-IDA*&amp;#039;&amp;#039;&amp;#039; — сокращение английского словосочетания &amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039;M&amp;#039;&amp;#039;&amp;#039;emory-&amp;#039;&amp;#039;&amp;#039;E&amp;#039;&amp;#039;&amp;#039;nhanced-&amp;#039;&amp;#039;&amp;#039;IDA*&amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039; (рус. &amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039;IDA*&amp;#039;&amp;#039;&amp;#039; с расширенной памятью&amp;#039;&amp;#039;)&amp;lt;/ref&amp;gt;), поскольку она использует некоторую память. Кроме того, &amp;#039;&amp;#039;&amp;#039;IDA*&amp;#039;&amp;#039;&amp;#039; повторяет все предыдущие операции поиска снова и снова, что необходимо для работы без хранилища. Сохраняя листовые узлы предыдущей итерации и используя их в качестве начальной позиции следующей, эффективность &amp;#039;&amp;#039;&amp;#039;IDA*&amp;#039;&amp;#039;&amp;#039; значительно повышается (в противном случае на последней итерации он всегда должен был бы посещать каждый узел в дереве).&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Поиск по краям&amp;#039;&amp;#039;&amp;#039; реализует эти улучшения в &amp;#039;&amp;#039;&amp;#039;IDA*&amp;#039;&amp;#039;&amp;#039;, используя [[Структура данных|структуру данных]], состоящую более или менее из двух [[Список (информатика)|списков]] для итерации по границе или по краю дерева поиска. Один список &amp;#039;&amp;#039;«сейчас»&amp;#039;&amp;#039; хранит текущую итерацию, а другой список &amp;#039;&amp;#039;«позже»&amp;#039;&amp;#039; хранит ближайшую следующую итерацию. Таким образом, корневой узел дерева поиска &amp;#039;&amp;#039;«сейчас»&amp;#039;&amp;#039; является корнем, а &amp;#039;&amp;#039;«позже»&amp;#039;&amp;#039; — пустым. Затем алгоритм выполняет одно из двух действий: Если {{math|&amp;#039;&amp;#039;ƒ&amp;#039;&amp;#039;(&amp;#039;&amp;#039;голова&amp;#039;&amp;#039;)}} больше порогового значения, удаляет &amp;#039;&amp;#039;голову&amp;#039;&amp;#039; из &amp;#039;&amp;#039;«сейчас»&amp;#039;&amp;#039; и добавляет его в конец &amp;#039;&amp;#039;«позже»&amp;#039;&amp;#039;, то есть сохраняет &amp;#039;&amp;#039;голову&amp;#039;&amp;#039; для следующей итерации. В противном случае, если {{math|&amp;#039;&amp;#039;ƒ&amp;#039;&amp;#039;(&amp;#039;&amp;#039;голова&amp;#039;&amp;#039;)}} меньше или равняется пороговому значению, разворачивает и отбрасывает &amp;#039;&amp;#039;голову&amp;#039;&amp;#039;, рассматривает его потомственные элементы, добавив их в начало &amp;#039;&amp;#039;«сейчас»&amp;#039;&amp;#039;. В конце итерации пороговое значение увеличивается, список &amp;#039;&amp;#039;«позже»&amp;#039;&amp;#039; становится списком &amp;#039;&amp;#039;«сейчас»&amp;#039;&amp;#039; и опустошается.&lt;br /&gt;
&lt;br /&gt;
Важное различие между  &amp;#039;&amp;#039;&amp;#039;поиск по краям&amp;#039;&amp;#039;&amp;#039; и &amp;#039;&amp;#039;&amp;#039;A*&amp;#039;&amp;#039;&amp;#039; состоит в том, что содержимое списков в &amp;#039;&amp;#039;&amp;#039;поиске по краям&amp;#039;&amp;#039;&amp;#039; необязательно должно быть отсортировано — это значительный выигрыш по сравнению с &amp;#039;&amp;#039;&amp;#039;A*&amp;#039;&amp;#039;&amp;#039;, который требует зачастую дорогостоящего поддержания порядка в его открытом списке. Однако &amp;#039;&amp;#039;&amp;#039;поиск по краям&amp;#039;&amp;#039;&amp;#039; должен будет посещать, в отличие от &amp;#039;&amp;#039;&amp;#039;A*&amp;#039;&amp;#039;&amp;#039;, одни и те же узлы неоднократно, но стоимость каждого такого посещения постоянна по сравнению с [[Временная сложность алгоритма#Логарифмическое время|логарифмическим временем]] сортировки списка в &amp;#039;&amp;#039;&amp;#039;A*&amp;#039;&amp;#039;&amp;#039; в худшем случае.&lt;br /&gt;
&lt;br /&gt;
== Псевдокод ==&lt;br /&gt;
Реализация обоих списков в одном двусвязном списке, где узлы, предшествующие текущему узлу, являются частью &amp;#039;&amp;#039;«позже»&amp;#039;&amp;#039;, а всё остальное — списком &amp;#039;&amp;#039;«сейчас»&amp;#039;&amp;#039;. Используя массив предварительно выделенных узлов в списке для каждого узла в сетке, время доступа к узлам в списке сокращается до постоянного. Точно так же массив маркеров позволяет выполнять поиск узла в списке за постоянное время. &amp;#039;&amp;#039;g&amp;#039;&amp;#039; сохраняется как [[хеш-таблица]], а последний массив маркеров сохраняется для постоянного поиска того, был ли ранее посещён узел и действительна ли запись в [[кэш]]е.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=cpp&amp;gt;&lt;br /&gt;
init(start, goal)&lt;br /&gt;
    fringe F = s&lt;br /&gt;
    cache C[start] = (0, null)&lt;br /&gt;
    flimit = h(start)&lt;br /&gt;
    found = false&lt;br /&gt;
&lt;br /&gt;
    while (found == false) AND (F not empty)&lt;br /&gt;
        fmin = ∞&lt;br /&gt;
        for node in F, from left to right&lt;br /&gt;
            (g, parent) = C[node]&lt;br /&gt;
            f = g + h(node)&lt;br /&gt;
            if f &amp;gt; flimit&lt;br /&gt;
                fmin = min(f, fmin)&lt;br /&gt;
                continue&lt;br /&gt;
            if node == goal&lt;br /&gt;
                found = true&lt;br /&gt;
                break&lt;br /&gt;
            for child in children(node), from right to left&lt;br /&gt;
                g_child = g + cost(node, child)&lt;br /&gt;
                if C[child] != null&lt;br /&gt;
                    (g_cached, parent) = C[child]&lt;br /&gt;
                    if g_child &amp;gt;= g_cached&lt;br /&gt;
                        continue&lt;br /&gt;
                if child in F&lt;br /&gt;
                    remove child from F&lt;br /&gt;
                insert child in F past node&lt;br /&gt;
                C[child] = (g_child, node)&lt;br /&gt;
            remove node from F&lt;br /&gt;
        flimit = fmin&lt;br /&gt;
&lt;br /&gt;
    if reachedgoal == true&lt;br /&gt;
        reverse_path(goal)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Обратный псевдокод.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=cpp&amp;gt;&lt;br /&gt;
reverse_path(node)&lt;br /&gt;
    (g, parent) = C[node]&lt;br /&gt;
    if parent != null&lt;br /&gt;
        reverse_path(parent)&lt;br /&gt;
    print node&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Эксперименты ==&lt;br /&gt;
При тестировании в сеточной среде, типичной для компьютерных игр, включая непроходимые препятствия, &amp;#039;&amp;#039;&amp;#039;поиск по краям&amp;#039;&amp;#039;&amp;#039; превзошёл &amp;#039;&amp;#039;&amp;#039;A*&amp;#039;&amp;#039;&amp;#039; примерно на {{ы|10—40 %}}, в зависимости от использования плиток или октилей. Возможные дальнейшие улучшения включают использование структуры данных, которая легче поддаётся [[кэш]]ированию. &lt;br /&gt;
&lt;br /&gt;
== Примечания ==&lt;br /&gt;
{{примечания}}&lt;br /&gt;
&lt;br /&gt;
== Ссылки ==&lt;br /&gt;
* [[Шеффер, Джонатан|Джонатан Шеффер]], Ингви Бьёрнссон, Маркус Энценбергер, Роберт К. Холте. &amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039;Поиск по Краям&amp;#039;&amp;#039;&amp;#039;: Победа над A* в поиске пути на игровых картах.&amp;#039;&amp;#039; Материалы симпозиума IEEE 2005 года по вычислительному интеллекту и играм (CIG05). [[Эссекский университет]], [[Колчестер]], [[Эссекс]] ([[Великобритания]]); 4&amp;amp;ndash;6 апреля 2005 года. IEEE 2005. https://web.archive.org/web/20090219220415/http://www.cs.ualberta.ca/~games/pathfind/publications/cig2005.pdf&lt;br /&gt;
&lt;br /&gt;
== Внешние ссылки ==&lt;br /&gt;
* Реализация &amp;#039;&amp;#039;&amp;#039;Поиска по Краям&amp;#039;&amp;#039;&amp;#039; на [[Си (язык программирования)|языке C]] от Хесуса Мануэля Магера Хойса https://github.com/pywirrarika/fringesearch&lt;br /&gt;
&lt;br /&gt;
{{Алгоритмы поиска на графах}}&lt;br /&gt;
&lt;br /&gt;
[[Категория:Алгоритмы на графах]]&lt;br /&gt;
[[Категория:Алгоритмы поиска]]&lt;/div&gt;</summary>
		<author><name>ru_wikipedia&gt;MagnusFit</name></author>
	</entry>
</feed>