<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="ru">
		<id>http://neerc.ifmo.ru/wiki/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=KirillTim</id>
		<title>Викиконспекты - Вклад участника [ru]</title>
		<link rel="self" type="application/atom+xml" href="http://neerc.ifmo.ru/wiki/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=KirillTim"/>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%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/KirillTim"/>
		<updated>2026-08-03T23:04:02Z</updated>
		<subtitle>Вклад участника</subtitle>
		<generator>MediaWiki 1.30.0</generator>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%9A%D0%BB%D0%B0%D1%81%D1%81%D0%B8%D1%84%D0%B8%D0%BA%D0%B0%D1%86%D0%B8%D1%8F_%D1%82%D0%B5%D0%BA%D1%81%D1%82%D0%BE%D0%B2_%D0%B8_%D0%B0%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7_%D1%82%D0%BE%D0%BD%D0%B0%D0%BB%D1%8C%D0%BD%D0%BE%D1%81%D1%82%D0%B8&amp;diff=70978</id>
		<title>Классификация текстов и анализ тональности</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%9A%D0%BB%D0%B0%D1%81%D1%81%D0%B8%D1%84%D0%B8%D0%BA%D0%B0%D1%86%D0%B8%D1%8F_%D1%82%D0%B5%D0%BA%D1%81%D1%82%D0%BE%D0%B2_%D0%B8_%D0%B0%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7_%D1%82%D0%BE%D0%BD%D0%B0%D0%BB%D1%8C%D0%BD%D0%BE%D1%81%D1%82%D0%B8&amp;diff=70978"/>
				<updated>2019-04-09T10:03:53Z</updated>
		
		<summary type="html">&lt;p&gt;KirillTim: typo&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Классификация текстов (документов)''' (''Document classification'') {{---}} задача компьютерной лингвистики&amp;lt;ref&amp;gt;[https://ru.wikipedia.org/wiki/%D0%9A%D0%BE%D0%BC%D0%BF%D1%8C%D1%8E%D1%82%D0%B5%D1%80%D0%BD%D0%B0%D1%8F_%D0%BB%D0%B8%D0%BD%D0%B3%D0%B2%D0%B8%D1%81%D1%82%D0%B8%D0%BA%D0%B0 Компьютерная лингвистика]&amp;lt;/ref&amp;gt;, заключающаяся в отнесении документа к одной из нескольких категорий на основании содержания документа.&lt;br /&gt;
&lt;br /&gt;
'''Анализ тональности текста''' (''Sentiment analysis'') {{---}} задача компьютерной лингвистики, заключающаяся в определении эмоциональной окраски (тональности) текста и, в частности, в выявлении эмоциональной оценки авторов по отношению к объектам, описываемым в тексте.&lt;br /&gt;
&lt;br /&gt;
== Задачи классификации текстов ==&lt;br /&gt;
Классификация текстов применяется, в том числе, для:&lt;br /&gt;
* Разделения веб страниц и сайтов по тематическим каталогам;&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;ref&amp;gt;[https://ru.wikipedia.org/wiki/%D0%AF%D0%B7%D1%8B%D0%BA_%D0%B2%D1%80%D0%B0%D0%B6%D0%B4%D1%8B Язык Вражды]&amp;lt;/ref&amp;gt;;&lt;br /&gt;
В общем случае, задача анализа тональности текста эквивалентна задаче классификации текста, где категориями текстов могут быть тональные оценки.&lt;br /&gt;
Примеры тональных оценок:&lt;br /&gt;
* позитивная;&lt;br /&gt;
* негативная;&lt;br /&gt;
* нейтральная;&lt;br /&gt;
Под «нейтральной» подразумевается, что текст не содержит эмоциональной окраски.&lt;br /&gt;
&lt;br /&gt;
== Классификация текстов методами машинного обучения ==&lt;br /&gt;
=== Постановка задачи ===&lt;br /&gt;
Имеется множество категорий (классов, меток) &amp;lt;math&amp;gt;\mathfrak{C}=\{c_1,...,c_{\left|\mathfrak{C}\right|}\}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Имеется множество документов &amp;lt;math&amp;gt;\mathfrak{D}= \{ d_1, ... , d_{ \left| \mathfrak{D} \right| } \}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Неизвестная целевая функция &amp;lt;math&amp;gt;\Phi\colon \mathfrak{C} \times \mathfrak{D} \rightarrow \{ 0, 1 \}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Необходимо построить классификатор &amp;lt;math&amp;gt; \Phi^\prime &amp;lt;/math&amp;gt;, максимально близкий к &amp;lt;math&amp;gt;\Phi&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Имеется некоторая начальная коллекция размеченных документов &amp;lt;math&amp;gt;\mathfrak{R} \subset \mathfrak{C} \times \mathfrak{D}&amp;lt;/math&amp;gt;, для которых известны значения &amp;lt;math&amp;gt;\Phi&amp;lt;/math&amp;gt;. Обычно её делят на «обучающую» и «проверочную» части. Первая используется для обучения классификатора, вторая — для независимой проверки качества его работы.&lt;br /&gt;
&lt;br /&gt;
Классификатор может выдавать точный ответ &amp;lt;math&amp;gt;\Phi^\prime\colon \mathfrak{C} \times \mathfrak{D} \rightarrow \{ 0, 1 \}&amp;lt;/math&amp;gt; или степень подобия &amp;lt;math&amp;gt;\Phi^\prime\colon \mathfrak{C} \times \mathfrak{D} \rightarrow [ 0, 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;
* Удаление пунктуации;&lt;br /&gt;
* Удаление редких и слишком частых слов;&lt;br /&gt;
* [http://neerc.ifmo.ru/wiki/index.php?title=%D0%9E%D0%B1%D1%80%D0%B0%D0%B1%D0%BE%D1%82%D0%BA%D0%B0_%D0%B5%D1%81%D1%82%D0%B5%D1%81%D1%82%D0%B2%D0%B5%D0%BD%D0%BD%D0%BE%D0%B3%D0%BE_%D1%8F%D0%B7%D1%8B%D0%BA%D0%B0#.D0.A1.D1.82.D0.B5.D0.BC.D0.BC.D0.B8.D0.BD.D0.B3 Стемминг] или [http://neerc.ifmo.ru/wiki/index.php?title=%D0%9E%D0%B1%D1%80%D0%B0%D0%B1%D0%BE%D1%82%D0%BA%D0%B0_%D0%B5%D1%81%D1%82%D0%B5%D1%81%D1%82%D0%B2%D0%B5%D0%BD%D0%BD%D0%BE%D0%B3%D0%BE_%D1%8F%D0%B7%D1%8B%D0%BA%D0%B0#.D0.9B.D0.B5.D0.BC.D0.BC.D0.B0.D1.82.D0.B8.D0.B7.D0.B0.D1.86.D0.B8.D1.8F Лемматизация];&lt;br /&gt;
==== Извлечение признаков из текстов ====&lt;br /&gt;
Большинство математических моделей работают в векторных пространствах больших размерностей, поэтому необходимо отобразить текст в векторном пространстве. Основным походом является мешок слов (bag-of-words): для документа формируется вектор размерности словаря, для каждого слова выделяется своя размерность, для документа записывается признак насколько часто слово встречается в нем, получаем вектор. Наиболее распространенным методом для вычисления признака является TF-IDF[4] (TF — частота слова, term frequency, IDF — обратная частота документа, inverse document frequency). Плюсами мешка слов является простая реализация, однако данный метод теряет часть информации, например, порядок слов. Для уменьшения потери информации можно использовать мешок N-грамм (добавлять не только слова, но и словосочетания), или использовать методы векторных представлений слов это, например, позволяет снизить ошибку на словах с одинаковыми написаниями, но разными значениями.&lt;br /&gt;
=== Алгоритмы классификации ===&lt;br /&gt;
==== Наивная байесовская модель ====&lt;br /&gt;
Пусть &amp;lt;math&amp;gt;P(c_i|d)&amp;lt;/math&amp;gt; {{---}} вероятность того, что документ, представленный вектором &amp;lt;math&amp;gt;d = (t_1, ..., t_n)&amp;lt;/math&amp;gt;, соответствует категории &amp;lt;math&amp;gt;c_i&amp;lt;/math&amp;gt; для &amp;lt;math&amp;gt;i = 1, ..., |C|&amp;lt;/math&amp;gt;. Задача классификатора заключается в том, чтобы подобрать такие значения &amp;lt;math&amp;gt;c_i&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt;, при которых значение вероятности &amp;lt;math&amp;gt;P(c_i|d)&amp;lt;/math&amp;gt; будет максимальным:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;c_m = \underset{c \in C}{\operatorname{argmax}} \, P(c|d)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Для вычисления значений &amp;lt;math&amp;gt;P(c_i|d)&amp;lt;/math&amp;gt; пользуются теоремой Байеса:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;P(c_i|d) = \frac{P(d|c_i)P(c_i)}{P(d)}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
где &amp;lt;math&amp;gt;P(c_i)&amp;lt;/math&amp;gt; – априорная вероятность того, что документ отнесен к категории &amp;lt;math&amp;gt;c_i&amp;lt;/math&amp;gt;; &amp;lt;math&amp;gt;P(d | c_i)&amp;lt;/math&amp;gt; – вероятность найти документ, представленный вектором &amp;lt;math&amp;gt;d = (t_1, ..., t_n)&amp;lt;/math&amp;gt;, в категории &amp;lt;math&amp;gt;c_i&amp;lt;/math&amp;gt;; &amp;lt;math&amp;gt;P(d)&amp;lt;/math&amp;gt; – вероятность того, что произвольно взятый документ можно представить в виде вектора признаков &amp;lt;math&amp;gt;d = (t_1, ..., t_n)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
По сути &amp;lt;math&amp;gt;P(c_i)&amp;lt;/math&amp;gt; является отношением количества документов из обучающей выборки &amp;lt;math&amp;gt;L&amp;lt;/math&amp;gt;, отнесенных в категорию c_i , к количеству всех документов из &amp;lt;math&amp;gt;L&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;P(d)&amp;lt;/math&amp;gt; не зависит от категории &amp;lt;math&amp;gt;c_i&amp;lt;/math&amp;gt;, а значения &amp;lt;math&amp;gt;t_1, ..., t_n&amp;lt;/math&amp;gt; заданы заранее, поэтому знаменатель {{---}} это константа, не влияющая на выбор наибольшего из значений &amp;lt;math&amp;gt;P(c_i|d)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Вычисление &amp;lt;math&amp;gt;P(d | c_i)&amp;lt;/math&amp;gt; затруднительно из-за большого количества признаков &amp;lt;math&amp;gt;t_1, ..., t_n&amp;lt;/math&amp;gt; , поэтому делают «наивное» предположение о том, что любые две координаты, рассматриваемые как случайные величины, статистически не зависят друг от друга. Тогда можно воспользоваться формулой&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;P(d|c_i) = \prod_{k=1}^{n} P(t_k|c)&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;
* легкая интерпретируемость результатов работы алгоритма.&lt;br /&gt;
&lt;br /&gt;
Недостатками являются относительно низкое качество классификации и неспособность учитывать зависимость результата классификации от сочетания признаков.&lt;br /&gt;
&lt;br /&gt;
==== [[Метод опорных векторов (SVM)]] ====&lt;br /&gt;
Будем представлять каждый документ, как вектор, задаваемый своим содержимым в общем векторном пространстве. После этого будем строить [http://neerc.ifmo.ru/wiki/index.php?title=%D0%9C%D0%B5%D1%82%D0%BE%D0%B4_%D0%BE%D0%BF%D0%BE%D1%80%D0%BD%D1%8B%D1%85_%D0%B2%D0%B5%D0%BA%D1%82%D0%BE%D1%80%D0%BE%D0%B2_(SVM)#.D0.A0.D0.B0.D0.B7.D0.B4.D0.B5.D0.BB.D1.8F.D1.8E.D1.89.D0.B0.D1.8F_.D0.B3.D0.B8.D0.BF.D0.B5.D1.80.D0.BF.D0.BB.D0.BE.D1.81.D0.BA.D0.BE.D1.81.D1.82.D1.8C разделяющую гиперплоскость] для каждого известного класса.&lt;br /&gt;
&lt;br /&gt;
Преимущества метода:&lt;br /&gt;
* один из наиболее качественных методов;&lt;br /&gt;
* возможность работы с небольшим набором данных для обучения;&lt;br /&gt;
* сводимость к задаче выпуклой оптимизации, имеющей единственное решение.&lt;br /&gt;
&lt;br /&gt;
Недостатки метода: сложная интерпретируемость параметров алгоритма и неустойчивость по отношению к выбросам в исходных данных.&lt;br /&gt;
&lt;br /&gt;
=== Оценка качества классификации ===&lt;br /&gt;
Для оценки качества классификации, как и для оценки качества работы многих других алгоритмов машинного обучения вычисляется [https://ru.wikipedia.org/wiki/%D0%98%D0%BD%D1%84%D0%BE%D1%80%D0%BC%D0%B0%D1%86%D0%B8%D0%BE%D0%BD%D0%BD%D1%8B%D0%B9_%D0%BF%D0%BE%D0%B8%D1%81%D0%BA#%D0%A2%D0%BE%D1%87%D0%BD%D0%BE%D1%81%D1%82%D1%8C_(precision) точность] и [https://ru.wikipedia.org/wiki/%D0%98%D0%BD%D1%84%D0%BE%D1%80%D0%BC%D0%B0%D1%86%D0%B8%D0%BE%D0%BD%D0%BD%D1%8B%D0%B9_%D0%BF%D0%BE%D0%B8%D1%81%D0%BA#%D0%9F%D0%BE%D0%BB%D0%BD%D0%BE%D1%82%D0%B0_(recall) полнота].&lt;br /&gt;
&lt;br /&gt;
== Применение семантических тезаурусов для анализа тональности текстов ==&lt;br /&gt;
Существуют тезаурусы&amp;lt;ref&amp;gt;[https://ru.wikipedia.org/wiki/%D0%A2%D0%B5%D0%B7%D0%B0%D1%83%D1%80%D1%83%D1%81 Тезаурус]&amp;lt;/ref&amp;gt;, размеченные силами людей с учётом эмоциональной окраски слов, содержащихся в них. Такие словари позволяют определять тональность текста без применения алгоритмов машинного обучения. Тональность текста определяется как сумма тональностей слов, содержащихся в размеченных словарях.&lt;br /&gt;
&lt;br /&gt;
Основной проблемой методов, основанных на словарях является трудоёмкость построения словаря: отдельного для каждого нового языка и каждой новой тематики.&lt;br /&gt;
&lt;br /&gt;
Известные тезаурусы:&lt;br /&gt;
* [http://wndomains.fbk.eu/wnaffect.html WordNet-Affect];&lt;br /&gt;
* [http://nmis.isti.cnr.it/sebastiani/Publications/LREC10.pdf SentiWordNet];&lt;br /&gt;
* [http://sentic.net/ SenticNet]&lt;br /&gt;
&lt;br /&gt;
== Примечания ==&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;/div&gt;</summary>
		<author><name>KirillTim</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%9A%D0%BB%D0%B0%D1%81%D1%81%D0%B8%D1%84%D0%B8%D0%BA%D0%B0%D1%86%D0%B8%D1%8F_%D1%82%D0%B5%D0%BA%D1%81%D1%82%D0%BE%D0%B2_%D0%B8_%D0%B0%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7_%D1%82%D0%BE%D0%BD%D0%B0%D0%BB%D1%8C%D0%BD%D0%BE%D1%81%D1%82%D0%B8&amp;diff=70977</id>
		<title>Классификация текстов и анализ тональности</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%9A%D0%BB%D0%B0%D1%81%D1%81%D0%B8%D1%84%D0%B8%D0%BA%D0%B0%D1%86%D0%B8%D1%8F_%D1%82%D0%B5%D0%BA%D1%81%D1%82%D0%BE%D0%B2_%D0%B8_%D0%B0%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7_%D1%82%D0%BE%D0%BD%D0%B0%D0%BB%D1%8C%D0%BD%D0%BE%D1%81%D1%82%D0%B8&amp;diff=70977"/>
				<updated>2019-04-09T09:56:56Z</updated>
		
		<summary type="html">&lt;p&gt;KirillTim: ...&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Классификация текстов (документов)''' (''Document classification'') {{---}} задача компьютерной лингвистики&amp;lt;ref&amp;gt;[https://ru.wikipedia.org/wiki/%D0%9A%D0%BE%D0%BC%D0%BF%D1%8C%D1%8E%D1%82%D0%B5%D1%80%D0%BD%D0%B0%D1%8F_%D0%BB%D0%B8%D0%BD%D0%B3%D0%B2%D0%B8%D1%81%D1%82%D0%B8%D0%BA%D0%B0 Компьютерная лингвистика]&amp;lt;/ref&amp;gt;, заключающаяся в отнесении документа к одной из нескольких категорий на основании содержания документа.&lt;br /&gt;
&lt;br /&gt;
'''Анализ тональности текста''' (''Sentiment analysis'') {{---}} задача компьютерной лингвистики, заключающаяся в определении эмоциональной окраски (тональности) текста и, в частности, в выявлении эмоциональной оценки авторов по отношению к объектам, описываемым в тексте.&lt;br /&gt;
&lt;br /&gt;
== Задачи классификации текстов ==&lt;br /&gt;
Классификация текстов применяется, в том числе, для:&lt;br /&gt;
* Разделения веб страниц и сайтов по тематическим каталогам;&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;ref&amp;gt;[https://ru.wikipedia.org/wiki/%D0%AF%D0%B7%D1%8B%D0%BA_%D0%B2%D1%80%D0%B0%D0%B6%D0%B4%D1%8B Язык Вражды]&amp;lt;/ref&amp;gt;;&lt;br /&gt;
В общем случае, задача анализа тональности текста эквивалентна задаче классификации текста, где категориями текстов могут быть тональные оценки.&lt;br /&gt;
Примеры тональных оценок:&lt;br /&gt;
* позитивня;&lt;br /&gt;
* негативня;&lt;br /&gt;
* нейтральная;&lt;br /&gt;
Под «нейтральной» подразумевается, что текст не содержит эмоциональной окраски.&lt;br /&gt;
&lt;br /&gt;
== Классификация текстов методами машинного обучения ==&lt;br /&gt;
=== Постановка задачи ===&lt;br /&gt;
Имеется множество категорий (классов, меток) &amp;lt;math&amp;gt;\mathfrak{C}=\{c_1,...,c_{\left|\mathfrak{C}\right|}\}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Имеется множество документов &amp;lt;math&amp;gt;\mathfrak{D}= \{ d_1, ... , d_{ \left| \mathfrak{D} \right| } \}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Неизвестная целевая функция &amp;lt;math&amp;gt;\Phi\colon \mathfrak{C} \times \mathfrak{D} \rightarrow \{ 0, 1 \}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Необходимо построить классификатор &amp;lt;math&amp;gt; \Phi^\prime &amp;lt;/math&amp;gt;, максимально близкий к &amp;lt;math&amp;gt;\Phi&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Имеется некоторая начальная коллекция размеченных документов &amp;lt;math&amp;gt;\mathfrak{R} \subset \mathfrak{C} \times \mathfrak{D}&amp;lt;/math&amp;gt;, для которых известны значения &amp;lt;math&amp;gt;\Phi&amp;lt;/math&amp;gt;. Обычно её делят на «обучающую» и «проверочную» части. Первая используется для обучения классификатора, вторая — для независимой проверки качества его работы.&lt;br /&gt;
&lt;br /&gt;
Классификатор может выдавать точный ответ &amp;lt;math&amp;gt;\Phi^\prime\colon \mathfrak{C} \times \mathfrak{D} \rightarrow \{ 0, 1 \}&amp;lt;/math&amp;gt; или степень подобия &amp;lt;math&amp;gt;\Phi^\prime\colon \mathfrak{C} \times \mathfrak{D} \rightarrow [ 0, 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;
* Удаление пунктуации;&lt;br /&gt;
* Удаление редких и слишком частых слов;&lt;br /&gt;
* [http://neerc.ifmo.ru/wiki/index.php?title=%D0%9E%D0%B1%D1%80%D0%B0%D0%B1%D0%BE%D1%82%D0%BA%D0%B0_%D0%B5%D1%81%D1%82%D0%B5%D1%81%D1%82%D0%B2%D0%B5%D0%BD%D0%BD%D0%BE%D0%B3%D0%BE_%D1%8F%D0%B7%D1%8B%D0%BA%D0%B0#.D0.A1.D1.82.D0.B5.D0.BC.D0.BC.D0.B8.D0.BD.D0.B3 Стемминг] или [http://neerc.ifmo.ru/wiki/index.php?title=%D0%9E%D0%B1%D1%80%D0%B0%D0%B1%D0%BE%D1%82%D0%BA%D0%B0_%D0%B5%D1%81%D1%82%D0%B5%D1%81%D1%82%D0%B2%D0%B5%D0%BD%D0%BD%D0%BE%D0%B3%D0%BE_%D1%8F%D0%B7%D1%8B%D0%BA%D0%B0#.D0.9B.D0.B5.D0.BC.D0.BC.D0.B0.D1.82.D0.B8.D0.B7.D0.B0.D1.86.D0.B8.D1.8F Лемматизация];&lt;br /&gt;
==== Извлечение признаков из текстов ====&lt;br /&gt;
Большинство математических моделей работают в векторных пространствах больших размерностей, поэтому необходимо отобразить текст в векторном пространстве. Основным походом является мешок слов (bag-of-words): для документа формируется вектор размерности словаря, для каждого слова выделяется своя размерность, для документа записывается признак насколько часто слово встречается в нем, получаем вектор. Наиболее распространенным методом для вычисления признака является TF-IDF[4] (TF — частота слова, term frequency, IDF — обратная частота документа, inverse document frequency). Плюсами мешка слов является простая реализация, однако данный метод теряет часть информации, например, порядок слов. Для уменьшения потери информации можно использовать мешок N-грамм (добавлять не только слова, но и словосочетания), или использовать методы векторных представлений слов это, например, позволяет снизить ошибку на словах с одинаковыми написаниями, но разными значениями.&lt;br /&gt;
=== Алгоритмы классификации ===&lt;br /&gt;
==== Наивная байесовская модель ====&lt;br /&gt;
Пусть &amp;lt;math&amp;gt;P(c_i|d)&amp;lt;/math&amp;gt; {{---}} вероятность того, что документ, представленный вектором &amp;lt;math&amp;gt;d = (t_1, ..., t_n)&amp;lt;/math&amp;gt;, соответствует категории &amp;lt;math&amp;gt;c_i&amp;lt;/math&amp;gt; для &amp;lt;math&amp;gt;i = 1, ..., |C|&amp;lt;/math&amp;gt;. Задача классификатора заключается в том, чтобы подобрать такие значения &amp;lt;math&amp;gt;c_i&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt;, при которых значение вероятности &amp;lt;math&amp;gt;P(c_i|d)&amp;lt;/math&amp;gt; будет максимальным:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;c_m = \underset{c \in C}{\operatorname{argmax}} \, P(c|d)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Для вычисления значений &amp;lt;math&amp;gt;P(c_i|d)&amp;lt;/math&amp;gt; пользуются теоремой Байеса:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;P(c_i|d) = \frac{P(d|c_i)P(c_i)}{P(d)}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
где &amp;lt;math&amp;gt;P(c_i)&amp;lt;/math&amp;gt; – априорная вероятность того, что документ отнесен к категории &amp;lt;math&amp;gt;c_i&amp;lt;/math&amp;gt;; &amp;lt;math&amp;gt;P(d | c_i)&amp;lt;/math&amp;gt; – вероятность найти документ, представленный вектором &amp;lt;math&amp;gt;d = (t_1, ..., t_n)&amp;lt;/math&amp;gt;, в категории &amp;lt;math&amp;gt;c_i&amp;lt;/math&amp;gt;; &amp;lt;math&amp;gt;P(d)&amp;lt;/math&amp;gt; – вероятность того, что произвольно взятый документ можно представить в виде вектора признаков &amp;lt;math&amp;gt;d = (t_1, ..., t_n)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
По сути &amp;lt;math&amp;gt;P(c_i)&amp;lt;/math&amp;gt; является отношением количества документов из обучающей выборки &amp;lt;math&amp;gt;L&amp;lt;/math&amp;gt;, отнесенных в категорию c_i , к количеству всех документов из &amp;lt;math&amp;gt;L&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;P(d)&amp;lt;/math&amp;gt; не зависит от категории &amp;lt;math&amp;gt;c_i&amp;lt;/math&amp;gt;, а значения &amp;lt;math&amp;gt;t_1, ..., t_n&amp;lt;/math&amp;gt; заданы заранее, поэтому знаменатель {{---}} это константа, не влияющая на выбор наибольшего из значений &amp;lt;math&amp;gt;P(c_i|d)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Вычисление &amp;lt;math&amp;gt;P(d | c_i)&amp;lt;/math&amp;gt; затруднительно из-за большого количества признаков &amp;lt;math&amp;gt;t_1, ..., t_n&amp;lt;/math&amp;gt; , поэтому делают «наивное» предположение о том, что любые две координаты, рассматриваемые как случайные величины, статистически не зависят друг от друга. Тогда можно воспользоваться формулой&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;P(d|c_i) = \prod_{k=1}^{n} P(t_k|c)&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;
* легкая интерпретируемость результатов работы алгоритма.&lt;br /&gt;
&lt;br /&gt;
Недостатками являются относительно низкое качество классификации и неспособность учитывать зависимость результата классификации от сочетания признаков.&lt;br /&gt;
&lt;br /&gt;
==== [[Метод опорных векторов (SVM)]] ====&lt;br /&gt;
Будем представлять каждый документ, как вектор, задаваемый своим содержимым в общем векторном пространстве. После этого будем строить [http://neerc.ifmo.ru/wiki/index.php?title=%D0%9C%D0%B5%D1%82%D0%BE%D0%B4_%D0%BE%D0%BF%D0%BE%D1%80%D0%BD%D1%8B%D1%85_%D0%B2%D0%B5%D0%BA%D1%82%D0%BE%D1%80%D0%BE%D0%B2_(SVM)#.D0.A0.D0.B0.D0.B7.D0.B4.D0.B5.D0.BB.D1.8F.D1.8E.D1.89.D0.B0.D1.8F_.D0.B3.D0.B8.D0.BF.D0.B5.D1.80.D0.BF.D0.BB.D0.BE.D1.81.D0.BA.D0.BE.D1.81.D1.82.D1.8C разделяющую гиперплоскость] для каждого известного класса.&lt;br /&gt;
&lt;br /&gt;
Преимущества метода:&lt;br /&gt;
* один из наиболее качественных методов;&lt;br /&gt;
* возможность работы с небольшим набором данных для обучения;&lt;br /&gt;
* сводимость к задаче выпуклой оптимизации, имеющей единственное решение.&lt;br /&gt;
&lt;br /&gt;
Недостатки метода: сложная интерпретируемость параметров алгоритма и неустойчивость по отношению к выбросам в исходных данных.&lt;br /&gt;
&lt;br /&gt;
=== Оценка качества классификации ===&lt;br /&gt;
Для оценки качества классификации, как и для оценки качества работы многих других алгоритмов машинного обучения вычисляется [https://ru.wikipedia.org/wiki/%D0%98%D0%BD%D1%84%D0%BE%D1%80%D0%BC%D0%B0%D1%86%D0%B8%D0%BE%D0%BD%D0%BD%D1%8B%D0%B9_%D0%BF%D0%BE%D0%B8%D1%81%D0%BA#%D0%A2%D0%BE%D1%87%D0%BD%D0%BE%D1%81%D1%82%D1%8C_(precision) точность] и [https://ru.wikipedia.org/wiki/%D0%98%D0%BD%D1%84%D0%BE%D1%80%D0%BC%D0%B0%D1%86%D0%B8%D0%BE%D0%BD%D0%BD%D1%8B%D0%B9_%D0%BF%D0%BE%D0%B8%D1%81%D0%BA#%D0%9F%D0%BE%D0%BB%D0%BD%D0%BE%D1%82%D0%B0_(recall) полнота].&lt;br /&gt;
&lt;br /&gt;
== Применение семантических тезаурусов для анализа тональности текстов ==&lt;br /&gt;
Существуют тезаурусы&amp;lt;ref&amp;gt;[https://ru.wikipedia.org/wiki/%D0%A2%D0%B5%D0%B7%D0%B0%D1%83%D1%80%D1%83%D1%81 Тезаурус]&amp;lt;/ref&amp;gt;, размеченные силами людей с учётом эмоциональной окраски слов, содержащихся в них. Такие словари позволяют определять тональность текста без применения алгоритмов машинного обучения. Тональность текста определяется как сумма тональностей слов, содержащихся в размеченных словарях.&lt;br /&gt;
&lt;br /&gt;
Основной проблемой методов, основанных на словарях является трудоёмкость построения словаря: отдельного для каждого нового языка и каждой новой тематики.&lt;br /&gt;
&lt;br /&gt;
Известные тезаурусы:&lt;br /&gt;
* [http://wndomains.fbk.eu/wnaffect.html WordNet-Affect];&lt;br /&gt;
* [http://nmis.isti.cnr.it/sebastiani/Publications/LREC10.pdf SentiWordNet];&lt;br /&gt;
* [http://sentic.net/ SenticNet]&lt;br /&gt;
&lt;br /&gt;
== Примечания ==&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;/div&gt;</summary>
		<author><name>KirillTim</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%9A%D0%BB%D0%B0%D1%81%D1%81%D0%B8%D1%84%D0%B8%D0%BA%D0%B0%D1%86%D0%B8%D1%8F_%D1%82%D0%B5%D0%BA%D1%81%D1%82%D0%BE%D0%B2_%D0%B8_%D0%B0%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7_%D1%82%D0%BE%D0%BD%D0%B0%D0%BB%D1%8C%D0%BD%D0%BE%D1%81%D1%82%D0%B8&amp;diff=70976</id>
		<title>Классификация текстов и анализ тональности</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%9A%D0%BB%D0%B0%D1%81%D1%81%D0%B8%D1%84%D0%B8%D0%BA%D0%B0%D1%86%D0%B8%D1%8F_%D1%82%D0%B5%D0%BA%D1%81%D1%82%D0%BE%D0%B2_%D0%B8_%D0%B0%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7_%D1%82%D0%BE%D0%BD%D0%B0%D0%BB%D1%8C%D0%BD%D0%BE%D1%81%D1%82%D0%B8&amp;diff=70976"/>
				<updated>2019-04-09T09:54:07Z</updated>
		
		<summary type="html">&lt;p&gt;KirillTim: + метод опорных векторов&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Классификация текстов (документов)''' (''Document classification'') {{---}} задача компьютерной лингвистики&amp;lt;ref&amp;gt;[https://ru.wikipedia.org/wiki/%D0%9A%D0%BE%D0%BC%D0%BF%D1%8C%D1%8E%D1%82%D0%B5%D1%80%D0%BD%D0%B0%D1%8F_%D0%BB%D0%B8%D0%BD%D0%B3%D0%B2%D0%B8%D1%81%D1%82%D0%B8%D0%BA%D0%B0 Компьютерная лингвистика]&amp;lt;/ref&amp;gt;, заключающаяся в отнесении документа к одной из нескольких категорий на основании содержания документа.&lt;br /&gt;
&lt;br /&gt;
'''Анализ тональности текста''' (''Sentiment analysis'') {{---}} задача компьютерной лингвистики, заключающаяся в определении эмоциональной окраски (тональности) текста и, в частности, в выявлении эмоциональной оценки авторов по отношению к объектам, описываемым в тексте.&lt;br /&gt;
&lt;br /&gt;
== Задачи классификации текстов ==&lt;br /&gt;
Классификация текстов применяется, в том числе, для:&lt;br /&gt;
* Разделения веб страниц и сайтов по тематическим каталогам;&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;ref&amp;gt;[https://ru.wikipedia.org/wiki/%D0%AF%D0%B7%D1%8B%D0%BA_%D0%B2%D1%80%D0%B0%D0%B6%D0%B4%D1%8B Язык Вражды]&amp;lt;/ref&amp;gt;;&lt;br /&gt;
В общем случае, задача анализа тональности текста эквивалентна задаче классификации текста, где категориями текстов могут быть тональные оценки.&lt;br /&gt;
Примеры тональных оценок:&lt;br /&gt;
* позитивня;&lt;br /&gt;
* негативня;&lt;br /&gt;
* нейтральная;&lt;br /&gt;
Под «нейтральной» подразумевается, что текст не содержит эмоциональной окраски.&lt;br /&gt;
&lt;br /&gt;
== Классификация текстов методами машинного обучения ==&lt;br /&gt;
=== Постановка задачи ===&lt;br /&gt;
Имеется множество категорий (классов, меток) &amp;lt;math&amp;gt;\mathfrak{C}=\{c_1,...,c_{\left|\mathfrak{C}\right|}\}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Имеется множество документов &amp;lt;math&amp;gt;\mathfrak{D}= \{ d_1, ... , d_{ \left| \mathfrak{D} \right| } \}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Неизвестная целевая функция &amp;lt;math&amp;gt;\Phi\colon \mathfrak{C} \times \mathfrak{D} \rightarrow \{ 0, 1 \}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Необходимо построить классификатор &amp;lt;math&amp;gt; \Phi^\prime &amp;lt;/math&amp;gt;, максимально близкий к &amp;lt;math&amp;gt;\Phi&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Имеется некоторая начальная коллекция размеченных документов &amp;lt;math&amp;gt;\mathfrak{R} \subset \mathfrak{C} \times \mathfrak{D}&amp;lt;/math&amp;gt;, для которых известны значения &amp;lt;math&amp;gt;\Phi&amp;lt;/math&amp;gt;. Обычно её делят на «обучающую» и «проверочную» части. Первая используется для обучения классификатора, вторая — для независимой проверки качества его работы.&lt;br /&gt;
&lt;br /&gt;
Классификатор может выдавать точный ответ &amp;lt;math&amp;gt;\Phi^\prime\colon \mathfrak{C} \times \mathfrak{D} \rightarrow \{ 0, 1 \}&amp;lt;/math&amp;gt; или степень подобия &amp;lt;math&amp;gt;\Phi^\prime\colon \mathfrak{C} \times \mathfrak{D} \rightarrow [ 0, 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;
* Удаление пунктуации;&lt;br /&gt;
* Удаление редких и слишком частых слов;&lt;br /&gt;
* [http://neerc.ifmo.ru/wiki/index.php?title=%D0%9E%D0%B1%D1%80%D0%B0%D0%B1%D0%BE%D1%82%D0%BA%D0%B0_%D0%B5%D1%81%D1%82%D0%B5%D1%81%D1%82%D0%B2%D0%B5%D0%BD%D0%BD%D0%BE%D0%B3%D0%BE_%D1%8F%D0%B7%D1%8B%D0%BA%D0%B0#.D0.A1.D1.82.D0.B5.D0.BC.D0.BC.D0.B8.D0.BD.D0.B3 Стемминг] или [http://neerc.ifmo.ru/wiki/index.php?title=%D0%9E%D0%B1%D1%80%D0%B0%D0%B1%D0%BE%D1%82%D0%BA%D0%B0_%D0%B5%D1%81%D1%82%D0%B5%D1%81%D1%82%D0%B2%D0%B5%D0%BD%D0%BD%D0%BE%D0%B3%D0%BE_%D1%8F%D0%B7%D1%8B%D0%BA%D0%B0#.D0.9B.D0.B5.D0.BC.D0.BC.D0.B0.D1.82.D0.B8.D0.B7.D0.B0.D1.86.D0.B8.D1.8F Лемматизация];&lt;br /&gt;
==== Извлечение признаков из текстов ====&lt;br /&gt;
Большинство математических моделей работают в векторных пространствах больших размерностей, поэтому необходимо отобразить текст в векторном пространстве. Основным походом является мешок слов (bag-of-words): для документа формируется вектор размерности словаря, для каждого слова выделяется своя размерность, для документа записывается признак насколько часто слово встречается в нем, получаем вектор. Наиболее распространенным методом для вычисления признака является TF-IDF[4] (TF — частота слова, term frequency, IDF — обратная частота документа, inverse document frequency). Плюсами мешка слов является простая реализация, однако данный метод теряет часть информации, например, порядок слов. Для уменьшения потери информации можно использовать мешок N-грамм (добавлять не только слова, но и словосочетания), или использовать методы векторных представлений слов это, например, позволяет снизить ошибку на словах с одинаковыми написаниями, но разными значениями.&lt;br /&gt;
=== Алгоритмы классификации ===&lt;br /&gt;
==== Наивная байесовская модель ====&lt;br /&gt;
Пусть &amp;lt;math&amp;gt;P(c_i|d)&amp;lt;/math&amp;gt; {{---}} вероятность того, что документ, представленный вектором &amp;lt;math&amp;gt;d = (t_1, ..., t_n)&amp;lt;/math&amp;gt;, соответствует категории &amp;lt;math&amp;gt;c_i&amp;lt;/math&amp;gt; для &amp;lt;math&amp;gt;i = 1, ..., |C|&amp;lt;/math&amp;gt;. Задача классификатора заключается в том, чтобы подобрать такие значения &amp;lt;math&amp;gt;c_i&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt;, при которых значение вероятности &amp;lt;math&amp;gt;P(c_i|d)&amp;lt;/math&amp;gt; будет максимальным:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;c_m = \underset{c \in C}{\operatorname{argmax}} \, P(c|d)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Для вычисления значений &amp;lt;math&amp;gt;P(c_i|d)&amp;lt;/math&amp;gt; пользуются теоремой Байеса:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;P(c_i|d) = \frac{P(d|c_i)P(c_i)}{P(d)}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
где &amp;lt;math&amp;gt;P(c_i)&amp;lt;/math&amp;gt; – априорная вероятность того, что документ отнесен к категории &amp;lt;math&amp;gt;c_i&amp;lt;/math&amp;gt;; &amp;lt;math&amp;gt;P(d | c_i)&amp;lt;/math&amp;gt; – вероятность найти документ, представленный вектором &amp;lt;math&amp;gt;d = (t_1, ..., t_n)&amp;lt;/math&amp;gt;, в категории &amp;lt;math&amp;gt;c_i&amp;lt;/math&amp;gt;; &amp;lt;math&amp;gt;P(d)&amp;lt;/math&amp;gt; – вероятность того, что произвольно взятый документ можно представить в виде вектора признаков &amp;lt;math&amp;gt;d = (t_1, ..., t_n)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
По сути &amp;lt;math&amp;gt;P(c_i)&amp;lt;/math&amp;gt; является отношением количества документов из обучающей выборки &amp;lt;math&amp;gt;L&amp;lt;/math&amp;gt;, отнесенных в категорию c_i , к количеству всех документов из &amp;lt;math&amp;gt;L&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;P(d)&amp;lt;/math&amp;gt; не зависит от категории &amp;lt;math&amp;gt;c_i&amp;lt;/math&amp;gt;, а значения &amp;lt;math&amp;gt;t_1, ..., t_n&amp;lt;/math&amp;gt; заданы заранее, поэтому знаменатель {{---}} это константа, не влияющая на выбор наибольшего из значений &amp;lt;math&amp;gt;P(c_i|d)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Вычисление &amp;lt;math&amp;gt;P(d | c_i)&amp;lt;/math&amp;gt; затруднительно из-за большого количества признаков &amp;lt;math&amp;gt;t_1, ..., t_n&amp;lt;/math&amp;gt; , поэтому делают «наивное» предположение о том, что любые две координаты, рассматриваемые как случайные величины, статистически не зависят друг от друга. Тогда можно воспользоваться формулой&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;P(d|c_i) = \prod_{k=1}^{n} P(t_k|c)&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;
* легкая интерпретируемость результатов работы алгоритма.&lt;br /&gt;
&lt;br /&gt;
Недостатками являются относительно низкое качество классификации и неспособность учитывать зависимость результата классификации от сочетания признаков.&lt;br /&gt;
&lt;br /&gt;
==== Метод K ближайших соседей ====&lt;br /&gt;
&lt;br /&gt;
==== [[Метод опорных векторов (SVM)]] ====&lt;br /&gt;
Будем представлять каждый документ, как вектор, задаваемый своим содержимым в общем векторном пространстве. После этого будем строить [http://neerc.ifmo.ru/wiki/index.php?title=%D0%9C%D0%B5%D1%82%D0%BE%D0%B4_%D0%BE%D0%BF%D0%BE%D1%80%D0%BD%D1%8B%D1%85_%D0%B2%D0%B5%D0%BA%D1%82%D0%BE%D1%80%D0%BE%D0%B2_(SVM)#.D0.A0.D0.B0.D0.B7.D0.B4.D0.B5.D0.BB.D1.8F.D1.8E.D1.89.D0.B0.D1.8F_.D0.B3.D0.B8.D0.BF.D0.B5.D1.80.D0.BF.D0.BB.D0.BE.D1.81.D0.BA.D0.BE.D1.81.D1.82.D1.8C разделяющую гиперплоскость] для каждого известного класса.&lt;br /&gt;
&lt;br /&gt;
Преимущества метода:&lt;br /&gt;
* один из наиболее качественных методов;&lt;br /&gt;
* возможность работы с небольшим набором данных для обучения;&lt;br /&gt;
* сводимость к задаче выпуклой оптимизации, имеющей единственное решение.&lt;br /&gt;
&lt;br /&gt;
Недостатки метода: сложная интерпретируемость параметров алгоритма и неустойчивость по отношению к выбросам в исходных данных.&lt;br /&gt;
&lt;br /&gt;
==== Свёрточная нейронная сеть ====&lt;br /&gt;
=== Оценка качества классификации ===&lt;br /&gt;
Для оценки качества классификации, как и для оценки качества работы многих других алгоритмов машинного обучения вычисляется [https://ru.wikipedia.org/wiki/%D0%98%D0%BD%D1%84%D0%BE%D1%80%D0%BC%D0%B0%D1%86%D0%B8%D0%BE%D0%BD%D0%BD%D1%8B%D0%B9_%D0%BF%D0%BE%D0%B8%D1%81%D0%BA#%D0%A2%D0%BE%D1%87%D0%BD%D0%BE%D1%81%D1%82%D1%8C_(precision) точность] и [https://ru.wikipedia.org/wiki/%D0%98%D0%BD%D1%84%D0%BE%D1%80%D0%BC%D0%B0%D1%86%D0%B8%D0%BE%D0%BD%D0%BD%D1%8B%D0%B9_%D0%BF%D0%BE%D0%B8%D1%81%D0%BA#%D0%9F%D0%BE%D0%BB%D0%BD%D0%BE%D1%82%D0%B0_(recall) полнота].&lt;br /&gt;
&lt;br /&gt;
== Применение семантических тезаурусов для анализа тональности текстов ==&lt;br /&gt;
Существуют тезаурусы&amp;lt;ref&amp;gt;[https://ru.wikipedia.org/wiki/%D0%A2%D0%B5%D0%B7%D0%B0%D1%83%D1%80%D1%83%D1%81 Тезаурус]&amp;lt;/ref&amp;gt;, размеченные силами людей с учётом эмоциональной окраски слов, содержащихся в них. Такие словари позволяют определять тональность текста без применения алгоритмов машинного обучения. Тональность текста определяется как сумма тональностей слов, содержащихся в размеченных словарях.&lt;br /&gt;
&lt;br /&gt;
Основной проблемой методов, основанных на словарях является трудоёмкость построения словаря: отдельного для каждого нового языка и каждой новой тематики.&lt;br /&gt;
&lt;br /&gt;
Известные тезаурусы:&lt;br /&gt;
* [http://wndomains.fbk.eu/wnaffect.html WordNet-Affect];&lt;br /&gt;
* [http://nmis.isti.cnr.it/sebastiani/Publications/LREC10.pdf SentiWordNet];&lt;br /&gt;
* [http://sentic.net/ SenticNet]&lt;br /&gt;
&lt;br /&gt;
== Примечания ==&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;/div&gt;</summary>
		<author><name>KirillTim</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%9A%D0%BB%D0%B0%D1%81%D1%81%D0%B8%D1%84%D0%B8%D0%BA%D0%B0%D1%86%D0%B8%D1%8F_%D1%82%D0%B5%D0%BA%D1%81%D1%82%D0%BE%D0%B2_%D0%B8_%D0%B0%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7_%D1%82%D0%BE%D0%BD%D0%B0%D0%BB%D1%8C%D0%BD%D0%BE%D1%81%D1%82%D0%B8&amp;diff=70971</id>
		<title>Классификация текстов и анализ тональности</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%9A%D0%BB%D0%B0%D1%81%D1%81%D0%B8%D1%84%D0%B8%D0%BA%D0%B0%D1%86%D0%B8%D1%8F_%D1%82%D0%B5%D0%BA%D1%81%D1%82%D0%BE%D0%B2_%D0%B8_%D0%B0%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7_%D1%82%D0%BE%D0%BD%D0%B0%D0%BB%D1%8C%D0%BD%D0%BE%D1%81%D1%82%D0%B8&amp;diff=70971"/>
				<updated>2019-04-09T09:37:19Z</updated>
		
		<summary type="html">&lt;p&gt;KirillTim: + Наивная байесовская модель&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Классификация текстов (документов)''' (''Document classification'') {{---}} задача компьютерной лингвистики&amp;lt;ref&amp;gt;[https://ru.wikipedia.org/wiki/%D0%9A%D0%BE%D0%BC%D0%BF%D1%8C%D1%8E%D1%82%D0%B5%D1%80%D0%BD%D0%B0%D1%8F_%D0%BB%D0%B8%D0%BD%D0%B3%D0%B2%D0%B8%D1%81%D1%82%D0%B8%D0%BA%D0%B0 Компьютерная лингвистика]&amp;lt;/ref&amp;gt;, заключающаяся в отнесении документа к одной из нескольких категорий на основании содержания документа.&lt;br /&gt;
&lt;br /&gt;
'''Анализ тональности текста''' (''Sentiment analysis'') {{---}} задача компьютерной лингвистики, заключающаяся в определении эмоциональной окраски (тональности) текста и, в частности, в выявлении эмоциональной оценки авторов по отношению к объектам, описываемым в тексте.&lt;br /&gt;
&lt;br /&gt;
== Задачи классификации текстов ==&lt;br /&gt;
Классификация текстов применяется, в том числе, для:&lt;br /&gt;
* Разделения веб страниц и сайтов по тематическим каталогам;&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;ref&amp;gt;[https://ru.wikipedia.org/wiki/%D0%AF%D0%B7%D1%8B%D0%BA_%D0%B2%D1%80%D0%B0%D0%B6%D0%B4%D1%8B Язык Вражды]&amp;lt;/ref&amp;gt;;&lt;br /&gt;
В общем случае, задача анализа тональности текста эквивалентна задаче классификации текста, где категориями текстов могут быть тональные оценки.&lt;br /&gt;
Примеры тональных оценок:&lt;br /&gt;
* позитивня;&lt;br /&gt;
* негативня;&lt;br /&gt;
* нейтральная;&lt;br /&gt;
Под «нейтральной» подразумевается, что текст не содержит эмоциональной окраски.&lt;br /&gt;
&lt;br /&gt;
== Классификация текстов методами машинного обучения ==&lt;br /&gt;
=== Постановка задачи ===&lt;br /&gt;
Имеется множество категорий (классов, меток) &amp;lt;math&amp;gt;\mathfrak{C}=\{c_1,...,c_{\left|\mathfrak{C}\right|}\}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Имеется множество документов &amp;lt;math&amp;gt;\mathfrak{D}= \{ d_1, ... , d_{ \left| \mathfrak{D} \right| } \}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Неизвестная целевая функция &amp;lt;math&amp;gt;\Phi\colon \mathfrak{C} \times \mathfrak{D} \rightarrow \{ 0, 1 \}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Необходимо построить классификатор &amp;lt;math&amp;gt; \Phi^\prime &amp;lt;/math&amp;gt;, максимально близкий к &amp;lt;math&amp;gt;\Phi&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Имеется некоторая начальная коллекция размеченных документов &amp;lt;math&amp;gt;\mathfrak{R} \subset \mathfrak{C} \times \mathfrak{D}&amp;lt;/math&amp;gt;, для которых известны значения &amp;lt;math&amp;gt;\Phi&amp;lt;/math&amp;gt;. Обычно её делят на «обучающую» и «проверочную» части. Первая используется для обучения классификатора, вторая — для независимой проверки качества его работы.&lt;br /&gt;
&lt;br /&gt;
Классификатор может выдавать точный ответ &amp;lt;math&amp;gt;\Phi^\prime\colon \mathfrak{C} \times \mathfrak{D} \rightarrow \{ 0, 1 \}&amp;lt;/math&amp;gt; или степень подобия &amp;lt;math&amp;gt;\Phi^\prime\colon \mathfrak{C} \times \mathfrak{D} \rightarrow [ 0, 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;
* Удаление пунктуации;&lt;br /&gt;
* Удаление редких и слишком частых слов;&lt;br /&gt;
* [http://neerc.ifmo.ru/wiki/index.php?title=%D0%9E%D0%B1%D1%80%D0%B0%D0%B1%D0%BE%D1%82%D0%BA%D0%B0_%D0%B5%D1%81%D1%82%D0%B5%D1%81%D1%82%D0%B2%D0%B5%D0%BD%D0%BD%D0%BE%D0%B3%D0%BE_%D1%8F%D0%B7%D1%8B%D0%BA%D0%B0#.D0.A1.D1.82.D0.B5.D0.BC.D0.BC.D0.B8.D0.BD.D0.B3 Стемминг] или [http://neerc.ifmo.ru/wiki/index.php?title=%D0%9E%D0%B1%D1%80%D0%B0%D0%B1%D0%BE%D1%82%D0%BA%D0%B0_%D0%B5%D1%81%D1%82%D0%B5%D1%81%D1%82%D0%B2%D0%B5%D0%BD%D0%BD%D0%BE%D0%B3%D0%BE_%D1%8F%D0%B7%D1%8B%D0%BA%D0%B0#.D0.9B.D0.B5.D0.BC.D0.BC.D0.B0.D1.82.D0.B8.D0.B7.D0.B0.D1.86.D0.B8.D1.8F Лемматизация];&lt;br /&gt;
==== Извлечение признаков из текстов ====&lt;br /&gt;
Большинство математических моделей работают в векторных пространствах больших размерностей, поэтому необходимо отобразить текст в векторном пространстве. Основным походом является мешок слов (bag-of-words): для документа формируется вектор размерности словаря, для каждого слова выделяется своя размерность, для документа записывается признак насколько часто слово встречается в нем, получаем вектор. Наиболее распространенным методом для вычисления признака является TF-IDF[4] (TF — частота слова, term frequency, IDF — обратная частота документа, inverse document frequency). Плюсами мешка слов является простая реализация, однако данный метод теряет часть информации, например, порядок слов. Для уменьшения потери информации можно использовать мешок N-грамм (добавлять не только слова, но и словосочетания), или использовать методы векторных представлений слов это, например, позволяет снизить ошибку на словах с одинаковыми написаниями, но разными значениями.&lt;br /&gt;
=== Алгоритмы классификации ===&lt;br /&gt;
==== Наивная байесовская модель ====&lt;br /&gt;
Пусть &amp;lt;math&amp;gt;P(c_i|d)&amp;lt;/math&amp;gt; {{---}} вероятность того, что документ, представленный вектором &amp;lt;math&amp;gt;d = (t_1, ..., t_n)&amp;lt;/math&amp;gt;, соответствует категории &amp;lt;math&amp;gt;c_i&amp;lt;/math&amp;gt; для &amp;lt;math&amp;gt;i = 1, ..., |C|&amp;lt;/math&amp;gt;. Задача классификатора заключается в том, чтобы подобрать такие значения &amp;lt;math&amp;gt;c_i&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt;, при которых значение вероятности &amp;lt;math&amp;gt;P(c_i|d)&amp;lt;/math&amp;gt; будет максимальным:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;c_m = \underset{c \in C}{\operatorname{argmax}} \, P(c|d)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Для вычисления значений &amp;lt;math&amp;gt;P(c_i|d)&amp;lt;/math&amp;gt; пользуются теоремой Байеса:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;P(c_i|d) = \frac{P(d|c_i)P(c_i)}{P(d)}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
где &amp;lt;math&amp;gt;P(c_i)&amp;lt;/math&amp;gt; – априорная вероятность того, что документ отнесен к категории &amp;lt;math&amp;gt;c_i&amp;lt;/math&amp;gt;; &amp;lt;math&amp;gt;P(d | c_i)&amp;lt;/math&amp;gt; – вероятность найти документ, представленный вектором &amp;lt;math&amp;gt;d = (t_1, ..., t_n)&amp;lt;/math&amp;gt;, в категории &amp;lt;math&amp;gt;c_i&amp;lt;/math&amp;gt;; &amp;lt;math&amp;gt;P(d)&amp;lt;/math&amp;gt; – вероятность того, что произвольно взятый документ можно представить в виде вектора признаков &amp;lt;math&amp;gt;d = (t_1, ..., t_n)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
По сути &amp;lt;math&amp;gt;P(c_i)&amp;lt;/math&amp;gt; является отношением количества документов из обучающей выборки &amp;lt;math&amp;gt;L&amp;lt;/math&amp;gt;, отнесенных в категорию c_i , к количеству всех документов из &amp;lt;math&amp;gt;L&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;P(d)&amp;lt;/math&amp;gt; не зависит от категории &amp;lt;math&amp;gt;c_i&amp;lt;/math&amp;gt;, а значения &amp;lt;math&amp;gt;t_1, ..., t_n&amp;lt;/math&amp;gt; заданы заранее, поэтому знаменатель {{---}} это константа, не влияющая на выбор наибольшего из значений &amp;lt;math&amp;gt;P(c_i|d)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Вычисление &amp;lt;math&amp;gt;P(d | c_i)&amp;lt;/math&amp;gt; затруднительно из-за большого количества признаков &amp;lt;math&amp;gt;t_1, ..., t_n&amp;lt;/math&amp;gt; , поэтому делают «наивное» предположение о том, что любые две координаты, рассматриваемые как случайные величины, статистически не зависят друг от друга. Тогда можно воспользоваться формулой&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;P(d|c_i) = \prod_{k=1}^{n} P(t_k|c)&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;
* легкая интерпретируемость результатов работы алгоритма.&lt;br /&gt;
&lt;br /&gt;
Недостатками являются относительно низкое качество классификации и неспособность учитывать зависимость результата классификации от сочетания признаков.&lt;br /&gt;
&lt;br /&gt;
==== Метод K ближайших соседей ====&lt;br /&gt;
==== Метод опорных векторов ====&lt;br /&gt;
==== Свёрточная нейронная сеть ====&lt;br /&gt;
=== Оценка качества классификации ===&lt;br /&gt;
Для оценки качества классификации, как и для оценки качества работы многих других алгоритмов машинного обучения вычисляется [https://ru.wikipedia.org/wiki/%D0%98%D0%BD%D1%84%D0%BE%D1%80%D0%BC%D0%B0%D1%86%D0%B8%D0%BE%D0%BD%D0%BD%D1%8B%D0%B9_%D0%BF%D0%BE%D0%B8%D1%81%D0%BA#%D0%A2%D0%BE%D1%87%D0%BD%D0%BE%D1%81%D1%82%D1%8C_(precision) точность] и [https://ru.wikipedia.org/wiki/%D0%98%D0%BD%D1%84%D0%BE%D1%80%D0%BC%D0%B0%D1%86%D0%B8%D0%BE%D0%BD%D0%BD%D1%8B%D0%B9_%D0%BF%D0%BE%D0%B8%D1%81%D0%BA#%D0%9F%D0%BE%D0%BB%D0%BD%D0%BE%D1%82%D0%B0_(recall) полнота].&lt;br /&gt;
&lt;br /&gt;
== Применение семантических тезаурусов для анализа тональности текстов ==&lt;br /&gt;
Существуют тезаурусы&amp;lt;ref&amp;gt;[https://ru.wikipedia.org/wiki/%D0%A2%D0%B5%D0%B7%D0%B0%D1%83%D1%80%D1%83%D1%81 Тезаурус]&amp;lt;/ref&amp;gt;, размеченные силами людей с учётом эмоциональной окраски слов, содержащихся в них. Такие словари позволяют определять тональность текста без применения алгоритмов машинного обучения. Тональность текста определяется как сумма тональностей слов, содержащихся в размеченных словарях.&lt;br /&gt;
&lt;br /&gt;
Основной проблемой методов, основанных на словарях является трудоёмкость построения словаря: отдельного для каждого нового языка и каждой новой тематики.&lt;br /&gt;
&lt;br /&gt;
Известные тезаурусы:&lt;br /&gt;
* [http://wndomains.fbk.eu/wnaffect.html WordNet-Affect];&lt;br /&gt;
* [http://nmis.isti.cnr.it/sebastiani/Publications/LREC10.pdf SentiWordNet];&lt;br /&gt;
* [http://sentic.net/ SenticNet]&lt;br /&gt;
&lt;br /&gt;
== Примечания ==&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;/div&gt;</summary>
		<author><name>KirillTim</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%9A%D0%BB%D0%B0%D1%81%D1%81%D0%B8%D1%84%D0%B8%D0%BA%D0%B0%D1%86%D0%B8%D1%8F_%D1%82%D0%B5%D0%BA%D1%81%D1%82%D0%BE%D0%B2_%D0%B8_%D0%B0%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7_%D1%82%D0%BE%D0%BD%D0%B0%D0%BB%D1%8C%D0%BD%D0%BE%D1%81%D1%82%D0%B8&amp;diff=70968</id>
		<title>Классификация текстов и анализ тональности</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%9A%D0%BB%D0%B0%D1%81%D1%81%D0%B8%D1%84%D0%B8%D0%BA%D0%B0%D1%86%D0%B8%D1%8F_%D1%82%D0%B5%D0%BA%D1%81%D1%82%D0%BE%D0%B2_%D0%B8_%D0%B0%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7_%D1%82%D0%BE%D0%BD%D0%B0%D0%BB%D1%8C%D0%BD%D0%BE%D1%81%D1%82%D0%B8&amp;diff=70968"/>
				<updated>2019-04-09T09:08:58Z</updated>
		
		<summary type="html">&lt;p&gt;KirillTim: + оценка качества&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Классификация текстов (документов)''' (''Document classification'') {{---}} задача компьютерной лингвистики&amp;lt;ref&amp;gt;[https://ru.wikipedia.org/wiki/%D0%9A%D0%BE%D0%BC%D0%BF%D1%8C%D1%8E%D1%82%D0%B5%D1%80%D0%BD%D0%B0%D1%8F_%D0%BB%D0%B8%D0%BD%D0%B3%D0%B2%D0%B8%D1%81%D1%82%D0%B8%D0%BA%D0%B0 Компьютерная лингвистика]&amp;lt;/ref&amp;gt;, заключающаяся в отнесении документа к одной из нескольких категорий на основании содержания документа.&lt;br /&gt;
&lt;br /&gt;
'''Анализ тональности текста''' (''Sentiment analysis'') {{---}} задача компьютерной лингвистики, заключающаяся в определении эмоциональной окраски (тональности) текста и, в частности, в выявлении эмоциональной оценки авторов по отношению к объектам, описываемым в тексте.&lt;br /&gt;
&lt;br /&gt;
== Задачи классификации текстов ==&lt;br /&gt;
Классификация текстов применяется, в том числе, для:&lt;br /&gt;
* Разделения веб страниц и сайтов по тематическим каталогам;&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;ref&amp;gt;[https://ru.wikipedia.org/wiki/%D0%AF%D0%B7%D1%8B%D0%BA_%D0%B2%D1%80%D0%B0%D0%B6%D0%B4%D1%8B Язык Вражды]&amp;lt;/ref&amp;gt;;&lt;br /&gt;
В общем случае, задача анализа тональности текста эквивалентна задаче классификации текста, где категориями текстов могут быть тональные оценки.&lt;br /&gt;
Примеры тональных оценок:&lt;br /&gt;
* позитивня;&lt;br /&gt;
* негативня;&lt;br /&gt;
* нейтральная;&lt;br /&gt;
Под «нейтральной» подразумевается, что текст не содержит эмоциональной окраски.&lt;br /&gt;
&lt;br /&gt;
== Классификация текстов методами машинного обучения ==&lt;br /&gt;
=== Постановка задачи ===&lt;br /&gt;
Имеется множество категорий (классов, меток) &amp;lt;math&amp;gt;\mathfrak{C}=\{c_1,...,c_{\left|\mathfrak{C}\right|}\}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Имеется множество документов &amp;lt;math&amp;gt;\mathfrak{D}= \{ d_1, ... , d_{ \left| \mathfrak{D} \right| } \}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Неизвестная целевая функция &amp;lt;math&amp;gt;\Phi\colon \mathfrak{C} \times \mathfrak{D} \rightarrow \{ 0, 1 \}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Необходимо построить классификатор &amp;lt;math&amp;gt; \Phi^\prime &amp;lt;/math&amp;gt;, максимально близкий к &amp;lt;math&amp;gt;\Phi&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Имеется некоторая начальная коллекция размеченных документов &amp;lt;math&amp;gt;\mathfrak{R} \subset \mathfrak{C} \times \mathfrak{D}&amp;lt;/math&amp;gt;, для которых известны значения &amp;lt;math&amp;gt;\Phi&amp;lt;/math&amp;gt;. Обычно её делят на «обучающую» и «проверочную» части. Первая используется для обучения классификатора, вторая — для независимой проверки качества его работы.&lt;br /&gt;
&lt;br /&gt;
Классификатор может выдавать точный ответ &amp;lt;math&amp;gt;\Phi^\prime\colon \mathfrak{C} \times \mathfrak{D} \rightarrow \{ 0, 1 \}&amp;lt;/math&amp;gt; или степень подобия &amp;lt;math&amp;gt;\Phi^\prime\colon \mathfrak{C} \times \mathfrak{D} \rightarrow [ 0, 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;
* Удаление пунктуации;&lt;br /&gt;
* Удаление редких и слишком частых слов;&lt;br /&gt;
* [http://neerc.ifmo.ru/wiki/index.php?title=%D0%9E%D0%B1%D1%80%D0%B0%D0%B1%D0%BE%D1%82%D0%BA%D0%B0_%D0%B5%D1%81%D1%82%D0%B5%D1%81%D1%82%D0%B2%D0%B5%D0%BD%D0%BD%D0%BE%D0%B3%D0%BE_%D1%8F%D0%B7%D1%8B%D0%BA%D0%B0#.D0.A1.D1.82.D0.B5.D0.BC.D0.BC.D0.B8.D0.BD.D0.B3 Стемминг] или [http://neerc.ifmo.ru/wiki/index.php?title=%D0%9E%D0%B1%D1%80%D0%B0%D0%B1%D0%BE%D1%82%D0%BA%D0%B0_%D0%B5%D1%81%D1%82%D0%B5%D1%81%D1%82%D0%B2%D0%B5%D0%BD%D0%BD%D0%BE%D0%B3%D0%BE_%D1%8F%D0%B7%D1%8B%D0%BA%D0%B0#.D0.9B.D0.B5.D0.BC.D0.BC.D0.B0.D1.82.D0.B8.D0.B7.D0.B0.D1.86.D0.B8.D1.8F Лемматизация];&lt;br /&gt;
==== Извлечение признаков из текстов ====&lt;br /&gt;
Большинство математических моделей работают в векторных пространствах больших размерностей, поэтому необходимо отобразить текст в векторном пространстве. Основным походом является мешок слов (bag-of-words): для документа формируется вектор размерности словаря, для каждого слова выделяется своя размерность, для документа записывается признак насколько часто слово встречается в нем, получаем вектор. Наиболее распространенным методом для вычисления признака является TF-IDF[4] (TF — частота слова, term frequency, IDF — обратная частота документа, inverse document frequency). Плюсами мешка слов является простая реализация, однако данный метод теряет часть информации, например, порядок слов. Для уменьшения потери информации можно использовать мешок N-грамм (добавлять не только слова, но и словосочетания), или использовать методы векторных представлений слов это, например, позволяет снизить ошибку на словах с одинаковыми написаниями, но разными значениями.&lt;br /&gt;
=== Алгоритмы классификации ===&lt;br /&gt;
==== Наивная байесовская модель ====&lt;br /&gt;
==== Метод K ближайших соседей ====&lt;br /&gt;
==== Метод опорных векторов ====&lt;br /&gt;
==== Свёрточная нейронная сеть ====&lt;br /&gt;
=== Оценка качества классификации ===&lt;br /&gt;
Для оценки качества классификации, как и для оценки качества работы многих других алгоритмов машинного обучения вычисляется [https://ru.wikipedia.org/wiki/%D0%98%D0%BD%D1%84%D0%BE%D1%80%D0%BC%D0%B0%D1%86%D0%B8%D0%BE%D0%BD%D0%BD%D1%8B%D0%B9_%D0%BF%D0%BE%D0%B8%D1%81%D0%BA#%D0%A2%D0%BE%D1%87%D0%BD%D0%BE%D1%81%D1%82%D1%8C_(precision) точность] и [https://ru.wikipedia.org/wiki/%D0%98%D0%BD%D1%84%D0%BE%D1%80%D0%BC%D0%B0%D1%86%D0%B8%D0%BE%D0%BD%D0%BD%D1%8B%D0%B9_%D0%BF%D0%BE%D0%B8%D1%81%D0%BA#%D0%9F%D0%BE%D0%BB%D0%BD%D0%BE%D1%82%D0%B0_(recall) полнота].&lt;br /&gt;
&lt;br /&gt;
== Применение семантических тезаурусов для анализа тональности текстов ==&lt;br /&gt;
Существуют тезаурусы&amp;lt;ref&amp;gt;[https://ru.wikipedia.org/wiki/%D0%A2%D0%B5%D0%B7%D0%B0%D1%83%D1%80%D1%83%D1%81 Тезаурус]&amp;lt;/ref&amp;gt;, размеченные силами людей с учётом эмоциональной окраски слов, содержащихся в них. Такие словари позволяют определять тональность текста без применения алгоритмов машинного обучения. Тональность текста определяется как сумма тональностей слов, содержащихся в размеченных словарях.&lt;br /&gt;
&lt;br /&gt;
Основной проблемой методов, основанных на словарях является трудоёмкость построения словаря: отдельного для каждого нового языка и каждой новой тематики.&lt;br /&gt;
&lt;br /&gt;
Известные тезаурусы:&lt;br /&gt;
* [http://wndomains.fbk.eu/wnaffect.html WordNet-Affect];&lt;br /&gt;
* [http://nmis.isti.cnr.it/sebastiani/Publications/LREC10.pdf SentiWordNet];&lt;br /&gt;
* [http://sentic.net/ SenticNet]&lt;br /&gt;
&lt;br /&gt;
== Примечания ==&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;/div&gt;</summary>
		<author><name>KirillTim</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%9A%D0%BB%D0%B0%D1%81%D1%81%D0%B8%D1%84%D0%B8%D0%BA%D0%B0%D1%86%D0%B8%D1%8F_%D1%82%D0%B5%D0%BA%D1%81%D1%82%D0%BE%D0%B2_%D0%B8_%D0%B0%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7_%D1%82%D0%BE%D0%BD%D0%B0%D0%BB%D1%8C%D0%BD%D0%BE%D1%81%D1%82%D0%B8&amp;diff=70965</id>
		<title>Классификация текстов и анализ тональности</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%9A%D0%BB%D0%B0%D1%81%D1%81%D0%B8%D1%84%D0%B8%D0%BA%D0%B0%D1%86%D0%B8%D1%8F_%D1%82%D0%B5%D0%BA%D1%81%D1%82%D0%BE%D0%B2_%D0%B8_%D0%B0%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7_%D1%82%D0%BE%D0%BD%D0%B0%D0%BB%D1%8C%D0%BD%D0%BE%D1%81%D1%82%D0%B8&amp;diff=70965"/>
				<updated>2019-04-09T08:56:19Z</updated>
		
		<summary type="html">&lt;p&gt;KirillTim: fix links&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Классификация текстов (документов)''' (''Document classification'') {{---}} задача компьютерной лингвистики&amp;lt;ref&amp;gt;[https://ru.wikipedia.org/wiki/%D0%9A%D0%BE%D0%BC%D0%BF%D1%8C%D1%8E%D1%82%D0%B5%D1%80%D0%BD%D0%B0%D1%8F_%D0%BB%D0%B8%D0%BD%D0%B3%D0%B2%D0%B8%D1%81%D1%82%D0%B8%D0%BA%D0%B0 Компьютерная лингвистика]&amp;lt;/ref&amp;gt;, заключающаяся в отнесении документа к одной из нескольких категорий на основании содержания документа.&lt;br /&gt;
&lt;br /&gt;
'''Анализ тональности текста''' (''Sentiment analysis'') {{---}} задача компьютерной лингвистики, заключающаяся в определении эмоциональной окраски (тональности) текста и, в частности, в выявлении эмоциональной оценки авторов по отношению к объектам, описываемым в тексте.&lt;br /&gt;
&lt;br /&gt;
== Задачи классификации текстов ==&lt;br /&gt;
Классификация текстов применяется, в том числе, для:&lt;br /&gt;
* Разделения веб страниц и сайтов по тематическим каталогам;&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;ref&amp;gt;[https://ru.wikipedia.org/wiki/%D0%AF%D0%B7%D1%8B%D0%BA_%D0%B2%D1%80%D0%B0%D0%B6%D0%B4%D1%8B Язык Вражды]&amp;lt;/ref&amp;gt;;&lt;br /&gt;
В общем случае, задача анализа тональности текста эквивалентна задаче классификации текста, где категориями текстов могут быть тональные оценки.&lt;br /&gt;
Примеры тональных оценок:&lt;br /&gt;
* позитивня;&lt;br /&gt;
* негативня;&lt;br /&gt;
* нейтральная;&lt;br /&gt;
Под «нейтральной» подразумевается, что текст не содержит эмоциональной окраски.&lt;br /&gt;
&lt;br /&gt;
== Классификация текстов методами машинного обучения ==&lt;br /&gt;
=== Постановка задачи ===&lt;br /&gt;
Имеется множество категорий (классов, меток) &amp;lt;math&amp;gt;\mathfrak{C}=\{c_1,...,c_{\left|\mathfrak{C}\right|}\}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Имеется множество документов &amp;lt;math&amp;gt;\mathfrak{D}= \{ d_1, ... , d_{ \left| \mathfrak{D} \right| } \}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Неизвестная целевая функция &amp;lt;math&amp;gt;\Phi\colon \mathfrak{C} \times \mathfrak{D} \rightarrow \{ 0, 1 \}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Необходимо построить классификатор &amp;lt;math&amp;gt; \Phi^\prime &amp;lt;/math&amp;gt;, максимально близкий к &amp;lt;math&amp;gt;\Phi&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Имеется некоторая начальная коллекция размеченных документов &amp;lt;math&amp;gt;\mathfrak{R} \subset \mathfrak{C} \times \mathfrak{D}&amp;lt;/math&amp;gt;, для которых известны значения &amp;lt;math&amp;gt;\Phi&amp;lt;/math&amp;gt;. Обычно её делят на «обучающую» и «проверочную» части. Первая используется для обучения классификатора, вторая — для независимой проверки качества его работы.&lt;br /&gt;
&lt;br /&gt;
Классификатор может выдавать точный ответ &amp;lt;math&amp;gt;\Phi^\prime\colon \mathfrak{C} \times \mathfrak{D} \rightarrow \{ 0, 1 \}&amp;lt;/math&amp;gt; или степень подобия &amp;lt;math&amp;gt;\Phi^\prime\colon \mathfrak{C} \times \mathfrak{D} \rightarrow [ 0, 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;
* Удаление пунктуации;&lt;br /&gt;
* Удаление редких и слишком частых слов;&lt;br /&gt;
* [http://neerc.ifmo.ru/wiki/index.php?title=%D0%9E%D0%B1%D1%80%D0%B0%D0%B1%D0%BE%D1%82%D0%BA%D0%B0_%D0%B5%D1%81%D1%82%D0%B5%D1%81%D1%82%D0%B2%D0%B5%D0%BD%D0%BD%D0%BE%D0%B3%D0%BE_%D1%8F%D0%B7%D1%8B%D0%BA%D0%B0#.D0.A1.D1.82.D0.B5.D0.BC.D0.BC.D0.B8.D0.BD.D0.B3 Стемминг] или [http://neerc.ifmo.ru/wiki/index.php?title=%D0%9E%D0%B1%D1%80%D0%B0%D0%B1%D0%BE%D1%82%D0%BA%D0%B0_%D0%B5%D1%81%D1%82%D0%B5%D1%81%D1%82%D0%B2%D0%B5%D0%BD%D0%BD%D0%BE%D0%B3%D0%BE_%D1%8F%D0%B7%D1%8B%D0%BA%D0%B0#.D0.9B.D0.B5.D0.BC.D0.BC.D0.B0.D1.82.D0.B8.D0.B7.D0.B0.D1.86.D0.B8.D1.8F Лемматизация];&lt;br /&gt;
==== Извлечение признаков из текстов ====&lt;br /&gt;
Большинство математических моделей работают в векторных пространствах больших размерностей, поэтому необходимо отобразить текст в векторном пространстве. Основным походом является мешок слов (bag-of-words): для документа формируется вектор размерности словаря, для каждого слова выделяется своя размерность, для документа записывается признак насколько часто слово встречается в нем, получаем вектор. Наиболее распространенным методом для вычисления признака является TF-IDF[4] (TF — частота слова, term frequency, IDF — обратная частота документа, inverse document frequency). Плюсами мешка слов является простая реализация, однако данный метод теряет часть информации, например, порядок слов. Для уменьшения потери информации можно использовать мешок N-грамм (добавлять не только слова, но и словосочетания), или использовать методы векторных представлений слов это, например, позволяет снизить ошибку на словах с одинаковыми написаниями, но разными значениями.&lt;br /&gt;
=== Алгоритмы классификации ===&lt;br /&gt;
==== Наивная байесовская модель ====&lt;br /&gt;
==== Метод K ближайших соседей ====&lt;br /&gt;
==== Метод опорных векторов ====&lt;br /&gt;
==== Свёрточная нейронная сеть ====&lt;br /&gt;
=== Оценка качества классификации ===&lt;br /&gt;
&lt;br /&gt;
== Применение семантических тезаурусов для анализа тональности текстов ==&lt;br /&gt;
Существуют тезаурусы&amp;lt;ref&amp;gt;[https://ru.wikipedia.org/wiki/%D0%A2%D0%B5%D0%B7%D0%B0%D1%83%D1%80%D1%83%D1%81 Тезаурус]&amp;lt;/ref&amp;gt;, размеченные силами людей с учётом эмоциональной окраски слов, содержащихся в них. Такие словари позволяют определять тональность текста без применения алгоритмов машинного обучения. Тональность текста определяется как сумма тональностей слов, содержащихся в размеченных словарях.&lt;br /&gt;
&lt;br /&gt;
Основной проблемой методов, основанных на словарях является трудоёмкость построения словаря: отдельного для каждого нового языка и каждой новой тематики.&lt;br /&gt;
&lt;br /&gt;
Известные тезаурусы:&lt;br /&gt;
* [http://wndomains.fbk.eu/wnaffect.html WordNet-Affect];&lt;br /&gt;
* [http://nmis.isti.cnr.it/sebastiani/Publications/LREC10.pdf SentiWordNet];&lt;br /&gt;
* [http://sentic.net/ SenticNet]&lt;br /&gt;
&lt;br /&gt;
== Примечания ==&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;/div&gt;</summary>
		<author><name>KirillTim</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%9A%D0%BB%D0%B0%D1%81%D1%81%D0%B8%D1%84%D0%B8%D0%BA%D0%B0%D1%86%D0%B8%D1%8F_%D1%82%D0%B5%D0%BA%D1%81%D1%82%D0%BE%D0%B2_%D0%B8_%D0%B0%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7_%D1%82%D0%BE%D0%BD%D0%B0%D0%BB%D1%8C%D0%BD%D0%BE%D1%81%D1%82%D0%B8&amp;diff=70963</id>
		<title>Классификация текстов и анализ тональности</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%9A%D0%BB%D0%B0%D1%81%D1%81%D0%B8%D1%84%D0%B8%D0%BA%D0%B0%D1%86%D0%B8%D1%8F_%D1%82%D0%B5%D0%BA%D1%81%D1%82%D0%BE%D0%B2_%D0%B8_%D0%B0%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7_%D1%82%D0%BE%D0%BD%D0%B0%D0%BB%D1%8C%D0%BD%D0%BE%D1%81%D1%82%D0%B8&amp;diff=70963"/>
				<updated>2019-04-09T08:51:11Z</updated>
		
		<summary type="html">&lt;p&gt;KirillTim: + line breaks&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Классификация текстов (документов)''' (''Document classification'') {{---}} задача компьютерной лингвистики&amp;lt;ref&amp;gt;[https://ru.wikipedia.org/wiki/%D0%9A%D0%BE%D0%BC%D0%BF%D1%8C%D1%8E%D1%82%D0%B5%D1%80%D0%BD%D0%B0%D1%8F_%D0%BB%D0%B8%D0%BD%D0%B3%D0%B2%D0%B8%D1%81%D1%82%D0%B8%D0%BA%D0%B0 Компьютерная лингвистика]&amp;lt;/ref&amp;gt;, заключающаяся в отнесении документа к одной из нескольких категорий на основании содержания документа.&lt;br /&gt;
&lt;br /&gt;
'''Анализ тональности текста''' (''Sentiment analysis'') {{---}} задача компьютерной лингвистики, заключающаяся в определении эмоциональной окраски (тональности) текста и, в частности, в выявлении эмоциональной оценки авторов по отношению к объектам, описываемым в тексте.&lt;br /&gt;
&lt;br /&gt;
== Задачи классификации текстов ==&lt;br /&gt;
Классификация текстов применяется, в том числе, для:&lt;br /&gt;
* Разделения веб страниц и сайтов по тематическим каталогам;&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;ref&amp;gt;[https://ru.wikipedia.org/wiki/%D0%AF%D0%B7%D1%8B%D0%BA_%D0%B2%D1%80%D0%B0%D0%B6%D0%B4%D1%8B Язык Вражды]&amp;lt;/ref&amp;gt;;&lt;br /&gt;
В общем случае, задача анализа тональности текста эквивалентна задаче классификации текста, где категориями текстов могут быть тональные оценки.&lt;br /&gt;
Примеры тональных оценок:&lt;br /&gt;
* позитивня;&lt;br /&gt;
* негативня;&lt;br /&gt;
* нейтральная;&lt;br /&gt;
Под «нейтральной» подразумевается, что текст не содержит эмоциональной окраски.&lt;br /&gt;
&lt;br /&gt;
== Классификация текстов методами машинного обучения ==&lt;br /&gt;
=== Постановка задачи ===&lt;br /&gt;
Имеется множество категорий (классов, меток) &amp;lt;math&amp;gt;\mathfrak{C}=\{c_1,...,c_{\left|\mathfrak{C}\right|}\}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Имеется множество документов &amp;lt;math&amp;gt;\mathfrak{D}= \{ d_1, ... , d_{ \left| \mathfrak{D} \right| } \}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Неизвестная целевая функция &amp;lt;math&amp;gt;\Phi\colon \mathfrak{C} \times \mathfrak{D} \rightarrow \{ 0, 1 \}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Необходимо построить классификатор &amp;lt;math&amp;gt; \Phi^\prime &amp;lt;/math&amp;gt;, максимально близкий к &amp;lt;math&amp;gt;\Phi&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Имеется некоторая начальная коллекция размеченных документов &amp;lt;math&amp;gt;\mathfrak{R} \subset \mathfrak{C} \times \mathfrak{D}&amp;lt;/math&amp;gt;, для которых известны значения &amp;lt;math&amp;gt;\Phi&amp;lt;/math&amp;gt;. Обычно её делят на «обучающую» и «проверочную» части. Первая используется для обучения классификатора, вторая — для независимой проверки качества его работы.&lt;br /&gt;
&lt;br /&gt;
Классификатор может выдавать точный ответ &amp;lt;math&amp;gt;\Phi^\prime\colon \mathfrak{C} \times \mathfrak{D} \rightarrow \{ 0, 1 \}&amp;lt;/math&amp;gt; или степень подобия &amp;lt;math&amp;gt;\Phi^\prime\colon \mathfrak{C} \times \mathfrak{D} \rightarrow [ 0, 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;
* Удаление пунктуации;&lt;br /&gt;
* Удаление редких и слишком частых слов;&lt;br /&gt;
* [http://neerc.ifmo.ru/wiki/index.php?title=%D0%9E%D0%B1%D1%80%D0%B0%D0%B1%D0%BE%D1%82%D0%BA%D0%B0_%D0%B5%D1%81%D1%82%D0%B5%D1%81%D1%82%D0%B2%D0%B5%D0%BD%D0%BD%D0%BE%D0%B3%D0%BE_%D1%8F%D0%B7%D1%8B%D0%BA%D0%B0#.D0.A1.D1.82.D0.B5.D0.BC.D0.BC.D0.B8.D0.BD.D0.B3| Стемминг] или [http://neerc.ifmo.ru/wiki/index.php?title=%D0%9E%D0%B1%D1%80%D0%B0%D0%B1%D0%BE%D1%82%D0%BA%D0%B0_%D0%B5%D1%81%D1%82%D0%B5%D1%81%D1%82%D0%B2%D0%B5%D0%BD%D0%BD%D0%BE%D0%B3%D0%BE_%D1%8F%D0%B7%D1%8B%D0%BA%D0%B0#.D0.9B.D0.B5.D0.BC.D0.BC.D0.B0.D1.82.D0.B8.D0.B7.D0.B0.D1.86.D0.B8.D1.8F| Лемматизация];&lt;br /&gt;
==== Извлечение признаков из текстов ====&lt;br /&gt;
Большинство математических моделей работают в векторных пространствах больших размерностей, поэтому необходимо отобразить текст в векторном пространстве. Основным походом является мешок слов (bag-of-words): для документа формируется вектор размерности словаря, для каждого слова выделяется своя размерность, для документа записывается признак насколько часто слово встречается в нем, получаем вектор. Наиболее распространенным методом для вычисления признака является TF-IDF[4] (TF — частота слова, term frequency, IDF — обратная частота документа, inverse document frequency). Плюсами мешка слов является простая реализация, однако данный метод теряет часть информации, например, порядок слов. Для уменьшения потери информации можно использовать мешок N-грамм (добавлять не только слова, но и словосочетания), или использовать методы векторных представлений слов это, например, позволяет снизить ошибку на словах с одинаковыми написаниями, но разными значениями.&lt;br /&gt;
=== Алгоритмы классификации ===&lt;br /&gt;
==== Наивная байесовская модель ====&lt;br /&gt;
==== Метод K ближайших соседей ====&lt;br /&gt;
==== Метод опорных векторов ====&lt;br /&gt;
==== Свёрточная нейронная сеть ====&lt;br /&gt;
=== Оценка качества классификации ===&lt;br /&gt;
&lt;br /&gt;
== Применение семантических тезаурусов для анализа тональности текстов ==&lt;br /&gt;
Существуют тезаурусы&amp;lt;ref&amp;gt;[https://ru.wikipedia.org/wiki/%D0%A2%D0%B5%D0%B7%D0%B0%D1%83%D1%80%D1%83%D1%81 Тезаурус]&amp;lt;/ref&amp;gt;, размеченные силами людей с учётом эмоциональной окраски слов, содержащихся в них. Такие словари позволяют определять тональность текста без применения алгоритмов машинного обучения. Тональность текста определяется как сумма тональностей слов, содержащихся в размеченных словарях.&lt;br /&gt;
&lt;br /&gt;
Основной проблемой методов, основанных на словарях является трудоёмкость построения словаря: отдельного для каждого нового языка и каждой новой тематики.&lt;br /&gt;
&lt;br /&gt;
Известные тезаурусы:&lt;br /&gt;
* [http://wndomains.fbk.eu/wnaffect.html| WordNet-Affect];&lt;br /&gt;
* [http://nmis.isti.cnr.it/sebastiani/Publications/LREC10.pdf| SentiWordNet];&lt;br /&gt;
* [http://sentic.net/| SenticNet]&lt;br /&gt;
&lt;br /&gt;
== Примечания ==&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;/div&gt;</summary>
		<author><name>KirillTim</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%9A%D0%BB%D0%B0%D1%81%D1%81%D0%B8%D1%84%D0%B8%D0%BA%D0%B0%D1%86%D0%B8%D1%8F_%D1%82%D0%B5%D0%BA%D1%81%D1%82%D0%BE%D0%B2_%D0%B8_%D0%B0%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7_%D1%82%D0%BE%D0%BD%D0%B0%D0%BB%D1%8C%D0%BD%D0%BE%D1%81%D1%82%D0%B8&amp;diff=70962</id>
		<title>Классификация текстов и анализ тональности</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%9A%D0%BB%D0%B0%D1%81%D1%81%D0%B8%D1%84%D0%B8%D0%BA%D0%B0%D1%86%D0%B8%D1%8F_%D1%82%D0%B5%D0%BA%D1%81%D1%82%D0%BE%D0%B2_%D0%B8_%D0%B0%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7_%D1%82%D0%BE%D0%BD%D0%B0%D0%BB%D1%8C%D0%BD%D0%BE%D1%81%D1%82%D0%B8&amp;diff=70962"/>
				<updated>2019-04-09T08:42:28Z</updated>
		
		<summary type="html">&lt;p&gt;KirillTim: + алгоритмы список + тезаурусы&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Классификация текстов (документов)''' (''Document classification'') {{---}} задача компьютерной лингвистики&amp;lt;ref&amp;gt;[https://ru.wikipedia.org/wiki/%D0%9A%D0%BE%D0%BC%D0%BF%D1%8C%D1%8E%D1%82%D0%B5%D1%80%D0%BD%D0%B0%D1%8F_%D0%BB%D0%B8%D0%BD%D0%B3%D0%B2%D0%B8%D1%81%D1%82%D0%B8%D0%BA%D0%B0 Компьютерная лингвистика]&amp;lt;/ref&amp;gt;, заключающаяся в отнесении документа к одной из нескольких категорий на основании содержания документа.&lt;br /&gt;
&lt;br /&gt;
'''Анализ тональности текста''' (''Sentiment analysis'') {{---}} задача компьютерной лингвистики, заключающаяся в определении эмоциональной окраски (тональности) текста и, в частности, в выявлении эмоциональной оценки авторов по отношению к объектам, описываемым в тексте.&lt;br /&gt;
&lt;br /&gt;
== Задачи классификации текстов ==&lt;br /&gt;
Классификация текстов применяется, в том числе, для:&lt;br /&gt;
* Разделения веб страниц и сайтов по тематическим каталогам;&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;ref&amp;gt;[https://ru.wikipedia.org/wiki/%D0%AF%D0%B7%D1%8B%D0%BA_%D0%B2%D1%80%D0%B0%D0%B6%D0%B4%D1%8B Язык Вражды]&amp;lt;/ref&amp;gt;;&lt;br /&gt;
В общем случае, задача анализа тональности текста эквивалентна задаче классификации текста, где категориями текстов могут быть тональные оценки.&lt;br /&gt;
Примеры тональных оценок:&lt;br /&gt;
* позитивня;&lt;br /&gt;
* негативня;&lt;br /&gt;
* нейтральная;&lt;br /&gt;
Под «нейтральной» подразумевается, что текст не содержит эмоциональной окраски.&lt;br /&gt;
&lt;br /&gt;
== Классификация текстов методами машинного обучения ==&lt;br /&gt;
=== Постановка задачи ===&lt;br /&gt;
Имеется множество категорий (классов, меток) &amp;lt;math&amp;gt;\mathfrak{C}=\{c_1,...,c_{\left|\mathfrak{C}\right|}\}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Имеется множество документов &amp;lt;math&amp;gt;\mathfrak{D}= \{ d_1, ... , d_{ \left| \mathfrak{D} \right| } \}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Неизвестная целевая функция &amp;lt;math&amp;gt;\Phi\colon \mathfrak{C} \times \mathfrak{D} \rightarrow \{ 0, 1 \}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Необходимо построить классификатор &amp;lt;math&amp;gt; \Phi^\prime &amp;lt;/math&amp;gt;, максимально близкий к &amp;lt;math&amp;gt;\Phi&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Имеется некоторая начальная коллекция размеченных документов &amp;lt;math&amp;gt;\mathfrak{R} \subset \mathfrak{C} \times \mathfrak{D}&amp;lt;/math&amp;gt;, для которых известны значения &amp;lt;math&amp;gt;\Phi&amp;lt;/math&amp;gt;. Обычно её делят на «обучающую» и «проверочную» части. Первая используется для обучения классификатора, вторая — для независимой проверки качества его работы.&lt;br /&gt;
&lt;br /&gt;
Классификатор может выдавать точный ответ &amp;lt;math&amp;gt;\Phi^\prime\colon \mathfrak{C} \times \mathfrak{D} \rightarrow \{ 0, 1 \}&amp;lt;/math&amp;gt; или степень подобия &amp;lt;math&amp;gt;\Phi^\prime\colon \mathfrak{C} \times \mathfrak{D} \rightarrow [ 0, 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;
* Удаление пунктуации;&lt;br /&gt;
* Удаление редких и слишком частых слов;&lt;br /&gt;
* [http://neerc.ifmo.ru/wiki/index.php?title=%D0%9E%D0%B1%D1%80%D0%B0%D0%B1%D0%BE%D1%82%D0%BA%D0%B0_%D0%B5%D1%81%D1%82%D0%B5%D1%81%D1%82%D0%B2%D0%B5%D0%BD%D0%BD%D0%BE%D0%B3%D0%BE_%D1%8F%D0%B7%D1%8B%D0%BA%D0%B0#.D0.A1.D1.82.D0.B5.D0.BC.D0.BC.D0.B8.D0.BD.D0.B3| Стемминг] или [http://neerc.ifmo.ru/wiki/index.php?title=%D0%9E%D0%B1%D1%80%D0%B0%D0%B1%D0%BE%D1%82%D0%BA%D0%B0_%D0%B5%D1%81%D1%82%D0%B5%D1%81%D1%82%D0%B2%D0%B5%D0%BD%D0%BD%D0%BE%D0%B3%D0%BE_%D1%8F%D0%B7%D1%8B%D0%BA%D0%B0#.D0.9B.D0.B5.D0.BC.D0.BC.D0.B0.D1.82.D0.B8.D0.B7.D0.B0.D1.86.D0.B8.D1.8F| Лемматизация];&lt;br /&gt;
==== Извлечение признаков из текстов ====&lt;br /&gt;
Большинство математических моделей работают в векторных пространствах больших размерностей, поэтому необходимо отобразить текст в векторном пространстве. Основным походом является мешок слов (bag-of-words): для документа формируется вектор размерности словаря, для каждого слова выделяется своя размерность, для документа записывается признак насколько часто слово встречается в нем, получаем вектор. Наиболее распространенным методом для вычисления признака является TF-IDF[4] (TF — частота слова, term frequency, IDF — обратная частота документа, inverse document frequency). Плюсами мешка слов является простая реализация, однако данный метод теряет часть информации, например, порядок слов. Для уменьшения потери информации можно использовать мешок N-грамм (добавлять не только слова, но и словосочетания), или использовать методы векторных представлений слов это, например, позволяет снизить ошибку на словах с одинаковыми написаниями, но разными значениями.&lt;br /&gt;
=== Алгоритмы классификации ===&lt;br /&gt;
==== Наивная байесовская модель ====&lt;br /&gt;
==== Метод K ближайших соседей ====&lt;br /&gt;
==== Метод опорных векторов ====&lt;br /&gt;
==== Свёрточная нейронная сеть ====&lt;br /&gt;
=== Оценка качества классификации ===&lt;br /&gt;
&lt;br /&gt;
== Применение семантических тезаурусов для анализа тональности текстов ==&lt;br /&gt;
Существуют тезаурусы&amp;lt;ref&amp;gt;[https://ru.wikipedia.org/wiki/%D0%A2%D0%B5%D0%B7%D0%B0%D1%83%D1%80%D1%83%D1%81 Тезаурус]&amp;lt;/ref&amp;gt;, размеченные силами людей с учётом эмоциональной окраски слов, содержащихся в них. Такие словари позволяют определять тональность текста без применения алгоритмов машинного обучения. Тональность текста определяется как сумма тональностей слов, содержащихся в размеченных словарях. &lt;br /&gt;
Основной проблемой методов, основанных на словарях является трудоёмкость построения словаря: отдельного для каждого нового языка и каждой новой тематики.&lt;br /&gt;
Известные тезаурусы:&lt;br /&gt;
* [http://wndomains.fbk.eu/wnaffect.html| WordNet-Affect];&lt;br /&gt;
* [http://nmis.isti.cnr.it/sebastiani/Publications/LREC10.pdf| SentiWordNet];&lt;br /&gt;
* [http://sentic.net/| SenticNet]&lt;br /&gt;
&lt;br /&gt;
== Примечания ==&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;/div&gt;</summary>
		<author><name>KirillTim</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%9A%D0%BB%D0%B0%D1%81%D1%81%D0%B8%D1%84%D0%B8%D0%BA%D0%B0%D1%86%D0%B8%D1%8F_%D1%82%D0%B5%D0%BA%D1%81%D1%82%D0%BE%D0%B2_%D0%B8_%D0%B0%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7_%D1%82%D0%BE%D0%BD%D0%B0%D0%BB%D1%8C%D0%BD%D0%BE%D1%81%D1%82%D0%B8&amp;diff=70954</id>
		<title>Классификация текстов и анализ тональности</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%9A%D0%BB%D0%B0%D1%81%D1%81%D0%B8%D1%84%D0%B8%D0%BA%D0%B0%D1%86%D0%B8%D1%8F_%D1%82%D0%B5%D0%BA%D1%81%D1%82%D0%BE%D0%B2_%D0%B8_%D0%B0%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7_%D1%82%D0%BE%D0%BD%D0%B0%D0%BB%D1%8C%D0%BD%D0%BE%D1%81%D1%82%D0%B8&amp;diff=70954"/>
				<updated>2019-04-09T08:06:46Z</updated>
		
		<summary type="html">&lt;p&gt;KirillTim: + предобработка&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Классификация текстов (документов)''' (''Document classification'') {{---}} задача компьютерной лингвистики&amp;lt;ref&amp;gt;[https://ru.wikipedia.org/wiki/%D0%9A%D0%BE%D0%BC%D0%BF%D1%8C%D1%8E%D1%82%D0%B5%D1%80%D0%BD%D0%B0%D1%8F_%D0%BB%D0%B8%D0%BD%D0%B3%D0%B2%D0%B8%D1%81%D1%82%D0%B8%D0%BA%D0%B0 Компьютерная лингвистика]&amp;lt;/ref&amp;gt;, заключающаяся в отнесении документа к одной из нескольких категорий на основании содержания документа.&lt;br /&gt;
&lt;br /&gt;
'''Анализ тональности текста''' (''Sentiment analysis'') {{---}} задача компьютерной лингвистики, заключающаяся в определении эмоциональной окраски (тональности) текста и, в частности, в выявлении эмоциональной оценки авторов по отношению к объектам, описываемым в тексте.&lt;br /&gt;
&lt;br /&gt;
== Задачи классификации текстов ==&lt;br /&gt;
Классификация текстов применяется, в том числе, для:&lt;br /&gt;
* Разделения веб страниц и сайтов по тематическим каталогам;&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;ref&amp;gt;[https://ru.wikipedia.org/wiki/%D0%AF%D0%B7%D1%8B%D0%BA_%D0%B2%D1%80%D0%B0%D0%B6%D0%B4%D1%8B Язык Вражды]&amp;lt;/ref&amp;gt;;&lt;br /&gt;
В общем случае, задача анализа тональности текста эквивалентна задаче классификации текста, где категориями текстов могут быть тональные оценки.&lt;br /&gt;
Примеры тональных оценок:&lt;br /&gt;
* позитивня;&lt;br /&gt;
* негативня;&lt;br /&gt;
* нейтральная;&lt;br /&gt;
Под «нейтральной» подразумевается, что текст не содержит эмоциональной окраски.&lt;br /&gt;
&lt;br /&gt;
== Классификация текстов методами машинного обучения ==&lt;br /&gt;
=== Постановка задачи ===&lt;br /&gt;
Имеется множество категорий (классов, меток) &amp;lt;math&amp;gt;\mathfrak{C}=\{c_1,...,c_{\left|\mathfrak{C}\right|}\}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Имеется множество документов &amp;lt;math&amp;gt;\mathfrak{D}= \{ d_1, ... , d_{ \left| \mathfrak{D} \right| } \}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Неизвестная целевая функция &amp;lt;math&amp;gt;\Phi\colon \mathfrak{C} \times \mathfrak{D} \rightarrow \{ 0, 1 \}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Необходимо построить классификатор &amp;lt;math&amp;gt; \Phi^\prime &amp;lt;/math&amp;gt;, максимально близкий к &amp;lt;math&amp;gt;\Phi&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Имеется некоторая начальная коллекция размеченных документов &amp;lt;math&amp;gt;\mathfrak{R} \subset \mathfrak{C} \times \mathfrak{D}&amp;lt;/math&amp;gt;, для которых известны значения &amp;lt;math&amp;gt;\Phi&amp;lt;/math&amp;gt;. Обычно её делят на «обучающую» и «проверочную» части. Первая используется для обучения классификатора, вторая — для независимой проверки качества его работы.&lt;br /&gt;
&lt;br /&gt;
Классификатор может выдавать точный ответ &amp;lt;math&amp;gt;\Phi^\prime\colon \mathfrak{C} \times \mathfrak{D} \rightarrow \{ 0, 1 \}&amp;lt;/math&amp;gt; или степень подобия &amp;lt;math&amp;gt;\Phi^\prime\colon \mathfrak{C} \times \mathfrak{D} \rightarrow [ 0, 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;
* Удаление пунктуации;&lt;br /&gt;
* Удаление редких и слишком частых слов;&lt;br /&gt;
* [http://neerc.ifmo.ru/wiki/index.php?title=%D0%9E%D0%B1%D1%80%D0%B0%D0%B1%D0%BE%D1%82%D0%BA%D0%B0_%D0%B5%D1%81%D1%82%D0%B5%D1%81%D1%82%D0%B2%D0%B5%D0%BD%D0%BD%D0%BE%D0%B3%D0%BE_%D1%8F%D0%B7%D1%8B%D0%BA%D0%B0#.D0.A1.D1.82.D0.B5.D0.BC.D0.BC.D0.B8.D0.BD.D0.B3| Стемминг] или [http://neerc.ifmo.ru/wiki/index.php?title=%D0%9E%D0%B1%D1%80%D0%B0%D0%B1%D0%BE%D1%82%D0%BA%D0%B0_%D0%B5%D1%81%D1%82%D0%B5%D1%81%D1%82%D0%B2%D0%B5%D0%BD%D0%BD%D0%BE%D0%B3%D0%BE_%D1%8F%D0%B7%D1%8B%D0%BA%D0%B0#.D0.9B.D0.B5.D0.BC.D0.BC.D0.B0.D1.82.D0.B8.D0.B7.D0.B0.D1.86.D0.B8.D1.8F| Лемматизация]&lt;br /&gt;
==== Извлечение признаков ====&lt;/div&gt;</summary>
		<author><name>KirillTim</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%9A%D0%BB%D0%B0%D1%81%D1%81%D0%B8%D1%84%D0%B8%D0%BA%D0%B0%D1%86%D0%B8%D1%8F_%D1%82%D0%B5%D0%BA%D1%81%D1%82%D0%BE%D0%B2_%D0%B8_%D0%B0%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7_%D1%82%D0%BE%D0%BD%D0%B0%D0%BB%D1%8C%D0%BD%D0%BE%D1%81%D1%82%D0%B8&amp;diff=70924</id>
		<title>Классификация текстов и анализ тональности</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%9A%D0%BB%D0%B0%D1%81%D1%81%D0%B8%D1%84%D0%B8%D0%BA%D0%B0%D1%86%D0%B8%D1%8F_%D1%82%D0%B5%D0%BA%D1%81%D1%82%D0%BE%D0%B2_%D0%B8_%D0%B0%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7_%D1%82%D0%BE%D0%BD%D0%B0%D0%BB%D1%8C%D0%BD%D0%BE%D1%81%D1%82%D0%B8&amp;diff=70924"/>
				<updated>2019-04-08T23:49:03Z</updated>
		
		<summary type="html">&lt;p&gt;KirillTim: + постановка задачи&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Классификация текстов (документов)''' (''Document classification'') {{---}} задача компьютерной лингвистики&amp;lt;ref&amp;gt;[https://ru.wikipedia.org/wiki/%D0%9A%D0%BE%D0%BC%D0%BF%D1%8C%D1%8E%D1%82%D0%B5%D1%80%D0%BD%D0%B0%D1%8F_%D0%BB%D0%B8%D0%BD%D0%B3%D0%B2%D0%B8%D1%81%D1%82%D0%B8%D0%BA%D0%B0 Компьютерная лингвистика]&amp;lt;/ref&amp;gt;, заключающаяся в отнесении документа к одной из нескольких категорий на основании содержания документа.&lt;br /&gt;
&lt;br /&gt;
'''Анализ тональности текста''' (''Sentiment analysis'') {{---}} задача компьютерной лингвистики, заключающаяся в определении эмоциональной окраски (тональности) текста и, в частности, в выявлении эмоциональной оценки авторов по отношению к объектам, описываемым в тексте.&lt;br /&gt;
&lt;br /&gt;
== Задачи классификации текстов ==&lt;br /&gt;
Классификация текстов применяется, в том числе, для:&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;ref&amp;gt;[https://ru.wikipedia.org/wiki/%D0%AF%D0%B7%D1%8B%D0%BA_%D0%B2%D1%80%D0%B0%D0%B6%D0%B4%D1%8B Язык Вражды]&amp;lt;/ref&amp;gt;&lt;br /&gt;
В общем случае, задача анализа тональности текста эквивалентна задаче классификации текста, где категориями текстов могут быть тональные оценки.&lt;br /&gt;
Примеры тональных оценок:&lt;br /&gt;
* позитивня&lt;br /&gt;
* негативня&lt;br /&gt;
* нейтральная&lt;br /&gt;
Под «нейтральной» подразумевается, что текст не содержит эмоциональной окраски.&lt;br /&gt;
&lt;br /&gt;
== Классификация текстов методами машинного обучения ==&lt;br /&gt;
=== Постановка задачи ===&lt;br /&gt;
Имеется множество категорий (классов, меток) &amp;lt;math&amp;gt;\mathfrak{C}=\{c_1,...,c_{\left|\mathfrak{C}\right|}\}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Имеется множество документов &amp;lt;math&amp;gt;\mathfrak{D}= \{ d_1, ... , d_{ \left| \mathfrak{D} \right| } \}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Неизвестная целевая функция &amp;lt;math&amp;gt;\Phi\colon \mathfrak{C} \times \mathfrak{D} \rightarrow \{ 0, 1 \}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Необходимо построить классификатор &amp;lt;math&amp;gt; \Phi^\prime &amp;lt;/math&amp;gt;, максимально близкий к &amp;lt;math&amp;gt;\Phi&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Имеется некоторая начальная коллекция размеченных документов &amp;lt;math&amp;gt;\mathfrak{R} \subset \mathfrak{C} \times \mathfrak{D}&amp;lt;/math&amp;gt;, для которых известны значения &amp;lt;math&amp;gt;\Phi&amp;lt;/math&amp;gt;. Обычно её делят на «обучающую» и «проверочную» части. Первая используется для обучения классификатора, вторая — для независимой проверки качества его работы.&lt;br /&gt;
&lt;br /&gt;
Классификатор может выдавать точный ответ &amp;lt;math&amp;gt;\Phi^\prime\colon \mathfrak{C} \times \mathfrak{D} \rightarrow \{ 0, 1 \}&amp;lt;/math&amp;gt; или степень подобия &amp;lt;math&amp;gt;\Phi^\prime\colon \mathfrak{C} \times \mathfrak{D} \rightarrow [ 0, 1 ]&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Этапы подготовки ===&lt;/div&gt;</summary>
		<author><name>KirillTim</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%9A%D0%BB%D0%B0%D1%81%D1%81%D0%B8%D1%84%D0%B8%D0%BA%D0%B0%D1%86%D0%B8%D1%8F_%D1%82%D0%B5%D0%BA%D1%81%D1%82%D0%BE%D0%B2_%D0%B8_%D0%B0%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7_%D1%82%D0%BE%D0%BD%D0%B0%D0%BB%D1%8C%D0%BD%D0%BE%D1%81%D1%82%D0%B8&amp;diff=70920</id>
		<title>Классификация текстов и анализ тональности</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%9A%D0%BB%D0%B0%D1%81%D1%81%D0%B8%D1%84%D0%B8%D0%BA%D0%B0%D1%86%D0%B8%D1%8F_%D1%82%D0%B5%D0%BA%D1%81%D1%82%D0%BE%D0%B2_%D0%B8_%D0%B0%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7_%D1%82%D0%BE%D0%BD%D0%B0%D0%BB%D1%8C%D0%BD%D0%BE%D1%81%D1%82%D0%B8&amp;diff=70920"/>
				<updated>2019-04-08T22:48:17Z</updated>
		
		<summary type="html">&lt;p&gt;KirillTim: + задачи&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Классификация текстов (документов)''' (''Document classification'') {{---}} задача компьютерной лингвистики&amp;lt;ref&amp;gt;[https://ru.wikipedia.org/wiki/%D0%9A%D0%BE%D0%BC%D0%BF%D1%8C%D1%8E%D1%82%D0%B5%D1%80%D0%BD%D0%B0%D1%8F_%D0%BB%D0%B8%D0%BD%D0%B3%D0%B2%D0%B8%D1%81%D1%82%D0%B8%D0%BA%D0%B0 Компьютерная лингвистика]&amp;lt;/ref&amp;gt;, заключающаяся в отнесении документа к одной из нескольких категорий на основании содержания документа.&lt;br /&gt;
&lt;br /&gt;
'''Анализ тональности текста''' (''Sentiment analysis'') {{---}} задача компьютерной лингвистики, заключающаяся в определении эмоциональной окраски (тональности) текста и, в частности, в выявлении эмоциональной оценки авторов по отношению к объектам, описываемым в тексте.&lt;br /&gt;
&lt;br /&gt;
== Задачи классификации текстов ==&lt;br /&gt;
Классификация текстов применяется, в том числе, для:&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;ref&amp;gt;[https://ru.wikipedia.org/wiki/%D0%AF%D0%B7%D1%8B%D0%BA_%D0%B2%D1%80%D0%B0%D0%B6%D0%B4%D1%8B Язык Вражды]&amp;lt;/ref&amp;gt;&lt;/div&gt;</summary>
		<author><name>KirillTim</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%9A%D0%BB%D0%B0%D1%81%D1%81%D0%B8%D1%84%D0%B8%D0%BA%D0%B0%D1%86%D0%B8%D1%8F_%D1%82%D0%B5%D0%BA%D1%81%D1%82%D0%BE%D0%B2_%D0%B8_%D0%B0%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7_%D1%82%D0%BE%D0%BD%D0%B0%D0%BB%D1%8C%D0%BD%D0%BE%D1%81%D1%82%D0%B8&amp;diff=70919</id>
		<title>Классификация текстов и анализ тональности</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%9A%D0%BB%D0%B0%D1%81%D1%81%D0%B8%D1%84%D0%B8%D0%BA%D0%B0%D1%86%D0%B8%D1%8F_%D1%82%D0%B5%D0%BA%D1%81%D1%82%D0%BE%D0%B2_%D0%B8_%D0%B0%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7_%D1%82%D0%BE%D0%BD%D0%B0%D0%BB%D1%8C%D0%BD%D0%BE%D1%81%D1%82%D0%B8&amp;diff=70919"/>
				<updated>2019-04-08T22:31:36Z</updated>
		
		<summary type="html">&lt;p&gt;KirillTim: init&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Классификация текстов (документов)''' (''Document classification'') {{---}} задача компьютерной лингвистики&amp;lt;ref&amp;gt;[https://ru.wikipedia.org/wiki/%D0%9A%D0%BE%D0%BC%D0%BF%D1%8C%D1%8E%D1%82%D0%B5%D1%80%D0%BD%D0%B0%D1%8F_%D0%BB%D0%B8%D0%BD%D0%B3%D0%B2%D0%B8%D1%81%D1%82%D0%B8%D0%BA%D0%B0 Компьютерная лингвистика]&amp;lt;/ref&amp;gt;, заключающаяся в отнесении документа к одной из нескольких категорий на основании содержания документа.&lt;br /&gt;
&lt;br /&gt;
'''Анализ тональности текста''' (''Sentiment analysis'') {{---}} задача компьютерной лингвистики&amp;lt;ref&amp;gt;[https://ru.wikipedia.org/wiki/%D0%9A%D0%BE%D0%BC%D0%BF%D1%8C%D1%8E%D1%82%D0%B5%D1%80%D0%BD%D0%B0%D1%8F_%D0%BB%D0%B8%D0%BD%D0%B3%D0%B2%D0%B8%D1%81%D1%82%D0%B8%D0%BA%D0%B0 Компьютерная лингвистика]&amp;lt;/ref&amp;gt;, заключающаяся в определении эмоциональной окраски текста и в частности, в выявлении эмоциональной оценки авторов по отношению к объектам, описываемым в тексте.&lt;/div&gt;</summary>
		<author><name>KirillTim</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%9C%D0%B0%D1%88%D0%B8%D0%BD%D0%BD%D0%BE%D0%B5_%D0%BE%D0%B1%D1%83%D1%87%D0%B5%D0%BD%D0%B8%D0%B5&amp;diff=70733</id>
		<title>Машинное обучение</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%9C%D0%B0%D1%88%D0%B8%D0%BD%D0%BD%D0%BE%D0%B5_%D0%BE%D0%B1%D1%83%D1%87%D0%B5%D0%BD%D0%B8%D0%B5&amp;diff=70733"/>
				<updated>2019-04-03T19:43:08Z</updated>
		
		<summary type="html">&lt;p&gt;KirillTim: /* Обработка естественного языка */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Категория: Машинное обучение]]&lt;br /&gt;
&lt;br /&gt;
=Общие понятия=&lt;br /&gt;
*[[Общие понятия]]&lt;br /&gt;
*[[Модель алгоритма и ее выбор]]&lt;br /&gt;
*[[Переобучение]]&lt;br /&gt;
*[[Кросс-валидация]]&lt;br /&gt;
*[[Выброс]]&lt;br /&gt;
*[[Ранжирование]]&lt;br /&gt;
*[[Стохастический градиентный спуск]]&lt;br /&gt;
*[[Обучение с частичным привлечением учителя]]&lt;br /&gt;
&lt;br /&gt;
=Классификация и регрессия=&lt;br /&gt;
*[[Метрический классификатор и метод ближайших соседей]]&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;tex&amp;gt;^\star&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Кластеризация=&lt;br /&gt;
*[[Кластеризация]]&lt;br /&gt;
*[[Иерархическая кластеризация]]&lt;br /&gt;
*[[Оценка качества в задаче кластеризации]]&amp;lt;tex&amp;gt;^\star&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Ансамбли=&lt;br /&gt;
*[[Виды ансамблей]]&lt;br /&gt;
*[[Бустинг, AdaBoost]]&lt;br /&gt;
*[[XGBoost]]&amp;lt;tex&amp;gt;^\star&amp;lt;/tex&amp;gt;&lt;br /&gt;
*[[CatBoost]]&amp;lt;tex&amp;gt;^\star&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Глубокое обучение=&lt;br /&gt;
*[[Глубокое обучение]]&lt;br /&gt;
*[[Настройка глубокой сети]]&lt;br /&gt;
*[[Batch-normalization]]&lt;br /&gt;
*[[Практики реализации нейронных сетей]]&lt;br /&gt;
*[[Рекуррентные нейронные сети]]&lt;br /&gt;
*[[Сегментация изображений]]&lt;br /&gt;
==Сверточные сети==&lt;br /&gt;
*[[Сверточные нейронные сети]]&lt;br /&gt;
==Порождающие модели==&lt;br /&gt;
*[[Generative Adversarial Nets (GAN)]]&amp;lt;tex&amp;gt;^\star&amp;lt;/tex&amp;gt;&lt;br /&gt;
*[[Автокодировщик]]&lt;br /&gt;
*[[Вариационный автокодировщик]]&lt;br /&gt;
&lt;br /&gt;
==Обработка естественного языка==&lt;br /&gt;
*[[Распознавание речи]]&lt;br /&gt;
*[[Обработка естественного языка]]&lt;br /&gt;
*[[Векторное представление слов]]&lt;br /&gt;
*[[Классификация текстов и анализ тональности]]&lt;br /&gt;
&lt;br /&gt;
=Уменьшение размерности=&lt;br /&gt;
*[[Уменьшение размерности]]&lt;br /&gt;
&lt;br /&gt;
=Обучение с подкреплением=&lt;br /&gt;
*[[Обучение с подкреплением]]&lt;br /&gt;
*[[Методы policy gradient и алгоритм асинхронного актора-критика]]&lt;br /&gt;
&lt;br /&gt;
=Примеры кода=&lt;br /&gt;
*[[Обзор библиотек для машинного обучения на Python]]&lt;br /&gt;
*[[Примеры кода на Scala]]&lt;br /&gt;
&lt;br /&gt;
=В разработке=&lt;br /&gt;
*[[Мета-обучение]]&lt;br /&gt;
*[[Оценка качества в задачах классификации и регрессии]]&lt;br /&gt;
*[[Задача нахождения объектов на изображении]]&amp;lt;tex&amp;gt;^\star&amp;lt;/tex&amp;gt;&lt;br /&gt;
*[[Neural Style Transfer]]&amp;lt;tex&amp;gt;^\star&amp;lt;/tex&amp;gt;&lt;br /&gt;
*[[Долгая краткосрочная память]]&lt;br /&gt;
*[[Метод опорных векторов (SVM)]]&lt;br /&gt;
*[[EM-алгоритм]]&lt;br /&gt;
*[[Рекомендательные системы]]&lt;br /&gt;
*[[Настройка гиперпараметров]]&lt;br /&gt;
*[[Активное обучение]]&lt;br /&gt;
*[[Примеры кода на R]]&lt;br /&gt;
*[[Примеры кода на Java]]&lt;br /&gt;
*[[Регуляризация]]&lt;br /&gt;
*[[Обратное распространение ошибки]]&lt;br /&gt;
*[[Порождающие модели]]&lt;br /&gt;
*[[Ядра]]&lt;br /&gt;
*[[Известные наборы данных]]&lt;/div&gt;</summary>
		<author><name>KirillTim</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=IPsec&amp;diff=57675</id>
		<title>IPsec</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=IPsec&amp;diff=57675"/>
				<updated>2016-12-12T13:58:00Z</updated>
		
		<summary type="html">&lt;p&gt;KirillTim: style fixes&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= История =&lt;br /&gt;
чуть-чуть&lt;br /&gt;
= Архитектура =&lt;br /&gt;
картинки&lt;br /&gt;
= Режимы =&lt;br /&gt;
=== Transport mode ===&lt;br /&gt;
=== Tunnel mode ===&lt;br /&gt;
&lt;br /&gt;
= Использование =&lt;br /&gt;
= Источники информации =&lt;br /&gt;
* [[wikipedia:IPsec|Wikipedia {{---}} IPsec]]&lt;br /&gt;
* [http://www.ixbt.com/comm/ipsecure.shtml IPSec — протокол защиты сетевого трафика на IP-уровне]&lt;br /&gt;
* [http://unixwiz.net/techtips/iguide-ipsec.html  An Illustrated Guide to IPsec ]&lt;br /&gt;
* [https://tools.ietf.org/html/rfc4301 Security Architecture for the Internet Protocol]&lt;/div&gt;</summary>
		<author><name>KirillTim</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=TLS._IPsec._%D0%9E%D1%81%D0%BD%D0%BE%D0%B2%D1%8B,_%D0%BE%D1%82%D0%BB%D0%B8%D1%87%D0%B8%D1%8F._IPv6_%D0%B8_%D1%88%D0%B8%D1%84%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5&amp;diff=57674</id>
		<title>TLS. IPsec. Основы, отличия. IPv6 и шифрование</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=TLS._IPsec._%D0%9E%D1%81%D0%BD%D0%BE%D0%B2%D1%8B,_%D0%BE%D1%82%D0%BB%D0%B8%D1%87%D0%B8%D1%8F._IPv6_%D0%B8_%D1%88%D0%B8%D1%84%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5&amp;diff=57674"/>
				<updated>2016-12-12T13:55:26Z</updated>
		
		<summary type="html">&lt;p&gt;KirillTim: ссылка на правильную страницу&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;http://neerc.ifmo.ru/wiki/index.php?title=IPsec&lt;/div&gt;</summary>
		<author><name>KirillTim</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=TLS._IPsec._%D0%9E%D1%81%D0%BD%D0%BE%D0%B2%D1%8B,_%D0%BE%D1%82%D0%BB%D0%B8%D1%87%D0%B8%D1%8F._IPv6_%D0%B8_%D1%88%D0%B8%D1%84%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5&amp;diff=57673</id>
		<title>TLS. IPsec. Основы, отличия. IPv6 и шифрование</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=TLS._IPsec._%D0%9E%D1%81%D0%BD%D0%BE%D0%B2%D1%8B,_%D0%BE%D1%82%D0%BB%D0%B8%D1%87%D0%B8%D1%8F._IPv6_%D0%B8_%D1%88%D0%B8%D1%84%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5&amp;diff=57673"/>
				<updated>2016-12-12T13:52:33Z</updated>
		
		<summary type="html">&lt;p&gt;KirillTim: удалил&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>KirillTim</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=IPsec&amp;diff=57671</id>
		<title>IPsec</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=IPsec&amp;diff=57671"/>
				<updated>2016-12-12T13:48:02Z</updated>
		
		<summary type="html">&lt;p&gt;KirillTim: Новая страница: «==== История ==== чуть-чуть ==== Архитектура ==== картинки ==== Режимы ==== === Transport mode === === Tunnel mode === ===...»&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==== История ====&lt;br /&gt;
чуть-чуть&lt;br /&gt;
==== Архитектура ====&lt;br /&gt;
картинки&lt;br /&gt;
==== Режимы ====&lt;br /&gt;
=== Transport mode ===&lt;br /&gt;
=== Tunnel mode ===&lt;br /&gt;
==== Использование ====&lt;br /&gt;
==== Источники информации ====&lt;br /&gt;
* [[wikipedia:IPsec|Wikipedia {{---}} IPsec]]&lt;br /&gt;
* [http://www.ixbt.com/comm/ipsecure.shtml IPSec — протокол защиты сетевого трафика на IP-уровне]&lt;br /&gt;
* [http://unixwiz.net/techtips/iguide-ipsec.html  An Illustrated Guide to IPsec ]&lt;br /&gt;
* [https://tools.ietf.org/html/rfc4301 Security Architecture for the Internet Protocol]&lt;/div&gt;</summary>
		<author><name>KirillTim</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%9A%D0%BE%D0%BC%D0%BF%D1%8C%D1%8E%D1%82%D0%B5%D1%80%D0%BD%D1%8B%D0%B5_%D1%81%D0%B5%D1%82%D0%B8&amp;diff=57670</id>
		<title>Компьютерные сети</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%9A%D0%BE%D0%BC%D0%BF%D1%8C%D1%8E%D1%82%D0%B5%D1%80%D0%BD%D1%8B%D0%B5_%D1%81%D0%B5%D1%82%D0%B8&amp;diff=57670"/>
				<updated>2016-12-12T13:46:50Z</updated>
		
		<summary type="html">&lt;p&gt;KirillTim: /* Блок 3 */ IPsec&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Блок 1=&lt;br /&gt;
* [[Коммутация на канальном уровне]]&lt;br /&gt;
* [[Сети с общей средой передачи данных (подуровень MAC, протоколы)]]&lt;br /&gt;
* [[Физическое кодирование]]&lt;br /&gt;
* [[Канальный уровень]]&lt;br /&gt;
* [[Физический уровень]]&lt;br /&gt;
* [[Ethernet]]&lt;br /&gt;
* [[Bluetooth]]&lt;br /&gt;
* [[Виртуальные локальные сети]]&lt;br /&gt;
* [[Протоколы стандарта 802.11]]&lt;br /&gt;
* [[Data link layer - LLC]]&lt;br /&gt;
* [[Data link layer - Flow control]]&lt;br /&gt;
* [[Data link layer - MAC - Aloha, CSMA]]&lt;br /&gt;
&lt;br /&gt;
=Блок 2=&lt;br /&gt;
* [[Сетевой уровень]]&lt;br /&gt;
* [[Broadcast. Broadcast routing.]]&lt;br /&gt;
* [[Мультикаст. Мультикаст маршрутизация]]&lt;br /&gt;
* [[IP]]&lt;br /&gt;
* [[Управляющие протоколы Internet]]&lt;br /&gt;
* [[Протоколы внешнего и внутреннего шлюза]]&lt;br /&gt;
* [[IPv6]]&lt;br /&gt;
* [[Транспортный уровень]]&lt;br /&gt;
* [[Протоколы транспортного уровня (TCP, UDP, SCTP)]]&lt;br /&gt;
&lt;br /&gt;
=Блок 3=&lt;br /&gt;
* [[DHCP]]&lt;br /&gt;
* [[Служба DNS. Пространство имен в Internet]]&lt;br /&gt;
* [[Служба электронной почты]]&lt;br /&gt;
* [[WWW. HTTP. Основы и развитие]]&lt;br /&gt;
* [[FTP. Telnet. SSH]]&lt;br /&gt;
* [[Авторизация. Аутентификация. Аудит. Radius. Diameter]]&lt;br /&gt;
* [[Шифрование]]&lt;br /&gt;
* [[SSL/TLS]]&lt;br /&gt;
* [[IPsec]]&lt;br /&gt;
* [[Протоколы аутентификации]]&lt;br /&gt;
* [[Firewall. Концепция, примеры]]&lt;br /&gt;
* [[SIP. Телефония поверх IP]]&lt;br /&gt;
* [[Одноранговые сети]]&lt;br /&gt;
* [[Сетевые атаки. Классификация, описания]]&lt;br /&gt;
* [[Мультимедиа поверх IP. RTSP]]&lt;br /&gt;
* [[NAT]]&lt;br /&gt;
* [[LTE и WiFi]]&lt;br /&gt;
* [[WAN - особенности, принципы построения сетей]]&lt;br /&gt;
* [[Wireless networks - WAN]]&lt;br /&gt;
* [[LAN - особенности топологии]]&lt;/div&gt;</summary>
		<author><name>KirillTim</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=TLS._IPsec._%D0%9E%D1%81%D0%BD%D0%BE%D0%B2%D1%8B,_%D0%BE%D1%82%D0%BB%D0%B8%D1%87%D0%B8%D1%8F._IPv6_%D0%B8_%D1%88%D0%B8%D1%84%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5&amp;diff=57668</id>
		<title>TLS. IPsec. Основы, отличия. IPv6 и шифрование</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=TLS._IPsec._%D0%9E%D1%81%D0%BD%D0%BE%D0%B2%D1%8B,_%D0%BE%D1%82%D0%BB%D0%B8%D1%87%D0%B8%D1%8F._IPv6_%D0%B8_%D1%88%D0%B8%D1%84%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5&amp;diff=57668"/>
				<updated>2016-12-12T13:45:41Z</updated>
		
		<summary type="html">&lt;p&gt;KirillTim: План + источники&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==== История ====&lt;br /&gt;
чуть-чуть&lt;br /&gt;
==== Архитектура ====&lt;br /&gt;
картинки&lt;br /&gt;
==== Режимы ====&lt;br /&gt;
=== Transport mode ===&lt;br /&gt;
=== Tunnel mode ===&lt;br /&gt;
==== Использование ====&lt;br /&gt;
==== Источники информации ====&lt;br /&gt;
* [[wikipedia:IPsec|Wikipedia {{---}} IPsec]]&lt;br /&gt;
* [http://www.ixbt.com/comm/ipsecure.shtml IPSec — протокол защиты сетевого трафика на IP-уровне]&lt;br /&gt;
* [http://unixwiz.net/techtips/iguide-ipsec.html  An Illustrated Guide to IPsec ]&lt;br /&gt;
* [https://tools.ietf.org/html/rfc4301 Security Architecture for the Internet Protocol]&lt;/div&gt;</summary>
		<author><name>KirillTim</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=NP-%D0%BF%D0%BE%D0%BB%D0%BD%D0%BE%D1%82%D0%B0_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B8_%D0%BE_%D1%81%D1%83%D0%BC%D0%BC%D0%B5_%D0%BF%D0%BE%D0%B4%D0%BC%D0%BD%D0%BE%D0%B6%D0%B5%D1%81%D1%82%D0%B2%D0%B0&amp;diff=54070</id>
		<title>NP-полнота задачи о сумме подмножества</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=NP-%D0%BF%D0%BE%D0%BB%D0%BD%D0%BE%D1%82%D0%B0_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B8_%D0%BE_%D1%81%D1%83%D0%BC%D0%BC%D0%B5_%D0%BF%D0%BE%D0%B4%D0%BC%D0%BD%D0%BE%D0%B6%D0%B5%D1%81%D1%82%D0%B2%D0%B0&amp;diff=54070"/>
				<updated>2016-05-17T18:36:40Z</updated>
		
		<summary type="html">&lt;p&gt;KirillTim: /* Доказательство принадлежности NPH */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Задача&lt;br /&gt;
|definition = Дано множество &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;, содержащие &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; целых чисел и целое число &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;. Требуется выяснить, возможно ли выбрать подмножество &amp;lt;tex&amp;gt;S' \subseteq S&amp;lt;/tex&amp;gt; с суммой &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;: &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;tex&amp;gt;\exists S' \subseteq S: \sum\limits_{s_{i} \in S'}{s_{i}} = s&amp;lt;/tex&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
==Доказательство NP-полноты==&lt;br /&gt;
Для доказательства того, что '''задаче о сумме подмножества''' (англ. ''Subset sum problem'', &amp;lt;tex&amp;gt;\mathrm{SSP}&amp;lt;/tex&amp;gt;) [[NPC | NP-полной]], необходимо доказать два факта:&lt;br /&gt;
*&amp;lt;tex&amp;gt;\mathrm{SSP} \in&amp;lt;/tex&amp;gt; [[NP | &amp;lt;tex&amp;gt;\mathrm{NP}&amp;lt;/tex&amp;gt;]] &lt;br /&gt;
*&amp;lt;tex&amp;gt;\mathrm{SSP} \in&amp;lt;/tex&amp;gt; [[NPH | &amp;lt;tex&amp;gt;\mathrm{NPH}&amp;lt;/tex&amp;gt;]] &lt;br /&gt;
&lt;br /&gt;
===Доказательство принадлежности NP===&lt;br /&gt;
В качестве сертификата возьмем удовлетворяющее условию задачи множество &amp;lt;tex&amp;gt;S'&amp;lt;/tex&amp;gt; с суммой &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;. Оно удовлетворяет всем требованиям, налагаемым на сертификат. Проверяющая функция проверит вхождение всех элементов &amp;lt;tex&amp;gt;S'&amp;lt;/tex&amp;gt; в множество &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; за время &amp;lt;tex&amp;gt;\left\vert{S'}\right\vert \times \left\vert{S}\right\vert&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
===Доказательство принадлежности NPH===&lt;br /&gt;
Сведем [[NP-полнота_задачи_о_выполнимости_булевой_формулы_в_форме_3-КНФ|&amp;lt;tex&amp;gt;\mathrm{3CNFSAT}&amp;lt;/tex&amp;gt;]] к задаче о сумме подмножества. Пусть задана &amp;lt;tex&amp;gt;\mathrm{3CNF}&amp;lt;/tex&amp;gt; формула &amp;lt;tex&amp;gt;\varphi&amp;lt;/tex&amp;gt; от &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt;&lt;br /&gt;
переменных &amp;lt;tex&amp;gt;x_{i}&amp;lt;/tex&amp;gt;, состоящая из &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; пар скобок &amp;lt;tex&amp;gt;C_{i}&amp;lt;/tex&amp;gt;. Будем считать, не умаляя общности, что ни одна пара скобок не содержит одновременно переменную и ее отрицание. Также предположим, что каждая переменная входит хотя бы в одну пару скобок. Построим сводящую функцию &amp;lt;tex&amp;gt;f\!\!:\varphi \to (S,s)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
====Построение сводящей функции====&lt;br /&gt;
Для каждой переменной &amp;lt;tex&amp;gt;x_{i}&amp;lt;/tex&amp;gt; и каждой пары скобок &amp;lt;tex&amp;gt;C_{j}&amp;lt;/tex&amp;gt; создадим по два числа в десятичной системе счисления, каждое длиной &amp;lt;tex&amp;gt;n+k&amp;lt;/tex&amp;gt; цифр. Эти числа образуют &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;. Также создадим число &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt; длиной &amp;lt;tex&amp;gt;n+k&amp;lt;/tex&amp;gt; цифр. Присвоим каждому разряду полученных чисел (одинаковую для всех чисел) метку, соответствующую либо переменной, либо паре скобок.&lt;br /&gt;
Метки, соответствующие парам скобок, присвоены &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; младшим разрядам чисел.&lt;br /&gt;
*В числе &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt; все разряды, соответствующие переменным, установим &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt;, а оставшиеся сделаем равными &amp;lt;tex&amp;gt;4&amp;lt;/tex&amp;gt;.&lt;br /&gt;
*Каждой переменной &amp;lt;tex&amp;gt;x_{i}&amp;lt;/tex&amp;gt; соответствуют два числа из &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;: &amp;lt;tex&amp;gt;v_{i}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;u_{i}&amp;lt;/tex&amp;gt;. Опишем создание этих чисел. Разряд, соответствующий &amp;lt;tex&amp;gt;x_{i}&amp;lt;/tex&amp;gt; установим равным &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt;, а все остальные разряды, соответствующие переменным, установим равными &amp;lt;tex&amp;gt;0&amp;lt;/tex&amp;gt;. Далее, для числа &amp;lt;tex&amp;gt;v_{i}&amp;lt;/tex&amp;gt; установим все разряды, соответствующие парам скобок, содержащих &amp;lt;tex&amp;gt;x_{i}&amp;lt;/tex&amp;gt;, равными &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt;. Во все остальные &amp;quot;скобочные&amp;quot; разряды поставим &amp;lt;tex&amp;gt;0&amp;lt;/tex&amp;gt;. В числе &amp;lt;tex&amp;gt;w_{i}&amp;lt;/tex&amp;gt; установим все разряды, соответствующие парам скобок, содержащих &amp;lt;tex&amp;gt;\neg x_{i}&amp;lt;/tex&amp;gt;, равными &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt;, а во все остальные &amp;quot;скобочные&amp;quot; разряды поставим &amp;lt;tex&amp;gt;0&amp;lt;/tex&amp;gt;.&lt;br /&gt;
*Каждой паре скобок &amp;lt;tex&amp;gt;C_{j}&amp;lt;/tex&amp;gt; соответствуют два числа из &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;: &amp;lt;tex&amp;gt;d_{i}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;e_{i}&amp;lt;/tex&amp;gt;. Оба этих числа содержат &amp;lt;tex&amp;gt;0&amp;lt;/tex&amp;gt; во всех разрядах, кроме соответствующего &amp;lt;tex&amp;gt;C_{j}&amp;lt;/tex&amp;gt;. В этом разряде у &amp;lt;tex&amp;gt;d_{i}&amp;lt;/tex&amp;gt; поставим &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt;, а у &amp;lt;tex&amp;gt;e_{i}&amp;lt;/tex&amp;gt; {{---}} &amp;lt;tex&amp;gt;2&amp;lt;/tex&amp;gt;.&lt;br /&gt;
====Корректность сводящей функции====&lt;br /&gt;
*Получаемое сводящей функцией множество &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; состоит из &amp;lt;tex&amp;gt;2(n+k)&amp;lt;/tex&amp;gt; десятичных чисел длиной &amp;lt;tex&amp;gt;(n+k)&amp;lt;/tex&amp;gt; каждое, выставление каждого разряда занимает полиномиальное время. Таким образом, сведение выполняется за полиномиальное время.&lt;br /&gt;
*Пусть формула &amp;lt;tex&amp;gt;\varphi&amp;lt;/tex&amp;gt; выполнима, то есть существует набор значений &amp;lt;tex&amp;gt;\{y_{i}\}^{n}_{i=1}:~\varphi(y_{1}\ldots y_{n})=1 &amp;lt;/tex&amp;gt;. И пусть &amp;lt;tex&amp;gt;(S,s) = f(\varphi)&amp;lt;/tex&amp;gt;. Тогда в полученном множестве &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; существует подмножество с суммой &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;. Действительно, для каждой переменной, если &amp;lt;tex&amp;gt;y_{k} = 1&amp;lt;/tex&amp;gt;, то добавим &amp;lt;tex&amp;gt;v_{i}&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;S'&amp;lt;/tex&amp;gt;. Иначе добавим &amp;lt;tex&amp;gt;w_{i}&amp;lt;/tex&amp;gt;. Теперь &amp;lt;tex&amp;gt;S'&amp;lt;/tex&amp;gt; содержит уже &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел. Заметим, что для каждого &amp;quot;скобочного&amp;quot; разряда в уже набранной части &amp;lt;tex&amp;gt;S'&amp;lt;/tex&amp;gt; есть не менее одного и не более трех чисел, у которых в данном разряде стоит &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt;. Значит для каждого соответствующего паре скобок &amp;lt;tex&amp;gt;C_{j}&amp;lt;/tex&amp;gt; разряда мы сможем выбрать одно или оба числа &amp;lt;tex&amp;gt;d_{j}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;e_{j}&amp;lt;/tex&amp;gt; так, чтобы сумма в данном разряде совпадала с требуемой (стала равна &amp;lt;tex&amp;gt;4&amp;lt;/tex&amp;gt;). Добавим их в &amp;lt;tex&amp;gt;S'&amp;lt;/tex&amp;gt;. Также заметим, что суммы во всех &amp;quot;переменных&amp;quot; разрядах равны &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt;, так как для каждого &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; выбиралось строго одно число из &amp;lt;tex&amp;gt;v_{i}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;u_{i}&amp;lt;/tex&amp;gt;. Значит, &amp;lt;tex&amp;gt; \sum\limits_{s_{k} \in S'}{s_{k}} = s&amp;lt;/tex&amp;gt;.&lt;br /&gt;
*Пусть теперь в наборе &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; есть подмножество &amp;lt;tex&amp;gt;S':~  \sum\limits_{s_{k} \in S'}{s_{k}} = s&amp;lt;/tex&amp;gt;. Тогда исходная формула &amp;lt;tex&amp;gt;\varphi&amp;lt;/tex&amp;gt; выполнима. Действительно, если &amp;lt;tex&amp;gt;v_{i} \in S'&amp;lt;/tex&amp;gt;, то установим переменную &amp;lt;tex&amp;gt;x_{i}=1&amp;lt;/tex&amp;gt;. Если же &amp;lt;tex&amp;gt;w_{i} \in S'&amp;lt;/tex&amp;gt;, то &amp;lt;tex&amp;gt;x_{i}=0&amp;lt;/tex&amp;gt;. Покажем, что &amp;lt;tex&amp;gt;\varphi(x_{1}\ldots x_{n}) = 1 &amp;lt;/tex&amp;gt;. Действительно, так как &amp;lt;tex&amp;gt; \sum\limits_{s_{k} \in S'}{s_{k}} = s&amp;lt;/tex&amp;gt;, в каждой паре скобок хотя бы один терм равен &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt;. Значит каждый терм равен &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt;. А тогда и вся &amp;lt;tex&amp;gt;\varphi = 1&amp;lt;/tex&amp;gt;.&lt;br /&gt;
====Пример сведения====&lt;br /&gt;
Пусть исходная функция &amp;lt;tex&amp;gt;\varphi(x_{1} \ldots x_{4}) = (x_{1} \lor x_{2} \lor \neg x_{3}) \land (\neg x_{1} \lor x_{2} \lor x_{4})&amp;lt;/tex&amp;gt;.&lt;br /&gt;
Пометим разряды следующим образом (слева направо): &amp;lt;tex&amp;gt;x_{1},x_{2},x_{3},x_{4},C_{1},C_{2}&amp;lt;/tex&amp;gt;. Тогда:&lt;br /&gt;
*&amp;lt;tex&amp;gt;v_{1} = 100010&amp;lt;/tex&amp;gt;&lt;br /&gt;
*&amp;lt;tex&amp;gt;w_{1} = 100001&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;tex&amp;gt;v_{2} = 010011 = 10011&amp;lt;/tex&amp;gt;&lt;br /&gt;
*&amp;lt;tex&amp;gt;w_{2} = 010000 = 10000&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;tex&amp;gt;v_{3} = 001000 = 1000&amp;lt;/tex&amp;gt;&lt;br /&gt;
*&amp;lt;tex&amp;gt;w_{3} = 001010 = 1010&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;tex&amp;gt;v_{4} = 000101 = 101&amp;lt;/tex&amp;gt;&lt;br /&gt;
*&amp;lt;tex&amp;gt;w_{4} = 000100 = 100&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;tex&amp;gt;d_{1} = 000010 = 10&amp;lt;/tex&amp;gt;&lt;br /&gt;
*&amp;lt;tex&amp;gt;e_{1} = 000020 = 20&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;tex&amp;gt;d_{2} = 000001 = 1&amp;lt;/tex&amp;gt;&lt;br /&gt;
*&amp;lt;tex&amp;gt;e_{2} = 000002 = 2&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;tex&amp;gt;s = 111144&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;S = (\bigcup\limits_{i=1}^{4} v_{i}) \cup (\bigcup\limits_{i=1}^{4} w_{i}) \cup (\bigcup\limits_{i=1}^{2} d_{i}) \cup (\bigcup\limits_{i=1}^{2} e_{i})&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Тогда набору значений &amp;lt;tex&amp;gt;Y = (0,0,0,1):~ \varphi(Y) = 1&amp;lt;/tex&amp;gt; соответствует &amp;lt;tex&amp;gt;S' = \{w_{1},~w_{2},~w_{3},~v_{4},~d_{1},~e_{1},~e_{2}\}&amp;lt;/tex&amp;gt;. И действительно, &amp;lt;tex&amp;gt;100001 + 10000 + 1010 + 101 + 10 + 20 + 2 = 111144&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==См. также==&lt;br /&gt;
* [[NP]]&lt;br /&gt;
* [[NPH]]&lt;br /&gt;
* [[NPC]]&lt;br /&gt;
* [[Классы NP и Σ₁]]&lt;br /&gt;
* [[3CNFSAT]]&lt;br /&gt;
* [[Примеры NP-полных языков]]&lt;br /&gt;
&lt;br /&gt;
==Источники информации==&lt;br /&gt;
* Thomas H. Cormen, Charles E. Leiserson, Ronald L. Rivest, Clifford Stein &amp;quot;Introduction to Algorithms, 3rd Edition&amp;quot; {{---}} Издательство MIT Press, 2009. {{---}} 1086 c. {{---}} ISBN 978-0-262-03384-8 (англ.)&lt;br /&gt;
* Хопкрофт Дж., Мотвани Р., Ульман Дж. Введение в теорию автоматов, языков и вычислений. 2-е издание. {{---}} М.: Издательский дом &amp;quot;Вильямс&amp;quot;, 2002. {{---}} 423 с. {{---}} ISBN 5-8459-0261-4 (рус.)&lt;br /&gt;
&lt;br /&gt;
[[Категория: Теория сложности]]&lt;br /&gt;
[[Категория: Детерминированные и недетерминированные вычисления, сложность по времени и по памяти]]&lt;br /&gt;
[[Категория: Примеры NP-полных языков]]&lt;/div&gt;</summary>
		<author><name>KirillTim</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=NP-%D0%BF%D0%BE%D0%BB%D0%BD%D0%BE%D1%82%D0%B0_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B8_%D0%BE_%D1%81%D1%83%D0%BC%D0%BC%D0%B5_%D0%BF%D0%BE%D0%B4%D0%BC%D0%BD%D0%BE%D0%B6%D0%B5%D1%81%D1%82%D0%B2%D0%B0&amp;diff=54069</id>
		<title>NP-полнота задачи о сумме подмножества</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=NP-%D0%BF%D0%BE%D0%BB%D0%BD%D0%BE%D1%82%D0%B0_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B8_%D0%BE_%D1%81%D1%83%D0%BC%D0%BC%D0%B5_%D0%BF%D0%BE%D0%B4%D0%BC%D0%BD%D0%BE%D0%B6%D0%B5%D1%81%D1%82%D0%B2%D0%B0&amp;diff=54069"/>
				<updated>2016-05-17T18:34:49Z</updated>
		
		<summary type="html">&lt;p&gt;KirillTim: /* Доказательство принадлежности NPH */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Задача&lt;br /&gt;
|definition = Дано множество &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;, содержащие &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; целых чисел и целое число &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;. Требуется выяснить, возможно ли выбрать подмножество &amp;lt;tex&amp;gt;S' \subseteq S&amp;lt;/tex&amp;gt; с суммой &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;: &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;tex&amp;gt;\exists S' \subseteq S: \sum\limits_{s_{i} \in S'}{s_{i}} = s&amp;lt;/tex&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
==Доказательство NP-полноты==&lt;br /&gt;
Для доказательства того, что '''задаче о сумме подмножества''' (англ. ''Subset sum problem'', &amp;lt;tex&amp;gt;\mathrm{SSP}&amp;lt;/tex&amp;gt;) [[NPC | NP-полной]], необходимо доказать два факта:&lt;br /&gt;
*&amp;lt;tex&amp;gt;\mathrm{SSP} \in&amp;lt;/tex&amp;gt; [[NP | &amp;lt;tex&amp;gt;\mathrm{NP}&amp;lt;/tex&amp;gt;]] &lt;br /&gt;
*&amp;lt;tex&amp;gt;\mathrm{SSP} \in&amp;lt;/tex&amp;gt; [[NPH | &amp;lt;tex&amp;gt;\mathrm{NPH}&amp;lt;/tex&amp;gt;]] &lt;br /&gt;
&lt;br /&gt;
===Доказательство принадлежности NP===&lt;br /&gt;
В качестве сертификата возьмем удовлетворяющее условию задачи множество &amp;lt;tex&amp;gt;S'&amp;lt;/tex&amp;gt; с суммой &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;. Оно удовлетворяет всем требованиям, налагаемым на сертификат. Проверяющая функция проверит вхождение всех элементов &amp;lt;tex&amp;gt;S'&amp;lt;/tex&amp;gt; в множество &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; за время &amp;lt;tex&amp;gt;\left\vert{S'}\right\vert \times \left\vert{S}\right\vert&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
===Доказательство принадлежности NPH===&lt;br /&gt;
Сведем [[NP-полнота_задачи_о_выполнимости_булевой_формулы_в_форме_3-КНФ|&amp;lt;tex&amp;gt;\mathrm{3CNFSAT}&amp;lt;/tex&amp;gt;]] к задаче о сумме подмножества. Пусть задана &amp;lt;tex&amp;gt;\mathrm{3-CNF}&amp;lt;/tex&amp;gt; формула &amp;lt;tex&amp;gt;\varphi&amp;lt;/tex&amp;gt; от &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt;&lt;br /&gt;
переменных &amp;lt;tex&amp;gt;x_{i}&amp;lt;/tex&amp;gt;, состоящая из &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; пар скобок &amp;lt;tex&amp;gt;C_{i}&amp;lt;/tex&amp;gt;. Будем считать, не умаляя общности, что ни одна пара скобок не содержит одновременно переменную и ее отрицание. Также предположим, что каждая переменная входит хотя бы в одну пару скобок. Построим сводящую функцию &amp;lt;tex&amp;gt;f\!\!:\varphi \to (S,s)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
====Построение сводящей функции====&lt;br /&gt;
Для каждой переменной &amp;lt;tex&amp;gt;x_{i}&amp;lt;/tex&amp;gt; и каждой пары скобок &amp;lt;tex&amp;gt;C_{j}&amp;lt;/tex&amp;gt; создадим по два числа в десятичной системе счисления, каждое длиной &amp;lt;tex&amp;gt;n+k&amp;lt;/tex&amp;gt; цифр. Эти числа образуют &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;. Также создадим число &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt; длиной &amp;lt;tex&amp;gt;n+k&amp;lt;/tex&amp;gt; цифр. Присвоим каждому разряду полученных чисел (одинаковую для всех чисел) метку, соответствующую либо переменной, либо паре скобок.&lt;br /&gt;
Метки, соответствующие парам скобок, присвоены &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; младшим разрядам чисел.&lt;br /&gt;
*В числе &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt; все разряды, соответствующие переменным, установим &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt;, а оставшиеся сделаем равными &amp;lt;tex&amp;gt;4&amp;lt;/tex&amp;gt;.&lt;br /&gt;
*Каждой переменной &amp;lt;tex&amp;gt;x_{i}&amp;lt;/tex&amp;gt; соответствуют два числа из &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;: &amp;lt;tex&amp;gt;v_{i}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;u_{i}&amp;lt;/tex&amp;gt;. Опишем создание этих чисел. Разряд, соответствующий &amp;lt;tex&amp;gt;x_{i}&amp;lt;/tex&amp;gt; установим равным &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt;, а все остальные разряды, соответствующие переменным, установим равными &amp;lt;tex&amp;gt;0&amp;lt;/tex&amp;gt;. Далее, для числа &amp;lt;tex&amp;gt;v_{i}&amp;lt;/tex&amp;gt; установим все разряды, соответствующие парам скобок, содержащих &amp;lt;tex&amp;gt;x_{i}&amp;lt;/tex&amp;gt;, равными &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt;. Во все остальные &amp;quot;скобочные&amp;quot; разряды поставим &amp;lt;tex&amp;gt;0&amp;lt;/tex&amp;gt;. В числе &amp;lt;tex&amp;gt;w_{i}&amp;lt;/tex&amp;gt; установим все разряды, соответствующие парам скобок, содержащих &amp;lt;tex&amp;gt;\neg x_{i}&amp;lt;/tex&amp;gt;, равными &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt;, а во все остальные &amp;quot;скобочные&amp;quot; разряды поставим &amp;lt;tex&amp;gt;0&amp;lt;/tex&amp;gt;.&lt;br /&gt;
*Каждой паре скобок &amp;lt;tex&amp;gt;C_{j}&amp;lt;/tex&amp;gt; соответствуют два числа из &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;: &amp;lt;tex&amp;gt;d_{i}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;e_{i}&amp;lt;/tex&amp;gt;. Оба этих числа содержат &amp;lt;tex&amp;gt;0&amp;lt;/tex&amp;gt; во всех разрядах, кроме соответствующего &amp;lt;tex&amp;gt;C_{j}&amp;lt;/tex&amp;gt;. В этом разряде у &amp;lt;tex&amp;gt;d_{i}&amp;lt;/tex&amp;gt; поставим &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt;, а у &amp;lt;tex&amp;gt;e_{i}&amp;lt;/tex&amp;gt; {{---}} &amp;lt;tex&amp;gt;2&amp;lt;/tex&amp;gt;.&lt;br /&gt;
====Корректность сводящей функции====&lt;br /&gt;
*Получаемое сводящей функцией множество &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; состоит из &amp;lt;tex&amp;gt;2(n+k)&amp;lt;/tex&amp;gt; десятичных чисел длиной &amp;lt;tex&amp;gt;(n+k)&amp;lt;/tex&amp;gt; каждое, выставление каждого разряда занимает полиномиальное время. Таким образом, сведение выполняется за полиномиальное время.&lt;br /&gt;
*Пусть формула &amp;lt;tex&amp;gt;\varphi&amp;lt;/tex&amp;gt; выполнима, то есть существует набор значений &amp;lt;tex&amp;gt;\{y_{i}\}^{n}_{i=1}:~\varphi(y_{1}\ldots y_{n})=1 &amp;lt;/tex&amp;gt;. И пусть &amp;lt;tex&amp;gt;(S,s) = f(\varphi)&amp;lt;/tex&amp;gt;. Тогда в полученном множестве &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; существует подмножество с суммой &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;. Действительно, для каждой переменной, если &amp;lt;tex&amp;gt;y_{k} = 1&amp;lt;/tex&amp;gt;, то добавим &amp;lt;tex&amp;gt;v_{i}&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;S'&amp;lt;/tex&amp;gt;. Иначе добавим &amp;lt;tex&amp;gt;w_{i}&amp;lt;/tex&amp;gt;. Теперь &amp;lt;tex&amp;gt;S'&amp;lt;/tex&amp;gt; содержит уже &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел. Заметим, что для каждого &amp;quot;скобочного&amp;quot; разряда в уже набранной части &amp;lt;tex&amp;gt;S'&amp;lt;/tex&amp;gt; есть не менее одного и не более трех чисел, у которых в данном разряде стоит &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt;. Значит для каждого соответствующего паре скобок &amp;lt;tex&amp;gt;C_{j}&amp;lt;/tex&amp;gt; разряда мы сможем выбрать одно или оба числа &amp;lt;tex&amp;gt;d_{j}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;e_{j}&amp;lt;/tex&amp;gt; так, чтобы сумма в данном разряде совпадала с требуемой (стала равна &amp;lt;tex&amp;gt;4&amp;lt;/tex&amp;gt;). Добавим их в &amp;lt;tex&amp;gt;S'&amp;lt;/tex&amp;gt;. Также заметим, что суммы во всех &amp;quot;переменных&amp;quot; разрядах равны &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt;, так как для каждого &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; выбиралось строго одно число из &amp;lt;tex&amp;gt;v_{i}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;u_{i}&amp;lt;/tex&amp;gt;. Значит, &amp;lt;tex&amp;gt; \sum\limits_{s_{k} \in S'}{s_{k}} = s&amp;lt;/tex&amp;gt;.&lt;br /&gt;
*Пусть теперь в наборе &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; есть подмножество &amp;lt;tex&amp;gt;S':~  \sum\limits_{s_{k} \in S'}{s_{k}} = s&amp;lt;/tex&amp;gt;. Тогда исходная формула &amp;lt;tex&amp;gt;\varphi&amp;lt;/tex&amp;gt; выполнима. Действительно, если &amp;lt;tex&amp;gt;v_{i} \in S'&amp;lt;/tex&amp;gt;, то установим переменную &amp;lt;tex&amp;gt;x_{i}=1&amp;lt;/tex&amp;gt;. Если же &amp;lt;tex&amp;gt;w_{i} \in S'&amp;lt;/tex&amp;gt;, то &amp;lt;tex&amp;gt;x_{i}=0&amp;lt;/tex&amp;gt;. Покажем, что &amp;lt;tex&amp;gt;\varphi(x_{1}\ldots x_{n}) = 1 &amp;lt;/tex&amp;gt;. Действительно, так как &amp;lt;tex&amp;gt; \sum\limits_{s_{k} \in S'}{s_{k}} = s&amp;lt;/tex&amp;gt;, в каждой паре скобок хотя бы один терм равен &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt;. Значит каждый терм равен &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt;. А тогда и вся &amp;lt;tex&amp;gt;\varphi = 1&amp;lt;/tex&amp;gt;.&lt;br /&gt;
====Пример сведения====&lt;br /&gt;
Пусть исходная функция &amp;lt;tex&amp;gt;\varphi(x_{1} \ldots x_{4}) = (x_{1} \lor x_{2} \lor \neg x_{3}) \land (\neg x_{1} \lor x_{2} \lor x_{4})&amp;lt;/tex&amp;gt;.&lt;br /&gt;
Пометим разряды следующим образом (слева направо): &amp;lt;tex&amp;gt;x_{1},x_{2},x_{3},x_{4},C_{1},C_{2}&amp;lt;/tex&amp;gt;. Тогда:&lt;br /&gt;
*&amp;lt;tex&amp;gt;v_{1} = 100010&amp;lt;/tex&amp;gt;&lt;br /&gt;
*&amp;lt;tex&amp;gt;w_{1} = 100001&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;tex&amp;gt;v_{2} = 010011 = 10011&amp;lt;/tex&amp;gt;&lt;br /&gt;
*&amp;lt;tex&amp;gt;w_{2} = 010000 = 10000&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;tex&amp;gt;v_{3} = 001000 = 1000&amp;lt;/tex&amp;gt;&lt;br /&gt;
*&amp;lt;tex&amp;gt;w_{3} = 001010 = 1010&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;tex&amp;gt;v_{4} = 000101 = 101&amp;lt;/tex&amp;gt;&lt;br /&gt;
*&amp;lt;tex&amp;gt;w_{4} = 000100 = 100&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;tex&amp;gt;d_{1} = 000010 = 10&amp;lt;/tex&amp;gt;&lt;br /&gt;
*&amp;lt;tex&amp;gt;e_{1} = 000020 = 20&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;tex&amp;gt;d_{2} = 000001 = 1&amp;lt;/tex&amp;gt;&lt;br /&gt;
*&amp;lt;tex&amp;gt;e_{2} = 000002 = 2&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;tex&amp;gt;s = 111144&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;S = (\bigcup\limits_{i=1}^{4} v_{i}) \cup (\bigcup\limits_{i=1}^{4} w_{i}) \cup (\bigcup\limits_{i=1}^{2} d_{i}) \cup (\bigcup\limits_{i=1}^{2} e_{i})&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Тогда набору значений &amp;lt;tex&amp;gt;Y = (0,0,0,1):~ \varphi(Y) = 1&amp;lt;/tex&amp;gt; соответствует &amp;lt;tex&amp;gt;S' = \{w_{1},~w_{2},~w_{3},~v_{4},~d_{1},~e_{1},~e_{2}\}&amp;lt;/tex&amp;gt;. И действительно, &amp;lt;tex&amp;gt;100001 + 10000 + 1010 + 101 + 10 + 20 + 2 = 111144&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==См. также==&lt;br /&gt;
* [[NP]]&lt;br /&gt;
* [[NPH]]&lt;br /&gt;
* [[NPC]]&lt;br /&gt;
* [[Классы NP и Σ₁]]&lt;br /&gt;
* [[3CNFSAT]]&lt;br /&gt;
* [[Примеры NP-полных языков]]&lt;br /&gt;
&lt;br /&gt;
==Источники информации==&lt;br /&gt;
* Thomas H. Cormen, Charles E. Leiserson, Ronald L. Rivest, Clifford Stein &amp;quot;Introduction to Algorithms, 3rd Edition&amp;quot; {{---}} Издательство MIT Press, 2009. {{---}} 1086 c. {{---}} ISBN 978-0-262-03384-8 (англ.)&lt;br /&gt;
* Хопкрофт Дж., Мотвани Р., Ульман Дж. Введение в теорию автоматов, языков и вычислений. 2-е издание. {{---}} М.: Издательский дом &amp;quot;Вильямс&amp;quot;, 2002. {{---}} 423 с. {{---}} ISBN 5-8459-0261-4 (рус.)&lt;br /&gt;
&lt;br /&gt;
[[Категория: Теория сложности]]&lt;br /&gt;
[[Категория: Детерминированные и недетерминированные вычисления, сложность по времени и по памяти]]&lt;br /&gt;
[[Категория: Примеры NP-полных языков]]&lt;/div&gt;</summary>
		<author><name>KirillTim</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=NP-%D0%BF%D0%BE%D0%BB%D0%BD%D0%BE%D1%82%D0%B0_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B8_%D0%BE_%D1%81%D1%83%D0%BC%D0%BC%D0%B5_%D0%BF%D0%BE%D0%B4%D0%BC%D0%BD%D0%BE%D0%B6%D0%B5%D1%81%D1%82%D0%B2%D0%B0&amp;diff=54068</id>
		<title>NP-полнота задачи о сумме подмножества</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=NP-%D0%BF%D0%BE%D0%BB%D0%BD%D0%BE%D1%82%D0%B0_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B8_%D0%BE_%D1%81%D1%83%D0%BC%D0%BC%D0%B5_%D0%BF%D0%BE%D0%B4%D0%BC%D0%BD%D0%BE%D0%B6%D0%B5%D1%81%D1%82%D0%B2%D0%B0&amp;diff=54068"/>
				<updated>2016-05-17T18:17:58Z</updated>
		
		<summary type="html">&lt;p&gt;KirillTim: mathrm 3-CNFSAT&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Задача&lt;br /&gt;
|definition = Дано множество &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;, содержащие &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; целых чисел и целое число &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;. Требуется выяснить, возможно ли выбрать подмножество &amp;lt;tex&amp;gt;S' \subseteq S&amp;lt;/tex&amp;gt; с суммой &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;: &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;tex&amp;gt;\exists S' \subseteq S: \sum\limits_{s_{i} \in S'}{s_{i}} = s&amp;lt;/tex&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
==Доказательство NP-полноты==&lt;br /&gt;
Для доказательства того, что '''задаче о сумме подмножества''' (англ. ''Subset sum problem'', &amp;lt;tex&amp;gt;\mathrm{SSP}&amp;lt;/tex&amp;gt;) [[NPC | NP-полной]], необходимо доказать два факта:&lt;br /&gt;
*&amp;lt;tex&amp;gt;\mathrm{SSP} \in&amp;lt;/tex&amp;gt; [[NP | &amp;lt;tex&amp;gt;\mathrm{NP}&amp;lt;/tex&amp;gt;]] &lt;br /&gt;
*&amp;lt;tex&amp;gt;\mathrm{SSP} \in&amp;lt;/tex&amp;gt; [[NPH | &amp;lt;tex&amp;gt;\mathrm{NPH}&amp;lt;/tex&amp;gt;]] &lt;br /&gt;
&lt;br /&gt;
===Доказательство принадлежности NP===&lt;br /&gt;
В качестве сертификата возьмем удовлетворяющее условию задачи множество &amp;lt;tex&amp;gt;S'&amp;lt;/tex&amp;gt; с суммой &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;. Оно удовлетворяет всем требованиям, налагаемым на сертификат. Проверяющая функция проверит вхождение всех элементов &amp;lt;tex&amp;gt;S'&amp;lt;/tex&amp;gt; в множество &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; за время &amp;lt;tex&amp;gt;\left\vert{S'}\right\vert \times \left\vert{S}\right\vert&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
===Доказательство принадлежности NPH===&lt;br /&gt;
Сведем [[NP-полнота_задачи_о_выполнимости_булевой_формулы_в_форме_3-КНФ|&amp;lt;tex&amp;gt;\mathrm{3-CNFSAT}&amp;lt;/tex&amp;gt;]] к задаче о сумме подмножества. Пусть задана 3-CNF формула &amp;lt;tex&amp;gt;\varphi&amp;lt;/tex&amp;gt; от &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt;&lt;br /&gt;
переменных &amp;lt;tex&amp;gt;x_{i}&amp;lt;/tex&amp;gt;, состоящая из &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; пар скобок &amp;lt;tex&amp;gt;C_{i}&amp;lt;/tex&amp;gt;. Будем считать, не умаляя общности, что ни одна пара скобок не содержит одновременно переменную и ее отрицание. Также предположим, что каждая переменная входит хотя бы в одну пару скобок. Построим сводящую функцию &amp;lt;tex&amp;gt;f\!\!:\varphi \to (S,s)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
====Построение сводящей функции====&lt;br /&gt;
Для каждой переменной &amp;lt;tex&amp;gt;x_{i}&amp;lt;/tex&amp;gt; и каждой пары скобок &amp;lt;tex&amp;gt;C_{j}&amp;lt;/tex&amp;gt; создадим по два числа в десятичной системе счисления, каждое длиной &amp;lt;tex&amp;gt;n+k&amp;lt;/tex&amp;gt; цифр. Эти числа образуют &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;. Также создадим число &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt; длиной &amp;lt;tex&amp;gt;n+k&amp;lt;/tex&amp;gt; цифр. Присвоим каждому разряду полученных чисел (одинаковую для всех чисел) метку, соответствующую либо переменной, либо паре скобок.&lt;br /&gt;
Метки, соответствующие парам скобок, присвоены &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; младшим разрядам чисел.&lt;br /&gt;
*В числе &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt; все разряды, соответствующие переменным, установим &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt;, а оставшиеся сделаем равными &amp;lt;tex&amp;gt;4&amp;lt;/tex&amp;gt;.&lt;br /&gt;
*Каждой переменной &amp;lt;tex&amp;gt;x_{i}&amp;lt;/tex&amp;gt; соответствуют два числа из &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;: &amp;lt;tex&amp;gt;v_{i}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;u_{i}&amp;lt;/tex&amp;gt;. Опишем создание этих чисел. Разряд, соответствующий &amp;lt;tex&amp;gt;x_{i}&amp;lt;/tex&amp;gt; установим равным &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt;, а все остальные разряды, соответствующие переменным, установим равными &amp;lt;tex&amp;gt;0&amp;lt;/tex&amp;gt;. Далее, для числа &amp;lt;tex&amp;gt;v_{i}&amp;lt;/tex&amp;gt; установим все разряды, соответствующие парам скобок, содержащих &amp;lt;tex&amp;gt;x_{i}&amp;lt;/tex&amp;gt;, равными &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt;. Во все остальные &amp;quot;скобочные&amp;quot; разряды поставим &amp;lt;tex&amp;gt;0&amp;lt;/tex&amp;gt;. В числе &amp;lt;tex&amp;gt;w_{i}&amp;lt;/tex&amp;gt; установим все разряды, соответствующие парам скобок, содержащих &amp;lt;tex&amp;gt;\neg x_{i}&amp;lt;/tex&amp;gt;, равными &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt;, а во все остальные &amp;quot;скобочные&amp;quot; разряды поставим &amp;lt;tex&amp;gt;0&amp;lt;/tex&amp;gt;.&lt;br /&gt;
*Каждой паре скобок &amp;lt;tex&amp;gt;C_{j}&amp;lt;/tex&amp;gt; соответствуют два числа из &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;: &amp;lt;tex&amp;gt;d_{i}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;e_{i}&amp;lt;/tex&amp;gt;. Оба этих числа содержат &amp;lt;tex&amp;gt;0&amp;lt;/tex&amp;gt; во всех разрядах, кроме соответствующего &amp;lt;tex&amp;gt;C_{j}&amp;lt;/tex&amp;gt;. В этом разряде у &amp;lt;tex&amp;gt;d_{i}&amp;lt;/tex&amp;gt; поставим &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt;, а у &amp;lt;tex&amp;gt;e_{i}&amp;lt;/tex&amp;gt; {{---}} &amp;lt;tex&amp;gt;2&amp;lt;/tex&amp;gt;.&lt;br /&gt;
====Корректность сводящей функции====&lt;br /&gt;
*Получаемое сводящей функцией множество &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; состоит из &amp;lt;tex&amp;gt;2(n+k)&amp;lt;/tex&amp;gt; десятичных чисел длиной &amp;lt;tex&amp;gt;(n+k)&amp;lt;/tex&amp;gt; каждое, выставление каждого разряда занимает полиномиальное время. Таким образом, сведение выполняется за полиномиальное время.&lt;br /&gt;
*Пусть формула &amp;lt;tex&amp;gt;\varphi&amp;lt;/tex&amp;gt; выполнима, то есть существует набор значений &amp;lt;tex&amp;gt;\{y_{i}\}^{n}_{i=1}:~\varphi(y_{1}\ldots y_{n})=1 &amp;lt;/tex&amp;gt;. И пусть &amp;lt;tex&amp;gt;(S,s) = f(\varphi)&amp;lt;/tex&amp;gt;. Тогда в полученном множестве &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; существует подмножество с суммой &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;. Действительно, для каждой переменной, если &amp;lt;tex&amp;gt;y_{k} = 1&amp;lt;/tex&amp;gt;, то добавим &amp;lt;tex&amp;gt;v_{i}&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;S'&amp;lt;/tex&amp;gt;. Иначе добавим &amp;lt;tex&amp;gt;w_{i}&amp;lt;/tex&amp;gt;. Теперь &amp;lt;tex&amp;gt;S'&amp;lt;/tex&amp;gt; содержит уже &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел. Заметим, что для каждого &amp;quot;скобочного&amp;quot; разряда в уже набранной части &amp;lt;tex&amp;gt;S'&amp;lt;/tex&amp;gt; есть не менее одного и не более трех чисел, у которых в данном разряде стоит &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt;. Значит для каждого соответствующего паре скобок &amp;lt;tex&amp;gt;C_{j}&amp;lt;/tex&amp;gt; разряда мы сможем выбрать одно или оба числа &amp;lt;tex&amp;gt;d_{j}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;e_{j}&amp;lt;/tex&amp;gt; так, чтобы сумма в данном разряде совпадала с требуемой (стала равна &amp;lt;tex&amp;gt;4&amp;lt;/tex&amp;gt;). Добавим их в &amp;lt;tex&amp;gt;S'&amp;lt;/tex&amp;gt;. Также заметим, что суммы во всех &amp;quot;переменных&amp;quot; разрядах равны &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt;, так как для каждого &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; выбиралось строго одно число из &amp;lt;tex&amp;gt;v_{i}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;u_{i}&amp;lt;/tex&amp;gt;. Значит, &amp;lt;tex&amp;gt; \sum\limits_{s_{k} \in S'}{s_{k}} = s&amp;lt;/tex&amp;gt;.&lt;br /&gt;
*Пусть теперь в наборе &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; есть подмножество &amp;lt;tex&amp;gt;S':~  \sum\limits_{s_{k} \in S'}{s_{k}} = s&amp;lt;/tex&amp;gt;. Тогда исходная формула &amp;lt;tex&amp;gt;\varphi&amp;lt;/tex&amp;gt; выполнима. Действительно, если &amp;lt;tex&amp;gt;v_{i} \in S'&amp;lt;/tex&amp;gt;, то установим переменную &amp;lt;tex&amp;gt;x_{i}=1&amp;lt;/tex&amp;gt;. Если же &amp;lt;tex&amp;gt;w_{i} \in S'&amp;lt;/tex&amp;gt;, то &amp;lt;tex&amp;gt;x_{i}=0&amp;lt;/tex&amp;gt;. Покажем, что &amp;lt;tex&amp;gt;\varphi(x_{1}\ldots x_{n}) = 1 &amp;lt;/tex&amp;gt;. Действительно, так как &amp;lt;tex&amp;gt; \sum\limits_{s_{k} \in S'}{s_{k}} = s&amp;lt;/tex&amp;gt;, в каждой паре скобок хотя бы один терм равен &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt;. Значит каждый терм равен &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt;. А тогда и вся &amp;lt;tex&amp;gt;\varphi = 1&amp;lt;/tex&amp;gt;.&lt;br /&gt;
====Пример сведения====&lt;br /&gt;
Пусть исходная функция &amp;lt;tex&amp;gt;\varphi(x_{1} \ldots x_{4}) = (x_{1} \lor x_{2} \lor \neg x_{3}) \land (\neg x_{1} \lor x_{2} \lor x_{4})&amp;lt;/tex&amp;gt;.&lt;br /&gt;
Пометим разряды следующим образом (слева направо): &amp;lt;tex&amp;gt;x_{1},x_{2},x_{3},x_{4},C_{1},C_{2}&amp;lt;/tex&amp;gt;. Тогда:&lt;br /&gt;
*&amp;lt;tex&amp;gt;v_{1} = 100010&amp;lt;/tex&amp;gt;&lt;br /&gt;
*&amp;lt;tex&amp;gt;w_{1} = 100001&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;tex&amp;gt;v_{2} = 010011 = 10011&amp;lt;/tex&amp;gt;&lt;br /&gt;
*&amp;lt;tex&amp;gt;w_{2} = 010000 = 10000&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;tex&amp;gt;v_{3} = 001000 = 1000&amp;lt;/tex&amp;gt;&lt;br /&gt;
*&amp;lt;tex&amp;gt;w_{3} = 001010 = 1010&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;tex&amp;gt;v_{4} = 000101 = 101&amp;lt;/tex&amp;gt;&lt;br /&gt;
*&amp;lt;tex&amp;gt;w_{4} = 000100 = 100&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;tex&amp;gt;d_{1} = 000010 = 10&amp;lt;/tex&amp;gt;&lt;br /&gt;
*&amp;lt;tex&amp;gt;e_{1} = 000020 = 20&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;tex&amp;gt;d_{2} = 000001 = 1&amp;lt;/tex&amp;gt;&lt;br /&gt;
*&amp;lt;tex&amp;gt;e_{2} = 000002 = 2&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;tex&amp;gt;s = 111144&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;S = (\bigcup\limits_{i=1}^{4} v_{i}) \cup (\bigcup\limits_{i=1}^{4} w_{i}) \cup (\bigcup\limits_{i=1}^{2} d_{i}) \cup (\bigcup\limits_{i=1}^{2} e_{i})&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Тогда набору значений &amp;lt;tex&amp;gt;Y = (0,0,0,1):~ \varphi(Y) = 1&amp;lt;/tex&amp;gt; соответствует &amp;lt;tex&amp;gt;S' = \{w_{1},~w_{2},~w_{3},~v_{4},~d_{1},~e_{1},~e_{2}\}&amp;lt;/tex&amp;gt;. И действительно, &amp;lt;tex&amp;gt;100001 + 10000 + 1010 + 101 + 10 + 20 + 2 = 111144&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==См. также==&lt;br /&gt;
* [[NP]]&lt;br /&gt;
* [[NPH]]&lt;br /&gt;
* [[NPC]]&lt;br /&gt;
* [[Классы NP и Σ₁]]&lt;br /&gt;
* [[3CNFSAT]]&lt;br /&gt;
* [[Примеры NP-полных языков]]&lt;br /&gt;
&lt;br /&gt;
==Источники информации==&lt;br /&gt;
* Thomas H. Cormen, Charles E. Leiserson, Ronald L. Rivest, Clifford Stein &amp;quot;Introduction to Algorithms, 3rd Edition&amp;quot; {{---}} Издательство MIT Press, 2009. {{---}} 1086 c. {{---}} ISBN 978-0-262-03384-8 (англ.)&lt;br /&gt;
* Хопкрофт Дж., Мотвани Р., Ульман Дж. Введение в теорию автоматов, языков и вычислений. 2-е издание. {{---}} М.: Издательский дом &amp;quot;Вильямс&amp;quot;, 2002. {{---}} 423 с. {{---}} ISBN 5-8459-0261-4 (рус.)&lt;br /&gt;
&lt;br /&gt;
[[Категория: Теория сложности]]&lt;br /&gt;
[[Категория: Детерминированные и недетерминированные вычисления, сложность по времени и по памяти]]&lt;br /&gt;
[[Категория: Примеры NP-полных языков]]&lt;/div&gt;</summary>
		<author><name>KirillTim</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=NP-%D0%BF%D0%BE%D0%BB%D0%BD%D0%BE%D1%82%D0%B0_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B8_%D0%BE_%D1%81%D1%83%D0%BC%D0%BC%D0%B5_%D0%BF%D0%BE%D0%B4%D0%BC%D0%BD%D0%BE%D0%B6%D0%B5%D1%81%D1%82%D0%B2%D0%B0&amp;diff=54067</id>
		<title>NP-полнота задачи о сумме подмножества</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=NP-%D0%BF%D0%BE%D0%BB%D0%BD%D0%BE%D1%82%D0%B0_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B8_%D0%BE_%D1%81%D1%83%D0%BC%D0%BC%D0%B5_%D0%BF%D0%BE%D0%B4%D0%BC%D0%BD%D0%BE%D0%B6%D0%B5%D1%81%D1%82%D0%B2%D0%B0&amp;diff=54067"/>
				<updated>2016-05-17T18:14:59Z</updated>
		
		<summary type="html">&lt;p&gt;KirillTim: math -&amp;gt; tex&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Задача&lt;br /&gt;
|definition = Дано множество &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;, содержащие &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; целых чисел и целое число &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;. Требуется выяснить, возможно ли выбрать подмножество &amp;lt;tex&amp;gt;S' \subseteq S&amp;lt;/tex&amp;gt; с суммой &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;: &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;tex&amp;gt;\exists S' \subseteq S: \sum\limits_{s_{i} \in S'}{s_{i}} = s&amp;lt;/tex&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
==Доказательство NP-полноты==&lt;br /&gt;
Для доказательства того, что '''задаче о сумме подмножества''' (англ. ''Subset sum problem'', &amp;lt;tex&amp;gt;\mathrm{SSP}&amp;lt;/tex&amp;gt;) [[NPC | NP-полной]], необходимо доказать два факта:&lt;br /&gt;
*&amp;lt;tex&amp;gt;\mathrm{SSP} \in&amp;lt;/tex&amp;gt; [[NP | &amp;lt;tex&amp;gt;\mathrm{NP}&amp;lt;/tex&amp;gt;]] &lt;br /&gt;
*&amp;lt;tex&amp;gt;\mathrm{SSP} \in&amp;lt;/tex&amp;gt; [[NPH | &amp;lt;tex&amp;gt;\mathrm{NPH}&amp;lt;/tex&amp;gt;]] &lt;br /&gt;
&lt;br /&gt;
===Доказательство принадлежности NP===&lt;br /&gt;
В качестве сертификата возьмем удовлетворяющее условию задачи множество &amp;lt;tex&amp;gt;S'&amp;lt;/tex&amp;gt; с суммой &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;. Оно удовлетворяет всем требованиям, налагаемым на сертификат. Проверяющая функция проверит вхождение всех элементов &amp;lt;tex&amp;gt;S'&amp;lt;/tex&amp;gt; в множество &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; за время &amp;lt;tex&amp;gt;\left\vert{S'}\right\vert \times \left\vert{S}\right\vert&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
===Доказательство принадлежности NPH===&lt;br /&gt;
Сведем [[NP-полнота_задачи_о_выполнимости_булевой_формулы_в_форме_3-КНФ|3-CNF_Sat]] к задаче о сумме подмножества. Пусть задана 3-CNF формула &amp;lt;tex&amp;gt;\varphi&amp;lt;/tex&amp;gt; от &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt;&lt;br /&gt;
переменных &amp;lt;tex&amp;gt;x_{i}&amp;lt;/tex&amp;gt;, состоящая из &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; пар скобок &amp;lt;tex&amp;gt;C_{i}&amp;lt;/tex&amp;gt;. Будем считать, не умаляя общности, что ни одна пара скобок не содержит одновременно переменную и ее отрицание. Также предположим, что каждая переменная входит хотя бы в одну пару скобок. Построим сводящую функцию &amp;lt;tex&amp;gt;f\!\!:\varphi \to (S,s)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
====Построение сводящей функции====&lt;br /&gt;
Для каждой переменной &amp;lt;tex&amp;gt;x_{i}&amp;lt;/tex&amp;gt; и каждой пары скобок &amp;lt;tex&amp;gt;C_{j}&amp;lt;/tex&amp;gt; создадим по два числа в десятичной системе счисления, каждое длиной &amp;lt;tex&amp;gt;n+k&amp;lt;/tex&amp;gt; цифр. Эти числа образуют &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;. Также создадим число &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt; длиной &amp;lt;tex&amp;gt;n+k&amp;lt;/tex&amp;gt; цифр. Присвоим каждому разряду полученных чисел (одинаковую для всех чисел) метку, соответствующую либо переменной, либо паре скобок.&lt;br /&gt;
Метки, соответствующие парам скобок, присвоены &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; младшим разрядам чисел.&lt;br /&gt;
*В числе &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt; все разряды, соответствующие переменным, установим &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt;, а оставшиеся сделаем равными &amp;lt;tex&amp;gt;4&amp;lt;/tex&amp;gt;.&lt;br /&gt;
*Каждой переменной &amp;lt;tex&amp;gt;x_{i}&amp;lt;/tex&amp;gt; соответствуют два числа из &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;: &amp;lt;tex&amp;gt;v_{i}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;u_{i}&amp;lt;/tex&amp;gt;. Опишем создание этих чисел. Разряд, соответствующий &amp;lt;tex&amp;gt;x_{i}&amp;lt;/tex&amp;gt; установим равным &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt;, а все остальные разряды, соответствующие переменным, установим равными &amp;lt;tex&amp;gt;0&amp;lt;/tex&amp;gt;. Далее, для числа &amp;lt;tex&amp;gt;v_{i}&amp;lt;/tex&amp;gt; установим все разряды, соответствующие парам скобок, содержащих &amp;lt;tex&amp;gt;x_{i}&amp;lt;/tex&amp;gt;, равными &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt;. Во все остальные &amp;quot;скобочные&amp;quot; разряды поставим &amp;lt;tex&amp;gt;0&amp;lt;/tex&amp;gt;. В числе &amp;lt;tex&amp;gt;w_{i}&amp;lt;/tex&amp;gt; установим все разряды, соответствующие парам скобок, содержащих &amp;lt;tex&amp;gt;\neg x_{i}&amp;lt;/tex&amp;gt;, равными &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt;, а во все остальные &amp;quot;скобочные&amp;quot; разряды поставим &amp;lt;tex&amp;gt;0&amp;lt;/tex&amp;gt;.&lt;br /&gt;
*Каждой паре скобок &amp;lt;tex&amp;gt;C_{j}&amp;lt;/tex&amp;gt; соответствуют два числа из &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;: &amp;lt;tex&amp;gt;d_{i}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;e_{i}&amp;lt;/tex&amp;gt;. Оба этих числа содержат &amp;lt;tex&amp;gt;0&amp;lt;/tex&amp;gt; во всех разрядах, кроме соответствующего &amp;lt;tex&amp;gt;C_{j}&amp;lt;/tex&amp;gt;. В этом разряде у &amp;lt;tex&amp;gt;d_{i}&amp;lt;/tex&amp;gt; поставим &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt;, а у &amp;lt;tex&amp;gt;e_{i}&amp;lt;/tex&amp;gt; {{---}} &amp;lt;tex&amp;gt;2&amp;lt;/tex&amp;gt;.&lt;br /&gt;
====Корректность сводящей функции====&lt;br /&gt;
*Получаемое сводящей функцией множество &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; состоит из &amp;lt;tex&amp;gt;2(n+k)&amp;lt;/tex&amp;gt; десятичных чисел длиной &amp;lt;tex&amp;gt;(n+k)&amp;lt;/tex&amp;gt; каждое, выставление каждого разряда занимает полиномиальное время. Таким образом, сведение выполняется за полиномиальное время.&lt;br /&gt;
*Пусть формула &amp;lt;tex&amp;gt;\varphi&amp;lt;/tex&amp;gt; выполнима, то есть существует набор значений &amp;lt;tex&amp;gt;\{y_{i}\}^{n}_{i=1}:~\varphi(y_{1}\ldots y_{n})=1 &amp;lt;/tex&amp;gt;. И пусть &amp;lt;tex&amp;gt;(S,s) = f(\varphi)&amp;lt;/tex&amp;gt;. Тогда в полученном множестве &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; существует подмножество с суммой &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;. Действительно, для каждой переменной, если &amp;lt;tex&amp;gt;y_{k} = 1&amp;lt;/tex&amp;gt;, то добавим &amp;lt;tex&amp;gt;v_{i}&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;S'&amp;lt;/tex&amp;gt;. Иначе добавим &amp;lt;tex&amp;gt;w_{i}&amp;lt;/tex&amp;gt;. Теперь &amp;lt;tex&amp;gt;S'&amp;lt;/tex&amp;gt; содержит уже &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел. Заметим, что для каждого &amp;quot;скобочного&amp;quot; разряда в уже набранной части &amp;lt;tex&amp;gt;S'&amp;lt;/tex&amp;gt; есть не менее одного и не более трех чисел, у которых в данном разряде стоит &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt;. Значит для каждого соответствующего паре скобок &amp;lt;tex&amp;gt;C_{j}&amp;lt;/tex&amp;gt; разряда мы сможем выбрать одно или оба числа &amp;lt;tex&amp;gt;d_{j}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;e_{j}&amp;lt;/tex&amp;gt; так, чтобы сумма в данном разряде совпадала с требуемой (стала равна &amp;lt;tex&amp;gt;4&amp;lt;/tex&amp;gt;). Добавим их в &amp;lt;tex&amp;gt;S'&amp;lt;/tex&amp;gt;. Также заметим, что суммы во всех &amp;quot;переменных&amp;quot; разрядах равны &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt;, так как для каждого &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; выбиралось строго одно число из &amp;lt;tex&amp;gt;v_{i}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;u_{i}&amp;lt;/tex&amp;gt;. Значит, &amp;lt;tex&amp;gt; \sum\limits_{s_{k} \in S'}{s_{k}} = s&amp;lt;/tex&amp;gt;.&lt;br /&gt;
*Пусть теперь в наборе &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; есть подмножество &amp;lt;tex&amp;gt;S':~  \sum\limits_{s_{k} \in S'}{s_{k}} = s&amp;lt;/tex&amp;gt;. Тогда исходная формула &amp;lt;tex&amp;gt;\varphi&amp;lt;/tex&amp;gt; выполнима. Действительно, если &amp;lt;tex&amp;gt;v_{i} \in S'&amp;lt;/tex&amp;gt;, то установим переменную &amp;lt;tex&amp;gt;x_{i}=1&amp;lt;/tex&amp;gt;. Если же &amp;lt;tex&amp;gt;w_{i} \in S'&amp;lt;/tex&amp;gt;, то &amp;lt;tex&amp;gt;x_{i}=0&amp;lt;/tex&amp;gt;. Покажем, что &amp;lt;tex&amp;gt;\varphi(x_{1}\ldots x_{n}) = 1 &amp;lt;/tex&amp;gt;. Действительно, так как &amp;lt;tex&amp;gt; \sum\limits_{s_{k} \in S'}{s_{k}} = s&amp;lt;/tex&amp;gt;, в каждой паре скобок хотя бы один терм равен &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt;. Значит каждый терм равен &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt;. А тогда и вся &amp;lt;tex&amp;gt;\varphi = 1&amp;lt;/tex&amp;gt;.&lt;br /&gt;
====Пример сведения====&lt;br /&gt;
Пусть исходная функция &amp;lt;tex&amp;gt;\varphi(x_{1} \ldots x_{4}) = (x_{1} \lor x_{2} \lor \neg x_{3}) \land (\neg x_{1} \lor x_{2} \lor x_{4})&amp;lt;/tex&amp;gt;.&lt;br /&gt;
Пометим разряды следующим образом (слева направо): &amp;lt;tex&amp;gt;x_{1},x_{2},x_{3},x_{4},C_{1},C_{2}&amp;lt;/tex&amp;gt;. Тогда:&lt;br /&gt;
*&amp;lt;tex&amp;gt;v_{1} = 100010&amp;lt;/tex&amp;gt;&lt;br /&gt;
*&amp;lt;tex&amp;gt;w_{1} = 100001&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;tex&amp;gt;v_{2} = 010011 = 10011&amp;lt;/tex&amp;gt;&lt;br /&gt;
*&amp;lt;tex&amp;gt;w_{2} = 010000 = 10000&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;tex&amp;gt;v_{3} = 001000 = 1000&amp;lt;/tex&amp;gt;&lt;br /&gt;
*&amp;lt;tex&amp;gt;w_{3} = 001010 = 1010&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;tex&amp;gt;v_{4} = 000101 = 101&amp;lt;/tex&amp;gt;&lt;br /&gt;
*&amp;lt;tex&amp;gt;w_{4} = 000100 = 100&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;tex&amp;gt;d_{1} = 000010 = 10&amp;lt;/tex&amp;gt;&lt;br /&gt;
*&amp;lt;tex&amp;gt;e_{1} = 000020 = 20&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;tex&amp;gt;d_{2} = 000001 = 1&amp;lt;/tex&amp;gt;&lt;br /&gt;
*&amp;lt;tex&amp;gt;e_{2} = 000002 = 2&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;tex&amp;gt;s = 111144&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;S = (\bigcup\limits_{i=1}^{4} v_{i}) \cup (\bigcup\limits_{i=1}^{4} w_{i}) \cup (\bigcup\limits_{i=1}^{2} d_{i}) \cup (\bigcup\limits_{i=1}^{2} e_{i})&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Тогда набору значений &amp;lt;tex&amp;gt;Y = (0,0,0,1):~ \varphi(Y) = 1&amp;lt;/tex&amp;gt; соответствует &amp;lt;tex&amp;gt;S' = \{w_{1},~w_{2},~w_{3},~v_{4},~d_{1},~e_{1},~e_{2}\}&amp;lt;/tex&amp;gt;. И действительно, &amp;lt;tex&amp;gt;100001 + 10000 + 1010 + 101 + 10 + 20 + 2 = 111144&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==См. также==&lt;br /&gt;
* [[NP]]&lt;br /&gt;
* [[NPH]]&lt;br /&gt;
* [[NPC]]&lt;br /&gt;
* [[Классы NP и Σ₁]]&lt;br /&gt;
* [[3CNFSAT]]&lt;br /&gt;
* [[Примеры NP-полных языков]]&lt;br /&gt;
&lt;br /&gt;
==Источники информации==&lt;br /&gt;
* Thomas H. Cormen, Charles E. Leiserson, Ronald L. Rivest, Clifford Stein &amp;quot;Introduction to Algorithms, 3rd Edition&amp;quot; {{---}} Издательство MIT Press, 2009. {{---}} 1086 c. {{---}} ISBN 978-0-262-03384-8 (англ.)&lt;br /&gt;
* Хопкрофт Дж., Мотвани Р., Ульман Дж. Введение в теорию автоматов, языков и вычислений. 2-е издание. {{---}} М.: Издательский дом &amp;quot;Вильямс&amp;quot;, 2002. {{---}} 423 с. {{---}} ISBN 5-8459-0261-4 (рус.)&lt;br /&gt;
&lt;br /&gt;
[[Категория: Теория сложности]]&lt;br /&gt;
[[Категория: Детерминированные и недетерминированные вычисления, сложность по времени и по памяти]]&lt;br /&gt;
[[Категория: Примеры NP-полных языков]]&lt;/div&gt;</summary>
		<author><name>KirillTim</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=NP-%D0%BF%D0%BE%D0%BB%D0%BD%D0%BE%D1%82%D0%B0_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B8_%D0%BE_%D1%81%D1%83%D0%BC%D0%BC%D0%B5_%D0%BF%D0%BE%D0%B4%D0%BC%D0%BD%D0%BE%D0%B6%D0%B5%D1%81%D1%82%D0%B2%D0%B0&amp;diff=54066</id>
		<title>NP-полнота задачи о сумме подмножества</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=NP-%D0%BF%D0%BE%D0%BB%D0%BD%D0%BE%D1%82%D0%B0_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B8_%D0%BE_%D1%81%D1%83%D0%BC%D0%BC%D0%B5_%D0%BF%D0%BE%D0%B4%D0%BC%D0%BD%D0%BE%D0%B6%D0%B5%D1%81%D1%82%D0%B2%D0%B0&amp;diff=54066"/>
				<updated>2016-05-17T18:11:52Z</updated>
		
		<summary type="html">&lt;p&gt;KirillTim: br&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Задача&lt;br /&gt;
|definition = Дано множество &amp;lt;math&amp;gt;S&amp;lt;/math&amp;gt;, содержащие &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; целых чисел и целое число &amp;lt;math&amp;gt;s&amp;lt;/math&amp;gt;. Требуется выяснить, возможно ли выбрать подмножество &amp;lt;math&amp;gt;S' \subseteq S&amp;lt;/math&amp;gt; с суммой &amp;lt;math&amp;gt;s&amp;lt;/math&amp;gt;: &amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;\exists S' \subseteq S: \sum\limits_{s_{i} \in S'}{s_{i}} = s&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
==Доказательство NP-полноты==&lt;br /&gt;
Для доказательства того, что '''задаче о сумме подмножества''' (англ. ''Subset sum problem'', &amp;lt;math&amp;gt;\mathrm{SSP}&amp;lt;/math&amp;gt;) [[NPC | NP-полной]], необходимо доказать два факта:&lt;br /&gt;
*&amp;lt;math&amp;gt;\mathrm{SSP} \in&amp;lt;/math&amp;gt; [[NP | &amp;lt;math&amp;gt;\mathrm{NP}&amp;lt;/math&amp;gt;]] &lt;br /&gt;
*&amp;lt;math&amp;gt;\mathrm{SSP} \in&amp;lt;/math&amp;gt; [[NPH | &amp;lt;math&amp;gt;\mathrm{NPH}&amp;lt;/math&amp;gt;]] &lt;br /&gt;
&lt;br /&gt;
===Доказательство принадлежности NP===&lt;br /&gt;
В качестве сертификата возьмем удовлетворяющее условию задачи множество &amp;lt;math&amp;gt;S'&amp;lt;/math&amp;gt; с суммой &amp;lt;math&amp;gt;s&amp;lt;/math&amp;gt;. Оно удовлетворяет всем требованиям, налагаемым на сертификат. Проверяющая функция проверит вхождение всех элементов &amp;lt;math&amp;gt;S'&amp;lt;/math&amp;gt; в множество &amp;lt;math&amp;gt;S&amp;lt;/math&amp;gt; за время &amp;lt;math&amp;gt;\left\vert{S'}\right\vert \times \left\vert{S}\right\vert&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
===Доказательство принадлежности NPH===&lt;br /&gt;
Сведем [[NP-полнота_задачи_о_выполнимости_булевой_формулы_в_форме_3-КНФ|3-CNF_Sat]] к задаче о сумме подмножества. Пусть задана 3-CNF формула &amp;lt;math&amp;gt;\varphi&amp;lt;/math&amp;gt; от &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;&lt;br /&gt;
переменных &amp;lt;math&amp;gt;x_{i}&amp;lt;/math&amp;gt;, состоящая из &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; пар скобок &amp;lt;math&amp;gt;C_{i}&amp;lt;/math&amp;gt;. Будем считать, не умаляя общности, что ни одна пара скобок не содержит одновременно переменную и ее отрицание. Также предположим, что каждая переменная входит хотя бы в одну пару скобок. Построим сводящую функцию &amp;lt;math&amp;gt;f\!\!:\varphi \to (S,s)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
====Построение сводящей функции====&lt;br /&gt;
Для каждой переменной &amp;lt;math&amp;gt;x_{i}&amp;lt;/math&amp;gt; и каждой пары скобок &amp;lt;math&amp;gt;C_{j}&amp;lt;/math&amp;gt; создадим по два числа в десятичной системе счисления, каждое длиной &amp;lt;math&amp;gt;n+k&amp;lt;/math&amp;gt; цифр. Эти числа образуют &amp;lt;math&amp;gt;S&amp;lt;/math&amp;gt;. Также создадим число &amp;lt;math&amp;gt;s&amp;lt;/math&amp;gt; длиной &amp;lt;math&amp;gt;n+k&amp;lt;/math&amp;gt; цифр. Присвоим каждому разряду полученных чисел (одинаковую для всех чисел) метку, соответствующую либо переменной, либо паре скобок.&lt;br /&gt;
Метки, соответствующие парам скобок, присвоены &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; младшим разрядам чисел.&lt;br /&gt;
*В числе &amp;lt;math&amp;gt;s&amp;lt;/math&amp;gt; все разряды, соответствующие переменным, установим &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt;, а оставшиеся сделаем равными &amp;lt;math&amp;gt;4&amp;lt;/math&amp;gt;.&lt;br /&gt;
*Каждой переменной &amp;lt;math&amp;gt;x_{i}&amp;lt;/math&amp;gt; соответствуют два числа из &amp;lt;math&amp;gt;S&amp;lt;/math&amp;gt;: &amp;lt;math&amp;gt;v_{i}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;u_{i}&amp;lt;/math&amp;gt;. Опишем создание этих чисел. Разряд, соответствующий &amp;lt;math&amp;gt;x_{i}&amp;lt;/math&amp;gt; установим равным &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt;, а все остальные разряды, соответствующие переменным, установим равными &amp;lt;math&amp;gt;0&amp;lt;/math&amp;gt;. Далее, для числа &amp;lt;math&amp;gt;v_{i}&amp;lt;/math&amp;gt; установим все разряды, соответствующие парам скобок, содержащих &amp;lt;math&amp;gt;x_{i}&amp;lt;/math&amp;gt;, равными &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt;. Во все остальные &amp;quot;скобочные&amp;quot; разряды поставим &amp;lt;math&amp;gt;0&amp;lt;/math&amp;gt;. В числе &amp;lt;math&amp;gt;w_{i}&amp;lt;/math&amp;gt; установим все разряды, соответствующие парам скобок, содержащих &amp;lt;math&amp;gt;\neg x_{i}&amp;lt;/math&amp;gt;, равными &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt;, а во все остальные &amp;quot;скобочные&amp;quot; разряды поставим &amp;lt;math&amp;gt;0&amp;lt;/math&amp;gt;.&lt;br /&gt;
*Каждой паре скобок &amp;lt;math&amp;gt;C_{j}&amp;lt;/math&amp;gt; соответствуют два числа из &amp;lt;math&amp;gt;S&amp;lt;/math&amp;gt;: &amp;lt;math&amp;gt;d_{i}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;e_{i}&amp;lt;/math&amp;gt;. Оба этих числа содержат &amp;lt;math&amp;gt;0&amp;lt;/math&amp;gt; во всех разрядах, кроме соответствующего &amp;lt;math&amp;gt;C_{j}&amp;lt;/math&amp;gt;. В этом разряде у &amp;lt;math&amp;gt;d_{i}&amp;lt;/math&amp;gt; поставим &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt;, а у &amp;lt;math&amp;gt;e_{i}&amp;lt;/math&amp;gt; {{---}} &amp;lt;math&amp;gt;2&amp;lt;/math&amp;gt;.&lt;br /&gt;
====Корректность сводящей функции====&lt;br /&gt;
*Получаемое сводящей функцией множество &amp;lt;math&amp;gt;S&amp;lt;/math&amp;gt; состоит из &amp;lt;math&amp;gt;2(n+k)&amp;lt;/math&amp;gt; десятичных чисел длиной &amp;lt;math&amp;gt;(n+k)&amp;lt;/math&amp;gt; каждое, выставление каждого разряда занимает полиномиальное время. Таким образом, сведение выполняется за полиномиальное время.&lt;br /&gt;
*Пусть формула &amp;lt;math&amp;gt;\varphi&amp;lt;/math&amp;gt; выполнима, то есть существует набор значений &amp;lt;math&amp;gt;\{y_{i}\}^{n}_{i=1}:~\varphi(y_{1}\ldots y_{n})=1 &amp;lt;/math&amp;gt;. И пусть &amp;lt;math&amp;gt;(S,s) = f(\varphi)&amp;lt;/math&amp;gt;. Тогда в полученном множестве &amp;lt;math&amp;gt;S&amp;lt;/math&amp;gt; существует подмножество с суммой &amp;lt;math&amp;gt;s&amp;lt;/math&amp;gt;. Действительно, для каждой переменной, если &amp;lt;math&amp;gt;y_{k} = 1&amp;lt;/math&amp;gt;, то добавим &amp;lt;math&amp;gt;v_{i}&amp;lt;/math&amp;gt; в &amp;lt;math&amp;gt;S'&amp;lt;/math&amp;gt;. Иначе добавим &amp;lt;math&amp;gt;w_{i}&amp;lt;/math&amp;gt;. Теперь &amp;lt;math&amp;gt;S'&amp;lt;/math&amp;gt; содержит уже &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; чисел. Заметим, что для каждого &amp;quot;скобочного&amp;quot; разряда в уже набранной части &amp;lt;math&amp;gt;S'&amp;lt;/math&amp;gt; есть не менее одного и не более трех чисел, у которых в данном разряде стоит &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt;. Значит для каждого соответствующего паре скобок &amp;lt;math&amp;gt;C_{j}&amp;lt;/math&amp;gt; разряда мы сможем выбрать одно или оба числа &amp;lt;math&amp;gt;d_{j}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;e_{j}&amp;lt;/math&amp;gt; так, чтобы сумма в данном разряде совпадала с требуемой (стала равна &amp;lt;math&amp;gt;4&amp;lt;/math&amp;gt;). Добавим их в &amp;lt;math&amp;gt;S'&amp;lt;/math&amp;gt;. Также заметим, что суммы во всех &amp;quot;переменных&amp;quot; разрядах равны &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt;, так как для каждого &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; выбиралось строго одно число из &amp;lt;math&amp;gt;v_{i}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;u_{i}&amp;lt;/math&amp;gt;. Значит, &amp;lt;math&amp;gt; \sum\limits_{s_{k} \in S'}{s_{k}} = s&amp;lt;/math&amp;gt;.&lt;br /&gt;
*Пусть теперь в наборе &amp;lt;math&amp;gt;S&amp;lt;/math&amp;gt; есть подмножество &amp;lt;math&amp;gt;S':~  \sum\limits_{s_{k} \in S'}{s_{k}} = s&amp;lt;/math&amp;gt;. Тогда исходная формула &amp;lt;math&amp;gt;\varphi&amp;lt;/math&amp;gt; выполнима. Действительно, если &amp;lt;math&amp;gt;v_{i} \in S'&amp;lt;/math&amp;gt;, то установим переменную &amp;lt;math&amp;gt;x_{i}=1&amp;lt;/math&amp;gt;. Если же &amp;lt;math&amp;gt;w_{i} \in S'&amp;lt;/math&amp;gt;, то &amp;lt;math&amp;gt;x_{i}=0&amp;lt;/math&amp;gt;. Покажем, что &amp;lt;math&amp;gt;\varphi(x_{1}\ldots x_{n}) = 1 &amp;lt;/math&amp;gt;. Действительно, так как &amp;lt;math&amp;gt; \sum\limits_{s_{k} \in S'}{s_{k}} = s&amp;lt;/math&amp;gt;, в каждой паре скобок хотя бы один терм равен &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt;. Значит каждый терм равен &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt;. А тогда и вся &amp;lt;math&amp;gt;\varphi = 1&amp;lt;/math&amp;gt;.&lt;br /&gt;
====Пример сведения====&lt;br /&gt;
Пусть исходная функция &amp;lt;math&amp;gt;\varphi(x_{1} \ldots x_{4}) = (x_{1} \lor x_{2} \lor \neg x_{3}) \land (\neg x_{1} \lor x_{2} \lor x_{4})&amp;lt;/math&amp;gt;.&lt;br /&gt;
Пометим разряды следующим образом (слева направо): &amp;lt;math&amp;gt;x_{1},x_{2},x_{3},x_{4},C_{1},C_{2}&amp;lt;/math&amp;gt;. Тогда:&lt;br /&gt;
*&amp;lt;math&amp;gt;v_{1} = 100010&amp;lt;/math&amp;gt;&lt;br /&gt;
*&amp;lt;math&amp;gt;w_{1} = 100001&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;math&amp;gt;v_{2} = 010011 = 10011&amp;lt;/math&amp;gt;&lt;br /&gt;
*&amp;lt;math&amp;gt;w_{2} = 010000 = 10000&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;math&amp;gt;v_{3} = 001000 = 1000&amp;lt;/math&amp;gt;&lt;br /&gt;
*&amp;lt;math&amp;gt;w_{3} = 001010 = 1010&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;math&amp;gt;v_{4} = 000101 = 101&amp;lt;/math&amp;gt;&lt;br /&gt;
*&amp;lt;math&amp;gt;w_{4} = 000100 = 100&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;math&amp;gt;d_{1} = 000010 = 10&amp;lt;/math&amp;gt;&lt;br /&gt;
*&amp;lt;math&amp;gt;e_{1} = 000020 = 20&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;math&amp;gt;d_{2} = 000001 = 1&amp;lt;/math&amp;gt;&lt;br /&gt;
*&amp;lt;math&amp;gt;e_{2} = 000002 = 2&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;math&amp;gt;s = 111144&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;S = (\bigcup\limits_{i=1}^{4} v_{i}) \cup (\bigcup\limits_{i=1}^{4} w_{i}) \cup (\bigcup\limits_{i=1}^{2} d_{i}) \cup (\bigcup\limits_{i=1}^{2} e_{i})&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Тогда набору значений &amp;lt;math&amp;gt;Y = (0,0,0,1):~ \varphi(Y) = 1&amp;lt;/math&amp;gt; соответствует &amp;lt;math&amp;gt;S' = \{w_{1},~w_{2},~w_{3},~v_{4},~d_{1},~e_{1},~e_{2}\}&amp;lt;/math&amp;gt;. И действительно, &amp;lt;math&amp;gt;100001 + 10000 + 1010 + 101 + 10 + 20 + 2 = 111144&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==См. также==&lt;br /&gt;
* [[NP]]&lt;br /&gt;
* [[NPH]]&lt;br /&gt;
* [[NPC]]&lt;br /&gt;
* [[Классы NP и Σ₁]]&lt;br /&gt;
* [[3CNFSAT]]&lt;br /&gt;
* [[Примеры NP-полных языков]]&lt;br /&gt;
&lt;br /&gt;
==Источники информации==&lt;br /&gt;
* Thomas H. Cormen, Charles E. Leiserson, Ronald L. Rivest, Clifford Stein &amp;quot;Introduction to Algorithms, 3rd Edition&amp;quot; {{---}} Издательство MIT Press, 2009. {{---}} 1086 c. {{---}} ISBN 978-0-262-03384-8 (англ.)&lt;br /&gt;
* Хопкрофт Дж., Мотвани Р., Ульман Дж. Введение в теорию автоматов, языков и вычислений. 2-е издание. {{---}} М.: Издательский дом &amp;quot;Вильямс&amp;quot;, 2002. {{---}} 423 с. {{---}} ISBN 5-8459-0261-4 (рус.)&lt;br /&gt;
&lt;br /&gt;
[[Категория: Теория сложности]]&lt;br /&gt;
[[Категория: Детерминированные и недетерминированные вычисления, сложность по времени и по памяти]]&lt;br /&gt;
[[Категория: Примеры NP-полных языков]]&lt;/div&gt;</summary>
		<author><name>KirillTim</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=NP-%D0%BF%D0%BE%D0%BB%D0%BD%D0%BE%D1%82%D0%B0_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B8_%D0%BE_%D1%81%D1%83%D0%BC%D0%BC%D0%B5_%D0%BF%D0%BE%D0%B4%D0%BC%D0%BD%D0%BE%D0%B6%D0%B5%D1%81%D1%82%D0%B2%D0%B0&amp;diff=54065</id>
		<title>NP-полнота задачи о сумме подмножества</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=NP-%D0%BF%D0%BE%D0%BB%D0%BD%D0%BE%D1%82%D0%B0_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B8_%D0%BE_%D1%81%D1%83%D0%BC%D0%BC%D0%B5_%D0%BF%D0%BE%D0%B4%D0%BC%D0%BD%D0%BE%D0%B6%D0%B5%D1%81%D1%82%D0%B2%D0%B0&amp;diff=54065"/>
				<updated>2016-05-17T17:55:16Z</updated>
		
		<summary type="html">&lt;p&gt;KirillTim: Страницы, описание времени работы&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Задача&lt;br /&gt;
|definition = Дано множество &amp;lt;math&amp;gt;S&amp;lt;/math&amp;gt;, содержащие &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; целых чисел и целое число &amp;lt;math&amp;gt;s&amp;lt;/math&amp;gt;. Требуется выяснить, возможно ли выбрать подмножество &amp;lt;math&amp;gt;S' \subseteq S&amp;lt;/math&amp;gt; с суммой &amp;lt;math&amp;gt;s&amp;lt;/math&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\exists S' \subseteq S: \sum\limits_{s_{i} \in S'}{s_{i}} = s&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
==Доказательство NP-полноты==&lt;br /&gt;
Для доказательства того, что '''задаче о сумме подмножества''' (англ. ''Subset sum problem'', &amp;lt;math&amp;gt;\mathrm{SSP}&amp;lt;/math&amp;gt;) [[NPC | NP-полной]], необходимо доказать два факта:&lt;br /&gt;
*&amp;lt;math&amp;gt;\mathrm{SSP} \in&amp;lt;/math&amp;gt; [[NP | &amp;lt;math&amp;gt;\mathrm{NP}&amp;lt;/math&amp;gt;]] &lt;br /&gt;
*&amp;lt;math&amp;gt;\mathrm{SSP} \in&amp;lt;/math&amp;gt; [[NPH | &amp;lt;math&amp;gt;\mathrm{NPH}&amp;lt;/math&amp;gt;]] &lt;br /&gt;
&lt;br /&gt;
===Доказательство принадлежности NP===&lt;br /&gt;
В качестве сертификата возьмем удовлетворяющее условию задачи множество &amp;lt;math&amp;gt;S'&amp;lt;/math&amp;gt; с суммой &amp;lt;math&amp;gt;s&amp;lt;/math&amp;gt;. Оно удовлетворяет всем требованиям, налагаемым на сертификат. Проверяющая функция проверит вхождение всех элементов &amp;lt;math&amp;gt;S'&amp;lt;/math&amp;gt; в множество &amp;lt;math&amp;gt;S&amp;lt;/math&amp;gt; за время &amp;lt;math&amp;gt;\left\vert{S'}\right\vert \times \left\vert{S}\right\vert&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
===Доказательство принадлежности NPH===&lt;br /&gt;
Сведем [[NP-полнота_задачи_о_выполнимости_булевой_формулы_в_форме_3-КНФ|3-CNF_Sat]] к задаче о сумме подмножества. Пусть задана 3-CNF формула &amp;lt;math&amp;gt;\varphi&amp;lt;/math&amp;gt; от &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;&lt;br /&gt;
переменных &amp;lt;math&amp;gt;x_{i}&amp;lt;/math&amp;gt;, состоящая из &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; пар скобок &amp;lt;math&amp;gt;C_{i}&amp;lt;/math&amp;gt;. Будем считать, не умаляя общности, что ни одна пара скобок не содержит одновременно переменную и ее отрицание. Также предположим, что каждая переменная входит хотя бы в одну пару скобок. Построим сводящую функцию &amp;lt;math&amp;gt;f\!\!:\varphi \to (S,s)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
====Построение сводящей функции====&lt;br /&gt;
Для каждой переменной &amp;lt;math&amp;gt;x_{i}&amp;lt;/math&amp;gt; и каждой пары скобок &amp;lt;math&amp;gt;C_{j}&amp;lt;/math&amp;gt; создадим по два числа в десятичной системе счисления, каждое длиной &amp;lt;math&amp;gt;n+k&amp;lt;/math&amp;gt; цифр. Эти числа образуют &amp;lt;math&amp;gt;S&amp;lt;/math&amp;gt;. Также создадим число &amp;lt;math&amp;gt;s&amp;lt;/math&amp;gt; длиной &amp;lt;math&amp;gt;n+k&amp;lt;/math&amp;gt; цифр. Присвоим каждому разряду полученных чисел (одинаковую для всех чисел) метку, соответствующую либо переменной, либо паре скобок.&lt;br /&gt;
Метки, соответствующие парам скобок, присвоены &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; младшим разрядам чисел.&lt;br /&gt;
*В числе &amp;lt;math&amp;gt;s&amp;lt;/math&amp;gt; все разряды, соответствующие переменным, установим &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt;, а оставшиеся сделаем равными &amp;lt;math&amp;gt;4&amp;lt;/math&amp;gt;.&lt;br /&gt;
*Каждой переменной &amp;lt;math&amp;gt;x_{i}&amp;lt;/math&amp;gt; соответствуют два числа из &amp;lt;math&amp;gt;S&amp;lt;/math&amp;gt;: &amp;lt;math&amp;gt;v_{i}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;u_{i}&amp;lt;/math&amp;gt;. Опишем создание этих чисел. Разряд, соответствующий &amp;lt;math&amp;gt;x_{i}&amp;lt;/math&amp;gt; установим равным &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt;, а все остальные разряды, соответствующие переменным, установим равными &amp;lt;math&amp;gt;0&amp;lt;/math&amp;gt;. Далее, для числа &amp;lt;math&amp;gt;v_{i}&amp;lt;/math&amp;gt; установим все разряды, соответствующие парам скобок, содержащих &amp;lt;math&amp;gt;x_{i}&amp;lt;/math&amp;gt;, равными &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt;. Во все остальные &amp;quot;скобочные&amp;quot; разряды поставим &amp;lt;math&amp;gt;0&amp;lt;/math&amp;gt;. В числе &amp;lt;math&amp;gt;w_{i}&amp;lt;/math&amp;gt; установим все разряды, соответствующие парам скобок, содержащих &amp;lt;math&amp;gt;\neg x_{i}&amp;lt;/math&amp;gt;, равными &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt;, а во все остальные &amp;quot;скобочные&amp;quot; разряды поставим &amp;lt;math&amp;gt;0&amp;lt;/math&amp;gt;.&lt;br /&gt;
*Каждой паре скобок &amp;lt;math&amp;gt;C_{j}&amp;lt;/math&amp;gt; соответствуют два числа из &amp;lt;math&amp;gt;S&amp;lt;/math&amp;gt;: &amp;lt;math&amp;gt;d_{i}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;e_{i}&amp;lt;/math&amp;gt;. Оба этих числа содержат &amp;lt;math&amp;gt;0&amp;lt;/math&amp;gt; во всех разрядах, кроме соответствующего &amp;lt;math&amp;gt;C_{j}&amp;lt;/math&amp;gt;. В этом разряде у &amp;lt;math&amp;gt;d_{i}&amp;lt;/math&amp;gt; поставим &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt;, а у &amp;lt;math&amp;gt;e_{i}&amp;lt;/math&amp;gt; {{---}} &amp;lt;math&amp;gt;2&amp;lt;/math&amp;gt;.&lt;br /&gt;
====Корректность сводящей функции====&lt;br /&gt;
*Получаемое сводящей функцией множество &amp;lt;math&amp;gt;S&amp;lt;/math&amp;gt; состоит из &amp;lt;math&amp;gt;2(n+k)&amp;lt;/math&amp;gt; десятичных чисел длиной &amp;lt;math&amp;gt;(n+k)&amp;lt;/math&amp;gt; каждое, выставление каждого разряда занимает полиномиальное время. Таким образом, сведение выполняется за полиномиальное время.&lt;br /&gt;
*Пусть формула &amp;lt;math&amp;gt;\varphi&amp;lt;/math&amp;gt; выполнима, то есть существует набор значений &amp;lt;math&amp;gt;\{y_{i}\}^{n}_{i=1}:~\varphi(y_{1}\ldots y_{n})=1 &amp;lt;/math&amp;gt;. И пусть &amp;lt;math&amp;gt;(S,s) = f(\varphi)&amp;lt;/math&amp;gt;. Тогда в полученном множестве &amp;lt;math&amp;gt;S&amp;lt;/math&amp;gt; существует подмножество с суммой &amp;lt;math&amp;gt;s&amp;lt;/math&amp;gt;. Действительно, для каждой переменной, если &amp;lt;math&amp;gt;y_{k} = 1&amp;lt;/math&amp;gt;, то добавим &amp;lt;math&amp;gt;v_{i}&amp;lt;/math&amp;gt; в &amp;lt;math&amp;gt;S'&amp;lt;/math&amp;gt;. Иначе добавим &amp;lt;math&amp;gt;w_{i}&amp;lt;/math&amp;gt;. Теперь &amp;lt;math&amp;gt;S'&amp;lt;/math&amp;gt; содержит уже &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; чисел. Заметим, что для каждого &amp;quot;скобочного&amp;quot; разряда в уже набранной части &amp;lt;math&amp;gt;S'&amp;lt;/math&amp;gt; есть не менее одного и не более трех чисел, у которых в данном разряде стоит &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt;. Значит для каждого соответствующего паре скобок &amp;lt;math&amp;gt;C_{j}&amp;lt;/math&amp;gt; разряда мы сможем выбрать одно или оба числа &amp;lt;math&amp;gt;d_{j}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;e_{j}&amp;lt;/math&amp;gt; так, чтобы сумма в данном разряде совпадала с требуемой (стала равна &amp;lt;math&amp;gt;4&amp;lt;/math&amp;gt;). Добавим их в &amp;lt;math&amp;gt;S'&amp;lt;/math&amp;gt;. Также заметим, что суммы во всех &amp;quot;переменных&amp;quot; разрядах равны &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt;, так как для каждого &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; выбиралось строго одно число из &amp;lt;math&amp;gt;v_{i}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;u_{i}&amp;lt;/math&amp;gt;. Значит, &amp;lt;math&amp;gt; \sum\limits_{s_{k} \in S'}{s_{k}} = s&amp;lt;/math&amp;gt;.&lt;br /&gt;
*Пусть теперь в наборе &amp;lt;math&amp;gt;S&amp;lt;/math&amp;gt; есть подмножество &amp;lt;math&amp;gt;S':~  \sum\limits_{s_{k} \in S'}{s_{k}} = s&amp;lt;/math&amp;gt;. Тогда исходная формула &amp;lt;math&amp;gt;\varphi&amp;lt;/math&amp;gt; выполнима. Действительно, если &amp;lt;math&amp;gt;v_{i} \in S'&amp;lt;/math&amp;gt;, то установим переменную &amp;lt;math&amp;gt;x_{i}=1&amp;lt;/math&amp;gt;. Если же &amp;lt;math&amp;gt;w_{i} \in S'&amp;lt;/math&amp;gt;, то &amp;lt;math&amp;gt;x_{i}=0&amp;lt;/math&amp;gt;. Покажем, что &amp;lt;math&amp;gt;\varphi(x_{1}\ldots x_{n}) = 1 &amp;lt;/math&amp;gt;. Действительно, так как &amp;lt;math&amp;gt; \sum\limits_{s_{k} \in S'}{s_{k}} = s&amp;lt;/math&amp;gt;, в каждой паре скобок хотя бы один терм равен &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt;. Значит каждый терм равен &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt;. А тогда и вся &amp;lt;math&amp;gt;\varphi = 1&amp;lt;/math&amp;gt;.&lt;br /&gt;
====Пример сведения====&lt;br /&gt;
Пусть исходная функция &amp;lt;math&amp;gt;\varphi(x_{1} \ldots x_{4}) = (x_{1} \lor x_{2} \lor \neg x_{3}) \land (\neg x_{1} \lor x_{2} \lor x_{4})&amp;lt;/math&amp;gt;.&lt;br /&gt;
Пометим разряды следующим образом (слева направо): &amp;lt;math&amp;gt;x_{1},x_{2},x_{3},x_{4},C_{1},C_{2}&amp;lt;/math&amp;gt;. Тогда:&lt;br /&gt;
*&amp;lt;math&amp;gt;v_{1} = 100010&amp;lt;/math&amp;gt;&lt;br /&gt;
*&amp;lt;math&amp;gt;w_{1} = 100001&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;math&amp;gt;v_{2} = 010011 = 10011&amp;lt;/math&amp;gt;&lt;br /&gt;
*&amp;lt;math&amp;gt;w_{2} = 010000 = 10000&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;math&amp;gt;v_{3} = 001000 = 1000&amp;lt;/math&amp;gt;&lt;br /&gt;
*&amp;lt;math&amp;gt;w_{3} = 001010 = 1010&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;math&amp;gt;v_{4} = 000101 = 101&amp;lt;/math&amp;gt;&lt;br /&gt;
*&amp;lt;math&amp;gt;w_{4} = 000100 = 100&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;math&amp;gt;d_{1} = 000010 = 10&amp;lt;/math&amp;gt;&lt;br /&gt;
*&amp;lt;math&amp;gt;e_{1} = 000020 = 20&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;math&amp;gt;d_{2} = 000001 = 1&amp;lt;/math&amp;gt;&lt;br /&gt;
*&amp;lt;math&amp;gt;e_{2} = 000002 = 2&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;math&amp;gt;s = 111144&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;S = (\bigcup\limits_{i=1}^{4} v_{i}) \cup (\bigcup\limits_{i=1}^{4} w_{i}) \cup (\bigcup\limits_{i=1}^{2} d_{i}) \cup (\bigcup\limits_{i=1}^{2} e_{i})&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Тогда набору значений &amp;lt;math&amp;gt;Y = (0,0,0,1):~ \varphi(Y) = 1&amp;lt;/math&amp;gt; соответствует &amp;lt;math&amp;gt;S' = \{w_{1},~w_{2},~w_{3},~v_{4},~d_{1},~e_{1},~e_{2}\}&amp;lt;/math&amp;gt;. И действительно, &amp;lt;math&amp;gt;100001 + 10000 + 1010 + 101 + 10 + 20 + 2 = 111144&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==См. также==&lt;br /&gt;
* [[NP]]&lt;br /&gt;
* [[NPH]]&lt;br /&gt;
* [[NPC]]&lt;br /&gt;
* [[Классы NP и Σ₁]]&lt;br /&gt;
* [[3CNFSAT]]&lt;br /&gt;
* [[Примеры NP-полных языков]]&lt;br /&gt;
&lt;br /&gt;
==Источники информации==&lt;br /&gt;
* Thomas H. Cormen, Charles E. Leiserson, Ronald L. Rivest, Clifford Stein &amp;quot;Introduction to Algorithms, 3rd Edition&amp;quot; {{---}} Издательство MIT Press, 2009. {{---}} 1086 c. {{---}} ISBN 978-0-262-03384-8 (англ.)&lt;br /&gt;
* Хопкрофт Дж., Мотвани Р., Ульман Дж. Введение в теорию автоматов, языков и вычислений. 2-е издание. {{---}} М.: Издательский дом &amp;quot;Вильямс&amp;quot;, 2002. {{---}} 423 с. {{---}} ISBN 5-8459-0261-4 (рус.)&lt;br /&gt;
&lt;br /&gt;
[[Категория: Теория сложности]]&lt;br /&gt;
[[Категория: Детерминированные и недетерминированные вычисления, сложность по времени и по памяти]]&lt;br /&gt;
[[Категория: Примеры NP-полных языков]]&lt;/div&gt;</summary>
		<author><name>KirillTim</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=NP-%D0%BF%D0%BE%D0%BB%D0%BD%D0%BE%D1%82%D0%B0_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B8_%D0%BE_%D1%81%D1%83%D0%BC%D0%BC%D0%B5_%D0%BF%D0%BE%D0%B4%D0%BC%D0%BD%D0%BE%D0%B6%D0%B5%D1%81%D1%82%D0%B2%D0%B0&amp;diff=54064</id>
		<title>NP-полнота задачи о сумме подмножества</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=NP-%D0%BF%D0%BE%D0%BB%D0%BD%D0%BE%D1%82%D0%B0_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B8_%D0%BE_%D1%81%D1%83%D0%BC%D0%BC%D0%B5_%D0%BF%D0%BE%D0%B4%D0%BC%D0%BD%D0%BE%D0%B6%D0%B5%D1%81%D1%82%D0%B2%D0%B0&amp;diff=54064"/>
				<updated>2016-05-17T17:45:35Z</updated>
		
		<summary type="html">&lt;p&gt;KirillTim: опечатки&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Задача&lt;br /&gt;
|definition = Дано множество &amp;lt;math&amp;gt;S&amp;lt;/math&amp;gt;, содержащие &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; целых чисел и целое число &amp;lt;math&amp;gt;s&amp;lt;/math&amp;gt;. Требуется выяснить, возможно ли выбрать подмножество &amp;lt;math&amp;gt;S' \subseteq S&amp;lt;/math&amp;gt; с суммой &amp;lt;math&amp;gt;s&amp;lt;/math&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\exists S' \subseteq S: \sum\limits_{s_{i} \in S'}{s_{i}} = s&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
==Доказательство NP-полноты==&lt;br /&gt;
Для доказательства того, что '''задаче о сумме подмножества''' (англ. ''Subset sum problem'', &amp;lt;math&amp;gt;\mathrm{SSP}&amp;lt;/math&amp;gt;) [[NPC | NP-полной]], необходимо доказать два факта:&lt;br /&gt;
*&amp;lt;math&amp;gt;\mathrm{SSP} \in&amp;lt;/math&amp;gt; [[NP | &amp;lt;math&amp;gt;\mathrm{NP}&amp;lt;/math&amp;gt;]] &lt;br /&gt;
*&amp;lt;math&amp;gt;\mathrm{SSP} \in&amp;lt;/math&amp;gt; [[NPH | &amp;lt;math&amp;gt;\mathrm{NPH}&amp;lt;/math&amp;gt;]] &lt;br /&gt;
&lt;br /&gt;
===Доказательство принадлежности NP===&lt;br /&gt;
В качестве сертификата возьмем удовлетворяющее условию задачи множество &amp;lt;math&amp;gt;S'&amp;lt;/math&amp;gt; с суммой &amp;lt;math&amp;gt;s&amp;lt;/math&amp;gt;. Оно удовлетворяет всем требованиям, налагаемым на сертификат. Проверяющая функция проверит вхождение всех элементов &amp;lt;math&amp;gt;S'&amp;lt;/math&amp;gt; в множество &amp;lt;math&amp;gt;S&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
===Доказательство принадлежности к NPH===&lt;br /&gt;
Сведем [[NP-полнота_задачи_о_выполнимости_булевой_формулы_в_форме_3-КНФ|3-CNF_Sat]] к задаче о сумме подмножества. Пусть задана 3-CNF формула &amp;lt;math&amp;gt;\varphi&amp;lt;/math&amp;gt; от &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;&lt;br /&gt;
переменных &amp;lt;math&amp;gt;x_{i}&amp;lt;/math&amp;gt;, состоящая из &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; пар скобок &amp;lt;math&amp;gt;C_{i}&amp;lt;/math&amp;gt;. Будем считать, не умаляя общности, что ни одна пара скобок не содержит одновременно переменную и ее отрицание. Также предположим, что каждая переменная входит хотя бы в одну пару скобок. Построим сводящую функцию &amp;lt;math&amp;gt;f\!\!:\varphi \to (S,s)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
====Построение сводящей функции====&lt;br /&gt;
Для каждой переменной &amp;lt;math&amp;gt;x_{i}&amp;lt;/math&amp;gt; и каждой пары скобок &amp;lt;math&amp;gt;C_{j}&amp;lt;/math&amp;gt; создадим по два числа в десятичной системе счисления, каждое длиной &amp;lt;math&amp;gt;n+k&amp;lt;/math&amp;gt; цифр. Эти числа образуют &amp;lt;math&amp;gt;S&amp;lt;/math&amp;gt;. Также создадим число &amp;lt;math&amp;gt;s&amp;lt;/math&amp;gt; длиной &amp;lt;math&amp;gt;n+k&amp;lt;/math&amp;gt; цифр. Присвоим каждому разряду полученных чисел (одинаковую для всех чисел) метку, соответствующую либо переменной, либо паре скобок.&lt;br /&gt;
Метки, соответствующие парам скобок, присвоены &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; младшим разрядам чисел.&lt;br /&gt;
*В числе &amp;lt;math&amp;gt;s&amp;lt;/math&amp;gt; все разряды, соответствующие переменным, установим &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt;, а оставшиеся сделаем равными &amp;lt;math&amp;gt;4&amp;lt;/math&amp;gt;.&lt;br /&gt;
*Каждой переменной &amp;lt;math&amp;gt;x_{i}&amp;lt;/math&amp;gt; соответствуют два числа из &amp;lt;math&amp;gt;S&amp;lt;/math&amp;gt;: &amp;lt;math&amp;gt;v_{i}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;u_{i}&amp;lt;/math&amp;gt;. Опишем создание этих чисел. Разряд, соответствующий &amp;lt;math&amp;gt;x_{i}&amp;lt;/math&amp;gt; установим равным &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt;, а все остальные разряды, соответствующие переменным, установим равными &amp;lt;math&amp;gt;0&amp;lt;/math&amp;gt;. Далее, для числа &amp;lt;math&amp;gt;v_{i}&amp;lt;/math&amp;gt; установим все разряды, соответствующие парам скобок, содержащих &amp;lt;math&amp;gt;x_{i}&amp;lt;/math&amp;gt;, равными &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt;. Во все остальные &amp;quot;скобочные&amp;quot; разряды поставим &amp;lt;math&amp;gt;0&amp;lt;/math&amp;gt;. В числе &amp;lt;math&amp;gt;w_{i}&amp;lt;/math&amp;gt; установим все разряды, соответствующие парам скобок, содержащих &amp;lt;math&amp;gt;\neg x_{i}&amp;lt;/math&amp;gt;, равными &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt;, а во все остальные &amp;quot;скобочные&amp;quot; разряды поставим &amp;lt;math&amp;gt;0&amp;lt;/math&amp;gt;.&lt;br /&gt;
*Каждой паре скобок &amp;lt;math&amp;gt;C_{j}&amp;lt;/math&amp;gt; соответствуют два числа из &amp;lt;math&amp;gt;S&amp;lt;/math&amp;gt;: &amp;lt;math&amp;gt;d_{i}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;e_{i}&amp;lt;/math&amp;gt;. Оба этих числа содержат &amp;lt;math&amp;gt;0&amp;lt;/math&amp;gt; во всех разрядах, кроме соответствующего &amp;lt;math&amp;gt;C_{j}&amp;lt;/math&amp;gt;. В этом разряде у &amp;lt;math&amp;gt;d_{i}&amp;lt;/math&amp;gt; поставим &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt;, а у &amp;lt;math&amp;gt;e_{i}&amp;lt;/math&amp;gt; {{---}} &amp;lt;math&amp;gt;2&amp;lt;/math&amp;gt;.&lt;br /&gt;
====Корректность сводящей функции====&lt;br /&gt;
*Получаемое сводящей функцией множество &amp;lt;math&amp;gt;S&amp;lt;/math&amp;gt; состоит из &amp;lt;math&amp;gt;2(n+k)&amp;lt;/math&amp;gt; десятичных чисел длиной &amp;lt;math&amp;gt;(n+k)&amp;lt;/math&amp;gt; каждое, выставление каждого разряда занимает полиномиальное время. Таким образом, сведение выполняется за полиномиальное время.&lt;br /&gt;
*Пусть формула &amp;lt;math&amp;gt;\varphi&amp;lt;/math&amp;gt; выполнима, то есть существует набор значений &amp;lt;math&amp;gt;\{y_{i}\}^{n}_{i=1}:~\varphi(y_{1}\ldots y_{n})=1 &amp;lt;/math&amp;gt;. И пусть &amp;lt;math&amp;gt;(S,s) = f(\varphi)&amp;lt;/math&amp;gt;. Тогда в полученном множестве &amp;lt;math&amp;gt;S&amp;lt;/math&amp;gt; существует подмножество с суммой &amp;lt;math&amp;gt;s&amp;lt;/math&amp;gt;. Действительно, для каждой переменной, если &amp;lt;math&amp;gt;y_{k} = 1&amp;lt;/math&amp;gt;, то добавим &amp;lt;math&amp;gt;v_{i}&amp;lt;/math&amp;gt; в &amp;lt;math&amp;gt;S'&amp;lt;/math&amp;gt;. Иначе добавим &amp;lt;math&amp;gt;w_{i}&amp;lt;/math&amp;gt;. Теперь &amp;lt;math&amp;gt;S'&amp;lt;/math&amp;gt; содержит уже &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; чисел. Заметим, что для каждого &amp;quot;скобочного&amp;quot; разряда в уже набранной части &amp;lt;math&amp;gt;S'&amp;lt;/math&amp;gt; есть не менее одного и не более трех чисел, у которых в данном разряде стоит &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt;. Значит для каждого соответствующего паре скобок &amp;lt;math&amp;gt;C_{j}&amp;lt;/math&amp;gt; разряда мы сможем выбрать одно или оба числа &amp;lt;math&amp;gt;d_{j}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;e_{j}&amp;lt;/math&amp;gt; так, чтобы сумма в данном разряде совпадала с требуемой (стала равна &amp;lt;math&amp;gt;4&amp;lt;/math&amp;gt;). Добавим их в &amp;lt;math&amp;gt;S'&amp;lt;/math&amp;gt;. Также заметим, что суммы во всех &amp;quot;переменных&amp;quot; разрядах равны &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt;, так как для каждого &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; выбиралось строго одно число из &amp;lt;math&amp;gt;v_{i}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;u_{i}&amp;lt;/math&amp;gt;. Значит, &amp;lt;math&amp;gt; \sum\limits_{s_{k} \in S'}{s_{k}} = s&amp;lt;/math&amp;gt;.&lt;br /&gt;
*Пусть теперь в наборе &amp;lt;math&amp;gt;S&amp;lt;/math&amp;gt; есть подмножество &amp;lt;math&amp;gt;S':~  \sum\limits_{s_{k} \in S'}{s_{k}} = s&amp;lt;/math&amp;gt;. Тогда исходная формула &amp;lt;math&amp;gt;\varphi&amp;lt;/math&amp;gt; выполнима. Действительно, если &amp;lt;math&amp;gt;v_{i} \in S'&amp;lt;/math&amp;gt;, то установим переменную &amp;lt;math&amp;gt;x_{i}=1&amp;lt;/math&amp;gt;. Если же &amp;lt;math&amp;gt;w_{i} \in S'&amp;lt;/math&amp;gt;, то &amp;lt;math&amp;gt;x_{i}=0&amp;lt;/math&amp;gt;. Покажем, что &amp;lt;math&amp;gt;\varphi(x_{1}\ldots x_{n}) = 1 &amp;lt;/math&amp;gt;. Действительно, так как &amp;lt;math&amp;gt; \sum\limits_{s_{k} \in S'}{s_{k}} = s&amp;lt;/math&amp;gt;, в каждой паре скобок хотя бы один терм равен &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt;. Значит каждый терм равен &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt;. А тогда и вся &amp;lt;math&amp;gt;\varphi = 1&amp;lt;/math&amp;gt;.&lt;br /&gt;
====Пример сведения====&lt;br /&gt;
Пусть исходная функция &amp;lt;math&amp;gt;\varphi(x_{1} \ldots x_{4}) = (x_{1} \lor x_{2} \lor \neg x_{3}) \land (\neg x_{1} \lor x_{2} \lor x_{4})&amp;lt;/math&amp;gt;.&lt;br /&gt;
Пометим разряды следующим образом (слева направо): &amp;lt;math&amp;gt;x_{1},x_{2},x_{3},x_{4},C_{1},C_{2}&amp;lt;/math&amp;gt;. Тогда:&lt;br /&gt;
*&amp;lt;math&amp;gt;v_{1} = 100010&amp;lt;/math&amp;gt;&lt;br /&gt;
*&amp;lt;math&amp;gt;w_{1} = 100001&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;math&amp;gt;v_{2} = 010011 = 10011&amp;lt;/math&amp;gt;&lt;br /&gt;
*&amp;lt;math&amp;gt;w_{2} = 010000 = 10000&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;math&amp;gt;v_{3} = 001000 = 1000&amp;lt;/math&amp;gt;&lt;br /&gt;
*&amp;lt;math&amp;gt;w_{3} = 001010 = 1010&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;math&amp;gt;v_{4} = 000101 = 101&amp;lt;/math&amp;gt;&lt;br /&gt;
*&amp;lt;math&amp;gt;w_{4} = 000100 = 100&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;math&amp;gt;d_{1} = 000010 = 10&amp;lt;/math&amp;gt;&lt;br /&gt;
*&amp;lt;math&amp;gt;e_{1} = 000020 = 20&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;math&amp;gt;d_{2} = 000001 = 1&amp;lt;/math&amp;gt;&lt;br /&gt;
*&amp;lt;math&amp;gt;e_{2} = 000002 = 2&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;math&amp;gt;s = 111144&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;S = (\bigcup\limits_{i=1}^{4} v_{i}) \cup (\bigcup\limits_{i=1}^{4} w_{i}) \cup (\bigcup\limits_{i=1}^{2} d_{i}) \cup (\bigcup\limits_{i=1}^{2} e_{i})&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Тогда набору значений &amp;lt;math&amp;gt;Y = (0,0,0,1):~ \varphi(Y) = 1&amp;lt;/math&amp;gt; соответствует &amp;lt;math&amp;gt;S' = \{w_{1},~w_{2},~w_{3},~v_{4},~d_{1},~e_{1},~e_{2}\}&amp;lt;/math&amp;gt;. И действительно, &amp;lt;math&amp;gt;100001 + 10000 + 1010 + 101 + 10 + 20 + 2 = 111144&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==См. также==&lt;br /&gt;
* [[NP]]&lt;br /&gt;
* [[NPH]]&lt;br /&gt;
* [[NPC]]&lt;br /&gt;
* [[Классы NP и Σ₁]]&lt;br /&gt;
* [[3CNFSAT]]&lt;br /&gt;
* [[Примеры NP-полных языков]]&lt;br /&gt;
&lt;br /&gt;
==Источники информации==&lt;br /&gt;
* Thomas H. Cormen, Charles E. Leiserson, Ronald L. Rivest, Clifford Stein &amp;quot;Introduction to Algorithms, 3rd Edition&amp;quot; {{---}} Издательство MIT Press, 2009. {{---}} 1292 с. {{---}} ISBN 978-0-262-03384-8 (англ.)&lt;br /&gt;
* Хопкрофт Дж., Мотвани Р., Ульман Дж. Введение в теорию автоматов, языков и вычислений. 2-е издание. {{---}} М.: Издательский дом &amp;quot;Вильямс&amp;quot;, 2002. {{---}} 528 с. {{---}} ISBN 5-8459-0261-4 (рус.)&lt;br /&gt;
&lt;br /&gt;
[[Категория: Теория сложности]]&lt;br /&gt;
[[Категория: Детерминированные и недетерминированные вычисления, сложность по времени и по памяти]]&lt;br /&gt;
[[Категория: Примеры NP-полных языков]]&lt;/div&gt;</summary>
		<author><name>KirillTim</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=NP-%D0%BF%D0%BE%D0%BB%D0%BD%D0%BE%D1%82%D0%B0_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B8_%D0%BE_%D1%81%D1%83%D0%BC%D0%BC%D0%B5_%D0%BF%D0%BE%D0%B4%D0%BC%D0%BD%D0%BE%D0%B6%D0%B5%D1%81%D1%82%D0%B2%D0%B0&amp;diff=54063</id>
		<title>NP-полнота задачи о сумме подмножества</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=NP-%D0%BF%D0%BE%D0%BB%D0%BD%D0%BE%D1%82%D0%B0_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B8_%D0%BE_%D1%81%D1%83%D0%BC%D0%BC%D0%B5_%D0%BF%D0%BE%D0%B4%D0%BC%D0%BD%D0%BE%D0%B6%D0%B5%D1%81%D1%82%D0%B2%D0%B0&amp;diff=54063"/>
				<updated>2016-05-17T17:42:30Z</updated>
		
		<summary type="html">&lt;p&gt;KirillTim: Задача, знаки сумм&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Задача&lt;br /&gt;
|definition = Дан набор из &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; целых чисел &amp;lt;math&amp;gt;S&amp;lt;/math&amp;gt; и целое число &amp;lt;math&amp;gt;s&amp;lt;/math&amp;gt;. Требуется выяснить, возможно ли выбрать подмножество &amp;lt;math&amp;gt;S' \subseteq S&amp;lt;/math&amp;gt; с суммой &amp;lt;math&amp;gt;s&amp;lt;/math&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\exists S' \subseteq S: \sum\limits_{s_{i} \in S'}{s_{i}} = s&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
==Доказательство NP-полноты==&lt;br /&gt;
Для доказательства того, что '''задаче о сумме подмножества''' (англ. ''Subset sum problem'', &amp;lt;math&amp;gt;\mathrm{SSP}&amp;lt;/math&amp;gt;) [[NPC | NP-полной]], необходимо доказать два факта:&lt;br /&gt;
*&amp;lt;math&amp;gt;\mathrm{SSP} \in&amp;lt;/math&amp;gt; [[NP | &amp;lt;math&amp;gt;\mathrm{NP}&amp;lt;/math&amp;gt;]] &lt;br /&gt;
*&amp;lt;math&amp;gt;\mathrm{SSP} \in&amp;lt;/math&amp;gt; [[NPH | &amp;lt;math&amp;gt;\mathrm{NPH}&amp;lt;/math&amp;gt;]] &lt;br /&gt;
&lt;br /&gt;
===Доказательство принадлежности к NP===&lt;br /&gt;
В качестве сертификата возьмем удовлетворяющее условию задачи множество &amp;lt;math&amp;gt;S'&amp;lt;/math&amp;gt; с суммой &amp;lt;math&amp;gt;s&amp;lt;/math&amp;gt;. Оно удовлетворяет всем требованиям, налагаемым на сертификат. Проверяющая функция проверит вхождение всех элементов &amp;lt;math&amp;gt;S'&amp;lt;/math&amp;gt; в множество &amp;lt;math&amp;gt;S&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
===Доказательство принадлежности к NPH===&lt;br /&gt;
Сведем [[NP-полнота_задачи_о_выполнимости_булевой_формулы_в_форме_3-КНФ|3-CNF_Sat]] к задаче о сумме подмножества. Пусть задана 3-CNF формула &amp;lt;math&amp;gt;\varphi&amp;lt;/math&amp;gt; от &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;&lt;br /&gt;
переменных &amp;lt;math&amp;gt;x_{i}&amp;lt;/math&amp;gt;, состоящая из &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; пар скобок &amp;lt;math&amp;gt;C_{i}&amp;lt;/math&amp;gt;. Будем считать, не умаляя общности, что ни одна пара скобок не содержит одновременно переменную и ее отрицание. Также предположим, что каждая переменная входит хотя бы в одну пару скобок. Построим сводящую функцию &amp;lt;math&amp;gt;f\!\!:\varphi \to (S,s)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
====Построение сводящей функции====&lt;br /&gt;
Для каждой переменной &amp;lt;math&amp;gt;x_{i}&amp;lt;/math&amp;gt; и каждой пары скобок &amp;lt;math&amp;gt;C_{j}&amp;lt;/math&amp;gt; создадим по два числа в десятичной системе счисления, каждое длиной &amp;lt;math&amp;gt;n+k&amp;lt;/math&amp;gt; цифр. Эти числа образуют &amp;lt;math&amp;gt;S&amp;lt;/math&amp;gt;. Также создадим число &amp;lt;math&amp;gt;s&amp;lt;/math&amp;gt; длиной &amp;lt;math&amp;gt;n+k&amp;lt;/math&amp;gt; цифр. Присвоим каждому разряду полученных чисел (одинаковую для всех чисел) метку, соответствующую либо переменной, либо паре скобок.&lt;br /&gt;
Метки, соответствующие парам скобок, присвоены &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; младшим разрядам чисел.&lt;br /&gt;
*В числе &amp;lt;math&amp;gt;s&amp;lt;/math&amp;gt; все разряды, соответствующие переменным, установим &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt;, а оставшиеся сделаем равными &amp;lt;math&amp;gt;4&amp;lt;/math&amp;gt;.&lt;br /&gt;
*Каждой переменной &amp;lt;math&amp;gt;x_{i}&amp;lt;/math&amp;gt; соответствуют два числа из &amp;lt;math&amp;gt;S&amp;lt;/math&amp;gt;: &amp;lt;math&amp;gt;v_{i}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;u_{i}&amp;lt;/math&amp;gt;. Опишем создание этих чисел. Разряд, соответствующий &amp;lt;math&amp;gt;x_{i}&amp;lt;/math&amp;gt; установим равным &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt;, а все остальные разряды, соответствующие переменным, установим равными &amp;lt;math&amp;gt;0&amp;lt;/math&amp;gt;. Далее, для числа &amp;lt;math&amp;gt;v_{i}&amp;lt;/math&amp;gt; установим все разряды, соответствующие парам скобок, содержащих &amp;lt;math&amp;gt;x_{i}&amp;lt;/math&amp;gt;, равными &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt;. Во все остальные &amp;quot;скобочные&amp;quot; разряды поставим &amp;lt;math&amp;gt;0&amp;lt;/math&amp;gt;. В числе &amp;lt;math&amp;gt;w_{i}&amp;lt;/math&amp;gt; установим все разряды, соответствующие парам скобок, содержащих &amp;lt;math&amp;gt;\neg x_{i}&amp;lt;/math&amp;gt;, равными &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt;, а во все остальные &amp;quot;скобочные&amp;quot; разряды поставим &amp;lt;math&amp;gt;0&amp;lt;/math&amp;gt;.&lt;br /&gt;
*Каждой паре скобок &amp;lt;math&amp;gt;C_{j}&amp;lt;/math&amp;gt; соответствуют два числа из &amp;lt;math&amp;gt;S&amp;lt;/math&amp;gt;: &amp;lt;math&amp;gt;d_{i}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;e_{i}&amp;lt;/math&amp;gt;. Оба этих числа содержат &amp;lt;math&amp;gt;0&amp;lt;/math&amp;gt; во всех разрядах, кроме соответствующего &amp;lt;math&amp;gt;C_{j}&amp;lt;/math&amp;gt;. В этом разряде у &amp;lt;math&amp;gt;d_{i}&amp;lt;/math&amp;gt; поставим &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt;, а у &amp;lt;math&amp;gt;e_{i}&amp;lt;/math&amp;gt; {{---}} &amp;lt;math&amp;gt;2&amp;lt;/math&amp;gt;.&lt;br /&gt;
====Корректность сводящей функции====&lt;br /&gt;
*Получаемое сводящей функцией множество &amp;lt;math&amp;gt;S&amp;lt;/math&amp;gt; состоит из &amp;lt;math&amp;gt;2(n+k)&amp;lt;/math&amp;gt; десятичных чисел длиной &amp;lt;math&amp;gt;(n+k)&amp;lt;/math&amp;gt; каждое, выставление каждого разряда занимает полиномиальное время. Таким образом, сведение выполняется за полиномиальное время.&lt;br /&gt;
*Пусть формула &amp;lt;math&amp;gt;\varphi&amp;lt;/math&amp;gt; выполнима, то есть существует набор значений &amp;lt;math&amp;gt;\{y_{i}\}^{n}_{i=1}:~\varphi(y_{1}\ldots y_{n})=1 &amp;lt;/math&amp;gt;. И пусть &amp;lt;math&amp;gt;(S,s) = f(\varphi)&amp;lt;/math&amp;gt;. Тогда в полученном множестве &amp;lt;math&amp;gt;S&amp;lt;/math&amp;gt; существует подмножество с суммой &amp;lt;math&amp;gt;s&amp;lt;/math&amp;gt;. Действительно, для каждой переменной, если &amp;lt;math&amp;gt;y_{k} = 1&amp;lt;/math&amp;gt;, то добавим &amp;lt;math&amp;gt;v_{i}&amp;lt;/math&amp;gt; в &amp;lt;math&amp;gt;S'&amp;lt;/math&amp;gt;. Иначе добавим &amp;lt;math&amp;gt;w_{i}&amp;lt;/math&amp;gt;. Теперь &amp;lt;math&amp;gt;S'&amp;lt;/math&amp;gt; содержит уже &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; чисел. Заметим, что для каждого &amp;quot;скобочного&amp;quot; разряда в уже набранной части &amp;lt;math&amp;gt;S'&amp;lt;/math&amp;gt; есть не менее одного и не более трех чисел, у которых в данном разряде стоит &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt;. Значит для каждого соответствующего паре скобок &amp;lt;math&amp;gt;C_{j}&amp;lt;/math&amp;gt; разряда мы сможем выбрать одно или оба числа &amp;lt;math&amp;gt;d_{j}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;e_{j}&amp;lt;/math&amp;gt; так, чтобы сумма в данном разряде совпадала с требуемой (стала равна &amp;lt;math&amp;gt;4&amp;lt;/math&amp;gt;). Добавим их в &amp;lt;math&amp;gt;S'&amp;lt;/math&amp;gt;. Также заметим, что суммы во всех &amp;quot;переменных&amp;quot; разрядах равны &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt;, так как для каждого &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; выбиралось строго одно число из &amp;lt;math&amp;gt;v_{i}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;u_{i}&amp;lt;/math&amp;gt;. Значит, &amp;lt;math&amp;gt; \sum\limits_{s_{k} \in S'}{s_{k}} = s&amp;lt;/math&amp;gt;.&lt;br /&gt;
*Пусть теперь в наборе &amp;lt;math&amp;gt;S&amp;lt;/math&amp;gt; есть подмножество &amp;lt;math&amp;gt;S':~  \sum\limits_{s_{k} \in S'}{s_{k}} = s&amp;lt;/math&amp;gt;. Тогда исходная формула &amp;lt;math&amp;gt;\varphi&amp;lt;/math&amp;gt; выполнима. Действительно, если &amp;lt;math&amp;gt;v_{i} \in S'&amp;lt;/math&amp;gt;, то установим переменную &amp;lt;math&amp;gt;x_{i}=1&amp;lt;/math&amp;gt;. Если же &amp;lt;math&amp;gt;w_{i} \in S'&amp;lt;/math&amp;gt;, то &amp;lt;math&amp;gt;x_{i}=0&amp;lt;/math&amp;gt;. Покажем, что &amp;lt;math&amp;gt;\varphi(x_{1}\ldots x_{n}) = 1 &amp;lt;/math&amp;gt;. Действительно, так как &amp;lt;math&amp;gt; \sum\limits_{s_{k} \in S'}{s_{k}} = s&amp;lt;/math&amp;gt;, в каждой паре скобок хотя бы один терм равен &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt;. Значит каждый терм равен &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt;. А тогда и вся &amp;lt;math&amp;gt;\varphi = 1&amp;lt;/math&amp;gt;.&lt;br /&gt;
====Пример сведения====&lt;br /&gt;
Пусть исходная функция &amp;lt;math&amp;gt;\varphi(x_{1} \ldots x_{4}) = (x_{1} \lor x_{2} \lor \neg x_{3}) \land (\neg x_{1} \lor x_{2} \lor x_{4})&amp;lt;/math&amp;gt;.&lt;br /&gt;
Пометим разряды следующим образом (слева направо): &amp;lt;math&amp;gt;x_{1},x_{2},x_{3},x_{4},C_{1},C_{2}&amp;lt;/math&amp;gt;. Тогда:&lt;br /&gt;
*&amp;lt;math&amp;gt;v_{1} = 100010&amp;lt;/math&amp;gt;&lt;br /&gt;
*&amp;lt;math&amp;gt;w_{1} = 100001&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;math&amp;gt;v_{2} = 010011 = 10011&amp;lt;/math&amp;gt;&lt;br /&gt;
*&amp;lt;math&amp;gt;w_{2} = 010000 = 10000&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;math&amp;gt;v_{3} = 001000 = 1000&amp;lt;/math&amp;gt;&lt;br /&gt;
*&amp;lt;math&amp;gt;w_{3} = 001010 = 1010&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;math&amp;gt;v_{4} = 000101 = 101&amp;lt;/math&amp;gt;&lt;br /&gt;
*&amp;lt;math&amp;gt;w_{4} = 000100 = 100&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;math&amp;gt;d_{1} = 000010 = 10&amp;lt;/math&amp;gt;&lt;br /&gt;
*&amp;lt;math&amp;gt;e_{1} = 000020 = 20&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;math&amp;gt;d_{2} = 000001 = 1&amp;lt;/math&amp;gt;&lt;br /&gt;
*&amp;lt;math&amp;gt;e_{2} = 000002 = 2&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;math&amp;gt;s = 111144&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;S = (\bigcup\limits_{i=1}^{4} v_{i}) \cup (\bigcup\limits_{i=1}^{4} w_{i}) \cup (\bigcup\limits_{i=1}^{2} d_{i}) \cup (\bigcup\limits_{i=1}^{2} e_{i})&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Тогда набору значений &amp;lt;math&amp;gt;Y = (0,0,0,1):~ \varphi(Y) = 1&amp;lt;/math&amp;gt; соответствует &amp;lt;math&amp;gt;S' = \{w_{1},~w_{2},~w_{3},~v_{4},~d_{1},~e_{1},~e_{2}\}&amp;lt;/math&amp;gt;. И действительно, &amp;lt;math&amp;gt;100001 + 10000 + 1010 + 101 + 10 + 20 + 2 = 111144&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==См. также==&lt;br /&gt;
* [[NP]]&lt;br /&gt;
* [[NPH]]&lt;br /&gt;
* [[NPC]]&lt;br /&gt;
* [[Классы NP и Σ₁]]&lt;br /&gt;
* [[3CNFSAT]]&lt;br /&gt;
* [[Примеры NP-полных языков]]&lt;br /&gt;
&lt;br /&gt;
==Источники информации==&lt;br /&gt;
* Thomas H. Cormen, Charles E. Leiserson, Ronald L. Rivest, Clifford Stein &amp;quot;Introduction to Algorithms, 3rd Edition&amp;quot; {{---}} Издательство MIT Press, 2009. {{---}} 1292 с. {{---}} ISBN 978-0-262-03384-8 (англ.)&lt;br /&gt;
* Хопкрофт Дж., Мотвани Р., Ульман Дж. Введение в теорию автоматов, языков и вычислений. 2-е издание. {{---}} М.: Издательский дом &amp;quot;Вильямс&amp;quot;, 2002. {{---}} 528 с. {{---}} ISBN 5-8459-0261-4 (рус.)&lt;br /&gt;
&lt;br /&gt;
[[Категория: Теория сложности]]&lt;br /&gt;
[[Категория: Детерминированные и недетерминированные вычисления, сложность по времени и по памяти]]&lt;br /&gt;
[[Категория: Примеры NP-полных языков]]&lt;/div&gt;</summary>
		<author><name>KirillTim</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=NP-%D0%BF%D0%BE%D0%BB%D0%BD%D0%BE%D1%82%D0%B0_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B8_%D0%BE_%D1%81%D1%83%D0%BC%D0%BC%D0%B5_%D0%BF%D0%BE%D0%B4%D0%BC%D0%BD%D0%BE%D0%B6%D0%B5%D1%81%D1%82%D0%B2%D0%B0&amp;diff=54062</id>
		<title>NP-полнота задачи о сумме подмножества</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=NP-%D0%BF%D0%BE%D0%BB%D0%BD%D0%BE%D1%82%D0%B0_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B8_%D0%BE_%D1%81%D1%83%D0%BC%D0%BC%D0%B5_%D0%BF%D0%BE%D0%B4%D0%BC%D0%BD%D0%BE%D0%B6%D0%B5%D1%81%D1%82%D0%B2%D0%B0&amp;diff=54062"/>
				<updated>2016-05-17T17:26:33Z</updated>
		
		<summary type="html">&lt;p&gt;KirillTim: \phi -&amp;gt; \varphi&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Формулировка задачи==&lt;br /&gt;
В '''задаче о сумме подмножества''' (англ. ''Subset sum problem'') входными данными являются набор из &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; целых чисел &amp;lt;math&amp;gt;S&amp;lt;/math&amp;gt; и целое число &amp;lt;math&amp;gt;s&amp;lt;/math&amp;gt;. Требуется выяснить, возможно ли выбрать подмножество &amp;lt;math&amp;gt;S' \subseteq S&amp;lt;/math&amp;gt; с суммой &amp;lt;math&amp;gt;s&amp;lt;/math&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\exists S' \subseteq S: \sum_{s_{i} \in S'}{s_{i}} = s&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Доказательство NP-полноты==&lt;br /&gt;
Для доказательства того, что задачи о сумме подмножества является [[NPC | NP-полной]], необходимо доказать два факта:&lt;br /&gt;
*Задачи о сумме подмножества &amp;lt;math&amp;gt;\in&amp;lt;/math&amp;gt; [[NP]] &lt;br /&gt;
*Задачи о сумме подмножества &amp;lt;math&amp;gt;\in&amp;lt;/math&amp;gt; [[NPH]]&lt;br /&gt;
&lt;br /&gt;
===Доказательство принадлежности к NP===&lt;br /&gt;
В качестве сертификата возьмем удовлетворяющее условию задачи множество &amp;lt;math&amp;gt;S'&amp;lt;/math&amp;gt; с суммой &amp;lt;math&amp;gt;s&amp;lt;/math&amp;gt;. Оно удовлетворяет всем требованиям, налагаемым на сертификат. Проверяющая функция проверит вхождение всех элементов &amp;lt;math&amp;gt;S'&amp;lt;/math&amp;gt; в множество &amp;lt;math&amp;gt;S&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
===Доказательство принадлежности к NPH===&lt;br /&gt;
Сведем [[NP-полнота_задачи_о_выполнимости_булевой_формулы_в_форме_3-КНФ|3-CNF_Sat]] к задаче о сумме подмножества. Пусть задана 3-CNF формула &amp;lt;math&amp;gt;\varphi&amp;lt;/math&amp;gt; от &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;&lt;br /&gt;
переменных &amp;lt;math&amp;gt;x_{i}&amp;lt;/math&amp;gt;, состоящая из &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; пар скобок &amp;lt;math&amp;gt;C_{i}&amp;lt;/math&amp;gt;. Будем считать, не умаляя общности, что ни одна пара скобок не содержит одновременно переменную и ее отрицание. Также предположим, что каждая переменная входит хотя бы в одну пару скобок. Построим сводящую функцию &amp;lt;math&amp;gt;f\!\!:\varphi \to (S,s)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
====Построение сводящей функции====&lt;br /&gt;
Для каждой переменной &amp;lt;math&amp;gt;x_{i}&amp;lt;/math&amp;gt; и каждой пары скобок &amp;lt;math&amp;gt;C_{j}&amp;lt;/math&amp;gt; создадим по два числа в десятичной системе счисления, каждое длиной &amp;lt;math&amp;gt;n+k&amp;lt;/math&amp;gt; цифр. Эти числа образуют &amp;lt;math&amp;gt;S&amp;lt;/math&amp;gt;. Также создадим число &amp;lt;math&amp;gt;s&amp;lt;/math&amp;gt; длиной &amp;lt;math&amp;gt;n+k&amp;lt;/math&amp;gt; цифр. Присвоим каждому разряду полученных чисел (одинаковую для всех чисел) метку, соответствующую либо переменной, либо паре скобок.&lt;br /&gt;
Метки, соответствующие парам скобок, присвоены &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; младшим разрядам чисел.&lt;br /&gt;
*В числе &amp;lt;math&amp;gt;s&amp;lt;/math&amp;gt; все разряды, соответствующие переменным, установим &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt;, а оставшиеся сделаем равными &amp;lt;math&amp;gt;4&amp;lt;/math&amp;gt;.&lt;br /&gt;
*Каждой переменной &amp;lt;math&amp;gt;x_{i}&amp;lt;/math&amp;gt; соответствуют два числа из &amp;lt;math&amp;gt;S&amp;lt;/math&amp;gt;: &amp;lt;math&amp;gt;v_{i}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;u_{i}&amp;lt;/math&amp;gt;. Опишем создание этих чисел. Разряд, соответствующий &amp;lt;math&amp;gt;x_{i}&amp;lt;/math&amp;gt; установим равным &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt;, а все остальные разряды, соответствующие переменным, установим равными &amp;lt;math&amp;gt;0&amp;lt;/math&amp;gt;. Далее, для числа &amp;lt;math&amp;gt;v_{i}&amp;lt;/math&amp;gt; установим все разряды, соответствующие парам скобок, содержащих &amp;lt;math&amp;gt;x_{i}&amp;lt;/math&amp;gt;, равными &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt;. Во все остальные &amp;quot;скобочные&amp;quot; разряды поставим &amp;lt;math&amp;gt;0&amp;lt;/math&amp;gt;. В числе &amp;lt;math&amp;gt;w_{i}&amp;lt;/math&amp;gt; установим все разряды, соответствующие парам скобок, содержащих &amp;lt;math&amp;gt;\neg x_{i}&amp;lt;/math&amp;gt;, равными &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt;, а во все остальные &amp;quot;скобочные&amp;quot; разряды поставим &amp;lt;math&amp;gt;0&amp;lt;/math&amp;gt;.&lt;br /&gt;
*Каждой паре скобок &amp;lt;math&amp;gt;C_{j}&amp;lt;/math&amp;gt; соответствуют два числа из &amp;lt;math&amp;gt;S&amp;lt;/math&amp;gt;: &amp;lt;math&amp;gt;d_{i}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;e_{i}&amp;lt;/math&amp;gt;. Оба этих числа содержат &amp;lt;math&amp;gt;0&amp;lt;/math&amp;gt; во всех разрядах, кроме соответствующего &amp;lt;math&amp;gt;C_{j}&amp;lt;/math&amp;gt;. В этом разряде у &amp;lt;math&amp;gt;d_{i}&amp;lt;/math&amp;gt; поставим &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt;, а у &amp;lt;math&amp;gt;e_{i}&amp;lt;/math&amp;gt; {{---}} &amp;lt;math&amp;gt;2&amp;lt;/math&amp;gt;.&lt;br /&gt;
====Корректность сводящей функции====&lt;br /&gt;
*Получаемое сводящей функцией множество &amp;lt;math&amp;gt;S&amp;lt;/math&amp;gt; состоит из &amp;lt;math&amp;gt;2(n+k)&amp;lt;/math&amp;gt; десятичных чисел длиной &amp;lt;math&amp;gt;(n+k)&amp;lt;/math&amp;gt; каждое, выставление каждого разряда занимает полиномиальное время. Таким образом, сведение выполняется за полиномиальное время.&lt;br /&gt;
*Пусть формула &amp;lt;math&amp;gt;\varphi&amp;lt;/math&amp;gt; выполнима, то есть существует набор значений &amp;lt;math&amp;gt;\{y_{i}\}^{n}_{i=1}:~\varphi(y_{1}\ldots y_{n})=1 &amp;lt;/math&amp;gt;. И пусть &amp;lt;math&amp;gt;(S,s) = f(\varphi)&amp;lt;/math&amp;gt;. Тогда в полученном множестве &amp;lt;math&amp;gt;S&amp;lt;/math&amp;gt; существует подмножество с суммой &amp;lt;math&amp;gt;s&amp;lt;/math&amp;gt;. Действительно, для каждой переменной, если &amp;lt;math&amp;gt;y_{k} = 1&amp;lt;/math&amp;gt;, то добавим &amp;lt;math&amp;gt;v_{i}&amp;lt;/math&amp;gt; в &amp;lt;math&amp;gt;S'&amp;lt;/math&amp;gt;. Иначе добавим &amp;lt;math&amp;gt;w_{i}&amp;lt;/math&amp;gt;. Теперь &amp;lt;math&amp;gt;S'&amp;lt;/math&amp;gt; содержит уже &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; чисел. Заметим, что для каждого &amp;quot;скобочного&amp;quot; разряда в уже набранной части &amp;lt;math&amp;gt;S'&amp;lt;/math&amp;gt; есть не менее одного и не более трех чисел, у которых в данном разряде стоит &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt;. Значит для каждого соответствующего паре скобок &amp;lt;math&amp;gt;C_{j}&amp;lt;/math&amp;gt; разряда мы сможем выбрать одно или оба числа &amp;lt;math&amp;gt;d_{j}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;e_{j}&amp;lt;/math&amp;gt; так, чтобы сумма в данном разряде совпадала с требуемой (стала равна &amp;lt;math&amp;gt;4&amp;lt;/math&amp;gt;). Добавим их в &amp;lt;math&amp;gt;S'&amp;lt;/math&amp;gt;. Также заметим, что суммы во всех &amp;quot;переменных&amp;quot; разрядах равны &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt;, так как для каждого &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; выбиралось строго одно число из &amp;lt;math&amp;gt;v_{i}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;u_{i}&amp;lt;/math&amp;gt;. Значит, &amp;lt;math&amp;gt; \sum_{s_{k} \in S'}{s_{k}} = s&amp;lt;/math&amp;gt;.&lt;br /&gt;
*Пусть теперь в наборе &amp;lt;math&amp;gt;S&amp;lt;/math&amp;gt; есть подмножество &amp;lt;math&amp;gt;S':~  \sum_{s_{k} \in S'}{s_{k}} = s&amp;lt;/math&amp;gt;. Тогда исходная формула &amp;lt;math&amp;gt;\varphi&amp;lt;/math&amp;gt; выполнима. Действительно, если &amp;lt;math&amp;gt;v_{i} \in S'&amp;lt;/math&amp;gt;, то установим переменную &amp;lt;math&amp;gt;x_{i}=1&amp;lt;/math&amp;gt;. Если же &amp;lt;math&amp;gt;w_{i} \in S'&amp;lt;/math&amp;gt;, то &amp;lt;math&amp;gt;x_{i}=0&amp;lt;/math&amp;gt;. Покажем, что &amp;lt;math&amp;gt;\varphi(x_{1}\ldots x_{n}) = 1 &amp;lt;/math&amp;gt;. Действительно, так как &amp;lt;math&amp;gt; \sum_{s_{k} \in S'}{s_{k}} = s&amp;lt;/math&amp;gt;, в каждой паре скобок хотя бы один терм равен &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt;. Значит каждый терм равен &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt;. А тогда и вся &amp;lt;math&amp;gt;\varphi = 1&amp;lt;/math&amp;gt;.&lt;br /&gt;
====Пример сведения====&lt;br /&gt;
Пусть исходная функция &amp;lt;math&amp;gt;\varphi(x_{1} \ldots x_{4}) = (x_{1} \lor x_{2} \lor \neg x_{3}) \land (\neg x_{1} \lor x_{2} \lor x_{4})&amp;lt;/math&amp;gt;.&lt;br /&gt;
Пометим разряды следующим образом (слева направо): &amp;lt;math&amp;gt;x_{1},x_{2},x_{3},x_{4},C_{1},C_{2}&amp;lt;/math&amp;gt;. Тогда:&lt;br /&gt;
*&amp;lt;math&amp;gt;v_{1} = 100010&amp;lt;/math&amp;gt;&lt;br /&gt;
*&amp;lt;math&amp;gt;w_{1} = 100001&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;math&amp;gt;v_{2} = 010011 = 10011&amp;lt;/math&amp;gt;&lt;br /&gt;
*&amp;lt;math&amp;gt;w_{2} = 010000 = 10000&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;math&amp;gt;v_{3} = 001000 = 1000&amp;lt;/math&amp;gt;&lt;br /&gt;
*&amp;lt;math&amp;gt;w_{3} = 001010 = 1010&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;math&amp;gt;v_{4} = 000101 = 101&amp;lt;/math&amp;gt;&lt;br /&gt;
*&amp;lt;math&amp;gt;w_{4} = 000100 = 100&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;math&amp;gt;d_{1} = 000010 = 10&amp;lt;/math&amp;gt;&lt;br /&gt;
*&amp;lt;math&amp;gt;e_{1} = 000020 = 20&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;math&amp;gt;d_{2} = 000001 = 1&amp;lt;/math&amp;gt;&lt;br /&gt;
*&amp;lt;math&amp;gt;e_{2} = 000002 = 2&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;math&amp;gt;s = 111144&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;S = (\bigcup\limits_{i=1}^{4} v_{i}) \cup (\bigcup\limits_{i=1}^{4} w_{i}) \cup (\bigcup\limits_{i=1}^{2} d_{i}) \cup (\bigcup\limits_{i=1}^{2} e_{i})&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Тогда набору значений &amp;lt;math&amp;gt;Y = (0,0,0,1):~ \varphi(Y) = 1&amp;lt;/math&amp;gt; соответствует &amp;lt;math&amp;gt;S' = \{w_{1},~w_{2},~w_{3},~v_{4},~d_{1},~e_{1},~e_{2}\}&amp;lt;/math&amp;gt;. И действительно, &amp;lt;math&amp;gt;100001 + 10000 + 1010 + 101 + 10 + 20 + 2 = 111144&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==См. также==&lt;br /&gt;
* [[NP]]&lt;br /&gt;
* [[NPH]]&lt;br /&gt;
* [[NPC]]&lt;br /&gt;
* [[Классы NP и Σ₁]]&lt;br /&gt;
* [[3CNFSAT]]&lt;br /&gt;
* [[Примеры NP-полных языков]]&lt;br /&gt;
&lt;br /&gt;
==Источники информации==&lt;br /&gt;
* Thomas H. Cormen, Charles E. Leiserson, Ronald L. Rivest, Clifford Stein &amp;quot;Introduction to Algorithms, 3rd Edition&amp;quot; {{---}} Издательство MIT Press, 2009. {{---}} 1292 с. {{---}} ISBN 978-0-262-03384-8 (англ.)&lt;br /&gt;
* Хопкрофт Дж., Мотвани Р., Ульман Дж. Введение в теорию автоматов, языков и вычислений. 2-е издание. {{---}} М.: Издательский дом &amp;quot;Вильямс&amp;quot;, 2002. {{---}} 528 с. {{---}} ISBN 5-8459-0261-4 (рус.)&lt;br /&gt;
&lt;br /&gt;
[[Категория: Теория сложности]]&lt;br /&gt;
[[Категория: Детерминированные и недетерминированные вычисления, сложность по времени и по памяти]]&lt;br /&gt;
[[Категория: Примеры NP-полных языков]]&lt;/div&gt;</summary>
		<author><name>KirillTim</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=NP-%D0%BF%D0%BE%D0%BB%D0%BD%D0%BE%D1%82%D0%B0_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B8_%D0%BE_%D1%81%D1%83%D0%BC%D0%BC%D0%B5_%D0%BF%D0%BE%D0%B4%D0%BC%D0%BD%D0%BE%D0%B6%D0%B5%D1%81%D1%82%D0%B2%D0%B0&amp;diff=54061</id>
		<title>NP-полнота задачи о сумме подмножества</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=NP-%D0%BF%D0%BE%D0%BB%D0%BD%D0%BE%D1%82%D0%B0_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B8_%D0%BE_%D1%81%D1%83%D0%BC%D0%BC%D0%B5_%D0%BF%D0%BE%D0%B4%D0%BC%D0%BD%D0%BE%D0%B6%D0%B5%D1%81%D1%82%D0%B2%D0%B0&amp;diff=54061"/>
				<updated>2016-05-17T17:23:18Z</updated>
		
		<summary type="html">&lt;p&gt;KirillTim: big union symbols&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Формулировка задачи==&lt;br /&gt;
В '''задаче о сумме подмножества''' (англ. ''Subset sum problem'') входными данными являются набор из &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; целых чисел &amp;lt;math&amp;gt;S&amp;lt;/math&amp;gt; и целое число &amp;lt;math&amp;gt;s&amp;lt;/math&amp;gt;. Требуется выяснить, возможно ли выбрать подмножество &amp;lt;math&amp;gt;S' \subseteq S&amp;lt;/math&amp;gt; с суммой &amp;lt;math&amp;gt;s&amp;lt;/math&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\exists S' \subseteq S: \sum_{s_{i} \in S'}{s_{i}} = s&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Доказательство NP-полноты==&lt;br /&gt;
Для доказательства того, что задачи о сумме подмножества является [[NPC | NP-полной]], необходимо доказать два факта:&lt;br /&gt;
*Задачи о сумме подмножества &amp;lt;math&amp;gt;\in&amp;lt;/math&amp;gt; [[NP]] &lt;br /&gt;
*Задачи о сумме подмножества &amp;lt;math&amp;gt;\in&amp;lt;/math&amp;gt; [[NPH]]&lt;br /&gt;
&lt;br /&gt;
===Доказательство принадлежности к NP===&lt;br /&gt;
В качестве сертификата возьмем удовлетворяющее условию задачи множество &amp;lt;math&amp;gt;S'&amp;lt;/math&amp;gt; с суммой &amp;lt;math&amp;gt;s&amp;lt;/math&amp;gt;. Оно удовлетворяет всем требованиям, налагаемым на сертификат. Проверяющая функция проверит вхождение всех элементов &amp;lt;math&amp;gt;S'&amp;lt;/math&amp;gt; в множество &amp;lt;math&amp;gt;S&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
===Доказательство принадлежности к NPH===&lt;br /&gt;
Сведем [[NP-полнота_задачи_о_выполнимости_булевой_формулы_в_форме_3-КНФ|3-CNF_Sat]] к задаче о сумме подмножества. Пусть задана 3-CNF формула &amp;lt;math&amp;gt;\phi&amp;lt;/math&amp;gt; от &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;&lt;br /&gt;
переменных &amp;lt;math&amp;gt;x_{i}&amp;lt;/math&amp;gt;, состоящая из &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; пар скобок &amp;lt;math&amp;gt;C_{i}&amp;lt;/math&amp;gt;. Будем считать, не умаляя общности, что ни одна пара скобок не содержит одновременно переменную и ее отрицание. Также предположим, что каждая переменная входит хотя бы в одну пару скобок. Построим сводящую функцию &amp;lt;math&amp;gt;f\!\!:\phi \to (S,s)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
====Построение сводящей функции====&lt;br /&gt;
Для каждой переменной &amp;lt;math&amp;gt;x_{i}&amp;lt;/math&amp;gt; и каждой пары скобок &amp;lt;math&amp;gt;C_{j}&amp;lt;/math&amp;gt; создадим по два числа в десятичной системе счисления, каждое длиной &amp;lt;math&amp;gt;n+k&amp;lt;/math&amp;gt; цифр. Эти числа образуют &amp;lt;math&amp;gt;S&amp;lt;/math&amp;gt;. Также создадим число &amp;lt;math&amp;gt;s&amp;lt;/math&amp;gt; длиной &amp;lt;math&amp;gt;n+k&amp;lt;/math&amp;gt; цифр. Присвоим каждому разряду полученных чисел (одинаковую для всех чисел) метку, соответствующую либо переменной, либо паре скобок.&lt;br /&gt;
Метки, соответствующие парам скобок, присвоены &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; младшим разрядам чисел.&lt;br /&gt;
*В числе &amp;lt;math&amp;gt;s&amp;lt;/math&amp;gt; все разряды, соответствующие переменным, установим &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt;, а оставшиеся сделаем равными &amp;lt;math&amp;gt;4&amp;lt;/math&amp;gt;.&lt;br /&gt;
*Каждой переменной &amp;lt;math&amp;gt;x_{i}&amp;lt;/math&amp;gt; соответствуют два числа из &amp;lt;math&amp;gt;S&amp;lt;/math&amp;gt;: &amp;lt;math&amp;gt;v_{i}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;u_{i}&amp;lt;/math&amp;gt;. Опишем создание этих чисел. Разряд, соответствующий &amp;lt;math&amp;gt;x_{i}&amp;lt;/math&amp;gt; установим равным &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt;, а все остальные разряды, соответствующие переменным, установим равными &amp;lt;math&amp;gt;0&amp;lt;/math&amp;gt;. Далее, для числа &amp;lt;math&amp;gt;v_{i}&amp;lt;/math&amp;gt; установим все разряды, соответствующие парам скобок, содержащих &amp;lt;math&amp;gt;x_{i}&amp;lt;/math&amp;gt;, равными &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt;. Во все остальные &amp;quot;скобочные&amp;quot; разряды поставим &amp;lt;math&amp;gt;0&amp;lt;/math&amp;gt;. В числе &amp;lt;math&amp;gt;w_{i}&amp;lt;/math&amp;gt; установим все разряды, соответствующие парам скобок, содержащих &amp;lt;math&amp;gt;\neg x_{i}&amp;lt;/math&amp;gt;, равными &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt;, а во все остальные &amp;quot;скобочные&amp;quot; разряды поставим &amp;lt;math&amp;gt;0&amp;lt;/math&amp;gt;.&lt;br /&gt;
*Каждой паре скобок &amp;lt;math&amp;gt;C_{j}&amp;lt;/math&amp;gt; соответствуют два числа из &amp;lt;math&amp;gt;S&amp;lt;/math&amp;gt;: &amp;lt;math&amp;gt;d_{i}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;e_{i}&amp;lt;/math&amp;gt;. Оба этих числа содержат &amp;lt;math&amp;gt;0&amp;lt;/math&amp;gt; во всех разрядах, кроме соответствующего &amp;lt;math&amp;gt;C_{j}&amp;lt;/math&amp;gt;. В этом разряде у &amp;lt;math&amp;gt;d_{i}&amp;lt;/math&amp;gt; поставим &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt;, а у &amp;lt;math&amp;gt;e_{i}&amp;lt;/math&amp;gt; {{---}} &amp;lt;math&amp;gt;2&amp;lt;/math&amp;gt;.&lt;br /&gt;
====Корректность сводящей функции====&lt;br /&gt;
*Получаемое сводящей функцией множество &amp;lt;math&amp;gt;S&amp;lt;/math&amp;gt; состоит из &amp;lt;math&amp;gt;2(n+k)&amp;lt;/math&amp;gt; десятичных чисел длиной &amp;lt;math&amp;gt;(n+k)&amp;lt;/math&amp;gt; каждое, выставление каждого разряда занимает полиномиальное время. Таким образом, сведение выполняется за полиномиальное время.&lt;br /&gt;
*Пусть формула &amp;lt;math&amp;gt;\phi&amp;lt;/math&amp;gt; выполнима, то есть существует набор значений &amp;lt;math&amp;gt;\{y_{i}\}^{n}_{i=1}:~\phi(y_{1}\ldots y_{n})=1 &amp;lt;/math&amp;gt;. И пусть &amp;lt;math&amp;gt;(S,s) = f(\phi)&amp;lt;/math&amp;gt;. Тогда в полученном множестве &amp;lt;math&amp;gt;S&amp;lt;/math&amp;gt; существует подмножество с суммой &amp;lt;math&amp;gt;s&amp;lt;/math&amp;gt;. Действительно, для каждой переменной, если &amp;lt;math&amp;gt;y_{k} = 1&amp;lt;/math&amp;gt;, то добавим &amp;lt;math&amp;gt;v_{i}&amp;lt;/math&amp;gt; в &amp;lt;math&amp;gt;S'&amp;lt;/math&amp;gt;. Иначе добавим &amp;lt;math&amp;gt;w_{i}&amp;lt;/math&amp;gt;. Теперь &amp;lt;math&amp;gt;S'&amp;lt;/math&amp;gt; содержит уже &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; чисел. Заметим, что для каждого &amp;quot;скобочного&amp;quot; разряда в уже набранной части &amp;lt;math&amp;gt;S'&amp;lt;/math&amp;gt; есть не менее одного и не более трех чисел, у которых в данном разряде стоит &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt;. Значит для каждого соответствующего паре скобок &amp;lt;math&amp;gt;C_{j}&amp;lt;/math&amp;gt; разряда мы сможем выбрать одно или оба числа &amp;lt;math&amp;gt;d_{j}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;e_{j}&amp;lt;/math&amp;gt; так, чтобы сумма в данном разряде совпадала с требуемой (стала равна &amp;lt;math&amp;gt;4&amp;lt;/math&amp;gt;). Добавим их в &amp;lt;math&amp;gt;S'&amp;lt;/math&amp;gt;. Также заметим, что суммы во всех &amp;quot;переменных&amp;quot; разрядах равны &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt;, так как для каждого &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; выбиралось строго одно число из &amp;lt;math&amp;gt;v_{i}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;u_{i}&amp;lt;/math&amp;gt;. Значит, &amp;lt;math&amp;gt; \sum_{s_{k} \in S'}{s_{k}} = s&amp;lt;/math&amp;gt;.&lt;br /&gt;
*Пусть теперь в наборе &amp;lt;math&amp;gt;S&amp;lt;/math&amp;gt; есть подмножество &amp;lt;math&amp;gt;S':~  \sum_{s_{k} \in S'}{s_{k}} = s&amp;lt;/math&amp;gt;. Тогда исходная формула &amp;lt;math&amp;gt;\phi&amp;lt;/math&amp;gt; выполнима. Действительно, если &amp;lt;math&amp;gt;v_{i} \in S'&amp;lt;/math&amp;gt;, то установим переменную &amp;lt;math&amp;gt;x_{i}=1&amp;lt;/math&amp;gt;. Если же &amp;lt;math&amp;gt;w_{i} \in S'&amp;lt;/math&amp;gt;, то &amp;lt;math&amp;gt;x_{i}=0&amp;lt;/math&amp;gt;. Покажем, что &amp;lt;math&amp;gt;\phi(x_{1}\ldots x_{n}) = 1 &amp;lt;/math&amp;gt;. Действительно, так как &amp;lt;math&amp;gt; \sum_{s_{k} \in S'}{s_{k}} = s&amp;lt;/math&amp;gt;, в каждой паре скобок хотя бы один терм равен &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt;. Значит каждый терм равен &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt;. А тогда и вся &amp;lt;math&amp;gt;\phi = 1&amp;lt;/math&amp;gt;.&lt;br /&gt;
====Пример сведения====&lt;br /&gt;
Пусть исходная функция &amp;lt;math&amp;gt;\phi(x_{1} \ldots x_{4}) = (x_{1} \lor x_{2} \lor \neg x_{3}) \land (\neg x_{1} \lor x_{2} \lor x_{4})&amp;lt;/math&amp;gt;.&lt;br /&gt;
Пометим разряды следующим образом (слева направо): &amp;lt;math&amp;gt;x_{1},x_{2},x_{3},x_{4},C_{1},C_{2}&amp;lt;/math&amp;gt;. Тогда:&lt;br /&gt;
*&amp;lt;math&amp;gt;v_{1} = 100010&amp;lt;/math&amp;gt;&lt;br /&gt;
*&amp;lt;math&amp;gt;w_{1} = 100001&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;math&amp;gt;v_{2} = 010011 = 10011&amp;lt;/math&amp;gt;&lt;br /&gt;
*&amp;lt;math&amp;gt;w_{2} = 010000 = 10000&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;math&amp;gt;v_{3} = 001000 = 1000&amp;lt;/math&amp;gt;&lt;br /&gt;
*&amp;lt;math&amp;gt;w_{3} = 001010 = 1010&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;math&amp;gt;v_{4} = 000101 = 101&amp;lt;/math&amp;gt;&lt;br /&gt;
*&amp;lt;math&amp;gt;w_{4} = 000100 = 100&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;math&amp;gt;d_{1} = 000010 = 10&amp;lt;/math&amp;gt;&lt;br /&gt;
*&amp;lt;math&amp;gt;e_{1} = 000020 = 20&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;math&amp;gt;d_{2} = 000001 = 1&amp;lt;/math&amp;gt;&lt;br /&gt;
*&amp;lt;math&amp;gt;e_{2} = 000002 = 2&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;math&amp;gt;s = 111144&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;S = (\bigcup\limits_{i=1}^{4} v_{i}) \cup (\bigcup\limits_{i=1}^{4} w_{i}) \cup (\bigcup\limits_{i=1}^{2} d_{i}) \cup (\bigcup\limits_{i=1}^{2} e_{i})&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Тогда набору значений &amp;lt;math&amp;gt;Y = (0,0,0,1):~ \phi(Y) = 1&amp;lt;/math&amp;gt; соответствует &amp;lt;math&amp;gt;S' = \{w_{1},~w_{2},~w_{3},~v_{4},~d_{1},~e_{1},~e_{2}\}&amp;lt;/math&amp;gt;. И действительно, &amp;lt;math&amp;gt;100001 + 10000 + 1010 + 101 + 10 + 20 + 2 = 111144&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==См. также==&lt;br /&gt;
* [[NP]]&lt;br /&gt;
* [[NPH]]&lt;br /&gt;
* [[NPC]]&lt;br /&gt;
* [[Классы NP и Σ₁]]&lt;br /&gt;
* [[3CNFSAT]]&lt;br /&gt;
* [[Примеры NP-полных языков]]&lt;br /&gt;
&lt;br /&gt;
==Источники информации==&lt;br /&gt;
* Thomas H. Cormen, Charles E. Leiserson, Ronald L. Rivest, Clifford Stein &amp;quot;Introduction to Algorithms, 3rd Edition&amp;quot; {{---}} Издательство MIT Press, 2009. {{---}} 1292 с. {{---}} ISBN 978-0-262-03384-8 (англ.)&lt;br /&gt;
* Хопкрофт Дж., Мотвани Р., Ульман Дж. Введение в теорию автоматов, языков и вычислений. 2-е издание. {{---}} М.: Издательский дом &amp;quot;Вильямс&amp;quot;, 2002. {{---}} 528 с. {{---}} ISBN 5-8459-0261-4 (рус.)&lt;br /&gt;
&lt;br /&gt;
[[Категория: Теория сложности]]&lt;br /&gt;
[[Категория: Детерминированные и недетерминированные вычисления, сложность по времени и по памяти]]&lt;br /&gt;
[[Категория: Примеры NP-полных языков]]&lt;/div&gt;</summary>
		<author><name>KirillTim</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=NP-%D0%BF%D0%BE%D0%BB%D0%BD%D0%BE%D1%82%D0%B0_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B8_%D0%BE_%D1%81%D1%83%D0%BC%D0%BC%D0%B5_%D0%BF%D0%BE%D0%B4%D0%BC%D0%BD%D0%BE%D0%B6%D0%B5%D1%81%D1%82%D0%B2%D0%B0&amp;diff=53999</id>
		<title>NP-полнота задачи о сумме подмножества</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=NP-%D0%BF%D0%BE%D0%BB%D0%BD%D0%BE%D1%82%D0%B0_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B8_%D0%BE_%D1%81%D1%83%D0%BC%D0%BC%D0%B5_%D0%BF%D0%BE%D0%B4%D0%BC%D0%BD%D0%BE%D0%B6%D0%B5%D1%81%D1%82%D0%B2%D0%B0&amp;diff=53999"/>
				<updated>2016-05-16T19:17:58Z</updated>
		
		<summary type="html">&lt;p&gt;KirillTim: /* Формулировка задачи */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Формулировка задачи==&lt;br /&gt;
В '''задаче о сумме подмножества''' (англ. ''Subset sum problem'') входными данными являются набор из &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; целых чисел &amp;lt;math&amp;gt;S&amp;lt;/math&amp;gt; и целое число &amp;lt;math&amp;gt;s&amp;lt;/math&amp;gt;. Требуется выяснить, возможно ли выбрать подмножество &amp;lt;math&amp;gt;S' \subseteq S&amp;lt;/math&amp;gt; с суммой &amp;lt;math&amp;gt;s&amp;lt;/math&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\exists S' \subseteq S: \sum_{s_{i} \in S'}{s_{i}} = s&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Доказательство NP-полноты==&lt;br /&gt;
Для доказательства того, что задачи о сумме подмножества является [[NPC | NP-полной]], необходимо доказать два факта:&lt;br /&gt;
*Задачи о сумме подмножества &amp;lt;math&amp;gt;\in&amp;lt;/math&amp;gt; [[NP]] &lt;br /&gt;
*Задачи о сумме подмножества &amp;lt;math&amp;gt;\in&amp;lt;/math&amp;gt; [[NPH]]&lt;br /&gt;
&lt;br /&gt;
===Доказательство принадлежности к NP===&lt;br /&gt;
В качестве сертификата возьмем удовлетворяющее условию задачи множество &amp;lt;math&amp;gt;S'&amp;lt;/math&amp;gt; с суммой &amp;lt;math&amp;gt;s&amp;lt;/math&amp;gt;. Оно удовлетворяет всем требованиям, налагаемым на сертификат. Проверяющая функция проверит вхождение всех элементов &amp;lt;math&amp;gt;S'&amp;lt;/math&amp;gt; в множество &amp;lt;math&amp;gt;S&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
===Доказательство принадлежности к NPH===&lt;br /&gt;
Сведем [[NP-полнота_задачи_о_выполнимости_булевой_формулы_в_форме_3-КНФ|3-CNF_Sat]] к задаче о сумме подмножества. Пусть задана 3-CNF формула &amp;lt;math&amp;gt;\phi&amp;lt;/math&amp;gt; от &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;&lt;br /&gt;
переменных &amp;lt;math&amp;gt;x_{i}&amp;lt;/math&amp;gt;, состоящая из &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; пар скобок &amp;lt;math&amp;gt;C_{i}&amp;lt;/math&amp;gt;. Будем считать, не умаляя общности, что ни одна пара скобок не содержит одновременно переменную и ее отрицание. Также предположим, что каждая переменная входит хотя бы в одну пару скобок. Построим сводящую функцию &amp;lt;math&amp;gt;f\!\!:\phi \to (S,s)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
====Построение сводящей функции====&lt;br /&gt;
Для каждой переменной &amp;lt;math&amp;gt;x_{i}&amp;lt;/math&amp;gt; и каждой пары скобок &amp;lt;math&amp;gt;C_{j}&amp;lt;/math&amp;gt; создадим по два числа в десятичной системе счисления, каждое длиной &amp;lt;math&amp;gt;n+k&amp;lt;/math&amp;gt; цифр. Эти числа образуют &amp;lt;math&amp;gt;S&amp;lt;/math&amp;gt;. Также создадим число &amp;lt;math&amp;gt;s&amp;lt;/math&amp;gt; длиной &amp;lt;math&amp;gt;n+k&amp;lt;/math&amp;gt; цифр. Присвоим каждому разряду полученных чисел (одинаковую для всех чисел) метку, соответствующую либо переменной, либо паре скобок.&lt;br /&gt;
Метки, соответствующие парам скобок, присвоены &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; младшим разрядам чисел.&lt;br /&gt;
*В числе &amp;lt;math&amp;gt;s&amp;lt;/math&amp;gt; все разряды, соответствующие переменным, установим &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt;, а оставшиеся сделаем равными &amp;lt;math&amp;gt;4&amp;lt;/math&amp;gt;.&lt;br /&gt;
*Каждой переменной &amp;lt;math&amp;gt;x_{i}&amp;lt;/math&amp;gt; соответствуют два числа из &amp;lt;math&amp;gt;S&amp;lt;/math&amp;gt;: &amp;lt;math&amp;gt;v_{i}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;u_{i}&amp;lt;/math&amp;gt;. Опишем создание этих чисел. Разряд, соответствующий &amp;lt;math&amp;gt;x_{i}&amp;lt;/math&amp;gt; установим равным &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt;, а все остальные разряды, соответствующие переменным, установим равными &amp;lt;math&amp;gt;0&amp;lt;/math&amp;gt;. Далее, для числа &amp;lt;math&amp;gt;v_{i}&amp;lt;/math&amp;gt; установим все разряды, соответствующие парам скобок, содержащих &amp;lt;math&amp;gt;x_{i}&amp;lt;/math&amp;gt;, равными &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt;. Во все остальные &amp;quot;скобочные&amp;quot; разряды поставим &amp;lt;math&amp;gt;0&amp;lt;/math&amp;gt;. В числе &amp;lt;math&amp;gt;w_{i}&amp;lt;/math&amp;gt; установим все разряды, соответствующие парам скобок, содержащих &amp;lt;math&amp;gt;\neg x_{i}&amp;lt;/math&amp;gt;, равными &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt;, а во все остальные &amp;quot;скобочные&amp;quot; разряды поставим &amp;lt;math&amp;gt;0&amp;lt;/math&amp;gt;.&lt;br /&gt;
*Каждой паре скобок &amp;lt;math&amp;gt;C_{j}&amp;lt;/math&amp;gt; соответствуют два числа из &amp;lt;math&amp;gt;S&amp;lt;/math&amp;gt;: &amp;lt;math&amp;gt;d_{i}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;e_{i}&amp;lt;/math&amp;gt;. Оба этих числа содержат &amp;lt;math&amp;gt;0&amp;lt;/math&amp;gt; во всех разрядах, кроме соответствующего &amp;lt;math&amp;gt;C_{j}&amp;lt;/math&amp;gt;. В этом разряде у &amp;lt;math&amp;gt;d_{i}&amp;lt;/math&amp;gt; поставим &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt;, а у &amp;lt;math&amp;gt;e_{i}&amp;lt;/math&amp;gt; {{---}} &amp;lt;math&amp;gt;2&amp;lt;/math&amp;gt;.&lt;br /&gt;
====Корректность сводящей функции====&lt;br /&gt;
*Получаемое сводящей функцией множество &amp;lt;math&amp;gt;S&amp;lt;/math&amp;gt; состоит из &amp;lt;math&amp;gt;2(n+k)&amp;lt;/math&amp;gt; десятичных чисел длиной &amp;lt;math&amp;gt;(n+k)&amp;lt;/math&amp;gt; каждое, выставление каждого разряда занимает полиномиальное время. Таким образом, сведение выполняется за полиномиальное время.&lt;br /&gt;
*Пусть формула &amp;lt;math&amp;gt;\phi&amp;lt;/math&amp;gt; выполнима, то есть существует набор значений &amp;lt;math&amp;gt;\{y_{i}\}^{n}_{i=1}:~\phi(y_{1}\ldots y_{n})=1 &amp;lt;/math&amp;gt;. И пусть &amp;lt;math&amp;gt;(S,s) = f(\phi)&amp;lt;/math&amp;gt;. Тогда в полученном множестве &amp;lt;math&amp;gt;S&amp;lt;/math&amp;gt; существует подмножество с суммой &amp;lt;math&amp;gt;s&amp;lt;/math&amp;gt;. Действительно, для каждой переменной, если &amp;lt;math&amp;gt;y_{k} = 1&amp;lt;/math&amp;gt;, то добавим &amp;lt;math&amp;gt;v_{i}&amp;lt;/math&amp;gt; в &amp;lt;math&amp;gt;S'&amp;lt;/math&amp;gt;. Иначе добавим &amp;lt;math&amp;gt;w_{i}&amp;lt;/math&amp;gt;. Теперь &amp;lt;math&amp;gt;S'&amp;lt;/math&amp;gt; содержит уже &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; чисел. Заметим, что для каждого &amp;quot;скобочного&amp;quot; разряда в уже набранной части &amp;lt;math&amp;gt;S'&amp;lt;/math&amp;gt; есть не менее одного и не более трех чисел, у которых в данном разряде стоит &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt;. Значит для каждого соответствующего паре скобок &amp;lt;math&amp;gt;C_{j}&amp;lt;/math&amp;gt; разряда мы сможем выбрать одно или оба числа &amp;lt;math&amp;gt;d_{j}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;e_{j}&amp;lt;/math&amp;gt; так, чтобы сумма в данном разряде совпадала с требуемой (стала равна &amp;lt;math&amp;gt;4&amp;lt;/math&amp;gt;). Добавим их в &amp;lt;math&amp;gt;S'&amp;lt;/math&amp;gt;. Также заметим, что суммы во всех &amp;quot;переменных&amp;quot; разрядах равны &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt;, так как для каждого &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; выбиралось строго одно число из &amp;lt;math&amp;gt;v_{i}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;u_{i}&amp;lt;/math&amp;gt;. Значит, &amp;lt;math&amp;gt; \sum_{s_{k} \in S'}{s_{k}} = s&amp;lt;/math&amp;gt;.&lt;br /&gt;
*Пусть теперь в наборе &amp;lt;math&amp;gt;S&amp;lt;/math&amp;gt; есть подмножество &amp;lt;math&amp;gt;S':~  \sum_{s_{k} \in S'}{s_{k}} = s&amp;lt;/math&amp;gt;. Тогда исходная формула &amp;lt;math&amp;gt;\phi&amp;lt;/math&amp;gt; выполнима. Действительно, если &amp;lt;math&amp;gt;v_{i} \in S'&amp;lt;/math&amp;gt;, то установим переменную &amp;lt;math&amp;gt;x_{i}=1&amp;lt;/math&amp;gt;. Если же &amp;lt;math&amp;gt;w_{i} \in S'&amp;lt;/math&amp;gt;, то &amp;lt;math&amp;gt;x_{i}=0&amp;lt;/math&amp;gt;. Покажем, что &amp;lt;math&amp;gt;\phi(x_{1}\ldots x_{n}) = 1 &amp;lt;/math&amp;gt;. Действительно, так как &amp;lt;math&amp;gt; \sum_{s_{k} \in S'}{s_{k}} = s&amp;lt;/math&amp;gt;, в каждой паре скобок хотя бы один терм равен &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt;. Значит каждый терм равен &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt;. А тогда и вся &amp;lt;math&amp;gt;\phi = 1&amp;lt;/math&amp;gt;.&lt;br /&gt;
====Пример сведения====&lt;br /&gt;
Пусть исходная функция &amp;lt;math&amp;gt;\phi(x_{1} \ldots x_{4}) = (x_{1} \lor x_{2} \lor \neg x_{3}) \land (\neg x_{1} \lor x_{2} \lor x_{4})&amp;lt;/math&amp;gt;.&lt;br /&gt;
Пометим разряды следующим образом (слева направо): &amp;lt;math&amp;gt;x_{1},x_{2},x_{3},x_{4},C_{1},C_{2}&amp;lt;/math&amp;gt;. Тогда:&lt;br /&gt;
*&amp;lt;math&amp;gt;v_{1} = 100010&amp;lt;/math&amp;gt;&lt;br /&gt;
*&amp;lt;math&amp;gt;w_{1} = 100001&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;math&amp;gt;v_{2} = 010011 = 10011&amp;lt;/math&amp;gt;&lt;br /&gt;
*&amp;lt;math&amp;gt;w_{2} = 010000 = 10000&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;math&amp;gt;v_{3} = 001000 = 1000&amp;lt;/math&amp;gt;&lt;br /&gt;
*&amp;lt;math&amp;gt;w_{3} = 001010 = 1010&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;math&amp;gt;v_{4} = 000101 = 101&amp;lt;/math&amp;gt;&lt;br /&gt;
*&amp;lt;math&amp;gt;w_{4} = 000100 = 100&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;math&amp;gt;d_{1} = 000010 = 10&amp;lt;/math&amp;gt;&lt;br /&gt;
*&amp;lt;math&amp;gt;e_{1} = 000020 = 20&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;math&amp;gt;d_{2} = 000001 = 1&amp;lt;/math&amp;gt;&lt;br /&gt;
*&amp;lt;math&amp;gt;e_{2} = 000002 = 2&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;math&amp;gt;s = 111144&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;S = (\cup_{i=1 \ldots 4} v_{i}) \cup (\cup_{i=1 \ldots 4} w_{i})  \cup (\cup_{i=1 \ldots 2} d_{i})  \cup (\cup_{i=1 \ldots 2} e_{i})&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Тогда набору значений &amp;lt;math&amp;gt;Y = (0,0,0,1):~ \phi(Y) = 1&amp;lt;/math&amp;gt; соответствует &amp;lt;math&amp;gt;S' = \{w_{1},~w_{2},~w_{3},~v_{4},~d_{1},~e_{1},~e_{2}\}&amp;lt;/math&amp;gt;. И действительно, &amp;lt;math&amp;gt;100001 + 10000 + 1010 + 101 + 10 + 20 + 2 = 111144&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==См. также==&lt;br /&gt;
* [[NP]]&lt;br /&gt;
* [[NPH]]&lt;br /&gt;
* [[NPC]]&lt;br /&gt;
* [[Классы NP и Σ₁]]&lt;br /&gt;
* [[3CNFSAT]]&lt;br /&gt;
* [[Примеры NP-полных языков]]&lt;br /&gt;
&lt;br /&gt;
==Источники информации==&lt;br /&gt;
* Thomas H. Cormen, Charles E. Leiserson, Ronald L. Rivest, Clifford Stein &amp;quot;Introduction to Algorithms, 3rd Edition&amp;quot; {{---}} Издательство MIT Press, 2009. {{---}} 1292 с. {{---}} ISBN 978-0-262-03384-8 (англ.)&lt;br /&gt;
* Хопкрофт Дж., Мотвани Р., Ульман Дж. Введение в теорию автоматов, языков и вычислений. 2-е издание. {{---}} М.: Издательский дом &amp;quot;Вильямс&amp;quot;, 2002. {{---}} 528 с. {{---}} ISBN 5-8459-0261-4 (рус.)&lt;br /&gt;
&lt;br /&gt;
[[Категория: Теория сложности]]&lt;br /&gt;
[[Категория: Детерминированные и недетерминированные вычисления, сложность по времени и по памяти]]&lt;br /&gt;
[[Категория: Примеры NP-полных языков]]&lt;/div&gt;</summary>
		<author><name>KirillTim</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=NP-%D0%BF%D0%BE%D0%BB%D0%BD%D0%BE%D1%82%D0%B0_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B8_%D0%BE_%D1%81%D1%83%D0%BC%D0%BC%D0%B5_%D0%BF%D0%BE%D0%B4%D0%BC%D0%BD%D0%BE%D0%B6%D0%B5%D1%81%D1%82%D0%B2%D0%B0&amp;diff=53998</id>
		<title>NP-полнота задачи о сумме подмножества</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=NP-%D0%BF%D0%BE%D0%BB%D0%BD%D0%BE%D1%82%D0%B0_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B8_%D0%BE_%D1%81%D1%83%D0%BC%D0%BC%D0%B5_%D0%BF%D0%BE%D0%B4%D0%BC%D0%BD%D0%BE%D0%B6%D0%B5%D1%81%D1%82%D0%B2%D0%B0&amp;diff=53998"/>
				<updated>2016-05-16T19:17:10Z</updated>
		
		<summary type="html">&lt;p&gt;KirillTim: /* Формулировка задачи */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Формулировка задачи==&lt;br /&gt;
В '''задаче о сумме подмножества''' (англ. Subset sum problem) входными данными являются набор из &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; целых чисел &amp;lt;math&amp;gt;S&amp;lt;/math&amp;gt; и целое число &amp;lt;math&amp;gt;s&amp;lt;/math&amp;gt;. Требуется выяснить, возможно ли выбрать подмножество &amp;lt;math&amp;gt;S' \subseteq S&amp;lt;/math&amp;gt; с суммой &amp;lt;math&amp;gt;s&amp;lt;/math&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\exists S' \subseteq S: \sum_{s_{i} \in S'}{s_{i}} = s&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Доказательство NP-полноты==&lt;br /&gt;
Для доказательства того, что задачи о сумме подмножества является [[NPC | NP-полной]], необходимо доказать два факта:&lt;br /&gt;
*Задачи о сумме подмножества &amp;lt;math&amp;gt;\in&amp;lt;/math&amp;gt; [[NP]] &lt;br /&gt;
*Задачи о сумме подмножества &amp;lt;math&amp;gt;\in&amp;lt;/math&amp;gt; [[NPH]]&lt;br /&gt;
&lt;br /&gt;
===Доказательство принадлежности к NP===&lt;br /&gt;
В качестве сертификата возьмем удовлетворяющее условию задачи множество &amp;lt;math&amp;gt;S'&amp;lt;/math&amp;gt; с суммой &amp;lt;math&amp;gt;s&amp;lt;/math&amp;gt;. Оно удовлетворяет всем требованиям, налагаемым на сертификат. Проверяющая функция проверит вхождение всех элементов &amp;lt;math&amp;gt;S'&amp;lt;/math&amp;gt; в множество &amp;lt;math&amp;gt;S&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
===Доказательство принадлежности к NPH===&lt;br /&gt;
Сведем [[NP-полнота_задачи_о_выполнимости_булевой_формулы_в_форме_3-КНФ|3-CNF_Sat]] к задаче о сумме подмножества. Пусть задана 3-CNF формула &amp;lt;math&amp;gt;\phi&amp;lt;/math&amp;gt; от &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;&lt;br /&gt;
переменных &amp;lt;math&amp;gt;x_{i}&amp;lt;/math&amp;gt;, состоящая из &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; пар скобок &amp;lt;math&amp;gt;C_{i}&amp;lt;/math&amp;gt;. Будем считать, не умаляя общности, что ни одна пара скобок не содержит одновременно переменную и ее отрицание. Также предположим, что каждая переменная входит хотя бы в одну пару скобок. Построим сводящую функцию &amp;lt;math&amp;gt;f\!\!:\phi \to (S,s)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
====Построение сводящей функции====&lt;br /&gt;
Для каждой переменной &amp;lt;math&amp;gt;x_{i}&amp;lt;/math&amp;gt; и каждой пары скобок &amp;lt;math&amp;gt;C_{j}&amp;lt;/math&amp;gt; создадим по два числа в десятичной системе счисления, каждое длиной &amp;lt;math&amp;gt;n+k&amp;lt;/math&amp;gt; цифр. Эти числа образуют &amp;lt;math&amp;gt;S&amp;lt;/math&amp;gt;. Также создадим число &amp;lt;math&amp;gt;s&amp;lt;/math&amp;gt; длиной &amp;lt;math&amp;gt;n+k&amp;lt;/math&amp;gt; цифр. Присвоим каждому разряду полученных чисел (одинаковую для всех чисел) метку, соответствующую либо переменной, либо паре скобок.&lt;br /&gt;
Метки, соответствующие парам скобок, присвоены &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; младшим разрядам чисел.&lt;br /&gt;
*В числе &amp;lt;math&amp;gt;s&amp;lt;/math&amp;gt; все разряды, соответствующие переменным, установим &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt;, а оставшиеся сделаем равными &amp;lt;math&amp;gt;4&amp;lt;/math&amp;gt;.&lt;br /&gt;
*Каждой переменной &amp;lt;math&amp;gt;x_{i}&amp;lt;/math&amp;gt; соответствуют два числа из &amp;lt;math&amp;gt;S&amp;lt;/math&amp;gt;: &amp;lt;math&amp;gt;v_{i}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;u_{i}&amp;lt;/math&amp;gt;. Опишем создание этих чисел. Разряд, соответствующий &amp;lt;math&amp;gt;x_{i}&amp;lt;/math&amp;gt; установим равным &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt;, а все остальные разряды, соответствующие переменным, установим равными &amp;lt;math&amp;gt;0&amp;lt;/math&amp;gt;. Далее, для числа &amp;lt;math&amp;gt;v_{i}&amp;lt;/math&amp;gt; установим все разряды, соответствующие парам скобок, содержащих &amp;lt;math&amp;gt;x_{i}&amp;lt;/math&amp;gt;, равными &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt;. Во все остальные &amp;quot;скобочные&amp;quot; разряды поставим &amp;lt;math&amp;gt;0&amp;lt;/math&amp;gt;. В числе &amp;lt;math&amp;gt;w_{i}&amp;lt;/math&amp;gt; установим все разряды, соответствующие парам скобок, содержащих &amp;lt;math&amp;gt;\neg x_{i}&amp;lt;/math&amp;gt;, равными &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt;, а во все остальные &amp;quot;скобочные&amp;quot; разряды поставим &amp;lt;math&amp;gt;0&amp;lt;/math&amp;gt;.&lt;br /&gt;
*Каждой паре скобок &amp;lt;math&amp;gt;C_{j}&amp;lt;/math&amp;gt; соответствуют два числа из &amp;lt;math&amp;gt;S&amp;lt;/math&amp;gt;: &amp;lt;math&amp;gt;d_{i}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;e_{i}&amp;lt;/math&amp;gt;. Оба этих числа содержат &amp;lt;math&amp;gt;0&amp;lt;/math&amp;gt; во всех разрядах, кроме соответствующего &amp;lt;math&amp;gt;C_{j}&amp;lt;/math&amp;gt;. В этом разряде у &amp;lt;math&amp;gt;d_{i}&amp;lt;/math&amp;gt; поставим &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt;, а у &amp;lt;math&amp;gt;e_{i}&amp;lt;/math&amp;gt; {{---}} &amp;lt;math&amp;gt;2&amp;lt;/math&amp;gt;.&lt;br /&gt;
====Корректность сводящей функции====&lt;br /&gt;
*Получаемое сводящей функцией множество &amp;lt;math&amp;gt;S&amp;lt;/math&amp;gt; состоит из &amp;lt;math&amp;gt;2(n+k)&amp;lt;/math&amp;gt; десятичных чисел длиной &amp;lt;math&amp;gt;(n+k)&amp;lt;/math&amp;gt; каждое, выставление каждого разряда занимает полиномиальное время. Таким образом, сведение выполняется за полиномиальное время.&lt;br /&gt;
*Пусть формула &amp;lt;math&amp;gt;\phi&amp;lt;/math&amp;gt; выполнима, то есть существует набор значений &amp;lt;math&amp;gt;\{y_{i}\}^{n}_{i=1}:~\phi(y_{1}\ldots y_{n})=1 &amp;lt;/math&amp;gt;. И пусть &amp;lt;math&amp;gt;(S,s) = f(\phi)&amp;lt;/math&amp;gt;. Тогда в полученном множестве &amp;lt;math&amp;gt;S&amp;lt;/math&amp;gt; существует подмножество с суммой &amp;lt;math&amp;gt;s&amp;lt;/math&amp;gt;. Действительно, для каждой переменной, если &amp;lt;math&amp;gt;y_{k} = 1&amp;lt;/math&amp;gt;, то добавим &amp;lt;math&amp;gt;v_{i}&amp;lt;/math&amp;gt; в &amp;lt;math&amp;gt;S'&amp;lt;/math&amp;gt;. Иначе добавим &amp;lt;math&amp;gt;w_{i}&amp;lt;/math&amp;gt;. Теперь &amp;lt;math&amp;gt;S'&amp;lt;/math&amp;gt; содержит уже &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; чисел. Заметим, что для каждого &amp;quot;скобочного&amp;quot; разряда в уже набранной части &amp;lt;math&amp;gt;S'&amp;lt;/math&amp;gt; есть не менее одного и не более трех чисел, у которых в данном разряде стоит &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt;. Значит для каждого соответствующего паре скобок &amp;lt;math&amp;gt;C_{j}&amp;lt;/math&amp;gt; разряда мы сможем выбрать одно или оба числа &amp;lt;math&amp;gt;d_{j}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;e_{j}&amp;lt;/math&amp;gt; так, чтобы сумма в данном разряде совпадала с требуемой (стала равна &amp;lt;math&amp;gt;4&amp;lt;/math&amp;gt;). Добавим их в &amp;lt;math&amp;gt;S'&amp;lt;/math&amp;gt;. Также заметим, что суммы во всех &amp;quot;переменных&amp;quot; разрядах равны &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt;, так как для каждого &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; выбиралось строго одно число из &amp;lt;math&amp;gt;v_{i}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;u_{i}&amp;lt;/math&amp;gt;. Значит, &amp;lt;math&amp;gt; \sum_{s_{k} \in S'}{s_{k}} = s&amp;lt;/math&amp;gt;.&lt;br /&gt;
*Пусть теперь в наборе &amp;lt;math&amp;gt;S&amp;lt;/math&amp;gt; есть подмножество &amp;lt;math&amp;gt;S':~  \sum_{s_{k} \in S'}{s_{k}} = s&amp;lt;/math&amp;gt;. Тогда исходная формула &amp;lt;math&amp;gt;\phi&amp;lt;/math&amp;gt; выполнима. Действительно, если &amp;lt;math&amp;gt;v_{i} \in S'&amp;lt;/math&amp;gt;, то установим переменную &amp;lt;math&amp;gt;x_{i}=1&amp;lt;/math&amp;gt;. Если же &amp;lt;math&amp;gt;w_{i} \in S'&amp;lt;/math&amp;gt;, то &amp;lt;math&amp;gt;x_{i}=0&amp;lt;/math&amp;gt;. Покажем, что &amp;lt;math&amp;gt;\phi(x_{1}\ldots x_{n}) = 1 &amp;lt;/math&amp;gt;. Действительно, так как &amp;lt;math&amp;gt; \sum_{s_{k} \in S'}{s_{k}} = s&amp;lt;/math&amp;gt;, в каждой паре скобок хотя бы один терм равен &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt;. Значит каждый терм равен &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt;. А тогда и вся &amp;lt;math&amp;gt;\phi = 1&amp;lt;/math&amp;gt;.&lt;br /&gt;
====Пример сведения====&lt;br /&gt;
Пусть исходная функция &amp;lt;math&amp;gt;\phi(x_{1} \ldots x_{4}) = (x_{1} \lor x_{2} \lor \neg x_{3}) \land (\neg x_{1} \lor x_{2} \lor x_{4})&amp;lt;/math&amp;gt;.&lt;br /&gt;
Пометим разряды следующим образом (слева направо): &amp;lt;math&amp;gt;x_{1},x_{2},x_{3},x_{4},C_{1},C_{2}&amp;lt;/math&amp;gt;. Тогда:&lt;br /&gt;
*&amp;lt;math&amp;gt;v_{1} = 100010&amp;lt;/math&amp;gt;&lt;br /&gt;
*&amp;lt;math&amp;gt;w_{1} = 100001&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;math&amp;gt;v_{2} = 010011 = 10011&amp;lt;/math&amp;gt;&lt;br /&gt;
*&amp;lt;math&amp;gt;w_{2} = 010000 = 10000&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;math&amp;gt;v_{3} = 001000 = 1000&amp;lt;/math&amp;gt;&lt;br /&gt;
*&amp;lt;math&amp;gt;w_{3} = 001010 = 1010&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;math&amp;gt;v_{4} = 000101 = 101&amp;lt;/math&amp;gt;&lt;br /&gt;
*&amp;lt;math&amp;gt;w_{4} = 000100 = 100&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;math&amp;gt;d_{1} = 000010 = 10&amp;lt;/math&amp;gt;&lt;br /&gt;
*&amp;lt;math&amp;gt;e_{1} = 000020 = 20&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;math&amp;gt;d_{2} = 000001 = 1&amp;lt;/math&amp;gt;&lt;br /&gt;
*&amp;lt;math&amp;gt;e_{2} = 000002 = 2&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;math&amp;gt;s = 111144&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;S = (\cup_{i=1 \ldots 4} v_{i}) \cup (\cup_{i=1 \ldots 4} w_{i})  \cup (\cup_{i=1 \ldots 2} d_{i})  \cup (\cup_{i=1 \ldots 2} e_{i})&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Тогда набору значений &amp;lt;math&amp;gt;Y = (0,0,0,1):~ \phi(Y) = 1&amp;lt;/math&amp;gt; соответствует &amp;lt;math&amp;gt;S' = \{w_{1},~w_{2},~w_{3},~v_{4},~d_{1},~e_{1},~e_{2}\}&amp;lt;/math&amp;gt;. И действительно, &amp;lt;math&amp;gt;100001 + 10000 + 1010 + 101 + 10 + 20 + 2 = 111144&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==См. также==&lt;br /&gt;
* [[NP]]&lt;br /&gt;
* [[NPH]]&lt;br /&gt;
* [[NPC]]&lt;br /&gt;
* [[Классы NP и Σ₁]]&lt;br /&gt;
* [[3CNFSAT]]&lt;br /&gt;
* [[Примеры NP-полных языков]]&lt;br /&gt;
&lt;br /&gt;
==Источники информации==&lt;br /&gt;
* Thomas H. Cormen, Charles E. Leiserson, Ronald L. Rivest, Clifford Stein &amp;quot;Introduction to Algorithms, 3rd Edition&amp;quot; {{---}} Издательство MIT Press, 2009. {{---}} 1292 с. {{---}} ISBN 978-0-262-03384-8 (англ.)&lt;br /&gt;
* Хопкрофт Дж., Мотвани Р., Ульман Дж. Введение в теорию автоматов, языков и вычислений. 2-е издание. {{---}} М.: Издательский дом &amp;quot;Вильямс&amp;quot;, 2002. {{---}} 528 с. {{---}} ISBN 5-8459-0261-4 (рус.)&lt;br /&gt;
&lt;br /&gt;
[[Категория: Теория сложности]]&lt;br /&gt;
[[Категория: Детерминированные и недетерминированные вычисления, сложность по времени и по памяти]]&lt;br /&gt;
[[Категория: Примеры NP-полных языков]]&lt;/div&gt;</summary>
		<author><name>KirillTim</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=NP-%D0%BF%D0%BE%D0%BB%D0%BD%D0%BE%D1%82%D0%B0_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B8_%D0%BE_%D1%81%D1%83%D0%BC%D0%BC%D0%B5_%D0%BF%D0%BE%D0%B4%D0%BC%D0%BD%D0%BE%D0%B6%D0%B5%D1%81%D1%82%D0%B2%D0%B0&amp;diff=53996</id>
		<title>NP-полнота задачи о сумме подмножества</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=NP-%D0%BF%D0%BE%D0%BB%D0%BD%D0%BE%D1%82%D0%B0_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B8_%D0%BE_%D1%81%D1%83%D0%BC%D0%BC%D0%B5_%D0%BF%D0%BE%D0%B4%D0%BC%D0%BD%D0%BE%D0%B6%D0%B5%D1%81%D1%82%D0%B2%D0%B0&amp;diff=53996"/>
				<updated>2016-05-16T19:09:42Z</updated>
		
		<summary type="html">&lt;p&gt;KirillTim: /* Доказательство NP-полноты */ опечатки&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Формулировка задачи==&lt;br /&gt;
В '''задаче о сумме подмножества''' (Subset sum problem) входными данными являются набор из &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; целых чисел &amp;lt;math&amp;gt;S&amp;lt;/math&amp;gt; и целое число &amp;lt;math&amp;gt;s&amp;lt;/math&amp;gt;. Требуется выяснить, возможно ли выбрать подмножество &amp;lt;math&amp;gt;S' \subseteq S&amp;lt;/math&amp;gt; с суммой &amp;lt;math&amp;gt;s&amp;lt;/math&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\exists S' \subseteq S: \sum_{s_{i} \in S'}{s_{i}} = s&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Доказательство NP-полноты==&lt;br /&gt;
Для доказательства того, что задачи о сумме подмножества является [[NPC | NP-полной]], необходимо доказать два факта:&lt;br /&gt;
*Задачи о сумме подмножества &amp;lt;math&amp;gt;\in&amp;lt;/math&amp;gt; [[NP]] &lt;br /&gt;
*Задачи о сумме подмножества &amp;lt;math&amp;gt;\in&amp;lt;/math&amp;gt; [[NPH]]&lt;br /&gt;
&lt;br /&gt;
===Доказательство принадлежности к NP===&lt;br /&gt;
В качестве сертификата возьмем удовлетворяющее условию задачи множество &amp;lt;math&amp;gt;S'&amp;lt;/math&amp;gt; с суммой &amp;lt;math&amp;gt;s&amp;lt;/math&amp;gt;. Оно удовлетворяет всем требованиям, налагаемым на сертификат. Проверяющая функция проверит вхождение всех элементов &amp;lt;math&amp;gt;S'&amp;lt;/math&amp;gt; в множество &amp;lt;math&amp;gt;S&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
===Доказательство принадлежности к NPH===&lt;br /&gt;
Сведем [[NP-полнота_задачи_о_выполнимости_булевой_формулы_в_форме_3-КНФ|3-CNF_Sat]] к задаче о сумме подмножества. Пусть задана 3-CNF формула &amp;lt;math&amp;gt;\phi&amp;lt;/math&amp;gt; от &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;&lt;br /&gt;
переменных &amp;lt;math&amp;gt;x_{i}&amp;lt;/math&amp;gt;, состоящая из &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; пар скобок &amp;lt;math&amp;gt;C_{i}&amp;lt;/math&amp;gt;. Будем считать, не умаляя общности, что ни одна пара скобок не содержит одновременно переменную и ее отрицание. Также предположим, что каждая переменная входит хотя бы в одну пару скобок. Построим сводящую функцию &amp;lt;math&amp;gt;f\!\!:\phi \to (S,s)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
====Построение сводящей функции====&lt;br /&gt;
Для каждой переменной &amp;lt;math&amp;gt;x_{i}&amp;lt;/math&amp;gt; и каждой пары скобок &amp;lt;math&amp;gt;C_{j}&amp;lt;/math&amp;gt; создадим по два числа в десятичной системе счисления, каждое длиной &amp;lt;math&amp;gt;n+k&amp;lt;/math&amp;gt; цифр. Эти числа образуют &amp;lt;math&amp;gt;S&amp;lt;/math&amp;gt;. Также создадим число &amp;lt;math&amp;gt;s&amp;lt;/math&amp;gt; длиной &amp;lt;math&amp;gt;n+k&amp;lt;/math&amp;gt; цифр. Присвоим каждому разряду полученных чисел (одинаковую для всех чисел) метку, соответствующую либо переменной, либо паре скобок.&lt;br /&gt;
Метки, соответствующие парам скобок, присвоены &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; младшим разрядам чисел.&lt;br /&gt;
*В числе &amp;lt;math&amp;gt;s&amp;lt;/math&amp;gt; все разряды, соответствующие переменным, установим &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt;, а оставшиеся сделаем равными &amp;lt;math&amp;gt;4&amp;lt;/math&amp;gt;.&lt;br /&gt;
*Каждой переменной &amp;lt;math&amp;gt;x_{i}&amp;lt;/math&amp;gt; соответствуют два числа из &amp;lt;math&amp;gt;S&amp;lt;/math&amp;gt;: &amp;lt;math&amp;gt;v_{i}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;u_{i}&amp;lt;/math&amp;gt;. Опишем создание этих чисел. Разряд, соответствующий &amp;lt;math&amp;gt;x_{i}&amp;lt;/math&amp;gt; установим равным &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt;, а все остальные разряды, соответствующие переменным, установим равными &amp;lt;math&amp;gt;0&amp;lt;/math&amp;gt;. Далее, для числа &amp;lt;math&amp;gt;v_{i}&amp;lt;/math&amp;gt; установим все разряды, соответствующие парам скобок, содержащих &amp;lt;math&amp;gt;x_{i}&amp;lt;/math&amp;gt;, равными &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt;. Во все остальные &amp;quot;скобочные&amp;quot; разряды поставим &amp;lt;math&amp;gt;0&amp;lt;/math&amp;gt;. В числе &amp;lt;math&amp;gt;w_{i}&amp;lt;/math&amp;gt; установим все разряды, соответствующие парам скобок, содержащих &amp;lt;math&amp;gt;\neg x_{i}&amp;lt;/math&amp;gt;, равными &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt;, а во все остальные &amp;quot;скобочные&amp;quot; разряды поставим &amp;lt;math&amp;gt;0&amp;lt;/math&amp;gt;.&lt;br /&gt;
*Каждой паре скобок &amp;lt;math&amp;gt;C_{j}&amp;lt;/math&amp;gt; соответствуют два числа из &amp;lt;math&amp;gt;S&amp;lt;/math&amp;gt;: &amp;lt;math&amp;gt;d_{i}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;e_{i}&amp;lt;/math&amp;gt;. Оба этих числа содержат &amp;lt;math&amp;gt;0&amp;lt;/math&amp;gt; во всех разрядах, кроме соответствующего &amp;lt;math&amp;gt;C_{j}&amp;lt;/math&amp;gt;. В этом разряде у &amp;lt;math&amp;gt;d_{i}&amp;lt;/math&amp;gt; поставим &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt;, а у &amp;lt;math&amp;gt;e_{i}&amp;lt;/math&amp;gt; {{---}} &amp;lt;math&amp;gt;2&amp;lt;/math&amp;gt;.&lt;br /&gt;
====Корректность сводящей функции====&lt;br /&gt;
*Получаемое сводящей функцией множество &amp;lt;math&amp;gt;S&amp;lt;/math&amp;gt; состоит из &amp;lt;math&amp;gt;2(n+k)&amp;lt;/math&amp;gt; десятичных чисел длиной &amp;lt;math&amp;gt;(n+k)&amp;lt;/math&amp;gt; каждое, выставление каждого разряда занимает полиномиальное время. Таким образом, сведение выполняется за полиномиальное время.&lt;br /&gt;
*Пусть формула &amp;lt;math&amp;gt;\phi&amp;lt;/math&amp;gt; выполнима, то есть существует набор значений &amp;lt;math&amp;gt;\{y_{i}\}^{n}_{i=1}:~\phi(y_{1}\ldots y_{n})=1 &amp;lt;/math&amp;gt;. И пусть &amp;lt;math&amp;gt;(S,s) = f(\phi)&amp;lt;/math&amp;gt;. Тогда в полученном множестве &amp;lt;math&amp;gt;S&amp;lt;/math&amp;gt; существует подмножество с суммой &amp;lt;math&amp;gt;s&amp;lt;/math&amp;gt;. Действительно, для каждой переменной, если &amp;lt;math&amp;gt;y_{k} = 1&amp;lt;/math&amp;gt;, то добавим &amp;lt;math&amp;gt;v_{i}&amp;lt;/math&amp;gt; в &amp;lt;math&amp;gt;S'&amp;lt;/math&amp;gt;. Иначе добавим &amp;lt;math&amp;gt;w_{i}&amp;lt;/math&amp;gt;. Теперь &amp;lt;math&amp;gt;S'&amp;lt;/math&amp;gt; содержит уже &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; чисел. Заметим, что для каждого &amp;quot;скобочного&amp;quot; разряда в уже набранной части &amp;lt;math&amp;gt;S'&amp;lt;/math&amp;gt; есть не менее одного и не более трех чисел, у которых в данном разряде стоит &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt;. Значит для каждого соответствующего паре скобок &amp;lt;math&amp;gt;C_{j}&amp;lt;/math&amp;gt; разряда мы сможем выбрать одно или оба числа &amp;lt;math&amp;gt;d_{j}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;e_{j}&amp;lt;/math&amp;gt; так, чтобы сумма в данном разряде совпадала с требуемой (стала равна &amp;lt;math&amp;gt;4&amp;lt;/math&amp;gt;). Добавим их в &amp;lt;math&amp;gt;S'&amp;lt;/math&amp;gt;. Также заметим, что суммы во всех &amp;quot;переменных&amp;quot; разрядах равны &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt;, так как для каждого &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; выбиралось строго одно число из &amp;lt;math&amp;gt;v_{i}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;u_{i}&amp;lt;/math&amp;gt;. Значит, &amp;lt;math&amp;gt; \sum_{s_{k} \in S'}{s_{k}} = s&amp;lt;/math&amp;gt;.&lt;br /&gt;
*Пусть теперь в наборе &amp;lt;math&amp;gt;S&amp;lt;/math&amp;gt; есть подмножество &amp;lt;math&amp;gt;S':~  \sum_{s_{k} \in S'}{s_{k}} = s&amp;lt;/math&amp;gt;. Тогда исходная формула &amp;lt;math&amp;gt;\phi&amp;lt;/math&amp;gt; выполнима. Действительно, если &amp;lt;math&amp;gt;v_{i} \in S'&amp;lt;/math&amp;gt;, то установим переменную &amp;lt;math&amp;gt;x_{i}=1&amp;lt;/math&amp;gt;. Если же &amp;lt;math&amp;gt;w_{i} \in S'&amp;lt;/math&amp;gt;, то &amp;lt;math&amp;gt;x_{i}=0&amp;lt;/math&amp;gt;. Покажем, что &amp;lt;math&amp;gt;\phi(x_{1}\ldots x_{n}) = 1 &amp;lt;/math&amp;gt;. Действительно, так как &amp;lt;math&amp;gt; \sum_{s_{k} \in S'}{s_{k}} = s&amp;lt;/math&amp;gt;, в каждой паре скобок хотя бы один терм равен &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt;. Значит каждый терм равен &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt;. А тогда и вся &amp;lt;math&amp;gt;\phi = 1&amp;lt;/math&amp;gt;.&lt;br /&gt;
====Пример сведения====&lt;br /&gt;
Пусть исходная функция &amp;lt;math&amp;gt;\phi(x_{1} \ldots x_{4}) = (x_{1} \lor x_{2} \lor \neg x_{3}) \land (\neg x_{1} \lor x_{2} \lor x_{4})&amp;lt;/math&amp;gt;.&lt;br /&gt;
Пометим разряды следующим образом (слева направо): &amp;lt;math&amp;gt;x_{1},x_{2},x_{3},x_{4},C_{1},C_{2}&amp;lt;/math&amp;gt;. Тогда:&lt;br /&gt;
*&amp;lt;math&amp;gt;v_{1} = 100010&amp;lt;/math&amp;gt;&lt;br /&gt;
*&amp;lt;math&amp;gt;w_{1} = 100001&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;math&amp;gt;v_{2} = 010011 = 10011&amp;lt;/math&amp;gt;&lt;br /&gt;
*&amp;lt;math&amp;gt;w_{2} = 010000 = 10000&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;math&amp;gt;v_{3} = 001000 = 1000&amp;lt;/math&amp;gt;&lt;br /&gt;
*&amp;lt;math&amp;gt;w_{3} = 001010 = 1010&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;math&amp;gt;v_{4} = 000101 = 101&amp;lt;/math&amp;gt;&lt;br /&gt;
*&amp;lt;math&amp;gt;w_{4} = 000100 = 100&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;math&amp;gt;d_{1} = 000010 = 10&amp;lt;/math&amp;gt;&lt;br /&gt;
*&amp;lt;math&amp;gt;e_{1} = 000020 = 20&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;math&amp;gt;d_{2} = 000001 = 1&amp;lt;/math&amp;gt;&lt;br /&gt;
*&amp;lt;math&amp;gt;e_{2} = 000002 = 2&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;math&amp;gt;s = 111144&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;S = (\cup_{i=1 \ldots 4} v_{i}) \cup (\cup_{i=1 \ldots 4} w_{i})  \cup (\cup_{i=1 \ldots 2} d_{i})  \cup (\cup_{i=1 \ldots 2} e_{i})&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Тогда набору значений &amp;lt;math&amp;gt;Y = (0,0,0,1):~ \phi(Y) = 1&amp;lt;/math&amp;gt; соответствует &amp;lt;math&amp;gt;S' = \{w_{1},~w_{2},~w_{3},~v_{4},~d_{1},~e_{1},~e_{2}\}&amp;lt;/math&amp;gt;. И действительно, &amp;lt;math&amp;gt;100001 + 10000 + 1010 + 101 + 10 + 20 + 2 = 111144&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==См. также==&lt;br /&gt;
* [[NP]]&lt;br /&gt;
* [[NPH]]&lt;br /&gt;
* [[NPC]]&lt;br /&gt;
* [[Классы NP и Σ₁]]&lt;br /&gt;
* [[3CNFSAT]]&lt;br /&gt;
* [[Примеры NP-полных языков]]&lt;br /&gt;
&lt;br /&gt;
==Источники информации==&lt;br /&gt;
* Thomas H. Cormen, Charles E. Leiserson, Ronald L. Rivest, Clifford Stein &amp;quot;Introduction to Algorithms, 3rd Edition&amp;quot; {{---}} Издательство MIT Press, 2009. {{---}} 1292 с. {{---}} ISBN 978-0-262-03384-8 (англ.)&lt;br /&gt;
* Хопкрофт Дж., Мотвани Р., Ульман Дж. Введение в теорию автоматов, языков и вычислений. 2-е издание. {{---}} М.: Издательский дом &amp;quot;Вильямс&amp;quot;, 2002. {{---}} 528 с. {{---}} ISBN 5-8459-0261-4 (рус.)&lt;br /&gt;
&lt;br /&gt;
[[Категория: Теория сложности]]&lt;br /&gt;
[[Категория: Детерминированные и недетерминированные вычисления, сложность по времени и по памяти]]&lt;br /&gt;
[[Категория: Примеры NP-полных языков]]&lt;/div&gt;</summary>
		<author><name>KirillTim</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=NP-%D0%BF%D0%BE%D0%BB%D0%BD%D0%BE%D1%82%D0%B0_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B8_%D0%BE_%D1%81%D1%83%D0%BC%D0%BC%D0%B5_%D0%BF%D0%BE%D0%B4%D0%BC%D0%BD%D0%BE%D0%B6%D0%B5%D1%81%D1%82%D0%B2%D0%B0&amp;diff=53990</id>
		<title>NP-полнота задачи о сумме подмножества</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=NP-%D0%BF%D0%BE%D0%BB%D0%BD%D0%BE%D1%82%D0%B0_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B8_%D0%BE_%D1%81%D1%83%D0%BC%D0%BC%D0%B5_%D0%BF%D0%BE%D0%B4%D0%BC%D0%BD%D0%BE%D0%B6%D0%B5%D1%81%D1%82%D0%B2%D0%B0&amp;diff=53990"/>
				<updated>2016-05-16T18:26:22Z</updated>
		
		<summary type="html">&lt;p&gt;KirillTim: См. также&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Формулировка задачи==&lt;br /&gt;
В '''задаче о сумме подмножества''' (Subset sum problem) входными данными являются набор из &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; целых чисел &amp;lt;math&amp;gt;S&amp;lt;/math&amp;gt; и целое число &amp;lt;math&amp;gt;s&amp;lt;/math&amp;gt;. Требуется выяснить, возможно ли выбрать подмножество &amp;lt;math&amp;gt;S' \subseteq S&amp;lt;/math&amp;gt; с суммой &amp;lt;math&amp;gt;s&amp;lt;/math&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\exists S' \subseteq S: \sum_{s_{i} \in S'}{s_{i}} = s&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Доказательство NP-полноты==&lt;br /&gt;
Для доказательства того, что Subset sum problem &amp;lt;math&amp;gt;\in&amp;lt;/math&amp;gt; [[NPC]], необходимо доказать два факта:&lt;br /&gt;
*Subset sum problem &amp;lt;math&amp;gt;\in&amp;lt;/math&amp;gt; [[NP]] &lt;br /&gt;
*Subset sum problem &amp;lt;math&amp;gt;\in&amp;lt;/math&amp;gt;[[NPH]] &lt;br /&gt;
===Доказательство принадлежности к NP===&lt;br /&gt;
В качестве сертификата возьмем удовлетворяющее условию задачи множество &amp;lt;math&amp;gt;S'&amp;lt;/math&amp;gt; с суммой &amp;lt;math&amp;gt;s&amp;lt;/math&amp;gt;. Очевидно, оно удовлетворяет всем требованиям, налагаемым на сертификат. Проверяющая функция строится очевидным образом, работает за полиномиальное от размера входа время.&lt;br /&gt;
===Доказательство принадлежности к NPH===&lt;br /&gt;
Сведем [[NP-полнота_задачи_о_выполнимости_булевой_формулы_в_форме_3-КНФ|3-CNF_Sat]] к задаче о сумме подмножества. Пусть задана 3-CNF формула &amp;lt;math&amp;gt;\phi&amp;lt;/math&amp;gt; от &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;&lt;br /&gt;
переменных &amp;lt;math&amp;gt;x_{i}&amp;lt;/math&amp;gt;, состоящая из &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; пар скобок &amp;lt;math&amp;gt;C_{i}&amp;lt;/math&amp;gt;. Будем считать, не умаляя общности, что ни одна пара скобок не содержит одновременно переменную и ее отрицание. Также предположим, что каждая переменная входит хотя бы в одну пару скобок. Построим сводящую функцию &amp;lt;math&amp;gt;f\!\!:\phi \to (S,s)&amp;lt;/math&amp;gt;.&lt;br /&gt;
====Построение сводящей функции====&lt;br /&gt;
Для каждой переменной &amp;lt;math&amp;gt;x_{i}&amp;lt;/math&amp;gt; и каждой пары скобок &amp;lt;math&amp;gt;C_{j}&amp;lt;/math&amp;gt; создадим по два числа в десятичной системе счисления, каждое длиной &amp;lt;math&amp;gt;n+k&amp;lt;/math&amp;gt; цифр. Эти числа образуют &amp;lt;math&amp;gt;S&amp;lt;/math&amp;gt;. Также создадим число &amp;lt;math&amp;gt;s&amp;lt;/math&amp;gt; длиной &amp;lt;math&amp;gt;n+k&amp;lt;/math&amp;gt; цифр. Присвоим каждому разряду полученных чисел (одинаковую для всех чисел) метку, соответствующую либо переменной, либо паре скобок.&lt;br /&gt;
Метки, соответствующие парам скобок, присвоены &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; младшим разрядам чисел.&lt;br /&gt;
*В числе &amp;lt;math&amp;gt;s&amp;lt;/math&amp;gt; все разряды, соответствующие переменным, установим &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt;, а оставшиеся сделаем равными &amp;lt;math&amp;gt;4&amp;lt;/math&amp;gt;.&lt;br /&gt;
*Каждой переменной &amp;lt;math&amp;gt;x_{i}&amp;lt;/math&amp;gt; соответствуют два числа из &amp;lt;math&amp;gt;S&amp;lt;/math&amp;gt;: &amp;lt;math&amp;gt;v_{i}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;u_{i}&amp;lt;/math&amp;gt;. Опишем создание этих чисел. Разряд, соответствующий &amp;lt;math&amp;gt;x_{i}&amp;lt;/math&amp;gt; установим равным &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt;, а все остальные разряды, соответствующие переменным, установим равными &amp;lt;math&amp;gt;0&amp;lt;/math&amp;gt;. Далее, для числа &amp;lt;math&amp;gt;v_{i}&amp;lt;/math&amp;gt; установим все разряды, соответствующие парам скобок, содержащих &amp;lt;math&amp;gt;x_{i}&amp;lt;/math&amp;gt;, равными &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt;. Во все остальные &amp;quot;скобочные&amp;quot; разряды поставим &amp;lt;math&amp;gt;0&amp;lt;/math&amp;gt;. В числе &amp;lt;math&amp;gt;w_{i}&amp;lt;/math&amp;gt; установим все разряды, соответствующие парам скобок, содержащих &amp;lt;math&amp;gt;\neg x_{i}&amp;lt;/math&amp;gt;, равными &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt;, а во все остальные &amp;quot;скобочные&amp;quot; разряды поставим &amp;lt;math&amp;gt;0&amp;lt;/math&amp;gt;.&lt;br /&gt;
*Каждой паре скобок &amp;lt;math&amp;gt;C_{j}&amp;lt;/math&amp;gt; соответствуют два числа из &amp;lt;math&amp;gt;S&amp;lt;/math&amp;gt;: &amp;lt;math&amp;gt;d_{i}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;e_{i}&amp;lt;/math&amp;gt;. Оба этих числа содержат &amp;lt;math&amp;gt;0&amp;lt;/math&amp;gt; во всех разрядах, кроме соответствующего &amp;lt;math&amp;gt;C_{j}&amp;lt;/math&amp;gt;. В этом разряде у &amp;lt;math&amp;gt;d_{i}&amp;lt;/math&amp;gt; поставим &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt;, а у &amp;lt;math&amp;gt;e_{i}&amp;lt;/math&amp;gt; поставим &amp;lt;math&amp;gt;2&amp;lt;/math&amp;gt;.&lt;br /&gt;
====Корректность сводящей функции====&lt;br /&gt;
*Получаемое сводящей функцией множество &amp;lt;math&amp;gt;S&amp;lt;/math&amp;gt; состоит из &amp;lt;math&amp;gt;2(n+k)&amp;lt;/math&amp;gt; десятичных чисел длиной &amp;lt;math&amp;gt;(n+k)&amp;lt;/math&amp;gt; каждое, выставление каждого разряда занимает полиномиальное время. Таким образом, сведение выполняется за полиномиальное время.&lt;br /&gt;
*Пусть формула &amp;lt;math&amp;gt;\phi&amp;lt;/math&amp;gt; выполнима, то есть существует набор значений &amp;lt;math&amp;gt;\{y_{i}\}^{n}_{i=1}:~\phi(y_{1}\ldots y_{n})=1 &amp;lt;/math&amp;gt;. И пусть &amp;lt;math&amp;gt;(S,s) = f(\phi)&amp;lt;/math&amp;gt;. Тогда в полученном множестве &amp;lt;math&amp;gt;S&amp;lt;/math&amp;gt; существует подмножество с суммой &amp;lt;math&amp;gt;s&amp;lt;/math&amp;gt;. Действительно, для каждой переменной, если &amp;lt;math&amp;gt;y_{k} = 1&amp;lt;/math&amp;gt;, то добавим в &amp;lt;math&amp;gt;S'~ v_{i}&amp;lt;/math&amp;gt;. Иначе добавим &amp;lt;math&amp;gt;w_{i}&amp;lt;/math&amp;gt;. Теперь &amp;lt;math&amp;gt;S'&amp;lt;/math&amp;gt; содержит уже &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; чисел. Заметим, что для каждого &amp;quot;скобочного&amp;quot;разряда в уже набранной части &amp;lt;math&amp;gt;S'&amp;lt;/math&amp;gt; есть не менее одного и не более трех чисел, у которых в данном разряде стоит &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt;. Значит для каждого соответствующего паре скобок &amp;lt;math&amp;gt;C_{j}&amp;lt;/math&amp;gt; разряда мы сможем выбрать одно или оба числа &amp;lt;math&amp;gt;d_{j}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;e_{j}&amp;lt;/math&amp;gt; так, чтобы сумма в данном разряде совпадала с требуемой (стала равна &amp;lt;math&amp;gt;4&amp;lt;/math&amp;gt;). Добавим их в &amp;lt;math&amp;gt;S'&amp;lt;/math&amp;gt;. Также заметим, что суммы во всех &amp;quot;переменных&amp;quot; разрядах равны &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt;, так как для каждого &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; выбиралось строго одно число из &amp;lt;math&amp;gt;v_{i}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;u_{i}&amp;lt;/math&amp;gt;. Значит, &amp;lt;math&amp;gt; \sum_{s_{k} \in S'}{s_{k}} = s&amp;lt;/math&amp;gt;.&lt;br /&gt;
*Пусть теперь в наборе &amp;lt;math&amp;gt;S&amp;lt;/math&amp;gt; есть подмножество &amp;lt;math&amp;gt;S':~  \sum_{s_{k} \in S'}{s_{k}} = s&amp;lt;/math&amp;gt;. Тогда исходная формула &amp;lt;math&amp;gt;\phi&amp;lt;/math&amp;gt; выполнима. Действительно, если &amp;lt;math&amp;gt;v_{i} \in S'&amp;lt;/math&amp;gt;, то установим переменную &amp;lt;math&amp;gt;x_{i}=1&amp;lt;/math&amp;gt;. Если же &amp;lt;math&amp;gt;w_{i} \in S'&amp;lt;/math&amp;gt;, то &amp;lt;math&amp;gt;x_{i}=0&amp;lt;/math&amp;gt;. Покажем, что &amp;lt;math&amp;gt;\phi(x_{1}\ldots x_{n}) = 1 &amp;lt;/math&amp;gt;. Действительно, так как &amp;lt;math&amp;gt; \sum_{s_{k} \in S'}{s_{k}} = s&amp;lt;/math&amp;gt;, в каждой паре скобок хотя бы один терм равен &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt;. Значит каждый терм равен &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt;. А тогда и вся &amp;lt;math&amp;gt;\phi = 1&amp;lt;/math&amp;gt;.&lt;br /&gt;
====Пример сведения====&lt;br /&gt;
Пусть исходная функция &amp;lt;math&amp;gt;\phi(x_{1} \ldots x_{4}) = (x_{1} \lor x_{2} \lor \neg x_{3}) \land (\neg x_{1} \lor x_{2} \lor x_{4})&amp;lt;/math&amp;gt;.&lt;br /&gt;
Пометим разряды следующим образом (слева направо): &amp;lt;math&amp;gt;x_{1},x_{2},x_{3},x_{4},C_{1},C_{2}&amp;lt;/math&amp;gt;. Тогда:&lt;br /&gt;
*&amp;lt;math&amp;gt;v_{1} = 100010&amp;lt;/math&amp;gt;&lt;br /&gt;
*&amp;lt;math&amp;gt;w_{1} = 100001&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;math&amp;gt;v_{2} = 010011 = 10011&amp;lt;/math&amp;gt;&lt;br /&gt;
*&amp;lt;math&amp;gt;w_{2} = 010000 = 10000&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;math&amp;gt;v_{3} = 001000 = 1000&amp;lt;/math&amp;gt;&lt;br /&gt;
*&amp;lt;math&amp;gt;w_{3} = 001010 = 1010&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;math&amp;gt;v_{4} = 000101 = 101&amp;lt;/math&amp;gt;&lt;br /&gt;
*&amp;lt;math&amp;gt;w_{4} = 000100 = 100&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;math&amp;gt;d_{1} = 000010 = 10&amp;lt;/math&amp;gt;&lt;br /&gt;
*&amp;lt;math&amp;gt;e_{1} = 000020 = 20&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;math&amp;gt;d_{2} = 000001 = 1&amp;lt;/math&amp;gt;&lt;br /&gt;
*&amp;lt;math&amp;gt;e_{2} = 000002 = 2&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;math&amp;gt;s = 111144&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;S = (\cup_{i=1 \ldots 4} v_{i}) \cup (\cup_{i=1 \ldots 4} w_{i})  \cup (\cup_{i=1 \ldots 2} d_{i})  \cup (\cup_{i=1 \ldots 2} e_{i})&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Тогда набору значений &amp;lt;math&amp;gt;Y = (0,0,0,1):~ \phi(Y) = 1&amp;lt;/math&amp;gt; соответствует &amp;lt;math&amp;gt;S' = \{w_{1},~w_{2},~w_{3},~v_{4},~d_{1},~e_{1},~e_{2}\}&amp;lt;/math&amp;gt;. И действительно, &amp;lt;math&amp;gt;100001 + 10000 + 1010 + 101 + 10 + 20 + 2 = 111144&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==См. также==&lt;br /&gt;
* [[NP]]&lt;br /&gt;
* [[NPH]]&lt;br /&gt;
* [[NPC]]&lt;br /&gt;
* [[Классы NP и Σ₁]]&lt;br /&gt;
* [[3CNFSAT]]&lt;br /&gt;
* [[Примеры NP-полных языков]]&lt;br /&gt;
&lt;br /&gt;
==Источники информации==&lt;br /&gt;
* Thomas H. Cormen, Charles E. Leiserson, Ronald L. Rivest, Clifford Stein &amp;quot;Introduction to Algorithms, 3rd Edition&amp;quot; {{---}} Издательство MIT Press, 2009. {{---}} 1292 с. {{---}} ISBN 978-0-262-03384-8 (англ.)&lt;br /&gt;
* Хопкрофт Дж., Мотвани Р., Ульман Дж. Введение в теорию автоматов, языков и вычислений. 2-е издание. {{---}} М.: Издательский дом &amp;quot;Вильямс&amp;quot;, 2002. {{---}} 528 с. {{---}} ISBN 5-8459-0261-4 (рус.)&lt;br /&gt;
&lt;br /&gt;
[[Категория: Теория сложности]]&lt;br /&gt;
[[Категория: Детерминированные и недетерминированные вычисления, сложность по времени и по памяти]]&lt;br /&gt;
[[Категория: Примеры NP-полных языков]]&lt;/div&gt;</summary>
		<author><name>KirillTim</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=NP-%D0%BF%D0%BE%D0%BB%D0%BD%D0%BE%D1%82%D0%B0_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B8_%D0%BE_%D1%81%D1%83%D0%BC%D0%BC%D0%B5_%D0%BF%D0%BE%D0%B4%D0%BC%D0%BD%D0%BE%D0%B6%D0%B5%D1%81%D1%82%D0%B2%D0%B0&amp;diff=53989</id>
		<title>NP-полнота задачи о сумме подмножества</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=NP-%D0%BF%D0%BE%D0%BB%D0%BD%D0%BE%D1%82%D0%B0_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B8_%D0%BE_%D1%81%D1%83%D0%BC%D0%BC%D0%B5_%D0%BF%D0%BE%D0%B4%D0%BC%D0%BD%D0%BE%D0%B6%D0%B5%D1%81%D1%82%D0%B2%D0%B0&amp;diff=53989"/>
				<updated>2016-05-16T18:25:35Z</updated>
		
		<summary type="html">&lt;p&gt;KirillTim: Источники информации&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Формулировка задачи==&lt;br /&gt;
В '''задаче о сумме подмножества''' (Subset sum problem) входными данными являются набор из &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; целых чисел &amp;lt;math&amp;gt;S&amp;lt;/math&amp;gt; и целое число &amp;lt;math&amp;gt;s&amp;lt;/math&amp;gt;. Требуется выяснить, возможно ли выбрать подмножество &amp;lt;math&amp;gt;S' \subseteq S&amp;lt;/math&amp;gt; с суммой &amp;lt;math&amp;gt;s&amp;lt;/math&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\exists S' \subseteq S: \sum_{s_{i} \in S'}{s_{i}} = s&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Доказательство NP-полноты==&lt;br /&gt;
Для доказательства того, что Subset sum problem &amp;lt;math&amp;gt;\in&amp;lt;/math&amp;gt; [[NPC]], необходимо доказать два факта:&lt;br /&gt;
*Subset sum problem &amp;lt;math&amp;gt;\in&amp;lt;/math&amp;gt; [[NP]] &lt;br /&gt;
*Subset sum problem &amp;lt;math&amp;gt;\in&amp;lt;/math&amp;gt;[[NPH]] &lt;br /&gt;
===Доказательство принадлежности к NP===&lt;br /&gt;
В качестве сертификата возьмем удовлетворяющее условию задачи множество &amp;lt;math&amp;gt;S'&amp;lt;/math&amp;gt; с суммой &amp;lt;math&amp;gt;s&amp;lt;/math&amp;gt;. Очевидно, оно удовлетворяет всем требованиям, налагаемым на сертификат. Проверяющая функция строится очевидным образом, работает за полиномиальное от размера входа время.&lt;br /&gt;
===Доказательство принадлежности к NPH===&lt;br /&gt;
Сведем [[NP-полнота_задачи_о_выполнимости_булевой_формулы_в_форме_3-КНФ|3-CNF_Sat]] к задаче о сумме подмножества. Пусть задана 3-CNF формула &amp;lt;math&amp;gt;\phi&amp;lt;/math&amp;gt; от &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;&lt;br /&gt;
переменных &amp;lt;math&amp;gt;x_{i}&amp;lt;/math&amp;gt;, состоящая из &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; пар скобок &amp;lt;math&amp;gt;C_{i}&amp;lt;/math&amp;gt;. Будем считать, не умаляя общности, что ни одна пара скобок не содержит одновременно переменную и ее отрицание. Также предположим, что каждая переменная входит хотя бы в одну пару скобок. Построим сводящую функцию &amp;lt;math&amp;gt;f\!\!:\phi \to (S,s)&amp;lt;/math&amp;gt;.&lt;br /&gt;
====Построение сводящей функции====&lt;br /&gt;
Для каждой переменной &amp;lt;math&amp;gt;x_{i}&amp;lt;/math&amp;gt; и каждой пары скобок &amp;lt;math&amp;gt;C_{j}&amp;lt;/math&amp;gt; создадим по два числа в десятичной системе счисления, каждое длиной &amp;lt;math&amp;gt;n+k&amp;lt;/math&amp;gt; цифр. Эти числа образуют &amp;lt;math&amp;gt;S&amp;lt;/math&amp;gt;. Также создадим число &amp;lt;math&amp;gt;s&amp;lt;/math&amp;gt; длиной &amp;lt;math&amp;gt;n+k&amp;lt;/math&amp;gt; цифр. Присвоим каждому разряду полученных чисел (одинаковую для всех чисел) метку, соответствующую либо переменной, либо паре скобок.&lt;br /&gt;
Метки, соответствующие парам скобок, присвоены &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; младшим разрядам чисел.&lt;br /&gt;
*В числе &amp;lt;math&amp;gt;s&amp;lt;/math&amp;gt; все разряды, соответствующие переменным, установим &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt;, а оставшиеся сделаем равными &amp;lt;math&amp;gt;4&amp;lt;/math&amp;gt;.&lt;br /&gt;
*Каждой переменной &amp;lt;math&amp;gt;x_{i}&amp;lt;/math&amp;gt; соответствуют два числа из &amp;lt;math&amp;gt;S&amp;lt;/math&amp;gt;: &amp;lt;math&amp;gt;v_{i}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;u_{i}&amp;lt;/math&amp;gt;. Опишем создание этих чисел. Разряд, соответствующий &amp;lt;math&amp;gt;x_{i}&amp;lt;/math&amp;gt; установим равным &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt;, а все остальные разряды, соответствующие переменным, установим равными &amp;lt;math&amp;gt;0&amp;lt;/math&amp;gt;. Далее, для числа &amp;lt;math&amp;gt;v_{i}&amp;lt;/math&amp;gt; установим все разряды, соответствующие парам скобок, содержащих &amp;lt;math&amp;gt;x_{i}&amp;lt;/math&amp;gt;, равными &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt;. Во все остальные &amp;quot;скобочные&amp;quot; разряды поставим &amp;lt;math&amp;gt;0&amp;lt;/math&amp;gt;. В числе &amp;lt;math&amp;gt;w_{i}&amp;lt;/math&amp;gt; установим все разряды, соответствующие парам скобок, содержащих &amp;lt;math&amp;gt;\neg x_{i}&amp;lt;/math&amp;gt;, равными &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt;, а во все остальные &amp;quot;скобочные&amp;quot; разряды поставим &amp;lt;math&amp;gt;0&amp;lt;/math&amp;gt;.&lt;br /&gt;
*Каждой паре скобок &amp;lt;math&amp;gt;C_{j}&amp;lt;/math&amp;gt; соответствуют два числа из &amp;lt;math&amp;gt;S&amp;lt;/math&amp;gt;: &amp;lt;math&amp;gt;d_{i}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;e_{i}&amp;lt;/math&amp;gt;. Оба этих числа содержат &amp;lt;math&amp;gt;0&amp;lt;/math&amp;gt; во всех разрядах, кроме соответствующего &amp;lt;math&amp;gt;C_{j}&amp;lt;/math&amp;gt;. В этом разряде у &amp;lt;math&amp;gt;d_{i}&amp;lt;/math&amp;gt; поставим &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt;, а у &amp;lt;math&amp;gt;e_{i}&amp;lt;/math&amp;gt; поставим &amp;lt;math&amp;gt;2&amp;lt;/math&amp;gt;.&lt;br /&gt;
====Корректность сводящей функции====&lt;br /&gt;
*Получаемое сводящей функцией множество &amp;lt;math&amp;gt;S&amp;lt;/math&amp;gt; состоит из &amp;lt;math&amp;gt;2(n+k)&amp;lt;/math&amp;gt; десятичных чисел длиной &amp;lt;math&amp;gt;(n+k)&amp;lt;/math&amp;gt; каждое, выставление каждого разряда занимает полиномиальное время. Таким образом, сведение выполняется за полиномиальное время.&lt;br /&gt;
*Пусть формула &amp;lt;math&amp;gt;\phi&amp;lt;/math&amp;gt; выполнима, то есть существует набор значений &amp;lt;math&amp;gt;\{y_{i}\}^{n}_{i=1}:~\phi(y_{1}\ldots y_{n})=1 &amp;lt;/math&amp;gt;. И пусть &amp;lt;math&amp;gt;(S,s) = f(\phi)&amp;lt;/math&amp;gt;. Тогда в полученном множестве &amp;lt;math&amp;gt;S&amp;lt;/math&amp;gt; существует подмножество с суммой &amp;lt;math&amp;gt;s&amp;lt;/math&amp;gt;. Действительно, для каждой переменной, если &amp;lt;math&amp;gt;y_{k} = 1&amp;lt;/math&amp;gt;, то добавим в &amp;lt;math&amp;gt;S'~ v_{i}&amp;lt;/math&amp;gt;. Иначе добавим &amp;lt;math&amp;gt;w_{i}&amp;lt;/math&amp;gt;. Теперь &amp;lt;math&amp;gt;S'&amp;lt;/math&amp;gt; содержит уже &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; чисел. Заметим, что для каждого &amp;quot;скобочного&amp;quot;разряда в уже набранной части &amp;lt;math&amp;gt;S'&amp;lt;/math&amp;gt; есть не менее одного и не более трех чисел, у которых в данном разряде стоит &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt;. Значит для каждого соответствующего паре скобок &amp;lt;math&amp;gt;C_{j}&amp;lt;/math&amp;gt; разряда мы сможем выбрать одно или оба числа &amp;lt;math&amp;gt;d_{j}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;e_{j}&amp;lt;/math&amp;gt; так, чтобы сумма в данном разряде совпадала с требуемой (стала равна &amp;lt;math&amp;gt;4&amp;lt;/math&amp;gt;). Добавим их в &amp;lt;math&amp;gt;S'&amp;lt;/math&amp;gt;. Также заметим, что суммы во всех &amp;quot;переменных&amp;quot; разрядах равны &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt;, так как для каждого &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; выбиралось строго одно число из &amp;lt;math&amp;gt;v_{i}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;u_{i}&amp;lt;/math&amp;gt;. Значит, &amp;lt;math&amp;gt; \sum_{s_{k} \in S'}{s_{k}} = s&amp;lt;/math&amp;gt;.&lt;br /&gt;
*Пусть теперь в наборе &amp;lt;math&amp;gt;S&amp;lt;/math&amp;gt; есть подмножество &amp;lt;math&amp;gt;S':~  \sum_{s_{k} \in S'}{s_{k}} = s&amp;lt;/math&amp;gt;. Тогда исходная формула &amp;lt;math&amp;gt;\phi&amp;lt;/math&amp;gt; выполнима. Действительно, если &amp;lt;math&amp;gt;v_{i} \in S'&amp;lt;/math&amp;gt;, то установим переменную &amp;lt;math&amp;gt;x_{i}=1&amp;lt;/math&amp;gt;. Если же &amp;lt;math&amp;gt;w_{i} \in S'&amp;lt;/math&amp;gt;, то &amp;lt;math&amp;gt;x_{i}=0&amp;lt;/math&amp;gt;. Покажем, что &amp;lt;math&amp;gt;\phi(x_{1}\ldots x_{n}) = 1 &amp;lt;/math&amp;gt;. Действительно, так как &amp;lt;math&amp;gt; \sum_{s_{k} \in S'}{s_{k}} = s&amp;lt;/math&amp;gt;, в каждой паре скобок хотя бы один терм равен &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt;. Значит каждый терм равен &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt;. А тогда и вся &amp;lt;math&amp;gt;\phi = 1&amp;lt;/math&amp;gt;.&lt;br /&gt;
====Пример сведения====&lt;br /&gt;
Пусть исходная функция &amp;lt;math&amp;gt;\phi(x_{1} \ldots x_{4}) = (x_{1} \lor x_{2} \lor \neg x_{3}) \land (\neg x_{1} \lor x_{2} \lor x_{4})&amp;lt;/math&amp;gt;.&lt;br /&gt;
Пометим разряды следующим образом (слева направо): &amp;lt;math&amp;gt;x_{1},x_{2},x_{3},x_{4},C_{1},C_{2}&amp;lt;/math&amp;gt;. Тогда:&lt;br /&gt;
*&amp;lt;math&amp;gt;v_{1} = 100010&amp;lt;/math&amp;gt;&lt;br /&gt;
*&amp;lt;math&amp;gt;w_{1} = 100001&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;math&amp;gt;v_{2} = 010011 = 10011&amp;lt;/math&amp;gt;&lt;br /&gt;
*&amp;lt;math&amp;gt;w_{2} = 010000 = 10000&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;math&amp;gt;v_{3} = 001000 = 1000&amp;lt;/math&amp;gt;&lt;br /&gt;
*&amp;lt;math&amp;gt;w_{3} = 001010 = 1010&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;math&amp;gt;v_{4} = 000101 = 101&amp;lt;/math&amp;gt;&lt;br /&gt;
*&amp;lt;math&amp;gt;w_{4} = 000100 = 100&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;math&amp;gt;d_{1} = 000010 = 10&amp;lt;/math&amp;gt;&lt;br /&gt;
*&amp;lt;math&amp;gt;e_{1} = 000020 = 20&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;math&amp;gt;d_{2} = 000001 = 1&amp;lt;/math&amp;gt;&lt;br /&gt;
*&amp;lt;math&amp;gt;e_{2} = 000002 = 2&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;math&amp;gt;s = 111144&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;S = (\cup_{i=1 \ldots 4} v_{i}) \cup (\cup_{i=1 \ldots 4} w_{i})  \cup (\cup_{i=1 \ldots 2} d_{i})  \cup (\cup_{i=1 \ldots 2} e_{i})&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Тогда набору значений &amp;lt;math&amp;gt;Y = (0,0,0,1):~ \phi(Y) = 1&amp;lt;/math&amp;gt; соответствует &amp;lt;math&amp;gt;S' = \{w_{1},~w_{2},~w_{3},~v_{4},~d_{1},~e_{1},~e_{2}\}&amp;lt;/math&amp;gt;. И действительно, &amp;lt;math&amp;gt;100001 + 10000 + 1010 + 101 + 10 + 20 + 2 = 111144&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Источники информации==&lt;br /&gt;
* Thomas H. Cormen, Charles E. Leiserson, Ronald L. Rivest, Clifford Stein &amp;quot;Introduction to Algorithms, 3rd Edition&amp;quot; {{---}} Издательство MIT Press, 2009. {{---}} 1292 с. {{---}} ISBN 978-0-262-03384-8 (англ.)&lt;br /&gt;
* Хопкрофт Дж., Мотвани Р., Ульман Дж. Введение в теорию автоматов, языков и вычислений. 2-е издание. {{---}} М.: Издательский дом &amp;quot;Вильямс&amp;quot;, 2002. {{---}} 528 с. {{---}} ISBN 5-8459-0261-4 (рус.)&lt;br /&gt;
&lt;br /&gt;
[[Категория: Теория сложности]]&lt;br /&gt;
[[Категория: Детерминированные и недетерминированные вычисления, сложность по времени и по памяти]]&lt;br /&gt;
[[Категория: Примеры NP-полных языков]]&lt;/div&gt;</summary>
		<author><name>KirillTim</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=NP-%D0%BF%D0%BE%D0%BB%D0%BD%D0%BE%D1%82%D0%B0_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B8_%D0%BE_%D1%81%D1%83%D0%BC%D0%BC%D0%B5_%D0%BF%D0%BE%D0%B4%D0%BC%D0%BD%D0%BE%D0%B6%D0%B5%D1%81%D1%82%D0%B2%D0%B0&amp;diff=53987</id>
		<title>NP-полнота задачи о сумме подмножества</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=NP-%D0%BF%D0%BE%D0%BB%D0%BD%D0%BE%D1%82%D0%B0_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B8_%D0%BE_%D1%81%D1%83%D0%BC%D0%BC%D0%B5_%D0%BF%D0%BE%D0%B4%D0%BC%D0%BD%D0%BE%D0%B6%D0%B5%D1%81%D1%82%D0%B2%D0%B0&amp;diff=53987"/>
				<updated>2016-05-16T17:34:58Z</updated>
		
		<summary type="html">&lt;p&gt;KirillTim: Добавил категории&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Формулировка задачи==&lt;br /&gt;
В '''задаче о сумме подмножества''' (Subset sum problem) входными данными являются набор из &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; целых чисел &amp;lt;math&amp;gt;S&amp;lt;/math&amp;gt; и целое число &amp;lt;math&amp;gt;s&amp;lt;/math&amp;gt;. Требуется выяснить, возможно ли выбрать подмножество &amp;lt;math&amp;gt;S' \subseteq S&amp;lt;/math&amp;gt; с суммой &amp;lt;math&amp;gt;s&amp;lt;/math&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\exists S' \subseteq S: \sum_{s_{i} \in S'}{s_{i}} = s&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Доказательство NP-полноты==&lt;br /&gt;
Для доказательства того, что Subset sum problem &amp;lt;math&amp;gt;\in&amp;lt;/math&amp;gt; [[NPC]], необходимо доказать два факта:&lt;br /&gt;
*Subset sum problem &amp;lt;math&amp;gt;\in&amp;lt;/math&amp;gt; [[NP]] &lt;br /&gt;
*Subset sum problem &amp;lt;math&amp;gt;\in&amp;lt;/math&amp;gt;[[NPH]] &lt;br /&gt;
===Доказательство принадлежности к NP===&lt;br /&gt;
В качестве сертификата возьмем удовлетворяющее условию задачи множество &amp;lt;math&amp;gt;S'&amp;lt;/math&amp;gt; с суммой &amp;lt;math&amp;gt;s&amp;lt;/math&amp;gt;. Очевидно, оно удовлетворяет всем требованиям, налагаемым на сертификат. Проверяющая функция строится очевидным образом, работает за полиномиальное от размера входа время.&lt;br /&gt;
===Доказательство принадлежности к NPH===&lt;br /&gt;
Сведем [[NP-полнота_задачи_о_выполнимости_булевой_формулы_в_форме_3-КНФ|3-CNF_Sat]] к задаче о сумме подмножества. Пусть задана 3-CNF формула &amp;lt;math&amp;gt;\phi&amp;lt;/math&amp;gt; от &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;&lt;br /&gt;
переменных &amp;lt;math&amp;gt;x_{i}&amp;lt;/math&amp;gt;, состоящая из &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; пар скобок &amp;lt;math&amp;gt;C_{i}&amp;lt;/math&amp;gt;. Будем считать, не умаляя общности, что ни одна пара скобок не содержит одновременно переменную и ее отрицание. Также предположим, что каждая переменная входит хотя бы в одну пару скобок. Построим сводящую функцию &amp;lt;math&amp;gt;f\!\!:\phi \to (S,s)&amp;lt;/math&amp;gt;.&lt;br /&gt;
====Построение сводящей функции====&lt;br /&gt;
Для каждой переменной &amp;lt;math&amp;gt;x_{i}&amp;lt;/math&amp;gt; и каждой пары скобок &amp;lt;math&amp;gt;C_{j}&amp;lt;/math&amp;gt; создадим по два числа в десятичной системе счисления, каждое длиной &amp;lt;math&amp;gt;n+k&amp;lt;/math&amp;gt; цифр. Эти числа образуют &amp;lt;math&amp;gt;S&amp;lt;/math&amp;gt;. Также создадим число &amp;lt;math&amp;gt;s&amp;lt;/math&amp;gt; длиной &amp;lt;math&amp;gt;n+k&amp;lt;/math&amp;gt; цифр. Присвоим каждому разряду полученных чисел (одинаковую для всех чисел) метку, соответствующую либо переменной, либо паре скобок.&lt;br /&gt;
Метки, соответствующие парам скобок, присвоены &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; младшим разрядам чисел.&lt;br /&gt;
*В числе &amp;lt;math&amp;gt;s&amp;lt;/math&amp;gt; все разряды, соответствующие переменным, установим &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt;, а оставшиеся сделаем равными &amp;lt;math&amp;gt;4&amp;lt;/math&amp;gt;.&lt;br /&gt;
*Каждой переменной &amp;lt;math&amp;gt;x_{i}&amp;lt;/math&amp;gt; соответствуют два числа из &amp;lt;math&amp;gt;S&amp;lt;/math&amp;gt;: &amp;lt;math&amp;gt;v_{i}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;u_{i}&amp;lt;/math&amp;gt;. Опишем создание этих чисел. Разряд, соответствующий &amp;lt;math&amp;gt;x_{i}&amp;lt;/math&amp;gt; установим равным &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt;, а все остальные разряды, соответствующие переменным, установим равными &amp;lt;math&amp;gt;0&amp;lt;/math&amp;gt;. Далее, для числа &amp;lt;math&amp;gt;v_{i}&amp;lt;/math&amp;gt; установим все разряды, соответствующие парам скобок, содержащих &amp;lt;math&amp;gt;x_{i}&amp;lt;/math&amp;gt;, равными &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt;. Во все остальные &amp;quot;скобочные&amp;quot; разряды поставим &amp;lt;math&amp;gt;0&amp;lt;/math&amp;gt;. В числе &amp;lt;math&amp;gt;w_{i}&amp;lt;/math&amp;gt; установим все разряды, соответствующие парам скобок, содержащих &amp;lt;math&amp;gt;\neg x_{i}&amp;lt;/math&amp;gt;, равными &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt;, а во все остальные &amp;quot;скобочные&amp;quot; разряды поставим &amp;lt;math&amp;gt;0&amp;lt;/math&amp;gt;.&lt;br /&gt;
*Каждой паре скобок &amp;lt;math&amp;gt;C_{j}&amp;lt;/math&amp;gt; соответствуют два числа из &amp;lt;math&amp;gt;S&amp;lt;/math&amp;gt;: &amp;lt;math&amp;gt;d_{i}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;e_{i}&amp;lt;/math&amp;gt;. Оба этих числа содержат &amp;lt;math&amp;gt;0&amp;lt;/math&amp;gt; во всех разрядах, кроме соответствующего &amp;lt;math&amp;gt;C_{j}&amp;lt;/math&amp;gt;. В этом разряде у &amp;lt;math&amp;gt;d_{i}&amp;lt;/math&amp;gt; поставим &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt;, а у &amp;lt;math&amp;gt;e_{i}&amp;lt;/math&amp;gt; поставим &amp;lt;math&amp;gt;2&amp;lt;/math&amp;gt;.&lt;br /&gt;
====Корректность сводящей функции====&lt;br /&gt;
*Получаемое сводящей функцией множество &amp;lt;math&amp;gt;S&amp;lt;/math&amp;gt; состоит из &amp;lt;math&amp;gt;2(n+k)&amp;lt;/math&amp;gt; десятичных чисел длиной &amp;lt;math&amp;gt;(n+k)&amp;lt;/math&amp;gt; каждое, выставление каждого разряда занимает полиномиальное время. Таким образом, сведение выполняется за полиномиальное время.&lt;br /&gt;
*Пусть формула &amp;lt;math&amp;gt;\phi&amp;lt;/math&amp;gt; выполнима, то есть существует набор значений &amp;lt;math&amp;gt;\{y_{i}\}^{n}_{i=1}:~\phi(y_{1}\ldots y_{n})=1 &amp;lt;/math&amp;gt;. И пусть &amp;lt;math&amp;gt;(S,s) = f(\phi)&amp;lt;/math&amp;gt;. Тогда в полученном множестве &amp;lt;math&amp;gt;S&amp;lt;/math&amp;gt; существует подмножество с суммой &amp;lt;math&amp;gt;s&amp;lt;/math&amp;gt;. Действительно, для каждой переменной, если &amp;lt;math&amp;gt;y_{k} = 1&amp;lt;/math&amp;gt;, то добавим в &amp;lt;math&amp;gt;S'~ v_{i}&amp;lt;/math&amp;gt;. Иначе добавим &amp;lt;math&amp;gt;w_{i}&amp;lt;/math&amp;gt;. Теперь &amp;lt;math&amp;gt;S'&amp;lt;/math&amp;gt; содержит уже &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; чисел. Заметим, что для каждого &amp;quot;скобочного&amp;quot;разряда в уже набранной части &amp;lt;math&amp;gt;S'&amp;lt;/math&amp;gt; есть не менее одного и не более трех чисел, у которых в данном разряде стоит &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt;. Значит для каждого соответствующего паре скобок &amp;lt;math&amp;gt;C_{j}&amp;lt;/math&amp;gt; разряда мы сможем выбрать одно или оба числа &amp;lt;math&amp;gt;d_{j}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;e_{j}&amp;lt;/math&amp;gt; так, чтобы сумма в данном разряде совпадала с требуемой (стала равна &amp;lt;math&amp;gt;4&amp;lt;/math&amp;gt;). Добавим их в &amp;lt;math&amp;gt;S'&amp;lt;/math&amp;gt;. Также заметим, что суммы во всех &amp;quot;переменных&amp;quot; разрядах равны &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt;, так как для каждого &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; выбиралось строго одно число из &amp;lt;math&amp;gt;v_{i}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;u_{i}&amp;lt;/math&amp;gt;. Значит, &amp;lt;math&amp;gt; \sum_{s_{k} \in S'}{s_{k}} = s&amp;lt;/math&amp;gt;.&lt;br /&gt;
*Пусть теперь в наборе &amp;lt;math&amp;gt;S&amp;lt;/math&amp;gt; есть подмножество &amp;lt;math&amp;gt;S':~  \sum_{s_{k} \in S'}{s_{k}} = s&amp;lt;/math&amp;gt;. Тогда исходная формула &amp;lt;math&amp;gt;\phi&amp;lt;/math&amp;gt; выполнима. Действительно, если &amp;lt;math&amp;gt;v_{i} \in S'&amp;lt;/math&amp;gt;, то установим переменную &amp;lt;math&amp;gt;x_{i}=1&amp;lt;/math&amp;gt;. Если же &amp;lt;math&amp;gt;w_{i} \in S'&amp;lt;/math&amp;gt;, то &amp;lt;math&amp;gt;x_{i}=0&amp;lt;/math&amp;gt;. Покажем, что &amp;lt;math&amp;gt;\phi(x_{1}\ldots x_{n}) = 1 &amp;lt;/math&amp;gt;. Действительно, так как &amp;lt;math&amp;gt; \sum_{s_{k} \in S'}{s_{k}} = s&amp;lt;/math&amp;gt;, в каждой паре скобок хотя бы один терм равен &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt;. Значит каждый терм равен &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt;. А тогда и вся &amp;lt;math&amp;gt;\phi = 1&amp;lt;/math&amp;gt;.&lt;br /&gt;
====Пример сведения====&lt;br /&gt;
Пусть исходная функция &amp;lt;math&amp;gt;\phi(x_{1} \ldots x_{4}) = (x_{1} \lor x_{2} \lor \neg x_{3}) \land (\neg x_{1} \lor x_{2} \lor x_{4})&amp;lt;/math&amp;gt;.&lt;br /&gt;
Пометим разряды следующим образом (слева направо): &amp;lt;math&amp;gt;x_{1},x_{2},x_{3},x_{4},C_{1},C_{2}&amp;lt;/math&amp;gt;. Тогда:&lt;br /&gt;
*&amp;lt;math&amp;gt;v_{1} = 100010&amp;lt;/math&amp;gt;&lt;br /&gt;
*&amp;lt;math&amp;gt;w_{1} = 100001&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;math&amp;gt;v_{2} = 010011 = 10011&amp;lt;/math&amp;gt;&lt;br /&gt;
*&amp;lt;math&amp;gt;w_{2} = 010000 = 10000&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;math&amp;gt;v_{3} = 001000 = 1000&amp;lt;/math&amp;gt;&lt;br /&gt;
*&amp;lt;math&amp;gt;w_{3} = 001010 = 1010&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;math&amp;gt;v_{4} = 000101 = 101&amp;lt;/math&amp;gt;&lt;br /&gt;
*&amp;lt;math&amp;gt;w_{4} = 000100 = 100&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;math&amp;gt;d_{1} = 000010 = 10&amp;lt;/math&amp;gt;&lt;br /&gt;
*&amp;lt;math&amp;gt;e_{1} = 000020 = 20&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;math&amp;gt;d_{2} = 000001 = 1&amp;lt;/math&amp;gt;&lt;br /&gt;
*&amp;lt;math&amp;gt;e_{2} = 000002 = 2&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;math&amp;gt;s = 111144&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;S = (\cup_{i=1 \ldots 4} v_{i}) \cup (\cup_{i=1 \ldots 4} w_{i})  \cup (\cup_{i=1 \ldots 2} d_{i})  \cup (\cup_{i=1 \ldots 2} e_{i})&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Тогда набору значений &amp;lt;math&amp;gt;Y = (0,0,0,1):~ \phi(Y) = 1&amp;lt;/math&amp;gt; соответствует &amp;lt;math&amp;gt;S' = \{w_{1},~w_{2},~w_{3},~v_{4},~d_{1},~e_{1},~e_{2}\}&amp;lt;/math&amp;gt;. И действительно, &amp;lt;math&amp;gt;100001 + 10000 + 1010 + 101 + 10 + 20 + 2 = 111144&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
[[Категория: Теория сложности]]&lt;br /&gt;
[[Категория: Детерминированные и недетерминированные вычисления, сложность по времени и по памяти]]&lt;br /&gt;
[[Категория: Примеры NP-полных языков]]&lt;/div&gt;</summary>
		<author><name>KirillTim</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%A3%D1%81%D1%82%D1%80%D0%B0%D0%BD%D0%B5%D0%BD%D0%B8%D0%B5_%D0%BB%D0%B5%D0%B2%D0%BE%D0%B9_%D1%80%D0%B5%D0%BA%D1%83%D1%80%D1%81%D0%B8%D0%B8&amp;diff=51306</id>
		<title>Устранение левой рекурсии</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A3%D1%81%D1%82%D1%80%D0%B0%D0%BD%D0%B5%D0%BD%D0%B8%D0%B5_%D0%BB%D0%B5%D0%B2%D0%BE%D0%B9_%D1%80%D0%B5%D0%BA%D1%83%D1%80%D1%81%D0%B8%D0%B8&amp;diff=51306"/>
				<updated>2016-01-17T15:05:09Z</updated>
		
		<summary type="html">&lt;p&gt;KirillTim: заменил скобки на большие&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition=Говорят, что [[Контекстно-свободные грамматики, вывод, лево- и правосторонний вывод, дерево разбора|контекстно-свободная (КС) грамматика]] &amp;lt;tex&amp;gt;\Gamma&amp;lt;/tex&amp;gt; содержит '''непосредственную левую рекурсию''' (англ. ''direct left recursion''), если она содержит правило вида &amp;lt;tex&amp;gt;A \to A\alpha&amp;lt;/tex&amp;gt;.&lt;br /&gt;
}}&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition=Говорят, что КС-грамматика &amp;lt;tex&amp;gt;\Gamma&amp;lt;/tex&amp;gt; содержит '''левую рекурсию'''  (англ. ''left recursion''), если в ней существует вывод вида &amp;lt;tex&amp;gt;A \Rightarrow^* A\alpha&amp;lt;/tex&amp;gt;.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
[[Методы трансляции#Нисходящий разбор|Методы нисходящего разбора]] не в состоянии работать с леворекурсивными грамматиками. Проблема в том, что продукция вида &amp;lt;tex&amp;gt;A \Rightarrow^* A\alpha&amp;lt;/tex&amp;gt; может применяться бесконечно долго, так и не выработав некий терминальный символ, который можно было бы сравнить со строкой. Поэтому требуется преобразование грамматики, которое бы устранило левую рекурсию.&lt;br /&gt;
&lt;br /&gt;
==Устранение непосредственной левой рекурсии==&lt;br /&gt;
Опишем процедуру, устраняющую все правила вида &amp;lt;tex&amp;gt;A \to A\alpha&amp;lt;/tex&amp;gt;, для фиксированного нетерминала &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;ol&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Запишем все правила вывода из &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; в виде: &lt;br /&gt;
&amp;lt;tex&amp;gt;A \to A\alpha_1 \mid \ldots \mid A\alpha_n \mid \beta_1 \mid \ldots \mid \beta_m &amp;lt;/tex&amp;gt;, где&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; &amp;lt;tex&amp;gt;\alpha&amp;lt;/tex&amp;gt; {{---}} непустая последовательность терминалов и нетерминалов (&amp;lt;tex&amp;gt;\alpha \nrightarrow \varepsilon &amp;lt;/tex&amp;gt;);&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; &amp;lt;tex&amp;gt;\beta&amp;lt;/tex&amp;gt; {{---}} непустая последовательность терминалов и нетерминалов, не начинающаяся с &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt;.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Заменим правила вывода из &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; на &amp;lt;tex&amp;gt;A \to\beta_1A^\prime \mid \ldots\ \mid \beta_mA^\prime \mid \beta_1 \mid \ldots \mid \beta_m&amp;lt;/tex&amp;gt;.&amp;lt;/li&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;li&amp;gt;Создадим новый нетерминал &amp;lt;tex&amp;gt;{A^\prime} \to \alpha_1{A^\prime} \mid \ldots \mid \alpha_n{A^\prime} \mid \alpha_1 \mid \ldots \mid \alpha_n&amp;lt;/tex&amp;gt;. &amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ol&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Изначально нетерминал &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; порождает сроки вида &amp;lt;tex&amp;gt;\beta\alpha_{i0}\alpha_{i1} \ldots \alpha_{ik}&amp;lt;/tex&amp;gt;. В новой грамматике нетерминал &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; порождает &amp;lt;tex&amp;gt;\beta{A^\prime}&amp;lt;/tex&amp;gt;, а &amp;lt;tex&amp;gt;A^\prime&amp;lt;/tex&amp;gt; порождает строки вида &amp;lt;tex&amp;gt;\alpha_{i0}\alpha_{i1} \ldots \alpha_{ik}&amp;lt;/tex&amp;gt;. Из этого очевидно, что изначальная грамматика эквивалентна новой.&lt;br /&gt;
&lt;br /&gt;
===Пример===&lt;br /&gt;
&amp;lt;tex&amp;gt;A \to S\alpha \mid A\alpha&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;S \to A\beta&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Есть непосредственная левая рекурсия &amp;lt;tex&amp;gt;A \to A\alpha&amp;lt;/tex&amp;gt;. Добавим нетерминал &amp;lt;tex&amp;gt;A^\prime&amp;lt;/tex&amp;gt; и добавим правила &amp;lt;tex&amp;gt;A \to S\alpha{A^{\prime}}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt; A^{\prime} \to \alpha{A^{\prime}} &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Новая грамматика:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;A \to S\alpha{A^{\prime}} \mid S\alpha&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;A^{\prime} \to \alpha{A^{\prime}}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;S \to A\beta&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
В новой грамматике нет непосредственной левой рекурсии, но нетерминал &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; леворекурсивен, так как есть &amp;lt;tex&amp;gt; A \Rightarrow S\alpha{A^{\prime}} \Rightarrow A\beta\alpha{A^{\prime}} &amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Алгоритм  устранения произвольной левой рекурсии==&lt;br /&gt;
Воспользуемся [[Удаление_eps-правил_из_грамматики | алгоритмом удаления &amp;lt;tex&amp;gt; \varepsilon &amp;lt;/tex&amp;gt;-правил]]. Получим грамматику без &amp;lt;tex&amp;gt; \varepsilon &amp;lt;/tex&amp;gt;-правил для языка &amp;lt;tex&amp;gt;L(\Gamma) \setminus \lbrace \varepsilon \rbrace&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Упорядочим нетерминалы, например по возрастанию индексов, и будем добиваться того, чтобы не было правил вида &amp;lt;tex&amp;gt;A_i \to A_j\alpha&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;j \leqslant i&amp;lt;/tex&amp;gt;.&lt;br /&gt;
Если данное условие выполняется для всех &amp;lt;tex&amp;gt;A_i&amp;lt;/tex&amp;gt;, то в грамматике нет &amp;lt;tex&amp;gt;A_i \Rightarrow^* A_i&amp;lt;/tex&amp;gt;, а значит не будет левой рекурсии. &lt;br /&gt;
&lt;br /&gt;
Пусть &amp;lt;tex&amp;gt;N = \lbrace A_1, A_2, \ldots , A_n \rbrace&amp;lt;/tex&amp;gt; {{---}} упорядоченное множество всех нетерминалов.&lt;br /&gt;
&lt;br /&gt;
  '''for''' &amp;lt;tex&amp;gt;A_i \in N&amp;lt;/tex&amp;gt;&lt;br /&gt;
    '''for''' &amp;lt;tex&amp;gt;A_j \in \{ N \mid 1 \leqslant j &amp;lt; i \}&amp;lt;/tex&amp;gt;&lt;br /&gt;
      '''for''' &amp;lt;tex&amp;gt;p \in \{ P \mid A_i \to A_j\gamma \}&amp;lt;/tex&amp;gt;&lt;br /&gt;
        удалить продукцию &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; &lt;br /&gt;
        '''for''' &amp;lt;tex&amp;gt;Q \to x_i \in \{A_j \to \delta_1 \mid \ldots \mid \delta_k\}&amp;lt;/tex&amp;gt;&lt;br /&gt;
          добавить правило &amp;lt;tex&amp;gt;A_i \to x_i\gamma&amp;lt;/tex&amp;gt;&lt;br /&gt;
    устранить непосредственную левую рекурсию для &amp;lt;tex&amp;gt;A_i&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Если &amp;lt;tex&amp;gt;\varepsilon&amp;lt;/tex&amp;gt; присутствовал в языке исходной грамматики, добавим новый начальный символ &amp;lt;tex&amp;gt;S'&amp;lt;/tex&amp;gt; и правила &amp;lt;tex&amp;gt;S' \to S \, \mid \, \varepsilon &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
После &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; итерации внешнего цикла в любой продукции внешнего цикла в любой продукции вида &amp;lt;tex&amp;gt;A_k \to A_l\alpha, k &amp;lt; i&amp;lt;/tex&amp;gt;, должно быть &amp;lt;tex&amp;gt;l &amp;gt; k&amp;lt;/tex&amp;gt;. В результате при следующей итерации внутреннего цикла растет нижний предел &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; всех продукций вида &amp;lt;tex&amp;gt;A_i \to A_m\alpha&amp;lt;/tex&amp;gt; до тех пор, пока не будет достигнуто &amp;lt;tex&amp;gt;i \leqslant m &amp;lt;/tex&amp;gt;.&lt;br /&gt;
   &lt;br /&gt;
После &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; итерации внешнего цикла в грамматике будут только правила вида &amp;lt;tex&amp;gt;A_i \to A_j\alpha&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;j &amp;gt; i&amp;lt;/tex&amp;gt;.&lt;br /&gt;
Можно заметить, что неравенство становится строгим только после применения алгоритма устранения непосредственной левой рекурсии. При этом добавляются новые нетерминалы. Пусть &amp;lt;tex&amp;gt;{A^\prime}_i &amp;lt;/tex&amp;gt; новый нетерминал. Можно заметить, что нет правила вида &amp;lt;tex&amp;gt;\ldots \to {A^\prime}_i&amp;lt;/tex&amp;gt;, где  &amp;lt;tex&amp;gt;{A^\prime}_i&amp;lt;/tex&amp;gt; самый левый нетерминал, а значит новые нетерминалы можно не рассматривать во внешнем цикле. &lt;br /&gt;
&lt;br /&gt;
На &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; итерации внешнего цикла все правила вида &amp;lt;tex&amp;gt;A_i \to A_j \gamma&amp;lt;/tex&amp;gt; где &amp;lt;tex&amp;gt; j &amp;lt; i &amp;lt;/tex&amp;gt; заменяются на &amp;lt;tex&amp;gt;A_i \to \delta_1\gamma \mid \ldots \mid \delta_k\gamma&amp;lt;/tex&amp;gt; где &amp;lt;tex&amp;gt;A_j \to \delta_1 \mid \ldots \mid \delta_k&amp;lt;/tex&amp;gt;. Очевидно, что одна итерация алгоритма не меняет язык, а значит язык получившийся в итоге грамматики совпадает с исходным.&lt;br /&gt;
&lt;br /&gt;
===Оценка времени работы===&lt;br /&gt;
Пусть &amp;lt;tex&amp;gt;a_i&amp;lt;/tex&amp;gt; количество правил для нетерминала &amp;lt;tex&amp;gt;A_i&amp;lt;/tex&amp;gt;.&lt;br /&gt;
Тогда &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; итерация внешнего цикла будет выполняться за &amp;lt;tex&amp;gt;O\left(\sum\limits_{A_i \to A_j, j &amp;lt; i} a_j\right) + O(a_i)&amp;lt;/tex&amp;gt;, что меньше чем &amp;lt;tex&amp;gt;O\left(\sum\limits_{i=1}^n a_j\right)&amp;lt;/tex&amp;gt;, значит асимптотика алгоритма &amp;lt;tex&amp;gt;O\left(n\sum\limits_{i=1}^n a_j\right)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
===Худший случай===&lt;br /&gt;
Проблема этого алгоритма в том, что в зависимости от порядка нетерминалов в множестве размер грамматки может получиться экспоненциальным.&lt;br /&gt;
&lt;br /&gt;
Пример грамматики для которой имеет значение порядок нетерминалов&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;A_1 \to 0 \mid 1&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;A_{i+1} \to {A_i}0 \mid {A_i}1 &amp;lt;/tex&amp;gt;  для &amp;lt;tex&amp;gt;1 \leqslant i &amp;lt; n&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Упорядочим множество нетерминалов по возрастанию индексов. Легко заметить, что правила для &amp;lt;tex&amp;gt;A_i&amp;lt;/tex&amp;gt; будут представлять из себя все двоичные вектора длины &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;, а значит размер грамматики будет экспоненциальным.&lt;br /&gt;
===Порядок выбора нетерминалов===&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition=Говорят, что нетерминал &amp;lt;tex&amp;gt;X&amp;lt;/tex&amp;gt; {{---}} '''прямой левый вывод''' (англ. ''direct left corner'') из &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt;, если существует правило вида &amp;lt;tex&amp;gt;A \to X\alpha&amp;lt;/tex&amp;gt;.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition='''Левый вывод''' (англ. ''left corner'') {{---}} [[Транзитивное_отношение|транзитивное]], [[Рефлексивное_отношение|рефлексивное]] замыкание отношения «быть прямым левым выводом».&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Во внутреннем цикле алгоритма для всех нетерминалов &amp;lt;tex&amp;gt;A_i&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;A_j&amp;lt;/tex&amp;gt;, таких что &amp;lt;tex&amp;gt;j &amp;lt; i&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;A_j&amp;lt;/tex&amp;gt; {{---}} прямой левый вывод из &amp;lt;tex&amp;gt;A_i&amp;lt;/tex&amp;gt; заменяем все прямые левые выводы &amp;lt;tex&amp;gt;A_j&amp;lt;/tex&amp;gt; из &amp;lt;tex&amp;gt;A_i&amp;lt;/tex&amp;gt; на все выводы из &amp;lt;tex&amp;gt;A_j&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Это действие удаляет левую рекурсию только если &amp;lt;tex&amp;gt;A_i&amp;lt;/tex&amp;gt; {{---}} леворекурсивный нетерминал и &amp;lt;tex&amp;gt;A_j&amp;lt;/tex&amp;gt; содержится в выводе &amp;lt;tex&amp;gt;A_i&amp;lt;/tex&amp;gt; (то есть &amp;lt;tex&amp;gt;A_i&amp;lt;/tex&amp;gt; {{---}} левый вывод из &amp;lt;tex&amp;gt;A_j&amp;lt;/tex&amp;gt;,в то время как &amp;lt;tex&amp;gt;A_j&amp;lt;/tex&amp;gt; {{---}} левый вывод из &amp;lt;tex&amp;gt;A_i&amp;lt;/tex&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
Перестанем добавлять бесполезные выводы, которые не участвуют в удалении левой рекурсии, упорядочив нетерминалы так: если &amp;lt;tex&amp;gt;j &amp;lt; i&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;A_j&amp;lt;/tex&amp;gt; {{---}} прямой левый вывод из &amp;lt;tex&amp;gt;A_i&amp;lt;/tex&amp;gt;, то &amp;lt;tex&amp;gt;A_i&amp;lt;/tex&amp;gt; {{---}} левый вывод из &amp;lt;tex&amp;gt;A_j&amp;lt;/tex&amp;gt;.&lt;br /&gt;
Упорядочим их по уменьшению количества различных прямых левых выводов из них.&lt;br /&gt;
&lt;br /&gt;
Так как отношение «быть левым выводом» транзитивно,то если &amp;lt;tex&amp;gt;C&amp;lt;/tex&amp;gt; {{---}} прямой левый вывод из &amp;lt;tex&amp;gt;B&amp;lt;/tex&amp;gt;, то каждый левый вывод из С также будет левым выводом из &amp;lt;tex&amp;gt;B&amp;lt;/tex&amp;gt;. А так как отношение «быть левым выводом» рефлексивно, &amp;lt;tex&amp;gt;B&amp;lt;/tex&amp;gt; явлеяется своим левым выводом, а значит если &amp;lt;tex&amp;gt;C&amp;lt;/tex&amp;gt; {{---}} прямой левый вывод из &amp;lt;tex&amp;gt;B&amp;lt;/tex&amp;gt; {{---}} он должен следовать за &amp;lt;tex&amp;gt;B&amp;lt;/tex&amp;gt; в упорядоченном множестве, если только &amp;lt;tex&amp;gt;B&amp;lt;/tex&amp;gt; не является левым выводом из &amp;lt;tex&amp;gt;C&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Пример==&lt;br /&gt;
Дана грамматика:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;A \to S\alpha &amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;S \to S\beta \mid A\gamma \mid \beta&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Среди правил &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; непосредственной рекурсии нет, поэтому во время первой итерации внешнего цикла ничего не происходит. &lt;br /&gt;
Во время второй итерации внешнего цикла правило &amp;lt;tex&amp;gt; S \to A\gamma &amp;lt;/tex&amp;gt; переходит в &amp;lt;tex&amp;gt; S \to S\alpha\gamma &amp;lt;/tex&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
Грамматика имеет вид &lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;A \to S\alpha &amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;S \to{S}{\beta} \mid {S}{\alpha}{\gamma} \mid \beta&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Устраняем левую рекурсию для &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt; S \to\beta{S_1}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt; {S_1} \to\beta{S_1} \mid \alpha\gamma{S_1} \mid {\beta} \mid {\alpha}{\gamma} &amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== См. также  ==&lt;br /&gt;
* [[Контекстно-свободные_грамматики,_вывод,_лево-_и_правосторонний_вывод,_дерево_разбора|Контекстно-свободные грамматики]]&lt;br /&gt;
* [[Нормальная_форма_Хомского|Нормальная форма Хомского]]&lt;br /&gt;
* [[Удаление_eps-правил_из_грамматики | Удаления &amp;lt;tex&amp;gt; \varepsilon &amp;lt;/tex&amp;gt;-правил из грамматики]]&lt;br /&gt;
&lt;br /&gt;
== Источники информации ==&lt;br /&gt;
* ''Хопкрофт Д., Мотвани Р., Ульман Д.'' — '''Введение в теорию автоматов, языков и вычислений''', 2-е изд. : Пер. с англ. — Москва, Издательский дом «Вильямс», 2002. — 528 с. : ISBN 5-8459-0261-4 (рус.)&lt;br /&gt;
* ''Robert C. Moore'' — [http://aclweb.org/anthology-new/A/A00/A00-2033.pdf Removing  Left  Recursion  from  Context-Free  Grammars ]&lt;br /&gt;
&lt;br /&gt;
[[Категория: Теория формальных языков]]&lt;br /&gt;
[[Категория: Контекстно-свободные грамматики]]&lt;br /&gt;
[[Категория: Нормальные формы КС-грамматик]]&lt;/div&gt;</summary>
		<author><name>KirillTim</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%A3%D1%81%D1%82%D1%80%D0%B0%D0%BD%D0%B5%D0%BD%D0%B8%D0%B5_%D0%BB%D0%B5%D0%B2%D0%BE%D0%B9_%D1%80%D0%B5%D0%BA%D1%83%D1%80%D1%81%D0%B8%D0%B8&amp;diff=51304</id>
		<title>Устранение левой рекурсии</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A3%D1%81%D1%82%D1%80%D0%B0%D0%BD%D0%B5%D0%BD%D0%B8%D0%B5_%D0%BB%D0%B5%D0%B2%D0%BE%D0%B9_%D1%80%D0%B5%D0%BA%D1%83%D1%80%D1%81%D0%B8%D0%B8&amp;diff=51304"/>
				<updated>2016-01-17T15:02:02Z</updated>
		
		<summary type="html">&lt;p&gt;KirillTim: поменял кавычки, добавил интервики&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition=Говорят, что [[Контекстно-свободные грамматики, вывод, лево- и правосторонний вывод, дерево разбора|контекстно-свободная (КС) грамматика]] &amp;lt;tex&amp;gt;\Gamma&amp;lt;/tex&amp;gt; содержит '''непосредственную левую рекурсию''' (англ. ''direct left recursion''), если она содержит правило вида &amp;lt;tex&amp;gt;A \to A\alpha&amp;lt;/tex&amp;gt;.&lt;br /&gt;
}}&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition=Говорят, что КС-грамматика &amp;lt;tex&amp;gt;\Gamma&amp;lt;/tex&amp;gt; содержит '''левую рекурсию'''  (англ. ''left recursion''), если в ней существует вывод вида &amp;lt;tex&amp;gt;A \Rightarrow^* A\alpha&amp;lt;/tex&amp;gt;.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
[[Методы трансляции#Нисходящий разбор|Методы нисходящего разбора]] не в состоянии работать с леворекурсивными грамматиками. Проблема в том, что продукция вида &amp;lt;tex&amp;gt;A \Rightarrow^* A\alpha&amp;lt;/tex&amp;gt; может применяться бесконечно долго, так и не выработав некий терминальный символ, который можно было бы сравнить со строкой. Поэтому требуется преобразование грамматики, которое бы устранило левую рекурсию.&lt;br /&gt;
&lt;br /&gt;
==Устранение непосредственной левой рекурсии==&lt;br /&gt;
Опишем процедуру, устраняющую все правила вида &amp;lt;tex&amp;gt;A \to A\alpha&amp;lt;/tex&amp;gt;, для фиксированного нетерминала &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;ol&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Запишем все правила вывода из &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; в виде: &lt;br /&gt;
&amp;lt;tex&amp;gt;A \to A\alpha_1 \mid \ldots \mid A\alpha_n \mid \beta_1 \mid \ldots \mid \beta_m &amp;lt;/tex&amp;gt;, где&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; &amp;lt;tex&amp;gt;\alpha&amp;lt;/tex&amp;gt; {{---}} непустая последовательность терминалов и нетерминалов (&amp;lt;tex&amp;gt;\alpha \nrightarrow \varepsilon &amp;lt;/tex&amp;gt;);&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; &amp;lt;tex&amp;gt;\beta&amp;lt;/tex&amp;gt; {{---}} непустая последовательность терминалов и нетерминалов, не начинающаяся с &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt;.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Заменим правила вывода из &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; на &amp;lt;tex&amp;gt;A \to\beta_1A^\prime \mid \ldots\ \mid \beta_mA^\prime \mid \beta_1 \mid \ldots \mid \beta_m&amp;lt;/tex&amp;gt;.&amp;lt;/li&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;li&amp;gt;Создадим новый нетерминал &amp;lt;tex&amp;gt;{A^\prime} \to \alpha_1{A^\prime} \mid \ldots \mid \alpha_n{A^\prime} \mid \alpha_1 \mid \ldots \mid \alpha_n&amp;lt;/tex&amp;gt;. &amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ol&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Изначально нетерминал &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; порождает сроки вида &amp;lt;tex&amp;gt;\beta\alpha_{i0}\alpha_{i1} \ldots \alpha_{ik}&amp;lt;/tex&amp;gt;. В новой грамматике нетерминал &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; порождает &amp;lt;tex&amp;gt;\beta{A^\prime}&amp;lt;/tex&amp;gt;, а &amp;lt;tex&amp;gt;A^\prime&amp;lt;/tex&amp;gt; порождает строки вида &amp;lt;tex&amp;gt;\alpha_{i0}\alpha_{i1} \ldots \alpha_{ik}&amp;lt;/tex&amp;gt;. Из этого очевидно, что изначальная грамматика эквивалентна новой.&lt;br /&gt;
&lt;br /&gt;
===Пример===&lt;br /&gt;
&amp;lt;tex&amp;gt;A \to S\alpha \mid A\alpha&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;S \to A\beta&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Есть непосредственная левая рекурсия &amp;lt;tex&amp;gt;A \to A\alpha&amp;lt;/tex&amp;gt;. Добавим нетерминал &amp;lt;tex&amp;gt;A^\prime&amp;lt;/tex&amp;gt; и добавим правила &amp;lt;tex&amp;gt;A \to S\alpha{A^{\prime}}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt; A^{\prime} \to \alpha{A^{\prime}} &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Новая грамматика:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;A \to S\alpha{A^{\prime}} \mid S\alpha&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;A^{\prime} \to \alpha{A^{\prime}}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;S \to A\beta&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
В новой грамматике нет непосредственной левой рекурсии, но нетерминал &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; леворекурсивен, так как есть &amp;lt;tex&amp;gt; A \Rightarrow S\alpha{A^{\prime}} \Rightarrow A\beta\alpha{A^{\prime}} &amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Алгоритм  устранения произвольной левой рекурсии==&lt;br /&gt;
Воспользуемся [[Удаление_eps-правил_из_грамматики | алгоритмом удаления &amp;lt;tex&amp;gt; \varepsilon &amp;lt;/tex&amp;gt;-правил]]. Получим грамматику без &amp;lt;tex&amp;gt; \varepsilon &amp;lt;/tex&amp;gt;-правил для языка &amp;lt;tex&amp;gt;L(\Gamma) \setminus \lbrace \varepsilon \rbrace&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Упорядочим нетерминалы, например по возрастанию индексов, и будем добиваться того, чтобы не было правил вида &amp;lt;tex&amp;gt;A_i \to A_j\alpha&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;j \leqslant i&amp;lt;/tex&amp;gt;.&lt;br /&gt;
Если данное условие выполняется для всех &amp;lt;tex&amp;gt;A_i&amp;lt;/tex&amp;gt;, то в грамматике нет &amp;lt;tex&amp;gt;A_i \Rightarrow^* A_i&amp;lt;/tex&amp;gt;, а значит не будет левой рекурсии. &lt;br /&gt;
&lt;br /&gt;
Пусть &amp;lt;tex&amp;gt;N = \lbrace A_1, A_2, \ldots , A_n \rbrace&amp;lt;/tex&amp;gt; {{---}} упорядоченное множество всех нетерминалов.&lt;br /&gt;
&lt;br /&gt;
  '''for''' &amp;lt;tex&amp;gt;A_i \in N&amp;lt;/tex&amp;gt;&lt;br /&gt;
    '''for''' &amp;lt;tex&amp;gt;A_j \in \{ N \mid 1 \leqslant j &amp;lt; i \}&amp;lt;/tex&amp;gt;&lt;br /&gt;
      '''for''' &amp;lt;tex&amp;gt;p \in \{ P \mid A_i \to A_j\gamma \}&amp;lt;/tex&amp;gt;&lt;br /&gt;
        удалить продукцию &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; &lt;br /&gt;
        '''for''' &amp;lt;tex&amp;gt;Q \to x_i \in \{A_j \to \delta_1 \mid \ldots \mid \delta_k\}&amp;lt;/tex&amp;gt;&lt;br /&gt;
          добавить правило &amp;lt;tex&amp;gt;A_i \to x_i\gamma&amp;lt;/tex&amp;gt;&lt;br /&gt;
    устранить непосредственную левую рекурсию для &amp;lt;tex&amp;gt;A_i&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Если &amp;lt;tex&amp;gt;\varepsilon&amp;lt;/tex&amp;gt; присутствовал в языке исходной грамматики, добавим новый начальный символ &amp;lt;tex&amp;gt;S'&amp;lt;/tex&amp;gt; и правила &amp;lt;tex&amp;gt;S' \to S \, \mid \, \varepsilon &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
После &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; итерации внешнего цикла в любой продукции внешнего цикла в любой продукции вида &amp;lt;tex&amp;gt;A_k \to A_l\alpha, k &amp;lt; i&amp;lt;/tex&amp;gt;, должно быть &amp;lt;tex&amp;gt;l &amp;gt; k&amp;lt;/tex&amp;gt;. В результате при следующей итерации внутреннего цикла растет нижний предел &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; всех продукций вида &amp;lt;tex&amp;gt;A_i \to A_m\alpha&amp;lt;/tex&amp;gt; до тех пор, пока не будет достигнуто &amp;lt;tex&amp;gt;i \leqslant m &amp;lt;/tex&amp;gt;.&lt;br /&gt;
   &lt;br /&gt;
После &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; итерации внешнего цикла в грамматике будут только правила вида &amp;lt;tex&amp;gt;A_i \to A_j\alpha&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;j &amp;gt; i&amp;lt;/tex&amp;gt;.&lt;br /&gt;
Можно заметить, что неравенство становится строгим только после применения алгоритма устранения непосредственной левой рекурсии. При этом добавляются новые нетерминалы. Пусть &amp;lt;tex&amp;gt;{A^\prime}_i &amp;lt;/tex&amp;gt; новый нетерминал. Можно заметить, что нет правила вида &amp;lt;tex&amp;gt;\ldots \to {A^\prime}_i&amp;lt;/tex&amp;gt;, где  &amp;lt;tex&amp;gt;{A^\prime}_i&amp;lt;/tex&amp;gt; самый левый нетерминал, а значит новые нетерминалы можно не рассматривать во внешнем цикле. &lt;br /&gt;
&lt;br /&gt;
На &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; итерации внешнего цикла все правила вида &amp;lt;tex&amp;gt;A_i \to A_j \gamma&amp;lt;/tex&amp;gt; где &amp;lt;tex&amp;gt; j &amp;lt; i &amp;lt;/tex&amp;gt; заменяются на &amp;lt;tex&amp;gt;A_i \to \delta_1\gamma \mid \ldots \mid \delta_k\gamma&amp;lt;/tex&amp;gt; где &amp;lt;tex&amp;gt;A_j \to \delta_1 \mid \ldots \mid \delta_k&amp;lt;/tex&amp;gt;. Очевидно, что одна итерация алгоритма не меняет язык, а значит язык получившийся в итоге грамматики совпадает с исходным.&lt;br /&gt;
&lt;br /&gt;
===Оценка времени работы===&lt;br /&gt;
Пусть &amp;lt;tex&amp;gt;a_i&amp;lt;/tex&amp;gt; количество правил для нетерминала &amp;lt;tex&amp;gt;A_i&amp;lt;/tex&amp;gt;.&lt;br /&gt;
Тогда &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; итерация внешнего цикла будет выполняться за &amp;lt;tex&amp;gt;O(\sum\limits_{A_i \to A_j, j &amp;lt; i} a_j) + O(a_i)&amp;lt;/tex&amp;gt;, что меньше чем &amp;lt;tex&amp;gt;O(\sum\limits_{i=1}^n a_j)&amp;lt;/tex&amp;gt;, значит асимптотика алгоритма &amp;lt;tex&amp;gt;O(n\sum\limits_{i=1}^n a_j)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
===Худший случай===&lt;br /&gt;
Проблема этого алгоритма в том, что в зависимости от порядка нетерминалов в множестве размер грамматки может получиться экспоненциальным.&lt;br /&gt;
&lt;br /&gt;
Пример грамматики для которой имеет значение порядок нетерминалов&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;A_1 \to 0 \mid 1&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;A_{i+1} \to {A_i}0 \mid {A_i}1 &amp;lt;/tex&amp;gt;  для &amp;lt;tex&amp;gt;1 \leqslant i &amp;lt; n&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Упорядочим множество нетерминалов по возрастанию индексов. Легко заметить, что правила для &amp;lt;tex&amp;gt;A_i&amp;lt;/tex&amp;gt; будут представлять из себя все двоичные вектора длины &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;, а значит размер грамматики будет экспоненциальным.&lt;br /&gt;
===Порядок выбора нетерминалов===&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition=Говорят, что нетерминал &amp;lt;tex&amp;gt;X&amp;lt;/tex&amp;gt; {{---}} '''прямой левый вывод''' (англ. ''direct left corner'') из &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt;, если существует правило вида &amp;lt;tex&amp;gt;A \to X\alpha&amp;lt;/tex&amp;gt;.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition='''Левый вывод''' (англ. ''left corner'') {{---}} [[Транзитивное_отношение|транзитивное]], [[Рефлексивное_отношение|рефлексивное]] замыкание отношения «быть прямым левым выводом».&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Во внутреннем цикле алгоритма для всех нетерминалов &amp;lt;tex&amp;gt;A_i&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;A_j&amp;lt;/tex&amp;gt;, таких что &amp;lt;tex&amp;gt;j &amp;lt; i&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;A_j&amp;lt;/tex&amp;gt; {{---}} прямой левый вывод из &amp;lt;tex&amp;gt;A_i&amp;lt;/tex&amp;gt; заменяем все прямые левые выводы &amp;lt;tex&amp;gt;A_j&amp;lt;/tex&amp;gt; из &amp;lt;tex&amp;gt;A_i&amp;lt;/tex&amp;gt; на все выводы из &amp;lt;tex&amp;gt;A_j&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Это действие удаляет левую рекурсию только если &amp;lt;tex&amp;gt;A_i&amp;lt;/tex&amp;gt; {{---}} леворекурсивный нетерминал и &amp;lt;tex&amp;gt;A_j&amp;lt;/tex&amp;gt; содержится в выводе &amp;lt;tex&amp;gt;A_i&amp;lt;/tex&amp;gt; (то есть &amp;lt;tex&amp;gt;A_i&amp;lt;/tex&amp;gt; {{---}} левый вывод из &amp;lt;tex&amp;gt;A_j&amp;lt;/tex&amp;gt;,в то время как &amp;lt;tex&amp;gt;A_j&amp;lt;/tex&amp;gt; {{---}} левый вывод из &amp;lt;tex&amp;gt;A_i&amp;lt;/tex&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
Перестанем добавлять бесполезные выводы, которые не участвуют в удалении левой рекурсии, упорядочив нетерминалы так: если &amp;lt;tex&amp;gt;j &amp;lt; i&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;A_j&amp;lt;/tex&amp;gt; {{---}} прямой левый вывод из &amp;lt;tex&amp;gt;A_i&amp;lt;/tex&amp;gt;, то &amp;lt;tex&amp;gt;A_i&amp;lt;/tex&amp;gt; {{---}} левый вывод из &amp;lt;tex&amp;gt;A_j&amp;lt;/tex&amp;gt;.&lt;br /&gt;
Упорядочим их по уменьшению количества различных прямых левых выводов из них.&lt;br /&gt;
&lt;br /&gt;
Так как отношение «быть левым выводом» транзитивно,то если &amp;lt;tex&amp;gt;C&amp;lt;/tex&amp;gt; {{---}} прямой левый вывод из &amp;lt;tex&amp;gt;B&amp;lt;/tex&amp;gt;, то каждый левый вывод из С также будет левым выводом из &amp;lt;tex&amp;gt;B&amp;lt;/tex&amp;gt;. А так как отношение «быть левым выводом» рефлексивно, &amp;lt;tex&amp;gt;B&amp;lt;/tex&amp;gt; явлеяется своим левым выводом, а значит если &amp;lt;tex&amp;gt;C&amp;lt;/tex&amp;gt; {{---}} прямой левый вывод из &amp;lt;tex&amp;gt;B&amp;lt;/tex&amp;gt; {{---}} он должен следовать за &amp;lt;tex&amp;gt;B&amp;lt;/tex&amp;gt; в упорядоченном множестве, если только &amp;lt;tex&amp;gt;B&amp;lt;/tex&amp;gt; не является левым выводом из &amp;lt;tex&amp;gt;C&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Пример==&lt;br /&gt;
Дана грамматика:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;A \to S\alpha &amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;S \to S\beta \mid A\gamma \mid \beta&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Среди правил &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; непосредственной рекурсии нет, поэтому во время первой итерации внешнего цикла ничего не происходит. &lt;br /&gt;
Во время второй итерации внешнего цикла правило &amp;lt;tex&amp;gt; S \to A\gamma &amp;lt;/tex&amp;gt; переходит в &amp;lt;tex&amp;gt; S \to S\alpha\gamma &amp;lt;/tex&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
Грамматика имеет вид &lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;A \to S\alpha &amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;S \to{S}{\beta} \mid {S}{\alpha}{\gamma} \mid \beta&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Устраняем левую рекурсию для &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt; S \to\beta{S_1}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt; {S_1} \to\beta{S_1} \mid \alpha\gamma{S_1} \mid {\beta} \mid {\alpha}{\gamma} &amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== См. также  ==&lt;br /&gt;
* [[Контекстно-свободные_грамматики,_вывод,_лево-_и_правосторонний_вывод,_дерево_разбора|Контекстно-свободные грамматики]]&lt;br /&gt;
* [[Нормальная_форма_Хомского|Нормальная форма Хомского]]&lt;br /&gt;
* [[Удаление_eps-правил_из_грамматики | Удаления &amp;lt;tex&amp;gt; \varepsilon &amp;lt;/tex&amp;gt;-правил из грамматики]]&lt;br /&gt;
&lt;br /&gt;
== Источники информации ==&lt;br /&gt;
* ''Хопкрофт Д., Мотвани Р., Ульман Д.'' — '''Введение в теорию автоматов, языков и вычислений''', 2-е изд. : Пер. с англ. — Москва, Издательский дом «Вильямс», 2002. — 528 с. : ISBN 5-8459-0261-4 (рус.)&lt;br /&gt;
* ''Robert C. Moore'' — [http://aclweb.org/anthology-new/A/A00/A00-2033.pdf Removing  Left  Recursion  from  Context-Free  Grammars ]&lt;br /&gt;
&lt;br /&gt;
[[Категория: Теория формальных языков]]&lt;br /&gt;
[[Категория: Контекстно-свободные грамматики]]&lt;br /&gt;
[[Категория: Нормальные формы КС-грамматик]]&lt;/div&gt;</summary>
		<author><name>KirillTim</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%A3%D1%81%D1%82%D1%80%D0%B0%D0%BD%D0%B5%D0%BD%D0%B8%D0%B5_%D0%BB%D0%B5%D0%B2%D0%BE%D0%B9_%D1%80%D0%B5%D0%BA%D1%83%D1%80%D1%81%D0%B8%D0%B8&amp;diff=51303</id>
		<title>Устранение левой рекурсии</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A3%D1%81%D1%82%D1%80%D0%B0%D0%BD%D0%B5%D0%BD%D0%B8%D0%B5_%D0%BB%D0%B5%D0%B2%D0%BE%D0%B9_%D1%80%D0%B5%D0%BA%D1%83%D1%80%D1%81%D0%B8%D0%B8&amp;diff=51303"/>
				<updated>2016-01-17T14:54:33Z</updated>
		
		<summary type="html">&lt;p&gt;KirillTim: много мелких правок&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition=Говорят, что [[Контекстно-свободные грамматики, вывод, лево- и правосторонний вывод, дерево разбора|контекстно-свободная (КС) грамматика]] &amp;lt;tex&amp;gt;\Gamma&amp;lt;/tex&amp;gt; содержит '''непосредственную левую рекурсию''' (англ. ''direct left recursion''), если она содержит правило вида &amp;lt;tex&amp;gt;A \to A\alpha&amp;lt;/tex&amp;gt;.&lt;br /&gt;
}}&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition=Говорят, что КС-грамматика &amp;lt;tex&amp;gt;\Gamma&amp;lt;/tex&amp;gt; содержит '''левую рекурсию'''  (англ. ''left recursion''), если в ней существует вывод вида &amp;lt;tex&amp;gt;A \Rightarrow^* A\alpha&amp;lt;/tex&amp;gt;.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
[[Методы трансляции#Нисходящий разбор|Методы нисходящего разбора]] не в состоянии работать с леворекурсивными грамматиками. Проблема в том, что продукция вида &amp;lt;tex&amp;gt;A \Rightarrow^* A\alpha&amp;lt;/tex&amp;gt; может применяться бесконечно долго, так и не выработав некий терминальный символ, который можно было бы сравнить со строкой. Поэтому требуется преобразование грамматики, которое бы устранило левую рекурсию.&lt;br /&gt;
&lt;br /&gt;
==Устранение непосредственной левой рекурсии==&lt;br /&gt;
Опишем процедуру, устраняющую все правила вида &amp;lt;tex&amp;gt;A \to A\alpha&amp;lt;/tex&amp;gt;, для фиксированного нетерминала &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;ol&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Запишем все правила вывода из &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; в виде: &lt;br /&gt;
&amp;lt;tex&amp;gt;A \to A\alpha_1 \mid \ldots \mid A\alpha_n \mid \beta_1 \mid \ldots \mid \beta_m &amp;lt;/tex&amp;gt;, где&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; &amp;lt;tex&amp;gt;\alpha&amp;lt;/tex&amp;gt; {{---}} непустая последовательность терминалов и нетерминалов (&amp;lt;tex&amp;gt;\alpha \nrightarrow \varepsilon &amp;lt;/tex&amp;gt;);&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; &amp;lt;tex&amp;gt;\beta&amp;lt;/tex&amp;gt; {{---}} непустая последовательность терминалов и нетерминалов, не начинающаяся с &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt;.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Заменим правила вывода из &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; на &amp;lt;tex&amp;gt;A \to\beta_1A^\prime \mid \ldots\ \mid \beta_mA^\prime \mid \beta_1 \mid \ldots \mid \beta_m&amp;lt;/tex&amp;gt;.&amp;lt;/li&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;li&amp;gt;Создадим новый нетерминал &amp;lt;tex&amp;gt;{A^\prime} \to \alpha_1{A^\prime} \mid \ldots \mid \alpha_n{A^\prime} \mid \alpha_1 \mid \ldots \mid \alpha_n&amp;lt;/tex&amp;gt;. &amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ol&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Изначально нетерминал &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; порождает сроки вида &amp;lt;tex&amp;gt;\beta\alpha_{i0}\alpha_{i1} \ldots \alpha_{ik}&amp;lt;/tex&amp;gt;. В новой грамматике нетерминал &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; порождает &amp;lt;tex&amp;gt;\beta{A^\prime}&amp;lt;/tex&amp;gt;, а &amp;lt;tex&amp;gt;A^\prime&amp;lt;/tex&amp;gt; порождает строки вида &amp;lt;tex&amp;gt;\alpha_{i0}\alpha_{i1} \ldots \alpha_{ik}&amp;lt;/tex&amp;gt;. Из этого очевидно, что изначальная грамматика эквивалентна новой.&lt;br /&gt;
&lt;br /&gt;
===Пример===&lt;br /&gt;
&amp;lt;tex&amp;gt;A \to S\alpha \mid A\alpha&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;S \to A\beta&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Есть непосредственная левая рекурсия &amp;lt;tex&amp;gt;A \to A\alpha&amp;lt;/tex&amp;gt;. Добавим нетерминал &amp;lt;tex&amp;gt;A^\prime&amp;lt;/tex&amp;gt; и добавим правила &amp;lt;tex&amp;gt;A \to S\alpha{A^{\prime}}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt; A^{\prime} \to \alpha{A^{\prime}} &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Новая грамматика:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;A \to S\alpha{A^{\prime}} \mid S\alpha&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;A^{\prime} \to \alpha{A^{\prime}}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;S \to A\beta&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
В новой грамматике нет непосредственной левой рекурсии, но нетерминал &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; леворекурсивен, так как есть &amp;lt;tex&amp;gt; A \Rightarrow S\alpha{A^{\prime}} \Rightarrow A\beta\alpha{A^{\prime}} &amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Алгоритм  устранения произвольной левой рекурсии==&lt;br /&gt;
Воспользуемся [[Удаление_eps-правил_из_грамматики | алгоритмом удаления &amp;lt;tex&amp;gt; \varepsilon &amp;lt;/tex&amp;gt;-правил]]. Получим грамматику без &amp;lt;tex&amp;gt; \varepsilon &amp;lt;/tex&amp;gt;-правил для языка &amp;lt;tex&amp;gt;L(\Gamma) \setminus \lbrace \varepsilon \rbrace&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Упорядочим нетерминалы, например по возрастанию индексов, и будем добиваться того, чтобы не было правил вида &amp;lt;tex&amp;gt;A_i \to A_j\alpha&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;j \leqslant i&amp;lt;/tex&amp;gt;.&lt;br /&gt;
Если данное условие выполняется для всех &amp;lt;tex&amp;gt;A_i&amp;lt;/tex&amp;gt;, то в грамматике нет &amp;lt;tex&amp;gt;A_i \Rightarrow^* A_i&amp;lt;/tex&amp;gt;, а значит не будет левой рекурсии. &lt;br /&gt;
&lt;br /&gt;
Пусть &amp;lt;tex&amp;gt;N = \lbrace A_1, A_2, \ldots , A_n \rbrace&amp;lt;/tex&amp;gt; {{---}} упорядоченное множество всех нетерминалов.&lt;br /&gt;
&lt;br /&gt;
  '''for''' &amp;lt;tex&amp;gt;A_i \in N&amp;lt;/tex&amp;gt;&lt;br /&gt;
    '''for''' &amp;lt;tex&amp;gt;A_j \in \{ N \mid 1 \leqslant j &amp;lt; i \}&amp;lt;/tex&amp;gt;&lt;br /&gt;
      '''for''' &amp;lt;tex&amp;gt;p \in \{ P \mid A_i \to A_j\gamma \}&amp;lt;/tex&amp;gt;&lt;br /&gt;
        удалить продукцию &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; &lt;br /&gt;
        '''for''' &amp;lt;tex&amp;gt;Q \to x_i \in \{A_j \to \delta_1 \mid \ldots \mid \delta_k\}&amp;lt;/tex&amp;gt;&lt;br /&gt;
          добавить правило &amp;lt;tex&amp;gt;A_i \to x_i\gamma&amp;lt;/tex&amp;gt;&lt;br /&gt;
    устранить непосредственную левую рекурсию для &amp;lt;tex&amp;gt;A_i&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Если &amp;lt;tex&amp;gt;\varepsilon&amp;lt;/tex&amp;gt; присутствовал в языке исходной грамматики, добавим новый начальный символ &amp;lt;tex&amp;gt;S'&amp;lt;/tex&amp;gt; и правила &amp;lt;tex&amp;gt;S' \to S \, \mid \, \varepsilon &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
После &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; итерации внешнего цикла в любой продукции внешнего цикла в любой продукции вида &amp;lt;tex&amp;gt;A_k \to A_l\alpha, k &amp;lt; i&amp;lt;/tex&amp;gt;, должно быть &amp;lt;tex&amp;gt;l &amp;gt; k&amp;lt;/tex&amp;gt;. В результате при следующей итерации внутреннего цикла растет нижний предел &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; всех продукций вида &amp;lt;tex&amp;gt;A_i \to A_m\alpha&amp;lt;/tex&amp;gt; до тех пор, пока не будет достигнуто &amp;lt;tex&amp;gt;i \leqslant m &amp;lt;/tex&amp;gt;.&lt;br /&gt;
   &lt;br /&gt;
После &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; итерации внешнего цикла в грамматике будут только правила вида &amp;lt;tex&amp;gt;A_i \to A_j\alpha&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;j &amp;gt; i&amp;lt;/tex&amp;gt;.&lt;br /&gt;
Можно заметить, что неравенство становится строгим только после применения алгоритма устранения непосредственной левой рекурсии. При этом добавляются новые нетерминалы. Пусть &amp;lt;tex&amp;gt;{A^\prime}_i &amp;lt;/tex&amp;gt; новый нетерминал. Можно заметить, что нет правила вида &amp;lt;tex&amp;gt;\ldots \to {A^\prime}_i&amp;lt;/tex&amp;gt;, где  &amp;lt;tex&amp;gt;{A^\prime}_i&amp;lt;/tex&amp;gt; самый левый нетерминал, а значит новые нетерминалы можно не рассматривать во внешнем цикле. &lt;br /&gt;
&lt;br /&gt;
На &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; итерации внешнего цикла все правила вида &amp;lt;tex&amp;gt;A_i \to A_j \gamma&amp;lt;/tex&amp;gt; где &amp;lt;tex&amp;gt; j &amp;lt; i &amp;lt;/tex&amp;gt; заменяются на &amp;lt;tex&amp;gt;A_i \to \delta_1\gamma \mid \ldots \mid \delta_k\gamma&amp;lt;/tex&amp;gt; где &amp;lt;tex&amp;gt;A_j \to \delta_1 \mid \ldots \mid \delta_k&amp;lt;/tex&amp;gt;. Очевидно, что одна итерация алгоритма не меняет язык, а значит язык получившийся в итоге грамматики совпадает с исходным.&lt;br /&gt;
&lt;br /&gt;
===Оценка времени работы===&lt;br /&gt;
Пусть &amp;lt;tex&amp;gt;a_i&amp;lt;/tex&amp;gt; количество правил для нетерминала &amp;lt;tex&amp;gt;A_i&amp;lt;/tex&amp;gt;.&lt;br /&gt;
Тогда &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; итерация внешнего цикла будет выполняться за &amp;lt;tex&amp;gt;O(\sum\limits_{A_i \to A_j, j &amp;lt; i} a_j) + O(a_i)&amp;lt;/tex&amp;gt;, что меньше чем &amp;lt;tex&amp;gt;O(\sum\limits_{i=1}^n a_j)&amp;lt;/tex&amp;gt;, значит асимптотика алгоритма &amp;lt;tex&amp;gt;O(n\sum\limits_{i=1}^n a_j)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
===Худший случай===&lt;br /&gt;
Проблема этого алгоритма в том, что в зависимости от порядка нетерминалов в множестве размер грамматки может получиться экспоненциальным.&lt;br /&gt;
&lt;br /&gt;
Пример грамматики для которой имеет значение порядок нетерминалов&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;A_1 \to 0 \mid 1&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;A_{i+1} \to {A_i}0 \mid {A_i}1 &amp;lt;/tex&amp;gt;  для &amp;lt;tex&amp;gt;1 \leqslant i &amp;lt; n&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Упорядочим множество нетерминалов по возрастанию индексов. Легко заметить, что правила для &amp;lt;tex&amp;gt;A_i&amp;lt;/tex&amp;gt; будут представлять из себя все двоичные вектора длины &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;, а значит размер грамматики будет экспоненциальным.&lt;br /&gt;
===Порядок выбора нетерминалов===&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition=Говорят, что нетерминал &amp;lt;tex&amp;gt;X&amp;lt;/tex&amp;gt; {{---}} '''прямой левый вывод''' (англ. ''direct left corner'') из &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt;, если существует правило вида &amp;lt;tex&amp;gt;A \to X\alpha&amp;lt;/tex&amp;gt;.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition='''Левый вывод''' (англ. ''left corner'') {{---}} транзитивное, рефлексивное замыкание отношения &amp;quot;быть прямым левым выводом&amp;quot;.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Во внутреннем цикле алгоритма для всех нетерминалов &amp;lt;tex&amp;gt;A_i&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;A_j&amp;lt;/tex&amp;gt;, таких что &amp;lt;tex&amp;gt;j &amp;lt; i&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;A_j&amp;lt;/tex&amp;gt; {{---}} прямой левый вывод из &amp;lt;tex&amp;gt;A_i&amp;lt;/tex&amp;gt; заменяем все прямые левые выводы &amp;lt;tex&amp;gt;A_j&amp;lt;/tex&amp;gt; из &amp;lt;tex&amp;gt;A_i&amp;lt;/tex&amp;gt; на все выводы из &amp;lt;tex&amp;gt;A_j&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Это действие удаляет левую рекурсию только если &amp;lt;tex&amp;gt;A_i&amp;lt;/tex&amp;gt; {{---}} леворекурсивный нетерминал и &amp;lt;tex&amp;gt;A_j&amp;lt;/tex&amp;gt; содержится в выводе &amp;lt;tex&amp;gt;A_i&amp;lt;/tex&amp;gt; (то есть &amp;lt;tex&amp;gt;A_i&amp;lt;/tex&amp;gt; {{---}} левый вывод из &amp;lt;tex&amp;gt;A_j&amp;lt;/tex&amp;gt;,в то время как &amp;lt;tex&amp;gt;A_j&amp;lt;/tex&amp;gt; {{---}} левый вывод из &amp;lt;tex&amp;gt;A_i&amp;lt;/tex&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
Перестанем добавлять бесполезные выводы, которые не участвуют в удалении левой рекурсии, упорядочив нетерминалы так: если &amp;lt;tex&amp;gt;j &amp;lt; i&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;A_j&amp;lt;/tex&amp;gt; {{---}} прямой левый вывод из &amp;lt;tex&amp;gt;A_i&amp;lt;/tex&amp;gt;, то &amp;lt;tex&amp;gt;A_i&amp;lt;/tex&amp;gt; {{---}} левый вывод из &amp;lt;tex&amp;gt;A_j&amp;lt;/tex&amp;gt;.&lt;br /&gt;
Упорядочим их по уменьшению количества различных прямых левых выводов из них.&lt;br /&gt;
&lt;br /&gt;
Так как отношение &amp;quot;быть левым выводом&amp;quot; транзитивно,то если &amp;lt;tex&amp;gt;C&amp;lt;/tex&amp;gt; {{---}} прямой левый вывод из &amp;lt;tex&amp;gt;B&amp;lt;/tex&amp;gt;, то каждый левый вывод из С также будет левым выводом из &amp;lt;tex&amp;gt;B&amp;lt;/tex&amp;gt;. А так как отношение &amp;quot;быть левым выводом&amp;quot; рефлексивно, &amp;lt;tex&amp;gt;B&amp;lt;/tex&amp;gt; явлеяется своим левым выводом, а значит если &amp;lt;tex&amp;gt;C&amp;lt;/tex&amp;gt; {{---}} прямой левый вывод из &amp;lt;tex&amp;gt;B&amp;lt;/tex&amp;gt; {{---}} он должен следовать за &amp;lt;tex&amp;gt;B&amp;lt;/tex&amp;gt; в упорядоченном множестве, если только &amp;lt;tex&amp;gt;B&amp;lt;/tex&amp;gt; не является левым выводом из &amp;lt;tex&amp;gt;C&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Пример==&lt;br /&gt;
Дана грамматика:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;A \to S\alpha &amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;S \to S\beta \mid A\gamma \mid \beta&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Среди правил &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; непосредственной рекурсии нет, поэтому во время первой итерации внешнего цикла ничего не происходит. &lt;br /&gt;
Во время второй итерации внешнего цикла правило &amp;lt;tex&amp;gt; S \to A\gamma &amp;lt;/tex&amp;gt; переходит в &amp;lt;tex&amp;gt; S \to S\alpha\gamma &amp;lt;/tex&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
Грамматика имеет вид &lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;A \to S\alpha &amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;S \to{S}{\beta} \mid {S}{\alpha}{\gamma} \mid \beta&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Устраняем левую рекурсию для &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt; S \to\beta{S_1}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt; {S_1} \to\beta{S_1} \mid \alpha\gamma{S_1} \mid {\beta} \mid {\alpha}{\gamma} &amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== См. также  ==&lt;br /&gt;
* [[Контекстно-свободные_грамматики,_вывод,_лево-_и_правосторонний_вывод,_дерево_разбора|Контекстно-свободные грамматики]]&lt;br /&gt;
* [[Нормальная_форма_Хомского|Нормальная форма Хомского]]&lt;br /&gt;
* [[Удаление_eps-правил_из_грамматики | Удаления &amp;lt;tex&amp;gt; \varepsilon &amp;lt;/tex&amp;gt;-правил из грамматики]]&lt;br /&gt;
&lt;br /&gt;
== Источники информации ==&lt;br /&gt;
* ''Хопкрофт Д., Мотвани Р., Ульман Д.'' — '''Введение в теорию автоматов, языков и вычислений''', 2-е изд. : Пер. с англ. — Москва, Издательский дом «Вильямс», 2002. — 528 с. : ISBN 5-8459-0261-4 (рус.)&lt;br /&gt;
* ''Robert C. Moore'' — [http://aclweb.org/anthology-new/A/A00/A00-2033.pdf Removing  Left  Recursion  from  Context-Free  Grammars ]&lt;br /&gt;
&lt;br /&gt;
[[Категория: Теория формальных языков]]&lt;br /&gt;
[[Категория: Контекстно-свободные грамматики]]&lt;br /&gt;
[[Категория: Нормальные формы КС-грамматик]]&lt;/div&gt;</summary>
		<author><name>KirillTim</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%A3%D1%81%D1%82%D1%80%D0%B0%D0%BD%D0%B5%D0%BD%D0%B8%D0%B5_%D0%BB%D0%B5%D0%B2%D0%BE%D0%B9_%D1%80%D0%B5%D0%BA%D1%83%D1%80%D1%81%D0%B8%D0%B8&amp;diff=51302</id>
		<title>Устранение левой рекурсии</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A3%D1%81%D1%82%D1%80%D0%B0%D0%BD%D0%B5%D0%BD%D0%B8%D0%B5_%D0%BB%D0%B5%D0%B2%D0%BE%D0%B9_%D1%80%D0%B5%D0%BA%D1%83%D1%80%D1%81%D0%B8%D0%B8&amp;diff=51302"/>
				<updated>2016-01-17T14:39:53Z</updated>
		
		<summary type="html">&lt;p&gt;KirillTim: улучшил всевдокод&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition=Говорят, что [[Контекстно-свободные грамматики, вывод, лево- и правосторонний вывод, дерево разбора|контекстно-свободная (КС) грамматика]] &amp;lt;tex&amp;gt;\Gamma&amp;lt;/tex&amp;gt; содержит '''непосредственную левую рекурсию''' (англ. ''direct left recursion''), если она содержит правило вида &amp;lt;tex&amp;gt;A \to A\alpha&amp;lt;/tex&amp;gt;.&lt;br /&gt;
}}&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition=Говорят, что КС-грамматика &amp;lt;tex&amp;gt;\Gamma&amp;lt;/tex&amp;gt; содержит '''левую рекурсию'''  (англ. ''left recursion''), если в ней существует вывод вида &amp;lt;tex&amp;gt;A \Rightarrow^* A\alpha&amp;lt;/tex&amp;gt;.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
[[Методы трансляции#Нисходящий разбор|Методы нисходящего разбора]] не в состоянии работать с леворекурсивными грамматиками. Проблема в том, что продукция вида &amp;lt;tex&amp;gt;A \Rightarrow^* A\alpha&amp;lt;/tex&amp;gt; может применяться бесконечно долго, так и не выработав некий терминальный символ, который можно было бы сравнить со строкой. Поэтому требуется преобразование грамматики, которое бы устранило левую рекурсию.&lt;br /&gt;
&lt;br /&gt;
==Устранение непосредственной левой рекурсии==&lt;br /&gt;
Опишем процедуру, устраняющую все правила вида &amp;lt;tex&amp;gt;A \to A\alpha&amp;lt;/tex&amp;gt;, для фиксированного нетерминала &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;ol&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Запишем все правила вывода из &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; в виде: &lt;br /&gt;
&amp;lt;tex&amp;gt;A \to A\alpha_1\,|\,\ldots\,|\,A\alpha_n\,|\,\beta_1\,|\,\ldots\,|\,\beta_m &amp;lt;/tex&amp;gt;, где&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; &amp;lt;tex&amp;gt;\alpha&amp;lt;/tex&amp;gt; {{---}} непустая последовательность терминалов и нетерминалов (&amp;lt;tex&amp;gt;\alpha \nrightarrow \varepsilon &amp;lt;/tex&amp;gt;);&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; &amp;lt;tex&amp;gt;\beta&amp;lt;/tex&amp;gt; {{---}} непустая последовательность терминалов и нетерминалов, не начинающаяся с &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt;.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Заменим правила вывода из &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; на &amp;lt;tex&amp;gt;A \to\beta_1A^\prime\, |\, \ldots\,  |\,  \beta_mA^\prime \,|\, \beta_1 \,|\, \ldots \,|\, \beta_m&amp;lt;/tex&amp;gt;.&amp;lt;/li&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;li&amp;gt;Создадим новый нетерминал &amp;lt;tex&amp;gt;{A^\prime} \to \alpha_1{A^\prime},  |\,  \ldots\, |\, \alpha_n{A^\prime} | \alpha_1\,  |\,  \ldots\, |\, \alpha_n&amp;lt;/tex&amp;gt;. &amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ol&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Изначально нетерминал &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; порождает сроки вида &amp;lt;tex&amp;gt;\beta\alpha_{i0}\alpha_{i1} \ldots \alpha_{ik}&amp;lt;/tex&amp;gt;. В новой грамматике нетерминал &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; порождает &amp;lt;tex&amp;gt;\beta{A^\prime}&amp;lt;/tex&amp;gt;, а &amp;lt;tex&amp;gt;A^\prime&amp;lt;/tex&amp;gt; порождает строки вида &amp;lt;tex&amp;gt;\alpha_{i0}\alpha_{i1} \ldots \alpha_{ik}&amp;lt;/tex&amp;gt;. Из этого очевидно, что изначальная грамматика эквивалентна новой.&lt;br /&gt;
&lt;br /&gt;
===Пример===&lt;br /&gt;
&amp;lt;tex&amp;gt;A \to S\alpha | A\alpha&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;S \to A\beta&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Есть непосредственная левая рекурсия &amp;lt;tex&amp;gt;A \to A\alpha&amp;lt;/tex&amp;gt;. Добавим нетерминал &amp;lt;tex&amp;gt;A^\prime&amp;lt;/tex&amp;gt; и добавим правила &amp;lt;tex&amp;gt;A \to S\alpha{A^{\prime}}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt; A^{\prime} \to \alpha{A^{\prime}} &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Новая грамматика:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;A \to S\alpha{A^{\prime}} | S\alpha&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;A^{\prime} \to \alpha{A^{\prime}}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;S \to A\beta&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
В новой грамматике нет непосредственной левой рекурсии, но нетерминал &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; леворекурсивен, так как есть &amp;lt;tex&amp;gt; A \Rightarrow S\alpha{A^{\prime}} \Rightarrow A\beta\alpha{A^{\prime}} &amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Алгоритм  устранения произвольной левой рекурсии==&lt;br /&gt;
Воспользуемся [[Удаление_eps-правил_из_грамматики | алгоритмом удаления &amp;lt;tex&amp;gt; \varepsilon &amp;lt;/tex&amp;gt;-правил]]. Получим грамматику без &amp;lt;tex&amp;gt; \varepsilon &amp;lt;/tex&amp;gt;-правил для языка &amp;lt;tex&amp;gt;L(\Gamma) \setminus \lbrace \varepsilon \rbrace&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Упорядочим нетерминалы, например по возрастанию индексов, и будем добиваться того, чтобы не было правил вида &amp;lt;tex&amp;gt;A_i \to A_j\alpha&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;j \leqslant i&amp;lt;/tex&amp;gt;.&lt;br /&gt;
Если данное условие выполняется для всех &amp;lt;tex&amp;gt;A_i&amp;lt;/tex&amp;gt;, то в грамматике нет &amp;lt;tex&amp;gt;A_i \to^* A_i&amp;lt;/tex&amp;gt;, а значит не будет левой рекурсии. &lt;br /&gt;
&lt;br /&gt;
Пусть &amp;lt;tex&amp;gt;N = \lbrace A_1, A_2, \ldots , A_n \rbrace&amp;lt;/tex&amp;gt; {{---}} упорядоченное множество всех нетерминалов.&lt;br /&gt;
&lt;br /&gt;
  '''for''' &amp;lt;tex&amp;gt;A_i \in N&amp;lt;/tex&amp;gt;&lt;br /&gt;
    '''for''' &amp;lt;tex&amp;gt;A_j \in \{ N \mid 1 \leqslant j &amp;lt; i \}&amp;lt;/tex&amp;gt;&lt;br /&gt;
      '''for''' &amp;lt;tex&amp;gt;p \in \{ P \mid A_i \to A_j\gamma \}&amp;lt;/tex&amp;gt;&lt;br /&gt;
        удалить продукцию &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; &lt;br /&gt;
        '''for''' &amp;lt;tex&amp;gt;Q \to x_i \in \{A_j \to \delta_1 | \ldots | \delta_k\}&amp;lt;/tex&amp;gt;&lt;br /&gt;
          добавить правило &amp;lt;tex&amp;gt;A_i \to x_i\gamma&amp;lt;/tex&amp;gt;&lt;br /&gt;
    устранить непосредственную левую рекурсию для &amp;lt;tex&amp;gt;A_i&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Если &amp;lt;tex&amp;gt;\varepsilon&amp;lt;/tex&amp;gt; присутствовал в языке исходной грамматики, добавим новый начальный символ &amp;lt;tex&amp;gt;S'&amp;lt;/tex&amp;gt; и правила &amp;lt;tex&amp;gt;S' \to S \, | \, \varepsilon &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
После &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; итерации внешнего цикла в любой продукции внешнего цикла в любой продукции вида &amp;lt;tex&amp;gt;A_k \to A_l\alpha, k &amp;lt; i&amp;lt;/tex&amp;gt;, должно быть &amp;lt;tex&amp;gt;l &amp;gt; k&amp;lt;/tex&amp;gt;. В результате при следующей итерации внутреннего цикла растет нижний предел &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; всех продукций вида &amp;lt;tex&amp;gt;A_i \to A_m\alpha&amp;lt;/tex&amp;gt; до тех пор, пока не будет достигнуто &amp;lt;tex&amp;gt;i \leqslant m &amp;lt;/tex&amp;gt;.&lt;br /&gt;
   &lt;br /&gt;
После &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; итерации внешнего цикла в грамматике будут только правила вида &amp;lt;tex&amp;gt;A_i \to A_j\alpha&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;j &amp;gt; i&amp;lt;/tex&amp;gt;.&lt;br /&gt;
Можно заметить, что неравенство становится строгим только после применения алгоритма устранения непосредственной левой рекурсии. При этом добавляются новые нетерминалы. Пусть &amp;lt;tex&amp;gt;{A^\prime}_i &amp;lt;/tex&amp;gt; новый нетерминал. Можно заметить, что нет правила вида &amp;lt;tex&amp;gt;\ldots \to {A^\prime}_i&amp;lt;/tex&amp;gt;, где  &amp;lt;tex&amp;gt;{A^\prime}_i&amp;lt;/tex&amp;gt; самый левый нетерминал, а значит новые нетерминалы можно не рассматривать во внешнем цикле. &lt;br /&gt;
&lt;br /&gt;
На &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; итерации внешнего цикла все правила вида &amp;lt;tex&amp;gt;A_i \to A_j \gamma&amp;lt;/tex&amp;gt; где &amp;lt;tex&amp;gt; j &amp;lt; i &amp;lt;/tex&amp;gt; заменяются на &amp;lt;tex&amp;gt;A_i \to \delta_1\gamma | \ldots | \delta_k\gamma&amp;lt;/tex&amp;gt; где &amp;lt;tex&amp;gt;A_j \to \delta_1 | \ldots | \delta_k&amp;lt;/tex&amp;gt;. Очевидно, что одна итерация алгоритма не меняет язык, а значит язык получившийся в итоге грамматики совпадает с исходным.&lt;br /&gt;
&lt;br /&gt;
===Асимптотика===&lt;br /&gt;
Пусть &amp;lt;tex&amp;gt;a_i&amp;lt;/tex&amp;gt; количество правил для нетерминала &amp;lt;tex&amp;gt;A_i&amp;lt;/tex&amp;gt;.&lt;br /&gt;
Тогда &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; итерация внешнего цикла будет выполняться за &amp;lt;tex&amp;gt;O(\sum\limits_{A_i \to A_j, j &amp;lt; i} a_j) + O(a_i)&amp;lt;/tex&amp;gt;, что меньше чем &amp;lt;tex&amp;gt;O(\sum\limits_{i=1}^n a_j)&amp;lt;/tex&amp;gt;, значит асимптотика алгоритма &amp;lt;tex&amp;gt;O(n\sum\limits_{i=1}^n a_j)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Проблема этого алгоритма в том, что в зависимости от порядка нетерминалов в множестве размер грамматки может получиться экспоненциальным.&lt;br /&gt;
&lt;br /&gt;
Пример грамматики для которой имеет значение порядок нетерминалов&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;A_1 \to 0 | 1&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;A_{i+1} \to {A_i}0 | {A_i}1 &amp;lt;/tex&amp;gt;  для &amp;lt;tex&amp;gt;1 \leqslant i &amp;lt; n&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Упорядочим множество нетерминалов по возрастанию индексов. Легко заметить, что правила для &amp;lt;tex&amp;gt;A_i&amp;lt;/tex&amp;gt; будут представлять из себя все двоичные вектора длины &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;, а значит размер грамматики будет экспоненциальным.&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition=Говорят, что нетерминал &amp;lt;tex&amp;gt;X&amp;lt;/tex&amp;gt; {{---}} '''прямой левый вывод''' (англ. ''direct left corner'') из &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt;, если существует правило вида &amp;lt;tex&amp;gt;A \to X\alpha&amp;lt;/tex&amp;gt;.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition='''Левый вывод''' (англ. ''left corner'') {{---}} транзитивное, рефлексивное замыкание отношения &amp;quot;быть прямым левым выводом&amp;quot;.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Во внутреннем цикле алгоритма для всех нетерминалов &amp;lt;tex&amp;gt;A_i&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;A_j&amp;lt;/tex&amp;gt;, таких что &amp;lt;tex&amp;gt;j &amp;lt; i&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;A_j&amp;lt;/tex&amp;gt; - прямой левый вывод из &amp;lt;tex&amp;gt;A_i&amp;lt;/tex&amp;gt; заменяем все прямые левые выводы &amp;lt;tex&amp;gt;A_j&amp;lt;/tex&amp;gt; из &amp;lt;tex&amp;gt;A_i&amp;lt;/tex&amp;gt; на все выводы из &amp;lt;tex&amp;gt;A_j&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Это действие удаляет левую рекурсию только если &amp;lt;tex&amp;gt;A_i&amp;lt;/tex&amp;gt; - леворекурсивный нетерминал и &amp;lt;tex&amp;gt;A_j&amp;lt;/tex&amp;gt; содержится в выводе &amp;lt;tex&amp;gt;A_i&amp;lt;/tex&amp;gt; (то есть &amp;lt;tex&amp;gt;A_i&amp;lt;/tex&amp;gt; - левый вывод из &amp;lt;tex&amp;gt;A_j&amp;lt;/tex&amp;gt;,в то время как &amp;lt;tex&amp;gt;A_j&amp;lt;/tex&amp;gt; - левый вывод из &amp;lt;tex&amp;gt;A_i&amp;lt;/tex&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
Перестанем добавлять бесполезные выводы, которые не участвуют в удалении левой рекурсии, упорядочив нетерминалы так: если &amp;lt;tex&amp;gt;j &amp;lt; i&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;A_j&amp;lt;/tex&amp;gt; - прямой левый вывод из &amp;lt;tex&amp;gt;A_i&amp;lt;/tex&amp;gt;, то &amp;lt;tex&amp;gt;A_i&amp;lt;/tex&amp;gt; - левый вывод из &amp;lt;tex&amp;gt;A_j&amp;lt;/tex&amp;gt;.&lt;br /&gt;
Упорядочим их по уменьшению количества различных прямых левых выводов из них.&lt;br /&gt;
&lt;br /&gt;
Так как отношение &amp;quot;быть левым выводом&amp;quot; транзитивно,то если &amp;lt;tex&amp;gt;C&amp;lt;/tex&amp;gt; - прямой левый вывод из &amp;lt;tex&amp;gt;B&amp;lt;/tex&amp;gt;, то каждый левый вывод из С также будет левым выводом из &amp;lt;tex&amp;gt;B&amp;lt;/tex&amp;gt;. А так как отношение &amp;quot;быть левым выводом&amp;quot; рефлексивно, &amp;lt;tex&amp;gt;B&amp;lt;/tex&amp;gt; явлеяется своим левым выводом, а значит если &amp;lt;tex&amp;gt;C&amp;lt;/tex&amp;gt; - прямой левый вывод из &amp;lt;tex&amp;gt;B&amp;lt;/tex&amp;gt; - он должен следовать за &amp;lt;tex&amp;gt;B&amp;lt;/tex&amp;gt; в упорядоченном множестве, если только &amp;lt;tex&amp;gt;B&amp;lt;/tex&amp;gt; не является левым выводом из &amp;lt;tex&amp;gt;C&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Пример==&lt;br /&gt;
Дана грамматика:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;A \to S\alpha &amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;S \to S\beta \mid A\gamma \mid \beta&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Среди правил &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; непосредственной рекурсии нет, поэтому во время первой итерации внешнего цикла ничего не происходит. &lt;br /&gt;
Во время второй итерации внешнего цикла правило &amp;lt;tex&amp;gt; S \to A\gamma &amp;lt;/tex&amp;gt; переходит в &amp;lt;tex&amp;gt; S \to S\alpha\gamma &amp;lt;/tex&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
Грамматика имеет вид &lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;A \to S\alpha &amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;S \to{S}{\beta} | {S}{\alpha}{\gamma} | \beta&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Устраняем левую рекурсию для &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt; S \to\beta{S_1}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt; {S_1} \to\beta{S_1} | \alpha\gamma{S_1} | {\beta} | {\alpha}{\gamma} &amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== См. также  ==&lt;br /&gt;
* [[Контекстно-свободные_грамматики,_вывод,_лево-_и_правосторонний_вывод,_дерево_разбора|Контекстно-свободные грамматики]]&lt;br /&gt;
* [[Нормальная_форма_Хомского|Нормальная форма Хомского]]&lt;br /&gt;
* [[Удаление_eps-правил_из_грамматики | Удаления &amp;lt;tex&amp;gt; \varepsilon &amp;lt;/tex&amp;gt;-правил из грамматики]]&lt;br /&gt;
&lt;br /&gt;
== Источники информации ==&lt;br /&gt;
* ''Хопкрофт Д., Мотвани Р., Ульман Д.'' — '''Введение в теорию автоматов, языков и вычислений''', 2-е изд. : Пер. с англ. — Москва, Издательский дом «Вильямс», 2002. — 528 с. : ISBN 5-8459-0261-4 (рус.)&lt;br /&gt;
* ''Robert C. Moore'' — [http://aclweb.org/anthology-new/A/A00/A00-2033.pdf Removing  Left  Recursion  from  Context-Free  Grammars ]&lt;br /&gt;
&lt;br /&gt;
[[Категория: Теория формальных языков]]&lt;br /&gt;
[[Категория: Контекстно-свободные грамматики]]&lt;br /&gt;
[[Категория: Нормальные формы КС-грамматик]]&lt;/div&gt;</summary>
		<author><name>KirillTim</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%A3%D1%81%D1%82%D1%80%D0%B0%D0%BD%D0%B5%D0%BD%D0%B8%D0%B5_%D0%BB%D0%B5%D0%B2%D0%BE%D0%B9_%D1%80%D0%B5%D0%BA%D1%83%D1%80%D1%81%D0%B8%D0%B8&amp;diff=51301</id>
		<title>Устранение левой рекурсии</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A3%D1%81%D1%82%D1%80%D0%B0%D0%BD%D0%B5%D0%BD%D0%B8%D0%B5_%D0%BB%D0%B5%D0%B2%D0%BE%D0%B9_%D1%80%D0%B5%D0%BA%D1%83%D1%80%D1%81%D0%B8%D0%B8&amp;diff=51301"/>
				<updated>2016-01-17T14:17:53Z</updated>
		
		<summary type="html">&lt;p&gt;KirillTim: подвинул содержание, удалил &amp;quot;постановку задачи&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition=Говорят, что [[Контекстно-свободные грамматики, вывод, лево- и правосторонний вывод, дерево разбора|контекстно-свободная (КС) грамматика]] &amp;lt;tex&amp;gt;\Gamma&amp;lt;/tex&amp;gt; содержит '''непосредственную левую рекурсию''' (англ. ''direct left recursion''), если она содержит правило вида &amp;lt;tex&amp;gt;A \to A\alpha&amp;lt;/tex&amp;gt;.&lt;br /&gt;
}}&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition=Говорят, что КС-грамматика &amp;lt;tex&amp;gt;\Gamma&amp;lt;/tex&amp;gt; содержит '''левую рекурсию'''  (англ. ''left recursion''), если в ней существует вывод вида &amp;lt;tex&amp;gt;A \Rightarrow^* A\alpha&amp;lt;/tex&amp;gt;.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
[[Методы трансляции#Нисходящий разбор|Методы нисходящего разбора]] не в состоянии работать с леворекурсивными грамматиками. Проблема в том, что продукция вида &amp;lt;tex&amp;gt;A \Rightarrow^* A\alpha&amp;lt;/tex&amp;gt; может применяться бесконечно долго, так и не выработав некий терминальный символ, который можно было бы сравнить со строкой. Поэтому требуется преобразование грамматики, которое бы устранило левую рекурсию.&lt;br /&gt;
&lt;br /&gt;
==Устранение непосредственной левой рекурсии==&lt;br /&gt;
Опишем процедуру, устраняющую все правила вида &amp;lt;tex&amp;gt;A \to A\alpha&amp;lt;/tex&amp;gt;, для фиксированного нетерминала &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;ol&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Запишем все правила вывода из &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; в виде: &lt;br /&gt;
&amp;lt;tex&amp;gt;A \to A\alpha_1\,|\,\ldots\,|\,A\alpha_n\,|\,\beta_1\,|\,\ldots\,|\,\beta_m &amp;lt;/tex&amp;gt;, где&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; &amp;lt;tex&amp;gt;\alpha&amp;lt;/tex&amp;gt; {{---}} непустая последовательность терминалов и нетерминалов (&amp;lt;tex&amp;gt;\alpha \nrightarrow \varepsilon &amp;lt;/tex&amp;gt;);&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; &amp;lt;tex&amp;gt;\beta&amp;lt;/tex&amp;gt; {{---}} непустая последовательность терминалов и нетерминалов, не начинающаяся с &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt;.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Заменим правила вывода из &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; на &amp;lt;tex&amp;gt;A \to\beta_1A^\prime\, |\, \ldots\,  |\,  \beta_mA^\prime \,|\, \beta_1 \,|\, \ldots \,|\, \beta_m&amp;lt;/tex&amp;gt;.&amp;lt;/li&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;li&amp;gt;Создадим новый нетерминал &amp;lt;tex&amp;gt;{A^\prime} \to \alpha_1{A^\prime},  |\,  \ldots\, |\, \alpha_n{A^\prime} | \alpha_1\,  |\,  \ldots\, |\, \alpha_n&amp;lt;/tex&amp;gt;. &amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ol&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Изначально нетерминал &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; порождает сроки вида &amp;lt;tex&amp;gt;\beta\alpha_{i0}\alpha_{i1} \ldots \alpha_{ik}&amp;lt;/tex&amp;gt;. В новой грамматике нетерминал &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; порождает &amp;lt;tex&amp;gt;\beta{A^\prime}&amp;lt;/tex&amp;gt;, а &amp;lt;tex&amp;gt;A^\prime&amp;lt;/tex&amp;gt; порождает строки вида &amp;lt;tex&amp;gt;\alpha_{i0}\alpha_{i1} \ldots \alpha_{ik}&amp;lt;/tex&amp;gt;. Из этого очевидно, что изначальная грамматика эквивалентна новой.&lt;br /&gt;
&lt;br /&gt;
===Пример===&lt;br /&gt;
&amp;lt;tex&amp;gt;A \to S\alpha | A\alpha&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;S \to A\beta&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Есть непосредственная левая рекурсия &amp;lt;tex&amp;gt;A \to A\alpha&amp;lt;/tex&amp;gt;. Добавим нетерминал &amp;lt;tex&amp;gt;A^\prime&amp;lt;/tex&amp;gt; и добавим правила &amp;lt;tex&amp;gt;A \to S\alpha{A^{\prime}}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt; A^{\prime} \to \alpha{A^{\prime}} &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Новая грамматика:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;A \to S\alpha{A^{\prime}} | S\alpha&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;A^{\prime} \to \alpha{A^{\prime}}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;S \to A\beta&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
В новой грамматике нет непосредственной левой рекурсии, но нетерминал &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; леворекурсивен, так как есть &amp;lt;tex&amp;gt; A \Rightarrow S\alpha{A^{\prime}} \Rightarrow A\beta\alpha{A^{\prime}} &amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Алгоритм  устранения произвольной левой рекурсии==&lt;br /&gt;
Воспользуемся [[Удаление_eps-правил_из_грамматики | алгоритмом удаления &amp;lt;tex&amp;gt; \varepsilon &amp;lt;/tex&amp;gt;-правил]]. Получим грамматику без &amp;lt;tex&amp;gt; \varepsilon &amp;lt;/tex&amp;gt;-правил для языка &amp;lt;tex&amp;gt;L(\Gamma) \setminus \lbrace \varepsilon \rbrace&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Упорядочим нетерминалы, например по возрастанию индексов, и будем добиваться того, чтобы не было правил вида &amp;lt;tex&amp;gt;A_i \to A_j\alpha&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;j \leqslant i&amp;lt;/tex&amp;gt;.&lt;br /&gt;
Если данное условие выполняется для всех &amp;lt;tex&amp;gt;A_i&amp;lt;/tex&amp;gt;, то в грамматике нет &amp;lt;tex&amp;gt;A_i \to^* A_i&amp;lt;/tex&amp;gt;, а значит не будет левой рекурсии. &lt;br /&gt;
&lt;br /&gt;
Пусть &amp;lt;tex&amp;gt;N = \lbrace A_1, A_2, \ldots , A_n \rbrace&amp;lt;/tex&amp;gt; {{---}} упорядоченное множество всех нетерминалов.&lt;br /&gt;
&lt;br /&gt;
  '''for''' &amp;lt;tex&amp;gt;A_i \in N&amp;lt;/tex&amp;gt;&lt;br /&gt;
    '''for''' &amp;lt;tex&amp;gt;A_j \in \{ N \mid 1 \leqslant j &amp;lt; i \}&amp;lt;/tex&amp;gt;&lt;br /&gt;
      '''for''' &amp;lt;tex&amp;gt;production \in \{A_i \to A_j\gamma \}&amp;lt;/tex&amp;gt;&lt;br /&gt;
        удалить &amp;lt;tex&amp;gt;production&amp;lt;/tex&amp;gt; &amp;lt;font color=darkgreen&amp;gt;#production {{---}} правило вывода&amp;lt;/font&amp;gt;&lt;br /&gt;
        '''for''' &amp;lt;tex&amp;gt;P \to x_i \in \{A_j \to \delta_1 | \ldots | \delta_k\}&amp;lt;/tex&amp;gt;&lt;br /&gt;
          добавить правило &amp;lt;tex&amp;gt;A_i \to x_i\gamma&amp;lt;/tex&amp;gt;&lt;br /&gt;
    устранить непосредственную левую рекурсию для &amp;lt;tex&amp;gt;A_i&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Если &amp;lt;tex&amp;gt;\varepsilon&amp;lt;/tex&amp;gt; присутствовал в языке исходной грамматики, добавим новый начальный символ &amp;lt;tex&amp;gt;S'&amp;lt;/tex&amp;gt; и правила &amp;lt;tex&amp;gt;S' \to S \, | \, \varepsilon &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
После &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; итерации внешнего цикла в любой продукции внешнего цикла в любой продукции вида &amp;lt;tex&amp;gt;A_k \to A_l\alpha, k &amp;lt; i&amp;lt;/tex&amp;gt;, должно быть &amp;lt;tex&amp;gt;l &amp;gt; k&amp;lt;/tex&amp;gt;. В результате при следующей итерации внутреннего цикла растет нижний предел &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; всех продукций вида &amp;lt;tex&amp;gt;A_i \to A_m\alpha&amp;lt;/tex&amp;gt; до тех пор, пока не будет достигнуто &amp;lt;tex&amp;gt;i \leqslant m &amp;lt;/tex&amp;gt;.&lt;br /&gt;
   &lt;br /&gt;
После &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; итерации внешнего цикла в грамматике будут только правила вида &amp;lt;tex&amp;gt;A_i \to A_j\alpha&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;j &amp;gt; i&amp;lt;/tex&amp;gt;.&lt;br /&gt;
Можно заметить, что неравенство становится строгим только после применения алгоритма устранения непосредственной левой рекурсии. При этом добавляются новые нетерминалы. Пусть &amp;lt;tex&amp;gt;{A^\prime}_i &amp;lt;/tex&amp;gt; новый нетерминал. Можно заметить, что нет правила вида &amp;lt;tex&amp;gt;\ldots \to {A^\prime}_i&amp;lt;/tex&amp;gt;, где  &amp;lt;tex&amp;gt;{A^\prime}_i&amp;lt;/tex&amp;gt; самый левый нетерминал, а значит новые нетерминалы можно не рассматривать во внешнем цикле. &lt;br /&gt;
&lt;br /&gt;
На &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; итерации внешнего цикла все правила вида &amp;lt;tex&amp;gt;A_i \to A_j \gamma&amp;lt;/tex&amp;gt; где &amp;lt;tex&amp;gt; j &amp;lt; i &amp;lt;/tex&amp;gt; заменяются на &amp;lt;tex&amp;gt;A_i \to \delta_1\gamma | \ldots | \delta_k\gamma&amp;lt;/tex&amp;gt; где &amp;lt;tex&amp;gt;A_j \to \delta_1 | \ldots | \delta_k&amp;lt;/tex&amp;gt;. Очевидно, что одна итерация алгоритма не меняет язык, а значит язык получившийся в итоге грамматики совпадает с исходным.&lt;br /&gt;
&lt;br /&gt;
===Асимптотика===&lt;br /&gt;
Пусть &amp;lt;tex&amp;gt;a_i&amp;lt;/tex&amp;gt; количество правил для нетерминала &amp;lt;tex&amp;gt;A_i&amp;lt;/tex&amp;gt;.&lt;br /&gt;
Тогда &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; итерация внешнего цикла будет выполняться за &amp;lt;tex&amp;gt;O(\sum\limits_{A_i \to A_j, j &amp;lt; i} a_j) + O(a_i)&amp;lt;/tex&amp;gt;, что меньше чем &amp;lt;tex&amp;gt;O(\sum\limits_{i=1}^n a_j)&amp;lt;/tex&amp;gt;, значит асимптотика алгоритма &amp;lt;tex&amp;gt;O(n\sum\limits_{i=1}^n a_j)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Проблема этого алгоритма в том, что в зависимости от порядка нетерминалов в множестве размер грамматки может получиться экспоненциальным.&lt;br /&gt;
&lt;br /&gt;
Пример грамматики для которой имеет значение порядок нетерминалов&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;A_1 \to 0 | 1&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;A_{i+1} \to {A_i}0 | {A_i}1 &amp;lt;/tex&amp;gt;  для &amp;lt;tex&amp;gt;1 \leqslant i &amp;lt; n&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Упорядочим множество нетерминалов по возрастанию индексов. Легко заметить, что правила для &amp;lt;tex&amp;gt;A_i&amp;lt;/tex&amp;gt; будут представлять из себя все двоичные вектора длины &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;, а значит размер грамматики будет экспоненциальным.&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition=Говорят, что нетерминал &amp;lt;tex&amp;gt;X&amp;lt;/tex&amp;gt; {{---}} '''прямой левый вывод''' (англ. ''direct left corner'') из &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt;, если существует правило вида &amp;lt;tex&amp;gt;A \to X\alpha&amp;lt;/tex&amp;gt;.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition='''Левый вывод''' (англ. ''left corner'') {{---}} транзитивное, рефлексивное замыкание отношения &amp;quot;быть прямым левым выводом&amp;quot;.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Во внутреннем цикле алгоритма для всех нетерминалов &amp;lt;tex&amp;gt;A_i&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;A_j&amp;lt;/tex&amp;gt;, таких что &amp;lt;tex&amp;gt;j &amp;lt; i&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;A_j&amp;lt;/tex&amp;gt; - прямой левый вывод из &amp;lt;tex&amp;gt;A_i&amp;lt;/tex&amp;gt; заменяем все прямые левые выводы &amp;lt;tex&amp;gt;A_j&amp;lt;/tex&amp;gt; из &amp;lt;tex&amp;gt;A_i&amp;lt;/tex&amp;gt; на все выводы из &amp;lt;tex&amp;gt;A_j&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Это действие удаляет левую рекурсию только если &amp;lt;tex&amp;gt;A_i&amp;lt;/tex&amp;gt; - леворекурсивный нетерминал и &amp;lt;tex&amp;gt;A_j&amp;lt;/tex&amp;gt; содержится в выводе &amp;lt;tex&amp;gt;A_i&amp;lt;/tex&amp;gt; (то есть &amp;lt;tex&amp;gt;A_i&amp;lt;/tex&amp;gt; - левый вывод из &amp;lt;tex&amp;gt;A_j&amp;lt;/tex&amp;gt;,в то время как &amp;lt;tex&amp;gt;A_j&amp;lt;/tex&amp;gt; - левый вывод из &amp;lt;tex&amp;gt;A_i&amp;lt;/tex&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
Перестанем добавлять бесполезные выводы, которые не участвуют в удалении левой рекурсии, упорядочив нетерминалы так: если &amp;lt;tex&amp;gt;j &amp;lt; i&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;A_j&amp;lt;/tex&amp;gt; - прямой левый вывод из &amp;lt;tex&amp;gt;A_i&amp;lt;/tex&amp;gt;, то &amp;lt;tex&amp;gt;A_i&amp;lt;/tex&amp;gt; - левый вывод из &amp;lt;tex&amp;gt;A_j&amp;lt;/tex&amp;gt;.&lt;br /&gt;
Упорядочим их по уменьшению количества различных прямых левых выводов из них.&lt;br /&gt;
&lt;br /&gt;
Так как отношение &amp;quot;быть левым выводом&amp;quot; транзитивно,то если &amp;lt;tex&amp;gt;C&amp;lt;/tex&amp;gt; - прямой левый вывод из &amp;lt;tex&amp;gt;B&amp;lt;/tex&amp;gt;, то каждый левый вывод из С также будет левым выводом из &amp;lt;tex&amp;gt;B&amp;lt;/tex&amp;gt;. А так как отношение &amp;quot;быть левым выводом&amp;quot; рефлексивно, &amp;lt;tex&amp;gt;B&amp;lt;/tex&amp;gt; явлеяется своим левым выводом, а значит если &amp;lt;tex&amp;gt;C&amp;lt;/tex&amp;gt; - прямой левый вывод из &amp;lt;tex&amp;gt;B&amp;lt;/tex&amp;gt; - он должен следовать за &amp;lt;tex&amp;gt;B&amp;lt;/tex&amp;gt; в упорядоченном множестве, если только &amp;lt;tex&amp;gt;B&amp;lt;/tex&amp;gt; не является левым выводом из &amp;lt;tex&amp;gt;C&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Пример==&lt;br /&gt;
Дана грамматика:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;A \to S\alpha &amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;S \to S\beta \mid A\gamma \mid \beta&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Среди правил &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; непосредственной рекурсии нет, поэтому во время первой итерации внешнего цикла ничего не происходит. &lt;br /&gt;
Во время второй итерации внешнего цикла правило &amp;lt;tex&amp;gt; S \to A\gamma &amp;lt;/tex&amp;gt; переходит в &amp;lt;tex&amp;gt; S \to S\alpha\gamma &amp;lt;/tex&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
Грамматика имеет вид &lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;A \to S\alpha &amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;S \to{S}{\beta} | {S}{\alpha}{\gamma} | \beta&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Устраняем левую рекурсию для &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt; S \to\beta{S_1}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt; {S_1} \to\beta{S_1} | \alpha\gamma{S_1} | {\beta} | {\alpha}{\gamma} &amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== См. также  ==&lt;br /&gt;
* [[Контекстно-свободные_грамматики,_вывод,_лево-_и_правосторонний_вывод,_дерево_разбора|Контекстно-свободные грамматики]]&lt;br /&gt;
* [[Нормальная_форма_Хомского|Нормальная форма Хомского]]&lt;br /&gt;
* [[Удаление_eps-правил_из_грамматики | Удаления &amp;lt;tex&amp;gt; \varepsilon &amp;lt;/tex&amp;gt;-правил из грамматики]]&lt;br /&gt;
&lt;br /&gt;
== Источники информации ==&lt;br /&gt;
* ''Хопкрофт Д., Мотвани Р., Ульман Д.'' — '''Введение в теорию автоматов, языков и вычислений''', 2-е изд. : Пер. с англ. — Москва, Издательский дом «Вильямс», 2002. — 528 с. : ISBN 5-8459-0261-4 (рус.)&lt;br /&gt;
* ''Robert C. Moore'' — [http://aclweb.org/anthology-new/A/A00/A00-2033.pdf Removing  Left  Recursion  from  Context-Free  Grammars ]&lt;br /&gt;
&lt;br /&gt;
[[Категория: Теория формальных языков]]&lt;br /&gt;
[[Категория: Контекстно-свободные грамматики]]&lt;br /&gt;
[[Категория: Нормальные формы КС-грамматик]]&lt;/div&gt;</summary>
		<author><name>KirillTim</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%A3%D1%81%D1%82%D1%80%D0%B0%D0%BD%D0%B5%D0%BD%D0%B8%D0%B5_%D0%BB%D0%B5%D0%B2%D0%BE%D0%B9_%D1%80%D0%B5%D0%BA%D1%83%D1%80%D1%81%D0%B8%D0%B8&amp;diff=51300</id>
		<title>Устранение левой рекурсии</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A3%D1%81%D1%82%D1%80%D0%B0%D0%BD%D0%B5%D0%BD%D0%B8%D0%B5_%D0%BB%D0%B5%D0%B2%D0%BE%D0%B9_%D1%80%D0%B5%D0%BA%D1%83%D1%80%D1%81%D0%B8%D0%B8&amp;diff=51300"/>
				<updated>2016-01-17T13:54:31Z</updated>
		
		<summary type="html">&lt;p&gt;KirillTim: добавил описание порядка&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Определение&lt;br /&gt;
|definition=Говорят, что [[Контекстно-свободные грамматики, вывод, лево- и правосторонний вывод, дерево разбора|контекстно-свободная (КС) грамматика]] &amp;lt;tex&amp;gt;\Gamma&amp;lt;/tex&amp;gt; содержит '''непосредственную левую рекурсию''' (англ. ''direct left recursion''), если она содержит правило вида &amp;lt;tex&amp;gt;A \to A\alpha&amp;lt;/tex&amp;gt;.&lt;br /&gt;
}}&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition=Говорят, что КС-грамматика &amp;lt;tex&amp;gt;\Gamma&amp;lt;/tex&amp;gt; содержит '''левую рекурсию'''  (англ. ''left recursion''), если в ней существует вывод вида &amp;lt;tex&amp;gt;A \Rightarrow^* A\alpha&amp;lt;/tex&amp;gt;.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
== Постановка задачи ==&lt;br /&gt;
[[Методы трансляции#Нисходящий разбор|Методы нисходящего разбора]] не в состоянии работать с леворекурсивными грамматиками. Проблема в том, что продукция вида &amp;lt;tex&amp;gt;A \Rightarrow^* A\alpha&amp;lt;/tex&amp;gt; может применяться бесконечно долго, так и не выработав некий терминальный символ, который можно было бы сравнить со строкой. Поэтому требуется преобразование грамматики, которое бы устранило левую рекурсию.&lt;br /&gt;
&lt;br /&gt;
==Устранение непосредственной левой рекурсии==&lt;br /&gt;
Опишем процедуру, устраняющую все правила вида &amp;lt;tex&amp;gt;A \to A\alpha&amp;lt;/tex&amp;gt;, для фиксированного нетерминала &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;ol&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Запишем все правила вывода из &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; в виде: &lt;br /&gt;
&amp;lt;tex&amp;gt;A \to A\alpha_1\,|\,\ldots\,|\,A\alpha_n\,|\,\beta_1\,|\,\ldots\,|\,\beta_m &amp;lt;/tex&amp;gt;, где&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; &amp;lt;tex&amp;gt;\alpha&amp;lt;/tex&amp;gt; {{---}} непустая последовательность терминалов и нетерминалов (&amp;lt;tex&amp;gt;\alpha \nrightarrow \varepsilon &amp;lt;/tex&amp;gt;);&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; &amp;lt;tex&amp;gt;\beta&amp;lt;/tex&amp;gt; {{---}} непустая последовательность терминалов и нетерминалов, не начинающаяся с &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt;.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Заменим правила вывода из &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; на &amp;lt;tex&amp;gt;A \to\beta_1A^\prime\, |\, \ldots\,  |\,  \beta_mA^\prime \,|\, \beta_1 \,|\, \ldots \,|\, \beta_m&amp;lt;/tex&amp;gt;.&amp;lt;/li&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;li&amp;gt;Создадим новый нетерминал &amp;lt;tex&amp;gt;{A^\prime} \to \alpha_1{A^\prime},  |\,  \ldots\, |\, \alpha_n{A^\prime} | \alpha_1\,  |\,  \ldots\, |\, \alpha_n&amp;lt;/tex&amp;gt;. &amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ol&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Изначально нетерминал &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; порождает сроки вида &amp;lt;tex&amp;gt;\beta\alpha_{i0}\alpha_{i1} \ldots \alpha_{ik}&amp;lt;/tex&amp;gt;. В новой грамматике нетерминал &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; порождает &amp;lt;tex&amp;gt;\beta{A^\prime}&amp;lt;/tex&amp;gt;, а &amp;lt;tex&amp;gt;A^\prime&amp;lt;/tex&amp;gt; порождает строки вида &amp;lt;tex&amp;gt;\alpha_{i0}\alpha_{i1} \ldots \alpha_{ik}&amp;lt;/tex&amp;gt;. Из этого очевидно, что изначальная грамматика эквивалентна новой.&lt;br /&gt;
&lt;br /&gt;
===Пример===&lt;br /&gt;
&amp;lt;tex&amp;gt;A \to S\alpha | A\alpha&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;S \to A\beta&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Есть непосредственная левая рекурсия &amp;lt;tex&amp;gt;A \to A\alpha&amp;lt;/tex&amp;gt;. Добавим нетерминал &amp;lt;tex&amp;gt;A^\prime&amp;lt;/tex&amp;gt; и добавим правила &amp;lt;tex&amp;gt;A \to S\alpha{A^{\prime}}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt; A^{\prime} \to \alpha{A^{\prime}} &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Новая грамматика:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;A \to S\alpha{A^{\prime}} | S\alpha&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;A^{\prime} \to \alpha{A^{\prime}}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;S \to A\beta&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
В новой грамматике нет непосредственной левой рекурсии, но нетерминал &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; леворекурсивен, так как есть &amp;lt;tex&amp;gt; A \Rightarrow S\alpha{A^{\prime}} \Rightarrow A\beta\alpha{A^{\prime}} &amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Алгоритм  устранения произвольной левой рекурсии==&lt;br /&gt;
Воспользуемся [[Удаление_eps-правил_из_грамматики | алгоритмом удаления &amp;lt;tex&amp;gt; \varepsilon &amp;lt;/tex&amp;gt;-правил]]. Получим грамматику без &amp;lt;tex&amp;gt; \varepsilon &amp;lt;/tex&amp;gt;-правил для языка &amp;lt;tex&amp;gt;L(\Gamma) \setminus \lbrace \varepsilon \rbrace&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Упорядочим нетерминалы, например по возрастанию индексов, и будем добиваться того, чтобы не было правил вида &amp;lt;tex&amp;gt;A_i \to A_j\alpha&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;j \leqslant i&amp;lt;/tex&amp;gt;.&lt;br /&gt;
Если данное условие выполняется для всех &amp;lt;tex&amp;gt;A_i&amp;lt;/tex&amp;gt;, то в грамматике нет &amp;lt;tex&amp;gt;A_i \to^* A_i&amp;lt;/tex&amp;gt;, а значит не будет левой рекурсии. &lt;br /&gt;
&lt;br /&gt;
Пусть &amp;lt;tex&amp;gt;N = \lbrace A_1, A_2, \ldots , A_n \rbrace&amp;lt;/tex&amp;gt; {{---}} упорядоченное множество всех нетерминалов.&lt;br /&gt;
&lt;br /&gt;
  '''for''' &amp;lt;tex&amp;gt;A_i \in N&amp;lt;/tex&amp;gt;&lt;br /&gt;
    '''for''' &amp;lt;tex&amp;gt;A_j \in \{ N \mid 1 \leqslant j &amp;lt; i \}&amp;lt;/tex&amp;gt;&lt;br /&gt;
      '''for''' &amp;lt;tex&amp;gt;production \in \{A_i \to A_j\gamma \}&amp;lt;/tex&amp;gt;&lt;br /&gt;
        удалить &amp;lt;tex&amp;gt;production&amp;lt;/tex&amp;gt; &amp;lt;font color=darkgreen&amp;gt;#production {{---}} правило вывода&amp;lt;/font&amp;gt;&lt;br /&gt;
        '''for''' &amp;lt;tex&amp;gt;P \to x_i \in \{A_j \to \delta_1 | \ldots | \delta_k\}&amp;lt;/tex&amp;gt;&lt;br /&gt;
          добавить правило &amp;lt;tex&amp;gt;A_i \to x_i\gamma&amp;lt;/tex&amp;gt;&lt;br /&gt;
    устранить непосредственную левую рекурсию для &amp;lt;tex&amp;gt;A_i&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Если &amp;lt;tex&amp;gt;\varepsilon&amp;lt;/tex&amp;gt; присутствовал в языке исходной грамматики, добавим новый начальный символ &amp;lt;tex&amp;gt;S'&amp;lt;/tex&amp;gt; и правила &amp;lt;tex&amp;gt;S' \to S \, | \, \varepsilon &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
После &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; итерации внешнего цикла в любой продукции внешнего цикла в любой продукции вида &amp;lt;tex&amp;gt;A_k \to A_l\alpha, k &amp;lt; i&amp;lt;/tex&amp;gt;, должно быть &amp;lt;tex&amp;gt;l &amp;gt; k&amp;lt;/tex&amp;gt;. В результате при следующей итерации внутреннего цикла растет нижний предел &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; всех продукций вида &amp;lt;tex&amp;gt;A_i \to A_m\alpha&amp;lt;/tex&amp;gt; до тех пор, пока не будет достигнуто &amp;lt;tex&amp;gt;i \leqslant m &amp;lt;/tex&amp;gt;.&lt;br /&gt;
   &lt;br /&gt;
После &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; итерации внешнего цикла в грамматике будут только правила вида &amp;lt;tex&amp;gt;A_i \to A_j\alpha&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;j &amp;gt; i&amp;lt;/tex&amp;gt;.&lt;br /&gt;
Можно заметить, что неравенство становится строгим только после применения алгоритма устранения непосредственной левой рекурсии. При этом добавляются новые нетерминалы. Пусть &amp;lt;tex&amp;gt;{A^\prime}_i &amp;lt;/tex&amp;gt; новый нетерминал. Можно заметить, что нет правила вида &amp;lt;tex&amp;gt;\ldots \to {A^\prime}_i&amp;lt;/tex&amp;gt;, где  &amp;lt;tex&amp;gt;{A^\prime}_i&amp;lt;/tex&amp;gt; самый левый нетерминал, а значит новые нетерминалы можно не рассматривать во внешнем цикле. &lt;br /&gt;
&lt;br /&gt;
На &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; итерации внешнего цикла все правила вида &amp;lt;tex&amp;gt;A_i \to A_j \gamma&amp;lt;/tex&amp;gt; где &amp;lt;tex&amp;gt; j &amp;lt; i &amp;lt;/tex&amp;gt; заменяются на &amp;lt;tex&amp;gt;A_i \to \delta_1\gamma | \ldots | \delta_k\gamma&amp;lt;/tex&amp;gt; где &amp;lt;tex&amp;gt;A_j \to \delta_1 | \ldots | \delta_k&amp;lt;/tex&amp;gt;. Очевидно, что одна итерация алгоритма не меняет язык, а значит язык получившийся в итоге грамматики совпадает с исходным.&lt;br /&gt;
&lt;br /&gt;
===Асимптотика===&lt;br /&gt;
Пусть &amp;lt;tex&amp;gt;a_i&amp;lt;/tex&amp;gt; количество правил для нетерминала &amp;lt;tex&amp;gt;A_i&amp;lt;/tex&amp;gt;.&lt;br /&gt;
Тогда &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; итерация внешнего цикла будет выполняться за &amp;lt;tex&amp;gt;O(\sum\limits_{A_i \to A_j, j &amp;lt; i} a_j) + O(a_i)&amp;lt;/tex&amp;gt;, что меньше чем &amp;lt;tex&amp;gt;O(\sum\limits_{i=1}^n a_j)&amp;lt;/tex&amp;gt;, значит асимптотика алгоритма &amp;lt;tex&amp;gt;O(n\sum\limits_{i=1}^n a_j)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Проблема этого алгоритма в том, что в зависимости от порядка нетерминалов в множестве размер грамматки может получиться экспоненциальным.&lt;br /&gt;
&lt;br /&gt;
Пример грамматики для которой имеет значение порядок нетерминалов&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;A_1 \to 0 | 1&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;A_{i+1} \to {A_i}0 | {A_i}1 &amp;lt;/tex&amp;gt;  для &amp;lt;tex&amp;gt;1 \leqslant i &amp;lt; n&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Упорядочим множество нетерминалов по возрастанию индексов. Легко заметить, что правила для &amp;lt;tex&amp;gt;A_i&amp;lt;/tex&amp;gt; будут представлять из себя все двоичные вектора длины &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;, а значит размер грамматики будет экспоненциальным.&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition=Говорят, что нетерминал &amp;lt;tex&amp;gt;X&amp;lt;/tex&amp;gt; {{---}} '''прямой левый вывод''' (англ. ''direct left corner'') из &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt;, если существует правило вида &amp;lt;tex&amp;gt;A \to X\alpha&amp;lt;/tex&amp;gt;.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition='''Левый вывод''' (англ. ''left corner'') {{---}} транзитивное, рефлексивное замыкание отношения &amp;quot;быть прямым левым выводом&amp;quot;.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Во внутреннем цикле алгоритма для всех нетерминалов &amp;lt;tex&amp;gt;A_i&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;A_j&amp;lt;/tex&amp;gt;, таких что &amp;lt;tex&amp;gt;j &amp;lt; i&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;A_j&amp;lt;/tex&amp;gt; - прямой левый вывод из &amp;lt;tex&amp;gt;A_i&amp;lt;/tex&amp;gt; заменяем все прямые левые выводы &amp;lt;tex&amp;gt;A_j&amp;lt;/tex&amp;gt; из &amp;lt;tex&amp;gt;A_i&amp;lt;/tex&amp;gt; на все выводы из &amp;lt;tex&amp;gt;A_j&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Это действие удаляет левую рекурсию только если &amp;lt;tex&amp;gt;A_i&amp;lt;/tex&amp;gt; - леворекурсивный нетерминал и &amp;lt;tex&amp;gt;A_j&amp;lt;/tex&amp;gt; содержится в выводе &amp;lt;tex&amp;gt;A_i&amp;lt;/tex&amp;gt; (то есть &amp;lt;tex&amp;gt;A_i&amp;lt;/tex&amp;gt; - левый вывод из &amp;lt;tex&amp;gt;A_j&amp;lt;/tex&amp;gt;,в то время как &amp;lt;tex&amp;gt;A_j&amp;lt;/tex&amp;gt; - левый вывод из &amp;lt;tex&amp;gt;A_i&amp;lt;/tex&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
Перестанем добавлять бесполезные выводы, которые не участвуют в удалении левой рекурсии, упорядочив нетерминалы так: если &amp;lt;tex&amp;gt;j &amp;lt; i&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;A_j&amp;lt;/tex&amp;gt; - прямой левый вывод из &amp;lt;tex&amp;gt;A_i&amp;lt;/tex&amp;gt;, то &amp;lt;tex&amp;gt;A_i&amp;lt;/tex&amp;gt; - левый вывод из &amp;lt;tex&amp;gt;A_j&amp;lt;/tex&amp;gt;.&lt;br /&gt;
Упорядочим их по уменьшению количества различных прямых левых выводов из них.&lt;br /&gt;
&lt;br /&gt;
Так как отношение &amp;quot;быть левым выводом&amp;quot; транзитивно,то если &amp;lt;tex&amp;gt;C&amp;lt;/tex&amp;gt; - прямой левый вывод из &amp;lt;tex&amp;gt;B&amp;lt;/tex&amp;gt;, то каждый левый вывод из С также будет левым выводом из &amp;lt;tex&amp;gt;B&amp;lt;/tex&amp;gt;. А так как отношение &amp;quot;быть левым выводом&amp;quot; рефлексивно, &amp;lt;tex&amp;gt;B&amp;lt;/tex&amp;gt; явлеяется своим левым выводом, а значит если &amp;lt;tex&amp;gt;C&amp;lt;/tex&amp;gt; - прямой левый вывод из &amp;lt;tex&amp;gt;B&amp;lt;/tex&amp;gt; - он должен следовать за &amp;lt;tex&amp;gt;B&amp;lt;/tex&amp;gt; в упорядоченном множестве, если только &amp;lt;tex&amp;gt;B&amp;lt;/tex&amp;gt; не является левым выводом из &amp;lt;tex&amp;gt;C&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Пример==&lt;br /&gt;
Дана грамматика:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;A \to S\alpha &amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;S \to S\beta \mid A\gamma \mid \beta&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Среди правил &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; непосредственной рекурсии нет, поэтому во время первой итерации внешнего цикла ничего не происходит. &lt;br /&gt;
Во время второй итерации внешнего цикла правило &amp;lt;tex&amp;gt; S \to A\gamma &amp;lt;/tex&amp;gt; переходит в &amp;lt;tex&amp;gt; S \to S\alpha\gamma &amp;lt;/tex&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
Грамматика имеет вид &lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;A \to S\alpha &amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;S \to{S}{\beta} | {S}{\alpha}{\gamma} | \beta&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Устраняем левую рекурсию для &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt; S \to\beta{S_1}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt; {S_1} \to\beta{S_1} | \alpha\gamma{S_1} | {\beta} | {\alpha}{\gamma} &amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== См. также  ==&lt;br /&gt;
* [[Контекстно-свободные_грамматики,_вывод,_лево-_и_правосторонний_вывод,_дерево_разбора|Контекстно-свободные грамматики]]&lt;br /&gt;
* [[Нормальная_форма_Хомского|Нормальная форма Хомского]]&lt;br /&gt;
* [[Удаление_eps-правил_из_грамматики | Удаления &amp;lt;tex&amp;gt; \varepsilon &amp;lt;/tex&amp;gt;-правил из грамматики]]&lt;br /&gt;
&lt;br /&gt;
== Источники информации ==&lt;br /&gt;
* ''Хопкрофт Д., Мотвани Р., Ульман Д.'' — '''Введение в теорию автоматов, языков и вычислений''', 2-е изд. : Пер. с англ. — Москва, Издательский дом «Вильямс», 2002. — 528 с. : ISBN 5-8459-0261-4 (рус.)&lt;br /&gt;
* ''Robert C. Moore'' — [http://aclweb.org/anthology-new/A/A00/A00-2033.pdf Removing  Left  Recursion  from  Context-Free  Grammars ]&lt;br /&gt;
&lt;br /&gt;
[[Категория: Теория формальных языков]]&lt;br /&gt;
[[Категория: Контекстно-свободные грамматики]]&lt;br /&gt;
[[Категория: Нормальные формы КС-грамматик]]&lt;/div&gt;</summary>
		<author><name>KirillTim</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%A3%D1%81%D1%82%D1%80%D0%B0%D0%BD%D0%B5%D0%BD%D0%B8%D0%B5_%D0%BB%D0%B5%D0%B2%D0%BE%D0%B9_%D1%80%D0%B5%D0%BA%D1%83%D1%80%D1%81%D0%B8%D0%B8&amp;diff=51299</id>
		<title>Устранение левой рекурсии</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A3%D1%81%D1%82%D1%80%D0%B0%D0%BD%D0%B5%D0%BD%D0%B8%D0%B5_%D0%BB%D0%B5%D0%B2%D0%BE%D0%B9_%D1%80%D0%B5%D0%BA%D1%83%D1%80%D1%81%D0%B8%D0%B8&amp;diff=51299"/>
				<updated>2016-01-17T13:31:24Z</updated>
		
		<summary type="html">&lt;p&gt;KirillTim: /* Алгоритм  устранения произвольной левой рекурсии */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Определение&lt;br /&gt;
|definition=Говорят, что [[Контекстно-свободные грамматики, вывод, лево- и правосторонний вывод, дерево разбора|контекстно-свободная (КС) грамматика]] &amp;lt;tex&amp;gt;\Gamma&amp;lt;/tex&amp;gt; содержит '''непосредственную левую рекурсию''' (англ. ''direct left recursion''), если она содержит правило вида &amp;lt;tex&amp;gt;A \to A\alpha&amp;lt;/tex&amp;gt;.&lt;br /&gt;
}}&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition=Говорят, что КС-грамматика &amp;lt;tex&amp;gt;\Gamma&amp;lt;/tex&amp;gt; содержит '''левую рекурсию'''  (англ. ''left recursion''), если в ней существует вывод вида &amp;lt;tex&amp;gt;A \Rightarrow^* A\alpha&amp;lt;/tex&amp;gt;.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
== Постановка задачи ==&lt;br /&gt;
[[Методы трансляции#Нисходящий разбор|Методы нисходящего разбора]] не в состоянии работать с леворекурсивными грамматиками. Проблема в том, что продукция вида &amp;lt;tex&amp;gt;A \Rightarrow^* A\alpha&amp;lt;/tex&amp;gt; может применяться бесконечно долго, так и не выработав некий терминальный символ, который можно было бы сравнить со строкой. Поэтому требуется преобразование грамматики, которое бы устранило левую рекурсию.&lt;br /&gt;
&lt;br /&gt;
==Устранение непосредственной левой рекурсии==&lt;br /&gt;
Опишем процедуру, устраняющую все правила вида &amp;lt;tex&amp;gt;A \to A\alpha&amp;lt;/tex&amp;gt;, для фиксированного нетерминала &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;ol&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Запишем все правила вывода из &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; в виде: &lt;br /&gt;
&amp;lt;tex&amp;gt;A \to A\alpha_1\,|\,\ldots\,|\,A\alpha_n\,|\,\beta_1\,|\,\ldots\,|\,\beta_m &amp;lt;/tex&amp;gt;, где&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; &amp;lt;tex&amp;gt;\alpha&amp;lt;/tex&amp;gt; {{---}} непустая последовательность терминалов и нетерминалов (&amp;lt;tex&amp;gt;\alpha \nrightarrow \varepsilon &amp;lt;/tex&amp;gt;);&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; &amp;lt;tex&amp;gt;\beta&amp;lt;/tex&amp;gt; {{---}} непустая последовательность терминалов и нетерминалов, не начинающаяся с &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt;.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Заменим правила вывода из &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; на &amp;lt;tex&amp;gt;A \to\beta_1A^\prime\, |\, \ldots\,  |\,  \beta_mA^\prime \,|\, \beta_1 \,|\, \ldots \,|\, \beta_m&amp;lt;/tex&amp;gt;.&amp;lt;/li&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;li&amp;gt;Создадим новый нетерминал &amp;lt;tex&amp;gt;{A^\prime} \to \alpha_1{A^\prime},  |\,  \ldots\, |\, \alpha_n{A^\prime} | \alpha_1\,  |\,  \ldots\, |\, \alpha_n&amp;lt;/tex&amp;gt;. &amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ol&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Изначально нетерминал &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; порождает сроки вида &amp;lt;tex&amp;gt;\beta\alpha_{i0}\alpha_{i1} \ldots \alpha_{ik}&amp;lt;/tex&amp;gt;. В новой грамматике нетерминал &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; порождает &amp;lt;tex&amp;gt;\beta{A^\prime}&amp;lt;/tex&amp;gt;, а &amp;lt;tex&amp;gt;A^\prime&amp;lt;/tex&amp;gt; порождает строки вида &amp;lt;tex&amp;gt;\alpha_{i0}\alpha_{i1} \ldots \alpha_{ik}&amp;lt;/tex&amp;gt;. Из этого очевидно, что изначальная грамматика эквивалентна новой.&lt;br /&gt;
&lt;br /&gt;
===Пример===&lt;br /&gt;
&amp;lt;tex&amp;gt;A \to S\alpha | A\alpha&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;S \to A\beta&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Есть непосредственная левая рекурсия &amp;lt;tex&amp;gt;A \to A\alpha&amp;lt;/tex&amp;gt;. Добавим нетерминал &amp;lt;tex&amp;gt;A^\prime&amp;lt;/tex&amp;gt; и добавим правила &amp;lt;tex&amp;gt;A \to S\alpha{A^{\prime}}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt; A^{\prime} \to \alpha{A^{\prime}} &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Новая грамматика:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;A \to S\alpha{A^{\prime}} | S\alpha&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;A^{\prime} \to \alpha{A^{\prime}}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;S \to A\beta&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
В новой грамматике нет непосредственной левой рекурсии, но нетерминал &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; леворекурсивен, так как есть &amp;lt;tex&amp;gt; A \Rightarrow S\alpha{A^{\prime}} \Rightarrow A\beta\alpha{A^{\prime}} &amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Алгоритм  устранения произвольной левой рекурсии==&lt;br /&gt;
Воспользуемся [[Удаление_eps-правил_из_грамматики | алгоритмом удаления &amp;lt;tex&amp;gt; \varepsilon &amp;lt;/tex&amp;gt;-правил]]. Получим грамматику без &amp;lt;tex&amp;gt; \varepsilon &amp;lt;/tex&amp;gt;-правил для языка &amp;lt;tex&amp;gt;L(\Gamma) \setminus \lbrace \varepsilon \rbrace&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Упорядочим нетерминалы, например по возрастанию индексов, и будем добиваться того, чтобы не было правил вида &amp;lt;tex&amp;gt;A_i \to A_j\alpha&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;j \leqslant i&amp;lt;/tex&amp;gt;.&lt;br /&gt;
Если данное условие выполняется для всех &amp;lt;tex&amp;gt;A_i&amp;lt;/tex&amp;gt;, то в грамматике нет &amp;lt;tex&amp;gt;A_i \to^* A_i&amp;lt;/tex&amp;gt;, а значит не будет левой рекурсии. &lt;br /&gt;
&lt;br /&gt;
Пусть &amp;lt;tex&amp;gt;N = \lbrace A_1, A_2, \ldots , A_n \rbrace&amp;lt;/tex&amp;gt; {{---}} упорядоченное множество всех нетерминалов.&lt;br /&gt;
&lt;br /&gt;
  '''for''' &amp;lt;tex&amp;gt;A_i \in N&amp;lt;/tex&amp;gt;&lt;br /&gt;
    '''for''' &amp;lt;tex&amp;gt;A_j \in \{ N \mid 1 \leqslant j &amp;lt; i \}&amp;lt;/tex&amp;gt;&lt;br /&gt;
      '''for''' &amp;lt;tex&amp;gt;production \in \{A_i \to A_j\gamma \}&amp;lt;/tex&amp;gt;&lt;br /&gt;
        удалить &amp;lt;tex&amp;gt;production&amp;lt;/tex&amp;gt; &amp;lt;font color=darkgreen&amp;gt;#production {{---}} правило вывода&amp;lt;/font&amp;gt;&lt;br /&gt;
        '''for''' &amp;lt;tex&amp;gt;P \to x_i \in \{A_j \to \delta_1 | \ldots | \delta_k\}&amp;lt;/tex&amp;gt;&lt;br /&gt;
          добавить правило &amp;lt;tex&amp;gt;A_i \to x_i\gamma&amp;lt;/tex&amp;gt;&lt;br /&gt;
    устранить непосредственную левую рекурсию для &amp;lt;tex&amp;gt;A_i&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Если &amp;lt;tex&amp;gt;\varepsilon&amp;lt;/tex&amp;gt; присутствовал в языке исходной грамматики, добавим новый начальный символ &amp;lt;tex&amp;gt;S'&amp;lt;/tex&amp;gt; и правила &amp;lt;tex&amp;gt;S' \to S \, | \, \varepsilon &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
После &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; итерации внешнего цикла в любой продукции внешнего цикла в любой продукции вида &amp;lt;tex&amp;gt;A_k \to A_l\alpha, k &amp;lt; i&amp;lt;/tex&amp;gt;, должно быть &amp;lt;tex&amp;gt;l &amp;gt; k&amp;lt;/tex&amp;gt;. В результате при следующей итерации внутреннего цикла растет нижний предел &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; всех продукций вида &amp;lt;tex&amp;gt;A_i \to A_m\alpha&amp;lt;/tex&amp;gt; до тех пор, пока не будет достигнуто &amp;lt;tex&amp;gt;i \leqslant m &amp;lt;/tex&amp;gt;.&lt;br /&gt;
   &lt;br /&gt;
После &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; итерации внешнего цикла в грамматике будут только правила вида &amp;lt;tex&amp;gt;A_i \to A_j\alpha&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;j &amp;gt; i&amp;lt;/tex&amp;gt;.&lt;br /&gt;
Можно заметить, что неравенство становится строгим только после применения алгоритма устранения непосредственной левой рекурсии. При этом добавляются новые нетерминалы. Пусть &amp;lt;tex&amp;gt;{A^\prime}_i &amp;lt;/tex&amp;gt; новый нетерминал. Можно заметить, что нет правила вида &amp;lt;tex&amp;gt;\ldots \to {A^\prime}_i&amp;lt;/tex&amp;gt;, где  &amp;lt;tex&amp;gt;{A^\prime}_i&amp;lt;/tex&amp;gt; самый левый нетерминал, а значит новые нетерминалы можно не рассматривать во внешнем цикле. &lt;br /&gt;
&lt;br /&gt;
На &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; итерации внешнего цикла все правила вида &amp;lt;tex&amp;gt;A_i \to A_j \gamma&amp;lt;/tex&amp;gt; где &amp;lt;tex&amp;gt; j &amp;lt; i &amp;lt;/tex&amp;gt; заменяются на &amp;lt;tex&amp;gt;A_i \to \delta_1\gamma | \ldots | \delta_k\gamma&amp;lt;/tex&amp;gt; где &amp;lt;tex&amp;gt;A_j \to \delta_1 | \ldots | \delta_k&amp;lt;/tex&amp;gt;. Очевидно, что одна итерация алгоритма не меняет язык, а значит язык получившийся в итоге грамматики совпадает с исходным.&lt;br /&gt;
&lt;br /&gt;
===Асимптотика===&lt;br /&gt;
Пусть &amp;lt;tex&amp;gt;a_i&amp;lt;/tex&amp;gt; количество правил для нетерминала &amp;lt;tex&amp;gt;A_i&amp;lt;/tex&amp;gt;.&lt;br /&gt;
Тогда &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; итерация внешнего цикла будет выполняться за &amp;lt;tex&amp;gt;O(\sum\limits_{A_i \to A_j, j &amp;lt; i} a_j) + O(a_i)&amp;lt;/tex&amp;gt;, что меньше чем &amp;lt;tex&amp;gt;O(\sum\limits_{i=1}^n a_j)&amp;lt;/tex&amp;gt;, значит асимптотика алгоритма &amp;lt;tex&amp;gt;O(n\sum\limits_{i=1}^n a_j)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Проблема этого алгоритма в том, что в зависимости от порядка нетерминалов в множестве размер грамматки может получиться экспоненциальным.&lt;br /&gt;
&lt;br /&gt;
Пример грамматики для которой имеет значение порядок нетерминалов&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;A_1 \to 0 | 1&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;A_{i+1} \to {A_i}0 | {A_i}1 &amp;lt;/tex&amp;gt;  для &amp;lt;tex&amp;gt;1 \leqslant i &amp;lt; n&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Упорядочим множество нетерминалов по возрастанию индексов. Легко заметить, что правила для &amp;lt;tex&amp;gt;A_i&amp;lt;/tex&amp;gt; будут представлять из себя все двоичные вектора длины &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;, а значит размер грамматики будет экспоненциальным. Если упорядочить нетерминалы по убыванию в грамматике изменений не будет.&lt;br /&gt;
&lt;br /&gt;
==Пример==&lt;br /&gt;
Дана грамматика:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;A \to S\alpha &amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;S \to S\beta \mid A\gamma \mid \beta&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Среди правил &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; непосредственной рекурсии нет, поэтому во время первой итерации внешнего цикла ничего не происходит. &lt;br /&gt;
Во время второй итерации внешнего цикла правило &amp;lt;tex&amp;gt; S \to A\gamma &amp;lt;/tex&amp;gt; переходит в &amp;lt;tex&amp;gt; S \to S\alpha\gamma &amp;lt;/tex&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
Грамматика имеет вид &lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;A \to S\alpha &amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;S \to{S}{\beta} | {S}{\alpha}{\gamma} | \beta&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Устраняем левую рекурсию для &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt; S \to\beta{S_1}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt; {S_1} \to\beta{S_1} | \alpha\gamma{S_1} | {\beta} | {\alpha}{\gamma} &amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== См. также  ==&lt;br /&gt;
* [[Контекстно-свободные_грамматики,_вывод,_лево-_и_правосторонний_вывод,_дерево_разбора|Контекстно-свободные грамматики]]&lt;br /&gt;
* [[Нормальная_форма_Хомского|Нормальная форма Хомского]]&lt;br /&gt;
* [[Удаление_eps-правил_из_грамматики | Удаления &amp;lt;tex&amp;gt; \varepsilon &amp;lt;/tex&amp;gt;-правил из грамматики]]&lt;br /&gt;
&lt;br /&gt;
== Источники информации ==&lt;br /&gt;
* ''Хопкрофт Д., Мотвани Р., Ульман Д.'' — '''Введение в теорию автоматов, языков и вычислений''', 2-е изд. : Пер. с англ. — Москва, Издательский дом «Вильямс», 2002. — 528 с. : ISBN 5-8459-0261-4 (рус.)&lt;br /&gt;
* ''Robert C. Moore'' — [http://aclweb.org/anthology-new/A/A00/A00-2033.pdf Removing  Left  Recursion  from  Context-Free  Grammars ]&lt;br /&gt;
&lt;br /&gt;
[[Категория: Теория формальных языков]]&lt;br /&gt;
[[Категория: Контекстно-свободные грамматики]]&lt;br /&gt;
[[Категория: Нормальные формы КС-грамматик]]&lt;/div&gt;</summary>
		<author><name>KirillTim</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%A3%D1%81%D1%82%D1%80%D0%B0%D0%BD%D0%B5%D0%BD%D0%B8%D0%B5_%D0%BB%D0%B5%D0%B2%D0%BE%D0%B9_%D1%80%D0%B5%D0%BA%D1%83%D1%80%D1%81%D0%B8%D0%B8&amp;diff=51298</id>
		<title>Устранение левой рекурсии</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A3%D1%81%D1%82%D1%80%D0%B0%D0%BD%D0%B5%D0%BD%D0%B8%D0%B5_%D0%BB%D0%B5%D0%B2%D0%BE%D0%B9_%D1%80%D0%B5%D0%BA%D1%83%D1%80%D1%81%D0%B8%D0%B8&amp;diff=51298"/>
				<updated>2016-01-17T13:30:11Z</updated>
		
		<summary type="html">&lt;p&gt;KirillTim: как упорядочиваем&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Определение&lt;br /&gt;
|definition=Говорят, что [[Контекстно-свободные грамматики, вывод, лево- и правосторонний вывод, дерево разбора|контекстно-свободная (КС) грамматика]] &amp;lt;tex&amp;gt;\Gamma&amp;lt;/tex&amp;gt; содержит '''непосредственную левую рекурсию''' (англ. ''direct left recursion''), если она содержит правило вида &amp;lt;tex&amp;gt;A \to A\alpha&amp;lt;/tex&amp;gt;.&lt;br /&gt;
}}&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition=Говорят, что КС-грамматика &amp;lt;tex&amp;gt;\Gamma&amp;lt;/tex&amp;gt; содержит '''левую рекурсию'''  (англ. ''left recursion''), если в ней существует вывод вида &amp;lt;tex&amp;gt;A \Rightarrow^* A\alpha&amp;lt;/tex&amp;gt;.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
== Постановка задачи ==&lt;br /&gt;
[[Методы трансляции#Нисходящий разбор|Методы нисходящего разбора]] не в состоянии работать с леворекурсивными грамматиками. Проблема в том, что продукция вида &amp;lt;tex&amp;gt;A \Rightarrow^* A\alpha&amp;lt;/tex&amp;gt; может применяться бесконечно долго, так и не выработав некий терминальный символ, который можно было бы сравнить со строкой. Поэтому требуется преобразование грамматики, которое бы устранило левую рекурсию.&lt;br /&gt;
&lt;br /&gt;
==Устранение непосредственной левой рекурсии==&lt;br /&gt;
Опишем процедуру, устраняющую все правила вида &amp;lt;tex&amp;gt;A \to A\alpha&amp;lt;/tex&amp;gt;, для фиксированного нетерминала &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;ol&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Запишем все правила вывода из &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; в виде: &lt;br /&gt;
&amp;lt;tex&amp;gt;A \to A\alpha_1\,|\,\ldots\,|\,A\alpha_n\,|\,\beta_1\,|\,\ldots\,|\,\beta_m &amp;lt;/tex&amp;gt;, где&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; &amp;lt;tex&amp;gt;\alpha&amp;lt;/tex&amp;gt; {{---}} непустая последовательность терминалов и нетерминалов (&amp;lt;tex&amp;gt;\alpha \nrightarrow \varepsilon &amp;lt;/tex&amp;gt;);&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; &amp;lt;tex&amp;gt;\beta&amp;lt;/tex&amp;gt; {{---}} непустая последовательность терминалов и нетерминалов, не начинающаяся с &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt;.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Заменим правила вывода из &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; на &amp;lt;tex&amp;gt;A \to\beta_1A^\prime\, |\, \ldots\,  |\,  \beta_mA^\prime \,|\, \beta_1 \,|\, \ldots \,|\, \beta_m&amp;lt;/tex&amp;gt;.&amp;lt;/li&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;li&amp;gt;Создадим новый нетерминал &amp;lt;tex&amp;gt;{A^\prime} \to \alpha_1{A^\prime},  |\,  \ldots\, |\, \alpha_n{A^\prime} | \alpha_1\,  |\,  \ldots\, |\, \alpha_n&amp;lt;/tex&amp;gt;. &amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ol&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Изначально нетерминал &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; порождает сроки вида &amp;lt;tex&amp;gt;\beta\alpha_{i0}\alpha_{i1} \ldots \alpha_{ik}&amp;lt;/tex&amp;gt;. В новой грамматике нетерминал &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; порождает &amp;lt;tex&amp;gt;\beta{A^\prime}&amp;lt;/tex&amp;gt;, а &amp;lt;tex&amp;gt;A^\prime&amp;lt;/tex&amp;gt; порождает строки вида &amp;lt;tex&amp;gt;\alpha_{i0}\alpha_{i1} \ldots \alpha_{ik}&amp;lt;/tex&amp;gt;. Из этого очевидно, что изначальная грамматика эквивалентна новой.&lt;br /&gt;
&lt;br /&gt;
===Пример===&lt;br /&gt;
&amp;lt;tex&amp;gt;A \to S\alpha | A\alpha&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;S \to A\beta&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Есть непосредственная левая рекурсия &amp;lt;tex&amp;gt;A \to A\alpha&amp;lt;/tex&amp;gt;. Добавим нетерминал &amp;lt;tex&amp;gt;A^\prime&amp;lt;/tex&amp;gt; и добавим правила &amp;lt;tex&amp;gt;A \to S\alpha{A^{\prime}}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt; A^{\prime} \to \alpha{A^{\prime}} &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Новая грамматика:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;A \to S\alpha{A^{\prime}} | S\alpha&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;A^{\prime} \to \alpha{A^{\prime}}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;S \to A\beta&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
В новой грамматике нет непосредственной левой рекурсии, но нетерминал &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; леворекурсивен, так как есть &amp;lt;tex&amp;gt; A \Rightarrow S\alpha{A^{\prime}} \Rightarrow A\beta\alpha{A^{\prime}} &amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Алгоритм  устранения произвольной левой рекурсии==&lt;br /&gt;
Воспользуемся [[Удаление_eps-правил_из_грамматики | алгоритмом удаления &amp;lt;tex&amp;gt; \varepsilon &amp;lt;/tex&amp;gt;-правил]]. Получим грамматику без &amp;lt;tex&amp;gt; \varepsilon &amp;lt;/tex&amp;gt;-правил для языка &amp;lt;tex&amp;gt;L(\Gamma) \setminus \lbrace \varepsilon \rbrace&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Упорядочим нетерминалы, например лексикографически, и будем добиваться того, чтобы не было правил вида &amp;lt;tex&amp;gt;A_i \to A_j\alpha&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;j \leqslant i&amp;lt;/tex&amp;gt;.&lt;br /&gt;
Если данное условие выполняется для всех &amp;lt;tex&amp;gt;A_i&amp;lt;/tex&amp;gt;, то в грамматике нет &amp;lt;tex&amp;gt;A_i \to^* A_i&amp;lt;/tex&amp;gt;, а значит не будет левой рекурсии. &lt;br /&gt;
&lt;br /&gt;
Пусть &amp;lt;tex&amp;gt;N = \lbrace A_1, A_2, \ldots , A_n \rbrace&amp;lt;/tex&amp;gt; {{---}} упорядоченное множество всех нетерминалов.&lt;br /&gt;
&lt;br /&gt;
  '''for''' &amp;lt;tex&amp;gt;A_i \in N&amp;lt;/tex&amp;gt;&lt;br /&gt;
    '''for''' &amp;lt;tex&amp;gt;A_j \in \{ N \mid 1 \leqslant j &amp;lt; i \}&amp;lt;/tex&amp;gt;&lt;br /&gt;
      '''for''' &amp;lt;tex&amp;gt;production \in \{A_i \to A_j\gamma \}&amp;lt;/tex&amp;gt;&lt;br /&gt;
        удалить &amp;lt;tex&amp;gt;production&amp;lt;/tex&amp;gt; &amp;lt;font color=darkgreen&amp;gt;#production {{---}} правило вывода&amp;lt;/font&amp;gt;&lt;br /&gt;
        '''for''' &amp;lt;tex&amp;gt;P \to x_i \in \{A_j \to \delta_1 | \ldots | \delta_k\}&amp;lt;/tex&amp;gt;&lt;br /&gt;
          добавить правило &amp;lt;tex&amp;gt;A_i \to x_i\gamma&amp;lt;/tex&amp;gt;&lt;br /&gt;
    устранить непосредственную левую рекурсию для &amp;lt;tex&amp;gt;A_i&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Если &amp;lt;tex&amp;gt;\varepsilon&amp;lt;/tex&amp;gt; присутствовал в языке исходной грамматики, добавим новый начальный символ &amp;lt;tex&amp;gt;S'&amp;lt;/tex&amp;gt; и правила &amp;lt;tex&amp;gt;S' \to S \, | \, \varepsilon &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
После &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; итерации внешнего цикла в любой продукции внешнего цикла в любой продукции вида &amp;lt;tex&amp;gt;A_k \to A_l\alpha, k &amp;lt; i&amp;lt;/tex&amp;gt;, должно быть &amp;lt;tex&amp;gt;l &amp;gt; k&amp;lt;/tex&amp;gt;. В результате при следующей итерации внутреннего цикла растет нижний предел &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; всех продукций вида &amp;lt;tex&amp;gt;A_i \to A_m\alpha&amp;lt;/tex&amp;gt; до тех пор, пока не будет достигнуто &amp;lt;tex&amp;gt;i \leqslant m &amp;lt;/tex&amp;gt;.&lt;br /&gt;
   &lt;br /&gt;
После &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; итерации внешнего цикла в грамматике будут только правила вида &amp;lt;tex&amp;gt;A_i \to A_j\alpha&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;j &amp;gt; i&amp;lt;/tex&amp;gt;.&lt;br /&gt;
Можно заметить, что неравенство становится строгим только после применения алгоритма устранения непосредственной левой рекурсии. При этом добавляются новые нетерминалы. Пусть &amp;lt;tex&amp;gt;{A^\prime}_i &amp;lt;/tex&amp;gt; новый нетерминал. Можно заметить, что нет правила вида &amp;lt;tex&amp;gt;\ldots \to {A^\prime}_i&amp;lt;/tex&amp;gt;, где  &amp;lt;tex&amp;gt;{A^\prime}_i&amp;lt;/tex&amp;gt; самый левый нетерминал, а значит новые нетерминалы можно не рассматривать во внешнем цикле. &lt;br /&gt;
&lt;br /&gt;
На &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; итерации внешнего цикла все правила вида &amp;lt;tex&amp;gt;A_i \to A_j \gamma&amp;lt;/tex&amp;gt; где &amp;lt;tex&amp;gt; j &amp;lt; i &amp;lt;/tex&amp;gt; заменяются на &amp;lt;tex&amp;gt;A_i \to \delta_1\gamma | \ldots | \delta_k\gamma&amp;lt;/tex&amp;gt; где &amp;lt;tex&amp;gt;A_j \to \delta_1 | \ldots | \delta_k&amp;lt;/tex&amp;gt;. Очевидно, что одна итерация алгоритма не меняет язык, а значит язык получившийся в итоге грамматики совпадает с исходным.&lt;br /&gt;
&lt;br /&gt;
===Асимптотика===&lt;br /&gt;
Пусть &amp;lt;tex&amp;gt;a_i&amp;lt;/tex&amp;gt; количество правил для нетерминала &amp;lt;tex&amp;gt;A_i&amp;lt;/tex&amp;gt;.&lt;br /&gt;
Тогда &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; итерация внешнего цикла будет выполняться за &amp;lt;tex&amp;gt;O(\sum\limits_{A_i \to A_j, j &amp;lt; i} a_j) + O(a_i)&amp;lt;/tex&amp;gt;, что меньше чем &amp;lt;tex&amp;gt;O(\sum\limits_{i=1}^n a_j)&amp;lt;/tex&amp;gt;, значит асимптотика алгоритма &amp;lt;tex&amp;gt;O(n\sum\limits_{i=1}^n a_j)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Проблема этого алгоритма в том, что в зависимости от порядка нетерминалов в множестве размер грамматки может получиться экспоненциальным.&lt;br /&gt;
&lt;br /&gt;
Пример грамматики для которой имеет значение порядок нетерминалов&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;A_1 \to 0 | 1&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;A_{i+1} \to {A_i}0 | {A_i}1 &amp;lt;/tex&amp;gt;  для &amp;lt;tex&amp;gt;1 \leqslant i &amp;lt; n&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Упорядочим множество нетерминалов по возрастанию индексов. Легко заметить, что правила для &amp;lt;tex&amp;gt;A_i&amp;lt;/tex&amp;gt; будут представлять из себя все двоичные вектора длины &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;, а значит размер грамматики будет экспоненциальным. Если упорядочить нетерминалы по убыванию в грамматике изменений не будет.&lt;br /&gt;
&lt;br /&gt;
==Пример==&lt;br /&gt;
Дана грамматика:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;A \to S\alpha &amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;S \to S\beta \mid A\gamma \mid \beta&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Среди правил &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; непосредственной рекурсии нет, поэтому во время первой итерации внешнего цикла ничего не происходит. &lt;br /&gt;
Во время второй итерации внешнего цикла правило &amp;lt;tex&amp;gt; S \to A\gamma &amp;lt;/tex&amp;gt; переходит в &amp;lt;tex&amp;gt; S \to S\alpha\gamma &amp;lt;/tex&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
Грамматика имеет вид &lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;A \to S\alpha &amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;S \to{S}{\beta} | {S}{\alpha}{\gamma} | \beta&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Устраняем левую рекурсию для &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt; S \to\beta{S_1}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt; {S_1} \to\beta{S_1} | \alpha\gamma{S_1} | {\beta} | {\alpha}{\gamma} &amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== См. также  ==&lt;br /&gt;
* [[Контекстно-свободные_грамматики,_вывод,_лево-_и_правосторонний_вывод,_дерево_разбора|Контекстно-свободные грамматики]]&lt;br /&gt;
* [[Нормальная_форма_Хомского|Нормальная форма Хомского]]&lt;br /&gt;
* [[Удаление_eps-правил_из_грамматики | Удаления &amp;lt;tex&amp;gt; \varepsilon &amp;lt;/tex&amp;gt;-правил из грамматики]]&lt;br /&gt;
&lt;br /&gt;
== Источники информации ==&lt;br /&gt;
* ''Хопкрофт Д., Мотвани Р., Ульман Д.'' — '''Введение в теорию автоматов, языков и вычислений''', 2-е изд. : Пер. с англ. — Москва, Издательский дом «Вильямс», 2002. — 528 с. : ISBN 5-8459-0261-4 (рус.)&lt;br /&gt;
* ''Robert C. Moore'' — [http://aclweb.org/anthology-new/A/A00/A00-2033.pdf Removing  Left  Recursion  from  Context-Free  Grammars ]&lt;br /&gt;
&lt;br /&gt;
[[Категория: Теория формальных языков]]&lt;br /&gt;
[[Категория: Контекстно-свободные грамматики]]&lt;br /&gt;
[[Категория: Нормальные формы КС-грамматик]]&lt;/div&gt;</summary>
		<author><name>KirillTim</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%A3%D1%81%D1%82%D1%80%D0%B0%D0%BD%D0%B5%D0%BD%D0%B8%D0%B5_%D0%BB%D0%B5%D0%B2%D0%BE%D0%B9_%D1%80%D0%B5%D0%BA%D1%83%D1%80%D1%81%D0%B8%D0%B8&amp;diff=51283</id>
		<title>Устранение левой рекурсии</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A3%D1%81%D1%82%D1%80%D0%B0%D0%BD%D0%B5%D0%BD%D0%B8%D0%B5_%D0%BB%D0%B5%D0%B2%D0%BE%D0%B9_%D1%80%D0%B5%D0%BA%D1%83%D1%80%D1%81%D0%B8%D0%B8&amp;diff=51283"/>
				<updated>2016-01-17T09:48:37Z</updated>
		
		<summary type="html">&lt;p&gt;KirillTim: добавил комментарий к production&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Определение&lt;br /&gt;
|definition=Говорят, что [[Контекстно-свободные грамматики, вывод, лево- и правосторонний вывод, дерево разбора|контекстно-свободная (КС) грамматика]] &amp;lt;tex&amp;gt;\Gamma&amp;lt;/tex&amp;gt; содержит '''непосредственную левую рекурсию''' (англ. ''direct left recursion''), если она содержит правило вида &amp;lt;tex&amp;gt;A \to A\alpha&amp;lt;/tex&amp;gt;.&lt;br /&gt;
}}&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition=Говорят, что КС-грамматика &amp;lt;tex&amp;gt;\Gamma&amp;lt;/tex&amp;gt; содержит '''левую рекурсию'''  (англ. ''left recursion''), если в ней существует вывод вида &amp;lt;tex&amp;gt;A \Rightarrow^* A\alpha&amp;lt;/tex&amp;gt;.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
== Постановка задачи ==&lt;br /&gt;
[[Методы трансляции#Нисходящий разбор|Методы нисходящего разбора]] не в состоянии работать с леворекурсивными грамматиками. Проблема в том, что продукция вида &amp;lt;tex&amp;gt;A \Rightarrow^* A\alpha&amp;lt;/tex&amp;gt; может применяться бесконечно долго, так и не выработав некий терминальный символ, который можно было бы сравнить со строкой. Поэтому требуется преобразование грамматики, которое бы устранило левую рекурсию.&lt;br /&gt;
&lt;br /&gt;
==Устранение непосредственной левой рекурсии==&lt;br /&gt;
Опишем процедуру, устраняющую все правила вида &amp;lt;tex&amp;gt;A \to A\alpha&amp;lt;/tex&amp;gt;, для фиксированного нетерминала &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;ol&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Запишем все правила вывода из &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; в виде: &lt;br /&gt;
&amp;lt;tex&amp;gt;A \to A\alpha_1\,|\,\ldots\,|\,A\alpha_n\,|\,\beta_1\,|\,\ldots\,|\,\beta_m &amp;lt;/tex&amp;gt;, где&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; &amp;lt;tex&amp;gt;\alpha&amp;lt;/tex&amp;gt; {{---}} непустая последовательность терминалов и нетерминалов (&amp;lt;tex&amp;gt;\alpha \nrightarrow \varepsilon &amp;lt;/tex&amp;gt;);&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; &amp;lt;tex&amp;gt;\beta&amp;lt;/tex&amp;gt; {{---}} непустая последовательность терминалов и нетерминалов, не начинающаяся с &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt;.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Заменим правила вывода из &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; на &amp;lt;tex&amp;gt;A \to\beta_1A^\prime\, |\, \ldots\,  |\,  \beta_mA^\prime \,|\, \beta_1 \,|\, \ldots \,|\, \beta_m&amp;lt;/tex&amp;gt;.&amp;lt;/li&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;li&amp;gt;Создадим новый нетерминал &amp;lt;tex&amp;gt;{A^\prime} \to \alpha_1{A^\prime},  |\,  \ldots\, |\, \alpha_n{A^\prime} | \alpha_1\,  |\,  \ldots\, |\, \alpha_n&amp;lt;/tex&amp;gt;. &amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ol&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Изначально нетерминал &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; порождает сроки вида &amp;lt;tex&amp;gt;\beta\alpha_{i0}\alpha_{i1} \ldots \alpha_{ik}&amp;lt;/tex&amp;gt;. В новой грамматике нетерминал &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; порождает &amp;lt;tex&amp;gt;\beta{A^\prime}&amp;lt;/tex&amp;gt;, а &amp;lt;tex&amp;gt;A^\prime&amp;lt;/tex&amp;gt; порождает строки вида &amp;lt;tex&amp;gt;\alpha_{i0}\alpha_{i1} \ldots \alpha_{ik}&amp;lt;/tex&amp;gt;. Из этого очевидно, что изначальная грамматика эквивалентна новой.&lt;br /&gt;
&lt;br /&gt;
===Пример===&lt;br /&gt;
&amp;lt;tex&amp;gt;A \to S\alpha | A\alpha&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;S \to A\beta&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Есть непосредственная левая рекурсия &amp;lt;tex&amp;gt;A \to A\alpha&amp;lt;/tex&amp;gt;. Добавим нетерминал &amp;lt;tex&amp;gt;A^\prime&amp;lt;/tex&amp;gt; и добавим правила &amp;lt;tex&amp;gt;A \to S\alpha{A^{\prime}}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt; A^{\prime} \to \alpha{A^{\prime}} &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Новая грамматика:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;A \to S\alpha{A^{\prime}} | S\alpha&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;A^{\prime} \to \alpha{A^{\prime}}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;S \to A\beta&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
В новой грамматике нет непосредственной левой рекурсии, но нетерминал &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; леворекурсивен, так как есть &amp;lt;tex&amp;gt; A \Rightarrow S\alpha{A^{\prime}} \Rightarrow A\beta\alpha{A^{\prime}} &amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Алгоритм  устранения произвольной левой рекурсии==&lt;br /&gt;
Воспользуемся [[Удаление_eps-правил_из_грамматики | алгоритмом удаления &amp;lt;tex&amp;gt; \varepsilon &amp;lt;/tex&amp;gt;-правил]]. Получим грамматику без &amp;lt;tex&amp;gt; \varepsilon &amp;lt;/tex&amp;gt;-правил для языка &amp;lt;tex&amp;gt;L(\Gamma) \setminus \lbrace \varepsilon \rbrace&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Упорядочим нетерминалы и будем добиваться того, чтобы не было правил вида &amp;lt;tex&amp;gt;A_i \to A_j\alpha&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;j \leqslant i&amp;lt;/tex&amp;gt;.&lt;br /&gt;
Если данное условие выполняется для всех &amp;lt;tex&amp;gt;A_i&amp;lt;/tex&amp;gt;, то в грамматике нет &amp;lt;tex&amp;gt;A_i \to^* A_i&amp;lt;/tex&amp;gt;, а значит не будет левой рекурсии. &lt;br /&gt;
&lt;br /&gt;
Пусть &amp;lt;tex&amp;gt;N = \lbrace A_1, A_2, \ldots , A_n \rbrace&amp;lt;/tex&amp;gt; {{---}} упорядоченное множество всех нетерминалов.&lt;br /&gt;
&lt;br /&gt;
  '''for''' &amp;lt;tex&amp;gt;A_i \in N&amp;lt;/tex&amp;gt;&lt;br /&gt;
    '''for''' &amp;lt;tex&amp;gt;A_j \in \{ N \mid 1 \leqslant j &amp;lt; i \}&amp;lt;/tex&amp;gt;&lt;br /&gt;
      '''for''' &amp;lt;tex&amp;gt;production \in \{A_i \to A_j\gamma \}&amp;lt;/tex&amp;gt;&lt;br /&gt;
        удалить &amp;lt;tex&amp;gt;production&amp;lt;/tex&amp;gt; &amp;lt;font color=darkgreen&amp;gt;#production {{---}} правило вывода&amp;lt;/font&amp;gt;&lt;br /&gt;
        '''for''' &amp;lt;tex&amp;gt;P \to x_i \in \{A_j \to \delta_1 | \ldots | \delta_k\}&amp;lt;/tex&amp;gt;&lt;br /&gt;
          добавить правило &amp;lt;tex&amp;gt;A_i \to x_i\gamma&amp;lt;/tex&amp;gt;&lt;br /&gt;
    устранить непосредственную левую рекурсию для &amp;lt;tex&amp;gt;A_i&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Если &amp;lt;tex&amp;gt;\varepsilon&amp;lt;/tex&amp;gt; присутствовал в языке исходной грамматики, добавим новый начальный символ &amp;lt;tex&amp;gt;S'&amp;lt;/tex&amp;gt; и правила &amp;lt;tex&amp;gt;S' \to S \, | \, \varepsilon &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
После &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; итерации внешнего цикла в любой продукции внешнего цикла в любой продукции вида &amp;lt;tex&amp;gt;A_k \to A_l\alpha, k &amp;lt; i&amp;lt;/tex&amp;gt;, должно быть &amp;lt;tex&amp;gt;l &amp;gt; k&amp;lt;/tex&amp;gt;. В результате при следующей итерации внутреннего цикла растет нижний предел &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; всех продукций вида &amp;lt;tex&amp;gt;A_i \to A_m\alpha&amp;lt;/tex&amp;gt; до тех пор, пока не будет достигнуто &amp;lt;tex&amp;gt;i \leqslant m &amp;lt;/tex&amp;gt;.&lt;br /&gt;
   &lt;br /&gt;
После &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; итерации внешнего цикла в грамматике будут только правила вида &amp;lt;tex&amp;gt;A_i \to A_j\alpha&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;j &amp;gt; i&amp;lt;/tex&amp;gt;.&lt;br /&gt;
Можно заметить, что неравенство становится строгим только после применения алгоритма устранения непосредственной левой рекурсии. При этом добавляются новые нетерминалы. Пусть &amp;lt;tex&amp;gt;{A^\prime}_i &amp;lt;/tex&amp;gt; новый нетерминал. Можно заметить, что нет правила вида &amp;lt;tex&amp;gt;\ldots \to {A^\prime}_i&amp;lt;/tex&amp;gt;, где  &amp;lt;tex&amp;gt;{A^\prime}_i&amp;lt;/tex&amp;gt; самый левый нетерминал, а значит новые нетерминалы можно не рассматривать во внешнем цикле. &lt;br /&gt;
&lt;br /&gt;
На &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; итерации внешнего цикла все правила вида &amp;lt;tex&amp;gt;A_i \to A_j \gamma&amp;lt;/tex&amp;gt; где &amp;lt;tex&amp;gt; j &amp;lt; i &amp;lt;/tex&amp;gt; заменяются на &amp;lt;tex&amp;gt;A_i \to \delta_1\gamma | \ldots | \delta_k\gamma&amp;lt;/tex&amp;gt; где &amp;lt;tex&amp;gt;A_j \to \delta_1 | \ldots | \delta_k&amp;lt;/tex&amp;gt;. Очевидно, что одна итерация алгоритма не меняет язык, а значит язык получившийся в итоге грамматики совпадает с исходным.&lt;br /&gt;
&lt;br /&gt;
===Асимптотика===&lt;br /&gt;
Пусть &amp;lt;tex&amp;gt;a_i&amp;lt;/tex&amp;gt; количество правил для нетерминала &amp;lt;tex&amp;gt;A_i&amp;lt;/tex&amp;gt;.&lt;br /&gt;
Тогда &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; итерация внешнего цикла будет выполняться за &amp;lt;tex&amp;gt;O(\sum\limits_{A_i \to A_j, j &amp;lt; i} a_j) + O(a_i)&amp;lt;/tex&amp;gt;, что меньше чем &amp;lt;tex&amp;gt;O(\sum\limits_{i=1}^n a_j)&amp;lt;/tex&amp;gt;, значит асимптотика алгоритма &amp;lt;tex&amp;gt;O(n\sum\limits_{i=1}^n a_j)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Проблема этого алгоритма в том, что в зависимости от порядка нетерминалов в множестве размер грамматки может получиться экспоненциальным.&lt;br /&gt;
&lt;br /&gt;
Пример грамматики для которой имеет значение порядок нетерминалов&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;A_1 \to 0 | 1&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;A_{i+1} \to {A_i}0 | {A_i}1 &amp;lt;/tex&amp;gt;  для &amp;lt;tex&amp;gt;1 \leqslant i &amp;lt; n&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Упорядочим множество нетерминалов по возрастанию индексов. Легко заметить, что правила для &amp;lt;tex&amp;gt;A_i&amp;lt;/tex&amp;gt; будут представлять из себя все двоичные вектора длины &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;, а значит размер грамматики будет экспоненциальным. Если упорядочить нетерминалы по убыванию в грамматике изменений не будет.&lt;br /&gt;
&lt;br /&gt;
==Пример==&lt;br /&gt;
Дана грамматика:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;A \to S\alpha &amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;S \to S\beta \mid A\gamma \mid \beta&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Среди правил &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; непосредственной рекурсии нет, поэтому во время первой итерации внешнего цикла ничего не происходит. &lt;br /&gt;
Во время второй итерации внешнего цикла правило &amp;lt;tex&amp;gt; S \to A\gamma &amp;lt;/tex&amp;gt; переходит в &amp;lt;tex&amp;gt; S \to S\alpha\gamma &amp;lt;/tex&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
Грамматика имеет вид &lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;A \to S\alpha &amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;S \to{S}{\beta} | {S}{\alpha}{\gamma} | \beta&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Устраняем левую рекурсию для &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt; S \to\beta{S_1}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt; {S_1} \to\beta{S_1} | \alpha\gamma{S_1} | {\beta} | {\alpha}{\gamma} &amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== См. также  ==&lt;br /&gt;
* [[Контекстно-свободные_грамматики,_вывод,_лево-_и_правосторонний_вывод,_дерево_разбора|Контекстно-свободные грамматики]]&lt;br /&gt;
* [[Нормальная_форма_Хомского|Нормальная форма Хомского]]&lt;br /&gt;
* [[Удаление_eps-правил_из_грамматики | Удаления &amp;lt;tex&amp;gt; \varepsilon &amp;lt;/tex&amp;gt;-правил из грамматики]]&lt;br /&gt;
&lt;br /&gt;
== Источники информации ==&lt;br /&gt;
* ''Хопкрофт Д., Мотвани Р., Ульман Д.'' — '''Введение в теорию автоматов, языков и вычислений''', 2-е изд. : Пер. с англ. — Москва, Издательский дом «Вильямс», 2002. — 528 с. : ISBN 5-8459-0261-4 (рус.)&lt;br /&gt;
* ''Robert C. Moore'' — [http://aclweb.org/anthology-new/A/A00/A00-2033.pdf Removing  Left  Recursion  from  Context-Free  Grammars ]&lt;br /&gt;
&lt;br /&gt;
[[Категория: Теория формальных языков]]&lt;br /&gt;
[[Категория: Контекстно-свободные грамматики]]&lt;br /&gt;
[[Категория: Нормальные формы КС-грамматик]]&lt;/div&gt;</summary>
		<author><name>KirillTim</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%A3%D1%81%D1%82%D1%80%D0%B0%D0%BD%D0%B5%D0%BD%D0%B8%D0%B5_%D0%BB%D0%B5%D0%B2%D0%BE%D0%B9_%D1%80%D0%B5%D0%BA%D1%83%D1%80%D1%81%D0%B8%D0%B8&amp;diff=51282</id>
		<title>Устранение левой рекурсии</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A3%D1%81%D1%82%D1%80%D0%B0%D0%BD%D0%B5%D0%BD%D0%B8%D0%B5_%D0%BB%D0%B5%D0%B2%D0%BE%D0%B9_%D1%80%D0%B5%D0%BA%D1%83%D1%80%D1%81%D0%B8%D0%B8&amp;diff=51282"/>
				<updated>2016-01-17T09:43:11Z</updated>
		
		<summary type="html">&lt;p&gt;KirillTim: /* См. также */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Определение&lt;br /&gt;
|definition=Говорят, что [[Контекстно-свободные грамматики, вывод, лево- и правосторонний вывод, дерево разбора|контекстно-свободная (КС) грамматика]] &amp;lt;tex&amp;gt;\Gamma&amp;lt;/tex&amp;gt; содержит '''непосредственную левую рекурсию''' (англ. ''direct left recursion''), если она содержит правило вида &amp;lt;tex&amp;gt;A \to A\alpha&amp;lt;/tex&amp;gt;.&lt;br /&gt;
}}&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition=Говорят, что КС-грамматика &amp;lt;tex&amp;gt;\Gamma&amp;lt;/tex&amp;gt; содержит '''левую рекурсию'''  (англ. ''left recursion''), если в ней существует вывод вида &amp;lt;tex&amp;gt;A \Rightarrow^* A\alpha&amp;lt;/tex&amp;gt;.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
== Постановка задачи ==&lt;br /&gt;
[[Методы трансляции#Нисходящий разбор|Методы нисходящего разбора]] не в состоянии работать с леворекурсивными грамматиками. Проблема в том, что продукция вида &amp;lt;tex&amp;gt;A \Rightarrow^* A\alpha&amp;lt;/tex&amp;gt; может применяться бесконечно долго, так и не выработав некий терминальный символ, который можно было бы сравнить со строкой. Поэтому требуется преобразование грамматики, которое бы устранило левую рекурсию.&lt;br /&gt;
&lt;br /&gt;
==Устранение непосредственной левой рекурсии==&lt;br /&gt;
Опишем процедуру, устраняющую все правила вида &amp;lt;tex&amp;gt;A \to A\alpha&amp;lt;/tex&amp;gt;, для фиксированного нетерминала &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;ol&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Запишем все правила вывода из &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; в виде: &lt;br /&gt;
&amp;lt;tex&amp;gt;A \to A\alpha_1\,|\,\ldots\,|\,A\alpha_n\,|\,\beta_1\,|\,\ldots\,|\,\beta_m &amp;lt;/tex&amp;gt;, где&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; &amp;lt;tex&amp;gt;\alpha&amp;lt;/tex&amp;gt; {{---}} непустая последовательность терминалов и нетерминалов (&amp;lt;tex&amp;gt;\alpha \nrightarrow \varepsilon &amp;lt;/tex&amp;gt;);&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; &amp;lt;tex&amp;gt;\beta&amp;lt;/tex&amp;gt; {{---}} непустая последовательность терминалов и нетерминалов, не начинающаяся с &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt;.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Заменим правила вывода из &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; на &amp;lt;tex&amp;gt;A \to\beta_1A^\prime\, |\, \ldots\,  |\,  \beta_mA^\prime \,|\, \beta_1 \,|\, \ldots \,|\, \beta_m&amp;lt;/tex&amp;gt;.&amp;lt;/li&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;li&amp;gt;Создадим новый нетерминал &amp;lt;tex&amp;gt;{A^\prime} \to \alpha_1{A^\prime},  |\,  \ldots\, |\, \alpha_n{A^\prime} | \alpha_1\,  |\,  \ldots\, |\, \alpha_n&amp;lt;/tex&amp;gt;. &amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ol&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Изначально нетерминал &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; порождает сроки вида &amp;lt;tex&amp;gt;\beta\alpha_{i0}\alpha_{i1} \ldots \alpha_{ik}&amp;lt;/tex&amp;gt;. В новой грамматике нетерминал &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; порождает &amp;lt;tex&amp;gt;\beta{A^\prime}&amp;lt;/tex&amp;gt;, а &amp;lt;tex&amp;gt;A^\prime&amp;lt;/tex&amp;gt; порождает строки вида &amp;lt;tex&amp;gt;\alpha_{i0}\alpha_{i1} \ldots \alpha_{ik}&amp;lt;/tex&amp;gt;. Из этого очевидно, что изначальная грамматика эквивалентна новой.&lt;br /&gt;
&lt;br /&gt;
===Пример===&lt;br /&gt;
&amp;lt;tex&amp;gt;A \to S\alpha | A\alpha&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;S \to A\beta&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Есть непосредственная левая рекурсия &amp;lt;tex&amp;gt;A \to A\alpha&amp;lt;/tex&amp;gt;. Добавим нетерминал &amp;lt;tex&amp;gt;A^\prime&amp;lt;/tex&amp;gt; и добавим правила &amp;lt;tex&amp;gt;A \to S\alpha{A^{\prime}}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt; A^{\prime} \to \alpha{A^{\prime}} &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Новая грамматика:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;A \to S\alpha{A^{\prime}} | S\alpha&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;A^{\prime} \to \alpha{A^{\prime}}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;S \to A\beta&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
В новой грамматике нет непосредственной левой рекурсии, но нетерминал &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; леворекурсивен, так как есть &amp;lt;tex&amp;gt; A \Rightarrow S\alpha{A^{\prime}} \Rightarrow A\beta\alpha{A^{\prime}} &amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Алгоритм  устранения произвольной левой рекурсии==&lt;br /&gt;
Воспользуемся [[Удаление_eps-правил_из_грамматики | алгоритмом удаления &amp;lt;tex&amp;gt; \varepsilon &amp;lt;/tex&amp;gt;-правил]]. Получим грамматику без &amp;lt;tex&amp;gt; \varepsilon &amp;lt;/tex&amp;gt;-правил для языка &amp;lt;tex&amp;gt;L(\Gamma) \setminus \lbrace \varepsilon \rbrace&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Упорядочим нетерминалы и будем добиваться того, чтобы не было правил вида &amp;lt;tex&amp;gt;A_i \to A_j\alpha&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;j \leqslant i&amp;lt;/tex&amp;gt;.&lt;br /&gt;
Если данное условие выполняется для всех &amp;lt;tex&amp;gt;A_i&amp;lt;/tex&amp;gt;, то в грамматике нет &amp;lt;tex&amp;gt;A_i \to^* A_i&amp;lt;/tex&amp;gt;, а значит не будет левой рекурсии. &lt;br /&gt;
&lt;br /&gt;
Пусть &amp;lt;tex&amp;gt;N = \lbrace A_1, A_2, \ldots , A_n \rbrace&amp;lt;/tex&amp;gt; {{---}} упорядоченное множество всех нетерминалов.&lt;br /&gt;
&lt;br /&gt;
  '''for''' &amp;lt;tex&amp;gt;A_i \in N&amp;lt;/tex&amp;gt;&lt;br /&gt;
    '''for''' &amp;lt;tex&amp;gt;A_j \in \{ N \mid 1 \leqslant j &amp;lt; i \}&amp;lt;/tex&amp;gt;&lt;br /&gt;
      '''for''' &amp;lt;tex&amp;gt;production \in \{A_i \to A_j\gamma \}&amp;lt;/tex&amp;gt;&lt;br /&gt;
        удалить &amp;lt;tex&amp;gt;production&amp;lt;/tex&amp;gt;&lt;br /&gt;
        '''for''' &amp;lt;tex&amp;gt;P \to x_i \in \{A_j \to \delta_1 | \ldots | \delta_k\}&amp;lt;/tex&amp;gt;&lt;br /&gt;
          добавить правило &amp;lt;tex&amp;gt;A_i \to x_i\gamma&amp;lt;/tex&amp;gt;&lt;br /&gt;
    устранить непосредственную левую рекурсию для &amp;lt;tex&amp;gt;A_i&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Если &amp;lt;tex&amp;gt;\varepsilon&amp;lt;/tex&amp;gt; присутствовал в языке исходной грамматики, добавим новый начальный символ &amp;lt;tex&amp;gt;S'&amp;lt;/tex&amp;gt; и правила &amp;lt;tex&amp;gt;S' \to S \, | \, \varepsilon &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
После &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; итерации внешнего цикла в любой продукции внешнего цикла в любой продукции вида &amp;lt;tex&amp;gt;A_k \to A_l\alpha, k &amp;lt; i&amp;lt;/tex&amp;gt;, должно быть &amp;lt;tex&amp;gt;l &amp;gt; k&amp;lt;/tex&amp;gt;. В результате при следующей итерации внутреннего цикла растет нижний предел &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; всех продукций вида &amp;lt;tex&amp;gt;A_i \to A_m\alpha&amp;lt;/tex&amp;gt; до тех пор, пока не будет достигнуто &amp;lt;tex&amp;gt;i \leqslant m &amp;lt;/tex&amp;gt;.&lt;br /&gt;
   &lt;br /&gt;
После &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; итерации внешнего цикла в грамматике будут только правила вида &amp;lt;tex&amp;gt;A_i \to A_j\alpha&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;j &amp;gt; i&amp;lt;/tex&amp;gt;.&lt;br /&gt;
Можно заметить, что неравенство становится строгим только после применения алгоритма устранения непосредственной левой рекурсии. При этом добавляются новые нетерминалы. Пусть &amp;lt;tex&amp;gt;{A^\prime}_i &amp;lt;/tex&amp;gt; новый нетерминал. Можно заметить, что нет правила вида &amp;lt;tex&amp;gt;\ldots \to {A^\prime}_i&amp;lt;/tex&amp;gt;, где  &amp;lt;tex&amp;gt;{A^\prime}_i&amp;lt;/tex&amp;gt; самый левый нетерминал, а значит новые нетерминалы можно не рассматривать во внешнем цикле. &lt;br /&gt;
&lt;br /&gt;
На &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; итерации внешнего цикла все правила вида &amp;lt;tex&amp;gt;A_i \to A_j \gamma&amp;lt;/tex&amp;gt; где &amp;lt;tex&amp;gt; j &amp;lt; i &amp;lt;/tex&amp;gt; заменяются на &amp;lt;tex&amp;gt;A_i \to \delta_1\gamma | \ldots | \delta_k\gamma&amp;lt;/tex&amp;gt; где &amp;lt;tex&amp;gt;A_j \to \delta_1 | \ldots | \delta_k&amp;lt;/tex&amp;gt;. Очевидно, что одна итерация алгоритма не меняет язык, а значит язык получившийся в итоге грамматики совпадает с исходным.&lt;br /&gt;
&lt;br /&gt;
===Асимптотика===&lt;br /&gt;
Пусть &amp;lt;tex&amp;gt;a_i&amp;lt;/tex&amp;gt; количество правил для нетерминала &amp;lt;tex&amp;gt;A_i&amp;lt;/tex&amp;gt;.&lt;br /&gt;
Тогда &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; итерация внешнего цикла будет выполняться за &amp;lt;tex&amp;gt;O(\sum\limits_{A_i \to A_j, j &amp;lt; i} a_j) + O(a_i)&amp;lt;/tex&amp;gt;, что меньше чем &amp;lt;tex&amp;gt;O(\sum\limits_{i=1}^n a_j)&amp;lt;/tex&amp;gt;, значит асимптотика алгоритма &amp;lt;tex&amp;gt;O(n\sum\limits_{i=1}^n a_j)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Проблема этого алгоритма в том, что в зависимости от порядка нетерминалов в множестве размер грамматки может получиться экспоненциальным.&lt;br /&gt;
&lt;br /&gt;
Пример грамматики для которой имеет значение порядок нетерминалов&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;A_1 \to 0 | 1&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;A_{i+1} \to {A_i}0 | {A_i}1 &amp;lt;/tex&amp;gt;  для &amp;lt;tex&amp;gt;1 \leqslant i &amp;lt; n&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Упорядочим множество нетерминалов по возрастанию индексов. Легко заметить, что правила для &amp;lt;tex&amp;gt;A_i&amp;lt;/tex&amp;gt; будут представлять из себя все двоичные вектора длины &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;, а значит размер грамматики будет экспоненциальным. Если упорядочить нетерминалы по убыванию в грамматике изменений не будет.&lt;br /&gt;
&lt;br /&gt;
==Пример==&lt;br /&gt;
Дана грамматика:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;A \to S\alpha &amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;S \to S\beta \mid A\gamma \mid \beta&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Среди правил &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; непосредственной рекурсии нет, поэтому во время первой итерации внешнего цикла ничего не происходит. &lt;br /&gt;
Во время второй итерации внешнего цикла правило &amp;lt;tex&amp;gt; S \to A\gamma &amp;lt;/tex&amp;gt; переходит в &amp;lt;tex&amp;gt; S \to S\alpha\gamma &amp;lt;/tex&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
Грамматика имеет вид &lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;A \to S\alpha &amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;S \to{S}{\beta} | {S}{\alpha}{\gamma} | \beta&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Устраняем левую рекурсию для &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt; S \to\beta{S_1}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt; {S_1} \to\beta{S_1} | \alpha\gamma{S_1} | {\beta} | {\alpha}{\gamma} &amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== См. также  ==&lt;br /&gt;
* [[Контекстно-свободные_грамматики,_вывод,_лево-_и_правосторонний_вывод,_дерево_разбора|Контекстно-свободные грамматики]]&lt;br /&gt;
* [[Нормальная_форма_Хомского|Нормальная форма Хомского]]&lt;br /&gt;
* [[Удаление_eps-правил_из_грамматики | Удаления &amp;lt;tex&amp;gt; \varepsilon &amp;lt;/tex&amp;gt;-правил из грамматики]]&lt;br /&gt;
&lt;br /&gt;
== Источники информации ==&lt;br /&gt;
* ''Хопкрофт Д., Мотвани Р., Ульман Д.'' — '''Введение в теорию автоматов, языков и вычислений''', 2-е изд. : Пер. с англ. — Москва, Издательский дом «Вильямс», 2002. — 528 с. : ISBN 5-8459-0261-4 (рус.)&lt;br /&gt;
* ''Robert C. Moore'' — [http://aclweb.org/anthology-new/A/A00/A00-2033.pdf Removing  Left  Recursion  from  Context-Free  Grammars ]&lt;br /&gt;
&lt;br /&gt;
[[Категория: Теория формальных языков]]&lt;br /&gt;
[[Категория: Контекстно-свободные грамматики]]&lt;br /&gt;
[[Категория: Нормальные формы КС-грамматик]]&lt;/div&gt;</summary>
		<author><name>KirillTim</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%A3%D1%81%D1%82%D1%80%D0%B0%D0%BD%D0%B5%D0%BD%D0%B8%D0%B5_%D0%BB%D0%B5%D0%B2%D0%BE%D0%B9_%D1%80%D0%B5%D0%BA%D1%83%D1%80%D1%81%D0%B8%D0%B8&amp;diff=51281</id>
		<title>Устранение левой рекурсии</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A3%D1%81%D1%82%D1%80%D0%B0%D0%BD%D0%B5%D0%BD%D0%B8%D0%B5_%D0%BB%D0%B5%D0%B2%D0%BE%D0%B9_%D1%80%D0%B5%D0%BA%D1%83%D1%80%D1%81%D0%B8%D0%B8&amp;diff=51281"/>
				<updated>2016-01-17T09:41:58Z</updated>
		
		<summary type="html">&lt;p&gt;KirillTim: добавил см. также&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Определение&lt;br /&gt;
|definition=Говорят, что [[Контекстно-свободные грамматики, вывод, лево- и правосторонний вывод, дерево разбора|контекстно-свободная (КС) грамматика]] &amp;lt;tex&amp;gt;\Gamma&amp;lt;/tex&amp;gt; содержит '''непосредственную левую рекурсию''' (англ. ''direct left recursion''), если она содержит правило вида &amp;lt;tex&amp;gt;A \to A\alpha&amp;lt;/tex&amp;gt;.&lt;br /&gt;
}}&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition=Говорят, что КС-грамматика &amp;lt;tex&amp;gt;\Gamma&amp;lt;/tex&amp;gt; содержит '''левую рекурсию'''  (англ. ''left recursion''), если в ней существует вывод вида &amp;lt;tex&amp;gt;A \Rightarrow^* A\alpha&amp;lt;/tex&amp;gt;.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
== Постановка задачи ==&lt;br /&gt;
[[Методы трансляции#Нисходящий разбор|Методы нисходящего разбора]] не в состоянии работать с леворекурсивными грамматиками. Проблема в том, что продукция вида &amp;lt;tex&amp;gt;A \Rightarrow^* A\alpha&amp;lt;/tex&amp;gt; может применяться бесконечно долго, так и не выработав некий терминальный символ, который можно было бы сравнить со строкой. Поэтому требуется преобразование грамматики, которое бы устранило левую рекурсию.&lt;br /&gt;
&lt;br /&gt;
==Устранение непосредственной левой рекурсии==&lt;br /&gt;
Опишем процедуру, устраняющую все правила вида &amp;lt;tex&amp;gt;A \to A\alpha&amp;lt;/tex&amp;gt;, для фиксированного нетерминала &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;ol&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Запишем все правила вывода из &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; в виде: &lt;br /&gt;
&amp;lt;tex&amp;gt;A \to A\alpha_1\,|\,\ldots\,|\,A\alpha_n\,|\,\beta_1\,|\,\ldots\,|\,\beta_m &amp;lt;/tex&amp;gt;, где&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; &amp;lt;tex&amp;gt;\alpha&amp;lt;/tex&amp;gt; {{---}} непустая последовательность терминалов и нетерминалов (&amp;lt;tex&amp;gt;\alpha \nrightarrow \varepsilon &amp;lt;/tex&amp;gt;);&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; &amp;lt;tex&amp;gt;\beta&amp;lt;/tex&amp;gt; {{---}} непустая последовательность терминалов и нетерминалов, не начинающаяся с &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt;.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Заменим правила вывода из &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; на &amp;lt;tex&amp;gt;A \to\beta_1A^\prime\, |\, \ldots\,  |\,  \beta_mA^\prime \,|\, \beta_1 \,|\, \ldots \,|\, \beta_m&amp;lt;/tex&amp;gt;.&amp;lt;/li&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;li&amp;gt;Создадим новый нетерминал &amp;lt;tex&amp;gt;{A^\prime} \to \alpha_1{A^\prime},  |\,  \ldots\, |\, \alpha_n{A^\prime} | \alpha_1\,  |\,  \ldots\, |\, \alpha_n&amp;lt;/tex&amp;gt;. &amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ol&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Изначально нетерминал &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; порождает сроки вида &amp;lt;tex&amp;gt;\beta\alpha_{i0}\alpha_{i1} \ldots \alpha_{ik}&amp;lt;/tex&amp;gt;. В новой грамматике нетерминал &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; порождает &amp;lt;tex&amp;gt;\beta{A^\prime}&amp;lt;/tex&amp;gt;, а &amp;lt;tex&amp;gt;A^\prime&amp;lt;/tex&amp;gt; порождает строки вида &amp;lt;tex&amp;gt;\alpha_{i0}\alpha_{i1} \ldots \alpha_{ik}&amp;lt;/tex&amp;gt;. Из этого очевидно, что изначальная грамматика эквивалентна новой.&lt;br /&gt;
&lt;br /&gt;
===Пример===&lt;br /&gt;
&amp;lt;tex&amp;gt;A \to S\alpha | A\alpha&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;S \to A\beta&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Есть непосредственная левая рекурсия &amp;lt;tex&amp;gt;A \to A\alpha&amp;lt;/tex&amp;gt;. Добавим нетерминал &amp;lt;tex&amp;gt;A^\prime&amp;lt;/tex&amp;gt; и добавим правила &amp;lt;tex&amp;gt;A \to S\alpha{A^{\prime}}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt; A^{\prime} \to \alpha{A^{\prime}} &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Новая грамматика:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;A \to S\alpha{A^{\prime}} | S\alpha&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;A^{\prime} \to \alpha{A^{\prime}}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;S \to A\beta&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
В новой грамматике нет непосредственной левой рекурсии, но нетерминал &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; леворекурсивен, так как есть &amp;lt;tex&amp;gt; A \Rightarrow S\alpha{A^{\prime}} \Rightarrow A\beta\alpha{A^{\prime}} &amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Алгоритм  устранения произвольной левой рекурсии==&lt;br /&gt;
Воспользуемся [[Удаление_eps-правил_из_грамматики | алгоритмом удаления &amp;lt;tex&amp;gt; \varepsilon &amp;lt;/tex&amp;gt;-правил]]. Получим грамматику без &amp;lt;tex&amp;gt; \varepsilon &amp;lt;/tex&amp;gt;-правил для языка &amp;lt;tex&amp;gt;L(\Gamma) \setminus \lbrace \varepsilon \rbrace&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Упорядочим нетерминалы и будем добиваться того, чтобы не было правил вида &amp;lt;tex&amp;gt;A_i \to A_j\alpha&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;j \leqslant i&amp;lt;/tex&amp;gt;.&lt;br /&gt;
Если данное условие выполняется для всех &amp;lt;tex&amp;gt;A_i&amp;lt;/tex&amp;gt;, то в грамматике нет &amp;lt;tex&amp;gt;A_i \to^* A_i&amp;lt;/tex&amp;gt;, а значит не будет левой рекурсии. &lt;br /&gt;
&lt;br /&gt;
Пусть &amp;lt;tex&amp;gt;N = \lbrace A_1, A_2, \ldots , A_n \rbrace&amp;lt;/tex&amp;gt; {{---}} упорядоченное множество всех нетерминалов.&lt;br /&gt;
&lt;br /&gt;
  '''for''' &amp;lt;tex&amp;gt;A_i \in N&amp;lt;/tex&amp;gt;&lt;br /&gt;
    '''for''' &amp;lt;tex&amp;gt;A_j \in \{ N \mid 1 \leqslant j &amp;lt; i \}&amp;lt;/tex&amp;gt;&lt;br /&gt;
      '''for''' &amp;lt;tex&amp;gt;production \in \{A_i \to A_j\gamma \}&amp;lt;/tex&amp;gt;&lt;br /&gt;
        удалить &amp;lt;tex&amp;gt;production&amp;lt;/tex&amp;gt;&lt;br /&gt;
        '''for''' &amp;lt;tex&amp;gt;P \to x_i \in \{A_j \to \delta_1 | \ldots | \delta_k\}&amp;lt;/tex&amp;gt;&lt;br /&gt;
          добавить правило &amp;lt;tex&amp;gt;A_i \to x_i\gamma&amp;lt;/tex&amp;gt;&lt;br /&gt;
    устранить непосредственную левую рекурсию для &amp;lt;tex&amp;gt;A_i&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Если &amp;lt;tex&amp;gt;\varepsilon&amp;lt;/tex&amp;gt; присутствовал в языке исходной грамматики, добавим новый начальный символ &amp;lt;tex&amp;gt;S'&amp;lt;/tex&amp;gt; и правила &amp;lt;tex&amp;gt;S' \to S \, | \, \varepsilon &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
После &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; итерации внешнего цикла в любой продукции внешнего цикла в любой продукции вида &amp;lt;tex&amp;gt;A_k \to A_l\alpha, k &amp;lt; i&amp;lt;/tex&amp;gt;, должно быть &amp;lt;tex&amp;gt;l &amp;gt; k&amp;lt;/tex&amp;gt;. В результате при следующей итерации внутреннего цикла растет нижний предел &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; всех продукций вида &amp;lt;tex&amp;gt;A_i \to A_m\alpha&amp;lt;/tex&amp;gt; до тех пор, пока не будет достигнуто &amp;lt;tex&amp;gt;i \leqslant m &amp;lt;/tex&amp;gt;.&lt;br /&gt;
   &lt;br /&gt;
После &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; итерации внешнего цикла в грамматике будут только правила вида &amp;lt;tex&amp;gt;A_i \to A_j\alpha&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;j &amp;gt; i&amp;lt;/tex&amp;gt;.&lt;br /&gt;
Можно заметить, что неравенство становится строгим только после применения алгоритма устранения непосредственной левой рекурсии. При этом добавляются новые нетерминалы. Пусть &amp;lt;tex&amp;gt;{A^\prime}_i &amp;lt;/tex&amp;gt; новый нетерминал. Можно заметить, что нет правила вида &amp;lt;tex&amp;gt;\ldots \to {A^\prime}_i&amp;lt;/tex&amp;gt;, где  &amp;lt;tex&amp;gt;{A^\prime}_i&amp;lt;/tex&amp;gt; самый левый нетерминал, а значит новые нетерминалы можно не рассматривать во внешнем цикле. &lt;br /&gt;
&lt;br /&gt;
На &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; итерации внешнего цикла все правила вида &amp;lt;tex&amp;gt;A_i \to A_j \gamma&amp;lt;/tex&amp;gt; где &amp;lt;tex&amp;gt; j &amp;lt; i &amp;lt;/tex&amp;gt; заменяются на &amp;lt;tex&amp;gt;A_i \to \delta_1\gamma | \ldots | \delta_k\gamma&amp;lt;/tex&amp;gt; где &amp;lt;tex&amp;gt;A_j \to \delta_1 | \ldots | \delta_k&amp;lt;/tex&amp;gt;. Очевидно, что одна итерация алгоритма не меняет язык, а значит язык получившийся в итоге грамматики совпадает с исходным.&lt;br /&gt;
&lt;br /&gt;
===Асимптотика===&lt;br /&gt;
Пусть &amp;lt;tex&amp;gt;a_i&amp;lt;/tex&amp;gt; количество правил для нетерминала &amp;lt;tex&amp;gt;A_i&amp;lt;/tex&amp;gt;.&lt;br /&gt;
Тогда &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; итерация внешнего цикла будет выполняться за &amp;lt;tex&amp;gt;O(\sum\limits_{A_i \to A_j, j &amp;lt; i} a_j) + O(a_i)&amp;lt;/tex&amp;gt;, что меньше чем &amp;lt;tex&amp;gt;O(\sum\limits_{i=1}^n a_j)&amp;lt;/tex&amp;gt;, значит асимптотика алгоритма &amp;lt;tex&amp;gt;O(n\sum\limits_{i=1}^n a_j)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Проблема этого алгоритма в том, что в зависимости от порядка нетерминалов в множестве размер грамматки может получиться экспоненциальным.&lt;br /&gt;
&lt;br /&gt;
Пример грамматики для которой имеет значение порядок нетерминалов&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;A_1 \to 0 | 1&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;A_{i+1} \to {A_i}0 | {A_i}1 &amp;lt;/tex&amp;gt;  для &amp;lt;tex&amp;gt;1 \leqslant i &amp;lt; n&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Упорядочим множество нетерминалов по возрастанию индексов. Легко заметить, что правила для &amp;lt;tex&amp;gt;A_i&amp;lt;/tex&amp;gt; будут представлять из себя все двоичные вектора длины &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;, а значит размер грамматики будет экспоненциальным. Если упорядочить нетерминалы по убыванию в грамматике изменений не будет.&lt;br /&gt;
&lt;br /&gt;
==Пример==&lt;br /&gt;
Дана грамматика:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;A \to S\alpha &amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;S \to S\beta \mid A\gamma \mid \beta&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Среди правил &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; непосредственной рекурсии нет, поэтому во время первой итерации внешнего цикла ничего не происходит. &lt;br /&gt;
Во время второй итерации внешнего цикла правило &amp;lt;tex&amp;gt; S \to A\gamma &amp;lt;/tex&amp;gt; переходит в &amp;lt;tex&amp;gt; S \to S\alpha\gamma &amp;lt;/tex&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
Грамматика имеет вид &lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;A \to S\alpha &amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;S \to{S}{\beta} | {S}{\alpha}{\gamma} | \beta&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Устраняем левую рекурсию для &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt; S \to\beta{S_1}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt; {S_1} \to\beta{S_1} | \alpha\gamma{S_1} | {\beta} | {\alpha}{\gamma} &amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== См. также  ==&lt;br /&gt;
* [[Контекстно-свободные_грамматики,_вывод,_лево-_и_правосторонний_вывод,_дерево_разбора|Контекстно-свободные грамматики]]&lt;br /&gt;
* [[Нормальная_форма_Хомского|Нормальная форма Хомского]]&lt;br /&gt;
* [[Удаление_eps-правил_из_грамматики | Удаления &amp;lt;tex&amp;gt; \varepsilon &amp;lt;/tex&amp;gt;-правил из грамматики]]&lt;br /&gt;
* [[Методы трансляции#Нисходящий разбор|Методы нисходящего разбора]]&lt;br /&gt;
&lt;br /&gt;
== Источники информации ==&lt;br /&gt;
* ''Хопкрофт Д., Мотвани Р., Ульман Д.'' — '''Введение в теорию автоматов, языков и вычислений''', 2-е изд. : Пер. с англ. — Москва, Издательский дом «Вильямс», 2002. — 528 с. : ISBN 5-8459-0261-4 (рус.)&lt;br /&gt;
* ''Robert C. Moore'' — [http://aclweb.org/anthology-new/A/A00/A00-2033.pdf Removing  Left  Recursion  from  Context-Free  Grammars ]&lt;br /&gt;
&lt;br /&gt;
[[Категория: Теория формальных языков]]&lt;br /&gt;
[[Категория: Контекстно-свободные грамматики]]&lt;br /&gt;
[[Категория: Нормальные формы КС-грамматик]]&lt;/div&gt;</summary>
		<author><name>KirillTim</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%A3%D1%81%D1%82%D1%80%D0%B0%D0%BD%D0%B5%D0%BD%D0%B8%D0%B5_%D0%BB%D0%B5%D0%B2%D0%BE%D0%B9_%D1%80%D0%B5%D0%BA%D1%83%D1%80%D1%81%D0%B8%D0%B8&amp;diff=51280</id>
		<title>Устранение левой рекурсии</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A3%D1%81%D1%82%D1%80%D0%B0%D0%BD%D0%B5%D0%BD%D0%B8%D0%B5_%D0%BB%D0%B5%D0%B2%D0%BE%D0%B9_%D1%80%D0%B5%D0%BA%D1%83%D1%80%D1%81%D0%B8%D0%B8&amp;diff=51280"/>
				<updated>2016-01-17T09:33:02Z</updated>
		
		<summary type="html">&lt;p&gt;KirillTim: много мелких правок&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Определение&lt;br /&gt;
|definition=Говорят, что [[Контекстно-свободные грамматики, вывод, лево- и правосторонний вывод, дерево разбора|контекстно-свободная (КС) грамматика]] &amp;lt;tex&amp;gt;\Gamma&amp;lt;/tex&amp;gt; содержит '''непосредственную левую рекурсию''' (англ. ''direct left recursion''), если она содержит правило вида &amp;lt;tex&amp;gt;A \to A\alpha&amp;lt;/tex&amp;gt;.&lt;br /&gt;
}}&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition=Говорят, что КС-грамматика &amp;lt;tex&amp;gt;\Gamma&amp;lt;/tex&amp;gt; содержит '''левую рекурсию'''  (англ. ''left recursion''), если в ней существует вывод вида &amp;lt;tex&amp;gt;A \Rightarrow^* A\alpha&amp;lt;/tex&amp;gt;.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
== Постановка задачи ==&lt;br /&gt;
[[Методы трансляции#Нисходящий разбор|Методы нисходящего разбора]] не в состоянии работать с леворекурсивными грамматиками. Проблема в том, что продукция вида &amp;lt;tex&amp;gt;A \Rightarrow^* A\alpha&amp;lt;/tex&amp;gt; может применяться бесконечно долго, так и не выработав некий терминальный символ, который можно было бы сравнить со строкой. Поэтому требуется преобразование грамматики, которое бы устранило левую рекурсию.&lt;br /&gt;
&lt;br /&gt;
==Устранение непосредственной левой рекурсии==&lt;br /&gt;
Опишем процедуру, устраняющую все правила вида &amp;lt;tex&amp;gt;A \to A\alpha&amp;lt;/tex&amp;gt;, для фиксированного нетерминала &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;ol&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Запишем все правила вывода из &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; в виде: &lt;br /&gt;
&amp;lt;tex&amp;gt;A \to A\alpha_1\,|\,\ldots\,|\,A\alpha_n\,|\,\beta_1\,|\,\ldots\,|\,\beta_m &amp;lt;/tex&amp;gt;, где&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; &amp;lt;tex&amp;gt;\alpha&amp;lt;/tex&amp;gt; {{---}} непустая последовательность терминалов и нетерминалов (&amp;lt;tex&amp;gt;\alpha \nrightarrow \varepsilon &amp;lt;/tex&amp;gt;);&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; &amp;lt;tex&amp;gt;\beta&amp;lt;/tex&amp;gt; {{---}} непустая последовательность терминалов и нетерминалов, не начинающаяся с &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt;.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Заменим правила вывода из &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; на &amp;lt;tex&amp;gt;A \to\beta_1A^\prime\, |\, \ldots\,  |\,  \beta_mA^\prime \,|\, \beta_1 \,|\, \ldots \,|\, \beta_m&amp;lt;/tex&amp;gt;.&amp;lt;/li&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;li&amp;gt;Создадим новый нетерминал &amp;lt;tex&amp;gt;{A^\prime} \to \alpha_1{A^\prime},  |\,  \ldots\, |\, \alpha_n{A^\prime} | \alpha_1\,  |\,  \ldots\, |\, \alpha_n&amp;lt;/tex&amp;gt;. &amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ol&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Изначально нетерминал &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; порождает сроки вида &amp;lt;tex&amp;gt;\beta\alpha_{i0}\alpha_{i1} \ldots \alpha_{ik}&amp;lt;/tex&amp;gt;. В новой грамматике нетерминал &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; порождает &amp;lt;tex&amp;gt;\beta{A^\prime}&amp;lt;/tex&amp;gt;, а &amp;lt;tex&amp;gt;A^\prime&amp;lt;/tex&amp;gt; порождает строки вида &amp;lt;tex&amp;gt;\alpha_{i0}\alpha_{i1} \ldots \alpha_{ik}&amp;lt;/tex&amp;gt;. Из этого очевидно, что изначальная грамматика эквивалентна новой.&lt;br /&gt;
&lt;br /&gt;
===Пример===&lt;br /&gt;
&amp;lt;tex&amp;gt;A \to S\alpha | A\alpha&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;S \to A\beta&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Есть непосредственная левая рекурсия &amp;lt;tex&amp;gt;A \to A\alpha&amp;lt;/tex&amp;gt;. Добавим нетерминал &amp;lt;tex&amp;gt;A^\prime&amp;lt;/tex&amp;gt; и добавим правила &amp;lt;tex&amp;gt;A \to S\alpha{A^{\prime}}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt; A^{\prime} \to \alpha{A^{\prime}} &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Новая грамматика:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;A \to S\alpha{A^{\prime}} | S\alpha&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;A^{\prime} \to \alpha{A^{\prime}}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;S \to A\beta&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
В новой грамматике нет непосредственной левой рекурсии, но нетерминал &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; леворекурсивен, так как есть &amp;lt;tex&amp;gt; A \Rightarrow S\alpha{A^{\prime}} \Rightarrow A\beta\alpha{A^{\prime}} &amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Алгоритм  устранения произвольной левой рекурсии==&lt;br /&gt;
Воспользуемся [[Удаление_eps-правил_из_грамматики | алгоритмом удаления &amp;lt;tex&amp;gt; \varepsilon &amp;lt;/tex&amp;gt;-правил]]. Получим грамматику без &amp;lt;tex&amp;gt; \varepsilon &amp;lt;/tex&amp;gt;-правил для языка &amp;lt;tex&amp;gt;L(\Gamma) \setminus \lbrace \varepsilon \rbrace&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Упорядочим нетерминалы и будем добиваться того, чтобы не было правил вида &amp;lt;tex&amp;gt;A_i \to A_j\alpha&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;j \leqslant i&amp;lt;/tex&amp;gt;.&lt;br /&gt;
Если данное условие выполняется для всех &amp;lt;tex&amp;gt;A_i&amp;lt;/tex&amp;gt;, то в грамматике нет &amp;lt;tex&amp;gt;A_i \to^* A_i&amp;lt;/tex&amp;gt;, а значит не будет левой рекурсии. &lt;br /&gt;
&lt;br /&gt;
Пусть &amp;lt;tex&amp;gt;N = \lbrace A_1, A_2, \ldots , A_n \rbrace&amp;lt;/tex&amp;gt; {{---}} упорядоченное множество всех нетерминалов.&lt;br /&gt;
&lt;br /&gt;
  '''for''' &amp;lt;tex&amp;gt;A_i \in N&amp;lt;/tex&amp;gt;&lt;br /&gt;
    '''for''' &amp;lt;tex&amp;gt;A_j \in \{ N \mid 1 \leqslant j &amp;lt; i \}&amp;lt;/tex&amp;gt;&lt;br /&gt;
      '''for''' &amp;lt;tex&amp;gt;production \in \{A_i \to A_j\gamma \}&amp;lt;/tex&amp;gt;&lt;br /&gt;
        удалить &amp;lt;tex&amp;gt;production&amp;lt;/tex&amp;gt;&lt;br /&gt;
        '''for''' &amp;lt;tex&amp;gt;P \to x_i \in \{A_j \to \delta_1 | \ldots | \delta_k\}&amp;lt;/tex&amp;gt;&lt;br /&gt;
          добавить правило &amp;lt;tex&amp;gt;A_i \to x_i\gamma&amp;lt;/tex&amp;gt;&lt;br /&gt;
    устранить непосредственную левую рекурсию для &amp;lt;tex&amp;gt;A_i&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Если &amp;lt;tex&amp;gt;\varepsilon&amp;lt;/tex&amp;gt; присутствовал в языке исходной грамматики, добавим новый начальный символ &amp;lt;tex&amp;gt;S'&amp;lt;/tex&amp;gt; и правила &amp;lt;tex&amp;gt;S' \to S \, | \, \varepsilon &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
После &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; итерации внешнего цикла в любой продукции внешнего цикла в любой продукции вида &amp;lt;tex&amp;gt;A_k \to A_l\alpha, k &amp;lt; i&amp;lt;/tex&amp;gt;, должно быть &amp;lt;tex&amp;gt;l &amp;gt; k&amp;lt;/tex&amp;gt;. В результате при следующей итерации внутреннего цикла растет нижний предел &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; всех продукций вида &amp;lt;tex&amp;gt;A_i \to A_m\alpha&amp;lt;/tex&amp;gt; до тех пор, пока не будет достигнуто &amp;lt;tex&amp;gt;i \leqslant m &amp;lt;/tex&amp;gt;.&lt;br /&gt;
   &lt;br /&gt;
После &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; итерации внешнего цикла в грамматике будут только правила вида &amp;lt;tex&amp;gt;A_i \to A_j\alpha&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;j &amp;gt; i&amp;lt;/tex&amp;gt;.&lt;br /&gt;
Можно заметить, что неравенство становится строгим только после применения алгоритма устранения непосредственной левой рекурсии. При этом добавляются новые нетерминалы. Пусть &amp;lt;tex&amp;gt;{A^\prime}_i &amp;lt;/tex&amp;gt; новый нетерминал. Можно заметить, что нет правила вида &amp;lt;tex&amp;gt;\ldots \to {A^\prime}_i&amp;lt;/tex&amp;gt;, где  &amp;lt;tex&amp;gt;{A^\prime}_i&amp;lt;/tex&amp;gt; самый левый нетерминал, а значит новые нетерминалы можно не рассматривать во внешнем цикле. &lt;br /&gt;
&lt;br /&gt;
На &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; итерации внешнего цикла все правила вида &amp;lt;tex&amp;gt;A_i \to A_j \gamma&amp;lt;/tex&amp;gt; где &amp;lt;tex&amp;gt; j &amp;lt; i &amp;lt;/tex&amp;gt; заменяются на &amp;lt;tex&amp;gt;A_i \to \delta_1\gamma | \ldots | \delta_k\gamma&amp;lt;/tex&amp;gt; где &amp;lt;tex&amp;gt;A_j \to \delta_1 | \ldots | \delta_k&amp;lt;/tex&amp;gt;. Очевидно, что одна итерация алгоритма не меняет язык, а значит язык получившийся в итоге грамматики совпадает с исходным.&lt;br /&gt;
&lt;br /&gt;
===Асимптотика===&lt;br /&gt;
Пусть &amp;lt;tex&amp;gt;a_i&amp;lt;/tex&amp;gt; количество правил для нетерминала &amp;lt;tex&amp;gt;A_i&amp;lt;/tex&amp;gt;.&lt;br /&gt;
Тогда &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; итерация внешнего цикла будет выполняться за &amp;lt;tex&amp;gt;O(\sum\limits_{A_i \to A_j, j &amp;lt; i} a_j) + O(a_i)&amp;lt;/tex&amp;gt;, что меньше чем &amp;lt;tex&amp;gt;O(\sum\limits_{i=1}^n a_j)&amp;lt;/tex&amp;gt;, значит асимптотика алгоритма &amp;lt;tex&amp;gt;O(n\sum\limits_{i=1}^n a_j)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Проблема этого алгоритма в том, что в зависимости от порядка нетерминалов в множестве размер грамматки может получиться экспоненциальным.&lt;br /&gt;
&lt;br /&gt;
Пример грамматики для которой имеет значение порядок нетерминалов&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;A_1 \to 0 | 1&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;A_{i+1} \to {A_i}0 | {A_i}1 &amp;lt;/tex&amp;gt;  для &amp;lt;tex&amp;gt;1 \leqslant i &amp;lt; n&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Упорядочим множество нетерминалов по возрастанию индексов. Легко заметить, что правила для &amp;lt;tex&amp;gt;A_i&amp;lt;/tex&amp;gt; будут представлять из себя все двоичные вектора длины &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;, а значит размер грамматики будет экспоненциальным. Если упорядочить нетерминалы по убыванию в грамматике изменений не будет.&lt;br /&gt;
&lt;br /&gt;
==Пример==&lt;br /&gt;
Дана грамматика:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;A \to S\alpha &amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;S \to S\beta \mid A\gamma \mid \beta&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Среди правил &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; непосредственной рекурсии нет, поэтому во время первой итерации внешнего цикла ничего не происходит. &lt;br /&gt;
Во время второй итерации внешнего цикла правило &amp;lt;tex&amp;gt; S \to A\gamma &amp;lt;/tex&amp;gt; переходит в &amp;lt;tex&amp;gt; S \to S\alpha\gamma &amp;lt;/tex&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
Грамматика имеет вид &lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;A \to S\alpha &amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;S \to{S}{\beta} | {S}{\alpha}{\gamma} | \beta&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Устраняем левую рекурсию для &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt; S \to\beta{S_1}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt; {S_1} \to\beta{S_1} | \alpha\gamma{S_1} | {\beta} | {\alpha}{\gamma} &amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Источники информации ==&lt;br /&gt;
* ''Хопкрофт Д., Мотвани Р., Ульман Д.'' — '''Введение в теорию автоматов, языков и вычислений''', 2-е изд. : Пер. с англ. — Москва, Издательский дом «Вильямс», 2002. — 528 с. : ISBN 5-8459-0261-4 (рус.)&lt;br /&gt;
* ''Robert C. Moore'' — [http://aclweb.org/anthology-new/A/A00/A00-2033.pdf Removing  Left  Recursion  from  Context-Free  Grammars ]&lt;br /&gt;
&lt;br /&gt;
[[Категория: Теория формальных языков]]&lt;br /&gt;
[[Категория: Контекстно-свободные грамматики]]&lt;br /&gt;
[[Категория: Нормальные формы КС-грамматик]]&lt;/div&gt;</summary>
		<author><name>KirillTim</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%A3%D1%81%D1%82%D1%80%D0%B0%D0%BD%D0%B5%D0%BD%D0%B8%D0%B5_%D0%BB%D0%B5%D0%B2%D0%BE%D0%B9_%D1%80%D0%B5%D0%BA%D1%83%D1%80%D1%81%D0%B8%D0%B8&amp;diff=51279</id>
		<title>Устранение левой рекурсии</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A3%D1%81%D1%82%D1%80%D0%B0%D0%BD%D0%B5%D0%BD%D0%B8%D0%B5_%D0%BB%D0%B5%D0%B2%D0%BE%D0%B9_%D1%80%D0%B5%D0%BA%D1%83%D1%80%D1%81%D0%B8%D0%B8&amp;diff=51279"/>
				<updated>2016-01-17T08:57:15Z</updated>
		
		<summary type="html">&lt;p&gt;KirillTim: /* Источники информации */  Добавил категорию&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Определение&lt;br /&gt;
|definition=Говорят, что [[Контекстно-свободные грамматики, вывод, лево- и правосторонний вывод, дерево разбора|контекстно-свободная (КС) грамматика]] &amp;lt;tex&amp;gt;\Gamma&amp;lt;/tex&amp;gt; содержит '''непосредственную левую рекурсию''' (англ. ''direct left recursion''), если она содержит правило вида &amp;lt;tex&amp;gt;A \to A\alpha&amp;lt;/tex&amp;gt;.&lt;br /&gt;
}}&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition=Говорят, что КС-грамматика &amp;lt;tex&amp;gt;\Gamma&amp;lt;/tex&amp;gt; содержит '''левую рекурсию'''  (англ. ''left recursion''), если в ней существует вывод вида &amp;lt;tex&amp;gt;A \Rightarrow^* A\alpha&amp;lt;/tex&amp;gt;.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
[[Методы трансляции#Нисходящий разбор|Методы нисходящего разбора]] (англ. ''top-down parsers'') не в состоянии работать с леворекурсивными грамматиками. Проблема в том, что продукция вида &amp;lt;tex&amp;gt;A \Rightarrow^* A\alpha&amp;lt;/tex&amp;gt; может применяться бесконечно долго, так и не выработав некий терминальный символ, который можно было бы сравнить со строкой. Поэтому требуется преобразование грамматики, которое бы устранило левую рекурсию.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Устранение непосредственной левой рекурсии==&lt;br /&gt;
Опишем процедуру, устраняющую все правила вида &amp;lt;tex&amp;gt;A \to A\alpha&amp;lt;/tex&amp;gt;, для фиксированного нетерминала &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;ol&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Запишем все правила вывода из &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; в виде: &lt;br /&gt;
&amp;lt;tex&amp;gt;A \to A\alpha_1\,|\,\ldots\,|\,A\alpha_n\,|\,\beta_1\,|\,\ldots\,|\,\beta_m &amp;lt;/tex&amp;gt;, где&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; &amp;lt;tex&amp;gt;\alpha&amp;lt;/tex&amp;gt; {{---}} непустая последовательность терминалов и нетерминалов (&amp;lt;tex&amp;gt;\alpha \nrightarrow \varepsilon &amp;lt;/tex&amp;gt;);&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; &amp;lt;tex&amp;gt;\beta&amp;lt;/tex&amp;gt; {{---}} непустая последовательность терминалов и нетерминалов, не начинающаяся с &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt;.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Заменим правила вывода из &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; на &amp;lt;tex&amp;gt;A \to\beta_1A^\prime\, |\, \ldots\,  |\,  \beta_mA^\prime \,|\, \beta_1 \,|\, \ldots \,|\, \beta_m&amp;lt;/tex&amp;gt;.&amp;lt;/li&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;li&amp;gt;Создадим новый нетерминал &amp;lt;tex&amp;gt;{A^\prime} \to \alpha_1{A^\prime},  |\,  \ldots\, |\, \alpha_n{A^\prime} | \alpha_1\,  |\,  \ldots\, |\, \alpha_n&amp;lt;/tex&amp;gt;. &amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ol&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Изначально нетерминал &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; порождает сроки вида &amp;lt;tex&amp;gt;\beta\alpha_{i0}\alpha_{i1} \ldots \alpha_{ik}&amp;lt;/tex&amp;gt;. В новой грамматике нетерминал &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; порождает &amp;lt;tex&amp;gt;\beta{A^\prime}&amp;lt;/tex&amp;gt;, а &amp;lt;tex&amp;gt;A^\prime&amp;lt;/tex&amp;gt; порождает строки вида &amp;lt;tex&amp;gt;\alpha_{i0}\alpha_{i1} \ldots \alpha_{ik}&amp;lt;/tex&amp;gt;. Из этого очевидно, что изначальная грамматика эквивалентна новой.&lt;br /&gt;
&lt;br /&gt;
===Пример===&lt;br /&gt;
&amp;lt;tex&amp;gt;A \to S\alpha | A\alpha&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;S \to A\beta&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Есть непосредственная левая рекурсия &amp;lt;tex&amp;gt;A \to A\alpha&amp;lt;/tex&amp;gt;. Добавим нетерминал &amp;lt;tex&amp;gt;A^\prime&amp;lt;/tex&amp;gt; и добавим правила &amp;lt;tex&amp;gt;A \to S\alpha{A^{\prime}}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt; A^{\prime} \to \alpha{A^{\prime}} &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Новая грамматика:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;A \to S\alpha{A^{\prime}} | S\alpha&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;A^{\prime} \to \alpha{A^{\prime}}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;S \to A\beta&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
В новой грамматике нет непосредственной левой рекурсии, но нетерминал &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; леворекурсивен, так как есть &amp;lt;tex&amp;gt; A \Rightarrow S\alpha{A^{\prime}} \Rightarrow A\beta\alpha{A^{\prime}} &amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Алгоритм  устранения произвольной левой рекурсии==&lt;br /&gt;
Воспользуемся [[Удаление_eps-правил_из_грамматики | алгоритмом удаления &amp;lt;tex&amp;gt; \varepsilon &amp;lt;/tex&amp;gt;-правил]]. Получим грамматику без &amp;lt;tex&amp;gt; \varepsilon &amp;lt;/tex&amp;gt;-правил для языка &amp;lt;tex&amp;gt;L(\Gamma) \setminus \lbrace \epsilon \rbrace&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Упорядочим нетерминалы и будем добиваться того, чтобы не было правил вида &amp;lt;tex&amp;gt;A_i \to A_j\alpha&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;j \leqslant i&amp;lt;/tex&amp;gt;.&lt;br /&gt;
Если данное условие выполняется для всех&amp;lt;tex&amp;gt;A_i&amp;lt;/tex&amp;gt;, то в грамматике нет &amp;lt;tex&amp;gt;A_i \to^* A_i&amp;lt;/tex&amp;gt;, а значит не будет левой рекурсии. &lt;br /&gt;
&lt;br /&gt;
Пусть &amp;lt;tex&amp;gt;N = \lbrace A_1, A_2, \ldots , A_n \rbrace&amp;lt;/tex&amp;gt; {{---}} упорядоченное множество всех нетерминалов.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div&amp;gt;&lt;br /&gt;
  for &amp;lt;tex&amp;gt;A_i \in N&amp;lt;/tex&amp;gt;&lt;br /&gt;
    for &amp;lt;tex&amp;gt;A_j \in \{ N \mid 1 \leqslant j &amp;lt; i \}&amp;lt;/tex&amp;gt;&lt;br /&gt;
      for &amp;lt;tex&amp;gt;production \in \{A_i \to A_j\gamma \}&amp;lt;/tex&amp;gt;&lt;br /&gt;
        удалить &amp;lt;tex&amp;gt;production&amp;lt;/tex&amp;gt;&lt;br /&gt;
        for &amp;lt;tex&amp;gt;P \to x_i \in \{A_j \to \delta_1 | \ldots | \delta_k\}&amp;lt;/tex&amp;gt;&lt;br /&gt;
          добавить правило &amp;lt;tex&amp;gt;A_i \to x_i\gamma&amp;lt;/tex&amp;gt;&lt;br /&gt;
    устранить непосредственную левую рекурсию для &amp;lt;tex&amp;gt;A_i&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Если &amp;lt;tex&amp;gt;\varepsilon&amp;lt;/tex&amp;gt; присутствовал в языке исходной грамматики, добавим новый начальный символ &amp;lt;tex&amp;gt;S'&amp;lt;/tex&amp;gt; и правила &amp;lt;tex&amp;gt;S' \to S \, | \, \varepsilon &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
После &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; итерации внешнего цикла в любой продукции внешнего цикла в любой продукции вида &amp;lt;tex&amp;gt;A_k \to A_l\alpha, k &amp;lt; i&amp;lt;/tex&amp;gt;, должно быть &amp;lt;tex&amp;gt;l &amp;gt; k&amp;lt;/tex&amp;gt;. В результате при следующей итерации внутреннего цикла растет нижний предел &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; всех продукций вида &amp;lt;tex&amp;gt;A_i \to A_m\alpha&amp;lt;/tex&amp;gt; до тех пор, пока не будет достигнуто &amp;lt;tex&amp;gt;i \leqslant m &amp;lt;/tex&amp;gt;.&lt;br /&gt;
   &lt;br /&gt;
После &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; итерации внешнего цикла в грамматике будут только правила вида &amp;lt;tex&amp;gt;A_i \to A_j\alpha&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;j &amp;gt; i&amp;lt;/tex&amp;gt;.&lt;br /&gt;
Можно заметить, что неравенство становится строгим только после применения алгоритма устранения непосредственной левой рекурсии. При этом добавляются новые нетерминалы. Пусть &amp;lt;tex&amp;gt;{A^\prime}_i &amp;lt;/tex&amp;gt; новый нетерминал. Можно заметить, что нет правила вида &amp;lt;tex&amp;gt;\ldots \to {A^\prime}_i&amp;lt;/tex&amp;gt;, где  &amp;lt;tex&amp;gt;{A^\prime}_i&amp;lt;/tex&amp;gt; самый левый нетерминал, а значит новые нетерминалы можно не рассматривать во внешнем цикле. &lt;br /&gt;
&lt;br /&gt;
На &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; итерации внешнего цикла все правила вида &amp;lt;tex&amp;gt;A_i \to A_j \gamma&amp;lt;/tex&amp;gt; где &amp;lt;tex&amp;gt; j &amp;lt; i &amp;lt;/tex&amp;gt; заменяются на &amp;lt;tex&amp;gt;A_i \to \delta_1\gamma | \ldots | \delta_k\gamma&amp;lt;/tex&amp;gt; где &amp;lt;tex&amp;gt;A_j \to \delta_1 | \ldots | \delta_k&amp;lt;/tex&amp;gt;. Очевидно, что одна итерация алгоритма не меняет язык, а значит язык получившийся в итоге грамматики совпадает с исходным.&lt;br /&gt;
&lt;br /&gt;
===Асимптотика===&lt;br /&gt;
Пусть &amp;lt;tex&amp;gt;a_i&amp;lt;/tex&amp;gt; количество правил для нетерминала &amp;lt;tex&amp;gt;A_i&amp;lt;/tex&amp;gt;.&lt;br /&gt;
Тогда &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; итерация внешнего цикла будет выполняться за &amp;lt;tex&amp;gt;O(\sum\limits_{A_i \to A_j, j &amp;lt; i} a_j) + O(a_i)&amp;lt;/tex&amp;gt;, что меньше чем &amp;lt;tex&amp;gt;O(\sum\limits_{i=1}^n a_j)&amp;lt;/tex&amp;gt;, значит асимптотика алгоритма &amp;lt;tex&amp;gt;O(n\sum\limits_{i=1}^n a_j)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Проблема этого алгоритма в том, что в зависимости от порядка нетерминалов в множестве размер грамматки может получиться экспоненциальным.&lt;br /&gt;
&lt;br /&gt;
Пример грамматики для которой имеет значение порядок нетерминалов&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;A_1 \to 0 | 1&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;A_{i+1} \to {A_i}0 | {A_i}1 &amp;lt;/tex&amp;gt;  для &amp;lt;tex&amp;gt;1 \leqslant i &amp;lt; n&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Упорядочим множество нетерминалов по возрастанию индексов. Легко заметить, что правила для &amp;lt;tex&amp;gt;A_i&amp;lt;/tex&amp;gt; будут представлять из себя все двоичные вектора длины &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;, а значит размер грамматики будет экспоненциальным. Если упорядочить нетерминалы по убыванию в грамматике изменений не будет.&lt;br /&gt;
&lt;br /&gt;
==Пример==&lt;br /&gt;
Дана грамматика&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;A \to S\alpha &amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;S \to S\beta | A\gamma | \beta&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Среди правил &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; непосредственной рекурсии нет, поэтому во время первой итерации внешнего цикла ничего не происходит. &lt;br /&gt;
Во время второй итерации внешнего цикла правило &amp;lt;tex&amp;gt; S \to A\gamma &amp;lt;/tex&amp;gt; переходит в &amp;lt;tex&amp;gt; S \to S\alpha\gamma &amp;lt;/tex&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
Грамматика имеет вид &lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;A \to S\alpha &amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;S \to{S}{\beta} | {S}{\alpha}{\gamma} | \beta&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Устраняем левую рекурсию для &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt; S \to\beta{S_1}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt; {S_1} \to\beta{S_1} | \alpha\gamma{S_1} | {\beta} | {\alpha}{\gamma} &amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Источники информации ==&lt;br /&gt;
* ''Хопкрофт Д., Мотвани Р., Ульман Д.'' — '''Введение в теорию автоматов, языков и вычислений''', 2-е изд. : Пер. с англ. — Москва, Издательский дом «Вильямс», 2002. — 528 с. : ISBN 5-8459-0261-4 (рус.)&lt;br /&gt;
* ''Robert C. Moore'' — [http://aclweb.org/anthology-new/A/A00/A00-2033.pdf Removing  Left  Recursion  from  Context-Free  Grammars ]&lt;br /&gt;
&lt;br /&gt;
[[Категория: Теория формальных языков]]&lt;br /&gt;
[[Категория: Контекстно-свободные грамматики]]&lt;br /&gt;
[[Категория: Нормальные формы КС-грамматик]]&lt;/div&gt;</summary>
		<author><name>KirillTim</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%A3%D1%81%D1%82%D1%80%D0%B0%D0%BD%D0%B5%D0%BD%D0%B8%D0%B5_%D0%BB%D0%B5%D0%B2%D0%BE%D0%B9_%D1%80%D0%B5%D0%BA%D1%83%D1%80%D1%81%D0%B8%D0%B8&amp;diff=51259</id>
		<title>Устранение левой рекурсии</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A3%D1%81%D1%82%D1%80%D0%B0%D0%BD%D0%B5%D0%BD%D0%B8%D0%B5_%D0%BB%D0%B5%D0%B2%D0%BE%D0%B9_%D1%80%D0%B5%D0%BA%D1%83%D1%80%D1%81%D0%B8%D0%B8&amp;diff=51259"/>
				<updated>2016-01-16T21:07:02Z</updated>
		
		<summary type="html">&lt;p&gt;KirillTim: /* Алгоритм  устранения произвольной левой рекурсии */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Определение&lt;br /&gt;
|definition=Говорят, что [[Контекстно-свободные грамматики, вывод, лево- и правосторонний вывод, дерево разбора|контекстно-свободная (КС) грамматика]] &amp;lt;tex&amp;gt;\Gamma&amp;lt;/tex&amp;gt; содержит '''непосредственную левую рекурсию''' (англ. ''direct left recursion''), если она содержит правило вида &amp;lt;tex&amp;gt;A \to A\alpha&amp;lt;/tex&amp;gt;.&lt;br /&gt;
}}&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition=Говорят, что КС-грамматика &amp;lt;tex&amp;gt;\Gamma&amp;lt;/tex&amp;gt; содержит '''левую рекурсию'''  (англ. ''left recursion''), если в ней существует вывод вида &amp;lt;tex&amp;gt;A \Rightarrow^* A\alpha&amp;lt;/tex&amp;gt;.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
[[Методы трансляции#Нисходящий разбор|Методы нисходящего разбора]] (англ. ''top-down parsers'') не в состоянии работать с леворекурсивными грамматиками. Проблема в том, что продукция вида &amp;lt;tex&amp;gt;A \Rightarrow^* A\alpha&amp;lt;/tex&amp;gt; может применяться бесконечно долго, так и не выработав некий терминальный символ, который можно было бы сравнить со строкой. Поэтому требуется преобразование грамматики, которое бы устранило левую рекурсию.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Устранение непосредственной левой рекурсии==&lt;br /&gt;
Опишем процедуру, устраняющую все правила вида &amp;lt;tex&amp;gt;A \to A\alpha&amp;lt;/tex&amp;gt;, для фиксированного нетерминала &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;ol&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Запишем все правила вывода из &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; в виде: &lt;br /&gt;
&amp;lt;tex&amp;gt;A \to A\alpha_1\,|\,\ldots\,|\,A\alpha_n\,|\,\beta_1\,|\,\ldots\,|\,\beta_m &amp;lt;/tex&amp;gt;, где&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; &amp;lt;tex&amp;gt;\alpha&amp;lt;/tex&amp;gt; {{---}} непустая последовательность терминалов и нетерминалов (&amp;lt;tex&amp;gt;\alpha \nrightarrow \varepsilon &amp;lt;/tex&amp;gt;);&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; &amp;lt;tex&amp;gt;\beta&amp;lt;/tex&amp;gt; {{---}} непустая последовательность терминалов и нетерминалов, не начинающаяся с &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt;.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Заменим правила вывода из &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; на &amp;lt;tex&amp;gt;A \to\beta_1A^\prime\, |\, \ldots\,  |\,  \beta_mA^\prime \,|\, \beta_1 \,|\, \ldots \,|\, \beta_m&amp;lt;/tex&amp;gt;.&amp;lt;/li&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;li&amp;gt;Создадим новый нетерминал &amp;lt;tex&amp;gt;{A^\prime} \to \alpha_1{A^\prime},  |\,  \ldots\, |\, \alpha_n{A^\prime} | \alpha_1\,  |\,  \ldots\, |\, \alpha_n&amp;lt;/tex&amp;gt;. &amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ol&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Изначально нетерминал &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; порождает сроки вида &amp;lt;tex&amp;gt;\beta\alpha_{i0}\alpha_{i1} \ldots \alpha_{ik}&amp;lt;/tex&amp;gt;. В новой грамматике нетерминал &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; порождает &amp;lt;tex&amp;gt;\beta{A^\prime}&amp;lt;/tex&amp;gt;, а &amp;lt;tex&amp;gt;A^\prime&amp;lt;/tex&amp;gt; порождает строки вида &amp;lt;tex&amp;gt;\alpha_{i0}\alpha_{i1} \ldots \alpha_{ik}&amp;lt;/tex&amp;gt;. Из этого очевидно, что изначальная грамматика эквивалентна новой.&lt;br /&gt;
&lt;br /&gt;
===Пример===&lt;br /&gt;
&amp;lt;tex&amp;gt;A \to S\alpha | A\alpha&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;S \to A\beta&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Есть непосредственная левая рекурсия &amp;lt;tex&amp;gt;A \to A\alpha&amp;lt;/tex&amp;gt;. Добавим нетерминал &amp;lt;tex&amp;gt;A^\prime&amp;lt;/tex&amp;gt; и добавим правила &amp;lt;tex&amp;gt;A \to S\alpha{A^{\prime}}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt; A^{\prime} \to \alpha{A^{\prime}} &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Новая грамматика:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;A \to S\alpha{A^{\prime}} | S\alpha&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;A^{\prime} \to \alpha{A^{\prime}}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;S \to A\beta&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
В новой грамматике нет непосредственной левой рекурсии, но нетерминал &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; леворекурсивен, так как есть &amp;lt;tex&amp;gt; A \Rightarrow S\alpha{A^{\prime}} \Rightarrow A\beta\alpha{A^{\prime}} &amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Алгоритм  устранения произвольной левой рекурсии==&lt;br /&gt;
Воспользуемся [[Удаление_eps-правил_из_грамматики | алгоритмом удаления &amp;lt;tex&amp;gt; \varepsilon &amp;lt;/tex&amp;gt;-правил]]. Получим грамматику без &amp;lt;tex&amp;gt; \varepsilon &amp;lt;/tex&amp;gt;-правил для языка &amp;lt;tex&amp;gt;L(\Gamma) \setminus \lbrace \epsilon \rbrace&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Упорядочим нетерминалы и будем добиваться того, чтобы не было правил вида &amp;lt;tex&amp;gt;A_i \to A_j\alpha&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;j \leqslant i&amp;lt;/tex&amp;gt;.&lt;br /&gt;
Если данное условие выполняется для всех&amp;lt;tex&amp;gt;A_i&amp;lt;/tex&amp;gt;, то в грамматике нет &amp;lt;tex&amp;gt;A_i \to^* A_i&amp;lt;/tex&amp;gt;, а значит не будет левой рекурсии. &lt;br /&gt;
&lt;br /&gt;
Пусть &amp;lt;tex&amp;gt;N = \lbrace A_1, A_2, \ldots , A_n \rbrace&amp;lt;/tex&amp;gt; {{---}} упорядоченное множество всех нетерминалов.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div&amp;gt;&lt;br /&gt;
  for &amp;lt;tex&amp;gt;A_i \in N&amp;lt;/tex&amp;gt;&lt;br /&gt;
    for &amp;lt;tex&amp;gt;A_j \in \{ N \mid 1 \leqslant j &amp;lt; i \}&amp;lt;/tex&amp;gt;&lt;br /&gt;
      for &amp;lt;tex&amp;gt;production \in \{A_i \to A_j\gamma \}&amp;lt;/tex&amp;gt;&lt;br /&gt;
        удалить &amp;lt;tex&amp;gt;production&amp;lt;/tex&amp;gt;&lt;br /&gt;
        for &amp;lt;tex&amp;gt;P \to x_i \in \{A_j \to \delta_1 | \ldots | \delta_k\}&amp;lt;/tex&amp;gt;&lt;br /&gt;
          добавить правило &amp;lt;tex&amp;gt;A_i \to x_i\gamma&amp;lt;/tex&amp;gt;&lt;br /&gt;
    устранить непосредственную левую рекурсию для &amp;lt;tex&amp;gt;A_i&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Если &amp;lt;tex&amp;gt;\varepsilon&amp;lt;/tex&amp;gt; присутствовал в языке исходной грамматики, добавим новый начальный символ &amp;lt;tex&amp;gt;S'&amp;lt;/tex&amp;gt; и правила &amp;lt;tex&amp;gt;S' \to S \, | \, \varepsilon &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
После &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; итерации внешнего цикла в любой продукции внешнего цикла в любой продукции вида &amp;lt;tex&amp;gt;A_k \to A_l\alpha, k &amp;lt; i&amp;lt;/tex&amp;gt;, должно быть &amp;lt;tex&amp;gt;l &amp;gt; k&amp;lt;/tex&amp;gt;. В результате при следующей итерации внутреннего цикла растет нижний предел &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; всех продукций вида &amp;lt;tex&amp;gt;A_i \to A_m\alpha&amp;lt;/tex&amp;gt; до тех пор, пока не будет достигнуто &amp;lt;tex&amp;gt;i \leqslant m &amp;lt;/tex&amp;gt;.&lt;br /&gt;
   &lt;br /&gt;
После &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; итерации внешнего цикла в грамматике будут только правила вида &amp;lt;tex&amp;gt;A_i \to A_j\alpha&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;j &amp;gt; i&amp;lt;/tex&amp;gt;.&lt;br /&gt;
Можно заметить, что неравенство становится строгим только после применения алгоритма устранения непосредственной левой рекурсии. При этом добавляются новые нетерминалы. Пусть &amp;lt;tex&amp;gt;{A^\prime}_i &amp;lt;/tex&amp;gt; новый нетерминал. Можно заметить, что нет правила вида &amp;lt;tex&amp;gt;\ldots \to {A^\prime}_i&amp;lt;/tex&amp;gt;, где  &amp;lt;tex&amp;gt;{A^\prime}_i&amp;lt;/tex&amp;gt; самый левый нетерминал, а значит новые нетерминалы можно не рассматривать во внешнем цикле. &lt;br /&gt;
&lt;br /&gt;
На &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; итерации внешнего цикла все правила вида &amp;lt;tex&amp;gt;A_i \to A_j \gamma&amp;lt;/tex&amp;gt; где &amp;lt;tex&amp;gt; j &amp;lt; i &amp;lt;/tex&amp;gt; заменяются на &amp;lt;tex&amp;gt;A_i \to \delta_1\gamma | \ldots | \delta_k\gamma&amp;lt;/tex&amp;gt; где &amp;lt;tex&amp;gt;A_j \to \delta_1 | \ldots | \delta_k&amp;lt;/tex&amp;gt;. Очевидно, что одна итерация алгоритма не меняет язык, а значит язык получившийся в итоге грамматики совпадает с исходным.&lt;br /&gt;
&lt;br /&gt;
===Асимптотика===&lt;br /&gt;
Пусть &amp;lt;tex&amp;gt;a_i&amp;lt;/tex&amp;gt; количество правил для нетерминала &amp;lt;tex&amp;gt;A_i&amp;lt;/tex&amp;gt;.&lt;br /&gt;
Тогда &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; итерация внешнего цикла будет выполняться за &amp;lt;tex&amp;gt;O(\sum\limits_{A_i \to A_j, j &amp;lt; i} a_j) + O(a_i)&amp;lt;/tex&amp;gt;, что меньше чем &amp;lt;tex&amp;gt;O(\sum\limits_{i=1}^n a_j)&amp;lt;/tex&amp;gt;, значит асимптотика алгоритма &amp;lt;tex&amp;gt;O(n\sum\limits_{i=1}^n a_j)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Проблема этого алгоритма в том, что в зависимости от порядка нетерминалов в множестве размер грамматки может получиться экспоненциальным.&lt;br /&gt;
&lt;br /&gt;
Пример грамматики для которой имеет значение порядок нетерминалов&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;A_1 \to 0 | 1&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;A_{i+1} \to {A_i}0 | {A_i}1 &amp;lt;/tex&amp;gt;  для &amp;lt;tex&amp;gt;1 \leqslant i &amp;lt; n&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Упорядочим множество нетерминалов по возрастанию индексов. Легко заметить, что правила для &amp;lt;tex&amp;gt;A_i&amp;lt;/tex&amp;gt; будут представлять из себя все двоичные вектора длины &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;, а значит размер грамматики будет экспоненциальным. Если упорядочить нетерминалы по убыванию в грамматике изменений не будет.&lt;br /&gt;
&lt;br /&gt;
==Пример==&lt;br /&gt;
Дана грамматика&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;A \to S\alpha &amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;S \to S\beta | A\gamma | \beta&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Среди правил &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; непосредственной рекурсии нет, поэтому во время первой итерации внешнего цикла ничего не происходит. &lt;br /&gt;
Во время второй итерации внешнего цикла правило &amp;lt;tex&amp;gt; S \to A\gamma &amp;lt;/tex&amp;gt; переходит в &amp;lt;tex&amp;gt; S \to S\alpha\gamma &amp;lt;/tex&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
Грамматика имеет вид &lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;A \to S\alpha &amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;S \to{S}{\beta} | {S}{\alpha}{\gamma} | \beta&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Устраняем левую рекурсию для &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt; S \to\beta{S_1}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt; {S_1} \to\beta{S_1} | \alpha\gamma{S_1} | {\beta} | {\alpha}{\gamma} &amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Источники информации ==&lt;br /&gt;
* ''Хопкрофт Д., Мотвани Р., Ульман Д.'' — '''Введение в теорию автоматов, языков и вычислений''', 2-е изд. : Пер. с англ. — Москва, Издательский дом «Вильямс», 2002. — 528 с. : ISBN 5-8459-0261-4 (рус.)&lt;br /&gt;
* ''Robert C. Moore'' — [http://aclweb.org/anthology-new/A/A00/A00-2033.pdf Removing  Left  Recursion  from  Context-Free  Grammars ]&lt;br /&gt;
&lt;br /&gt;
[[Категория: Теория формальных языков]]&lt;br /&gt;
[[Категория: Контекстно-свободные грамматики]]&lt;/div&gt;</summary>
		<author><name>KirillTim</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%A3%D1%81%D1%82%D1%80%D0%B0%D0%BD%D0%B5%D0%BD%D0%B8%D0%B5_%D0%BB%D0%B5%D0%B2%D0%BE%D0%B9_%D1%80%D0%B5%D0%BA%D1%83%D1%80%D1%81%D0%B8%D0%B8&amp;diff=51258</id>
		<title>Устранение левой рекурсии</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A3%D1%81%D1%82%D1%80%D0%B0%D0%BD%D0%B5%D0%BD%D0%B8%D0%B5_%D0%BB%D0%B5%D0%B2%D0%BE%D0%B9_%D1%80%D0%B5%D0%BA%D1%83%D1%80%D1%81%D0%B8%D0%B8&amp;diff=51258"/>
				<updated>2016-01-16T21:00:30Z</updated>
		
		<summary type="html">&lt;p&gt;KirillTim: /* Алгоритм  устранения произвольной левой рекурсии */ Улучшил псевдокод&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Определение&lt;br /&gt;
|definition=Говорят, что [[Контекстно-свободные грамматики, вывод, лево- и правосторонний вывод, дерево разбора|контекстно-свободная (КС) грамматика]] &amp;lt;tex&amp;gt;\Gamma&amp;lt;/tex&amp;gt; содержит '''непосредственную левую рекурсию''' (англ. ''direct left recursion''), если она содержит правило вида &amp;lt;tex&amp;gt;A \to A\alpha&amp;lt;/tex&amp;gt;.&lt;br /&gt;
}}&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition=Говорят, что КС-грамматика &amp;lt;tex&amp;gt;\Gamma&amp;lt;/tex&amp;gt; содержит '''левую рекурсию'''  (англ. ''left recursion''), если в ней существует вывод вида &amp;lt;tex&amp;gt;A \Rightarrow^* A\alpha&amp;lt;/tex&amp;gt;.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
[[Методы трансляции#Нисходящий разбор|Методы нисходящего разбора]] (англ. ''top-down parsers'') не в состоянии работать с леворекурсивными грамматиками. Проблема в том, что продукция вида &amp;lt;tex&amp;gt;A \Rightarrow^* A\alpha&amp;lt;/tex&amp;gt; может применяться бесконечно долго, так и не выработав некий терминальный символ, который можно было бы сравнить со строкой. Поэтому требуется преобразование грамматики, которое бы устранило левую рекурсию.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Устранение непосредственной левой рекурсии==&lt;br /&gt;
Опишем процедуру, устраняющую все правила вида &amp;lt;tex&amp;gt;A \to A\alpha&amp;lt;/tex&amp;gt;, для фиксированного нетерминала &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;ol&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Запишем все правила вывода из &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; в виде: &lt;br /&gt;
&amp;lt;tex&amp;gt;A \to A\alpha_1\,|\,\ldots\,|\,A\alpha_n\,|\,\beta_1\,|\,\ldots\,|\,\beta_m &amp;lt;/tex&amp;gt;, где&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; &amp;lt;tex&amp;gt;\alpha&amp;lt;/tex&amp;gt; {{---}} непустая последовательность терминалов и нетерминалов (&amp;lt;tex&amp;gt;\alpha \nrightarrow \varepsilon &amp;lt;/tex&amp;gt;);&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; &amp;lt;tex&amp;gt;\beta&amp;lt;/tex&amp;gt; {{---}} непустая последовательность терминалов и нетерминалов, не начинающаяся с &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt;.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Заменим правила вывода из &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; на &amp;lt;tex&amp;gt;A \to\beta_1A^\prime\, |\, \ldots\,  |\,  \beta_mA^\prime \,|\, \beta_1 \,|\, \ldots \,|\, \beta_m&amp;lt;/tex&amp;gt;.&amp;lt;/li&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;li&amp;gt;Создадим новый нетерминал &amp;lt;tex&amp;gt;{A^\prime} \to \alpha_1{A^\prime},  |\,  \ldots\, |\, \alpha_n{A^\prime} | \alpha_1\,  |\,  \ldots\, |\, \alpha_n&amp;lt;/tex&amp;gt;. &amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ol&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Изначально нетерминал &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; порождает сроки вида &amp;lt;tex&amp;gt;\beta\alpha_{i0}\alpha_{i1} \ldots \alpha_{ik}&amp;lt;/tex&amp;gt;. В новой грамматике нетерминал &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; порождает &amp;lt;tex&amp;gt;\beta{A^\prime}&amp;lt;/tex&amp;gt;, а &amp;lt;tex&amp;gt;A^\prime&amp;lt;/tex&amp;gt; порождает строки вида &amp;lt;tex&amp;gt;\alpha_{i0}\alpha_{i1} \ldots \alpha_{ik}&amp;lt;/tex&amp;gt;. Из этого очевидно, что изначальная грамматика эквивалентна новой.&lt;br /&gt;
&lt;br /&gt;
===Пример===&lt;br /&gt;
&amp;lt;tex&amp;gt;A \to S\alpha | A\alpha&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;S \to A\beta&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Есть непосредственная левая рекурсия &amp;lt;tex&amp;gt;A \to A\alpha&amp;lt;/tex&amp;gt;. Добавим нетерминал &amp;lt;tex&amp;gt;A^\prime&amp;lt;/tex&amp;gt; и добавим правила &amp;lt;tex&amp;gt;A \to S\alpha{A^{\prime}}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt; A^{\prime} \to \alpha{A^{\prime}} &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Новая грамматика:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;A \to S\alpha{A^{\prime}} | S\alpha&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;A^{\prime} \to \alpha{A^{\prime}}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;S \to A\beta&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
В новой грамматике нет непосредственной левой рекурсии, но нетерминал &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; леворекурсивен, так как есть &amp;lt;tex&amp;gt; A \Rightarrow S\alpha{A^{\prime}} \Rightarrow A\beta\alpha{A^{\prime}} &amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Алгоритм  устранения произвольной левой рекурсии==&lt;br /&gt;
Воспользуемся [[Удаление_eps-правил_из_грамматики | алгоритмом удаления &amp;lt;tex&amp;gt; \varepsilon &amp;lt;/tex&amp;gt;-правил]]. Получим грамматику без &amp;lt;tex&amp;gt; \varepsilon &amp;lt;/tex&amp;gt;-правил для языка &amp;lt;tex&amp;gt;L(\Gamma) \setminus \lbrace \epsilon \rbrace&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Упорядочим нетерминалы и будем добиваться того, чтобы не было правил вида &amp;lt;tex&amp;gt;A_i \to A_j\alpha&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;j \leqslant i&amp;lt;/tex&amp;gt;.&lt;br /&gt;
Если данное условие выполняется для всех&amp;lt;tex&amp;gt;A_i&amp;lt;/tex&amp;gt;, то в грамматике нет &amp;lt;tex&amp;gt;A_i \to^* A_i&amp;lt;/tex&amp;gt;, а значит не будет левой рекурсии. &lt;br /&gt;
&lt;br /&gt;
Пусть &amp;lt;tex&amp;gt;N = \lbrace A_1, A_2, \ldots , A_n \rbrace&amp;lt;/tex&amp;gt; {{---}} упорядоченное множество всех нетерминалов.&lt;br /&gt;
&lt;br /&gt;
стало:&lt;br /&gt;
&amp;lt;div&amp;gt;&lt;br /&gt;
  for &amp;lt;tex&amp;gt;A_i \in N&amp;lt;/tex&amp;gt;&lt;br /&gt;
    for &amp;lt;tex&amp;gt;A_j \in \{ N \mid 1 \leqslant j &amp;lt; i \}&amp;lt;/tex&amp;gt;&lt;br /&gt;
      for &amp;lt;tex&amp;gt;production \in \{A_i \to A_j\gamma \}&amp;lt;/tex&amp;gt;&lt;br /&gt;
        удалить &amp;lt;tex&amp;gt;production&amp;lt;/tex&amp;gt;&lt;br /&gt;
        for &amp;lt;tex&amp;gt;P \to x_i \in \{A_j \to \delta_1 | \ldots | \delta_k\}&amp;lt;/tex&amp;gt;&lt;br /&gt;
          добавить правило &amp;lt;tex&amp;gt;A_i \to x_i\gamma&amp;lt;/tex&amp;gt;&lt;br /&gt;
    устранить непосредственную левую рекурсию для &amp;lt;tex&amp;gt;A_i&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
было:&lt;br /&gt;
&amp;lt;div&amp;gt;&lt;br /&gt;
 for все нетерминалы &amp;lt;tex&amp;gt;A_i&amp;lt;/tex&amp;gt; &lt;br /&gt;
   for все нетерминалы &amp;lt;tex&amp;gt;A_j&amp;lt;/tex&amp;gt;, такие, что &amp;lt;tex&amp;gt; 1 \leqslant j &amp;lt; i &amp;lt;/tex&amp;gt; и &lt;br /&gt;
     рассмотреть все правила вывода из &amp;lt;tex&amp;gt;A_j&amp;lt;/tex&amp;gt;: &amp;lt;tex&amp;gt;A_j \to \delta_1 | \ldots | \delta_k&amp;lt;/tex&amp;gt;.&lt;br /&gt;
     заменить каждое правило &amp;lt;tex&amp;gt;A_i \to A_j \gamma&amp;lt;/tex&amp;gt; на &amp;lt;tex&amp;gt;A_i \to \delta_1\gamma | \ldots | \delta_k\gamma&amp;lt;/tex&amp;gt;.&lt;br /&gt;
   устранить непосредственную левую рекурсию для &amp;lt;tex&amp;gt;A_i&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Если &amp;lt;tex&amp;gt;\varepsilon&amp;lt;/tex&amp;gt; присутствовал в языке исходной грамматики, добавим новый начальный символ &amp;lt;tex&amp;gt;S'&amp;lt;/tex&amp;gt; и правила &amp;lt;tex&amp;gt;S' \to S \, | \, \varepsilon &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
После &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; итерации внешнего цикла в любой продукции внешнего цикла в любой продукции вида &amp;lt;tex&amp;gt;A_k \to A_l\alpha, k &amp;lt; i&amp;lt;/tex&amp;gt;, должно быть &amp;lt;tex&amp;gt;l &amp;gt; k&amp;lt;/tex&amp;gt;. В результате при следующей итерации внутреннего цикла растет нижний предел &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; всех продукций вида &amp;lt;tex&amp;gt;A_i \to A_m\alpha&amp;lt;/tex&amp;gt; до тех пор, пока не будет достигнуто &amp;lt;tex&amp;gt;i \leqslant m &amp;lt;/tex&amp;gt;.&lt;br /&gt;
   &lt;br /&gt;
После &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; итерации внешнего цикла в грамматике будут только правила вида &amp;lt;tex&amp;gt;A_i \to A_j\alpha&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;j &amp;gt; i&amp;lt;/tex&amp;gt;.&lt;br /&gt;
Можно заметить, что неравенство становится строгим только после применения алгоритма устранения непосредственной левой рекурсии. При этом добавляются новые нетерминалы. Пусть &amp;lt;tex&amp;gt;{A^\prime}_i &amp;lt;/tex&amp;gt; новый нетерминал. Можно заметить, что нет правила вида &amp;lt;tex&amp;gt;\ldots \to {A^\prime}_i&amp;lt;/tex&amp;gt;, где  &amp;lt;tex&amp;gt;{A^\prime}_i&amp;lt;/tex&amp;gt; самый левый нетерминал, а значит новые нетерминалы можно не рассматривать во внешнем цикле. &lt;br /&gt;
&lt;br /&gt;
На &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; итерации внешнего цикла все правила вида &amp;lt;tex&amp;gt;A_i \to A_j \gamma&amp;lt;/tex&amp;gt; где &amp;lt;tex&amp;gt; j &amp;lt; i &amp;lt;/tex&amp;gt; заменяются на &amp;lt;tex&amp;gt;A_i \to \delta_1\gamma | \ldots | \delta_k\gamma&amp;lt;/tex&amp;gt; где &amp;lt;tex&amp;gt;A_j \to \delta_1 | \ldots | \delta_k&amp;lt;/tex&amp;gt;. Очевидно, что одна итерация алгоритма не меняет язык, а значит язык получившийся в итоге грамматики совпадает с исходным.&lt;br /&gt;
&lt;br /&gt;
===Асимптотика===&lt;br /&gt;
Пусть &amp;lt;tex&amp;gt;a_i&amp;lt;/tex&amp;gt; количество правил для нетерминала &amp;lt;tex&amp;gt;A_i&amp;lt;/tex&amp;gt;.&lt;br /&gt;
Тогда &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; итерация внешнего цикла будет выполняться за &amp;lt;tex&amp;gt;O(\sum\limits_{A_i \to A_j, j &amp;lt; i} a_j) + O(a_i)&amp;lt;/tex&amp;gt;, что меньше чем &amp;lt;tex&amp;gt;O(\sum\limits_{i=1}^n a_j)&amp;lt;/tex&amp;gt;, значит асимптотика алгоритма &amp;lt;tex&amp;gt;O(n\sum\limits_{i=1}^n a_j)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Проблема этого алгоритма в том, что в зависимости от порядка нетерминалов в множестве размер грамматки может получиться экспоненциальным.&lt;br /&gt;
&lt;br /&gt;
Пример грамматики для которой имеет значение порядок нетерминалов&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;A_1 \to 0 | 1&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;A_{i+1} \to {A_i}0 | {A_i}1 &amp;lt;/tex&amp;gt;  для &amp;lt;tex&amp;gt;1 \leqslant i &amp;lt; n&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Упорядочим множество нетерминалов по возрастанию индексов. Легко заметить, что правила для &amp;lt;tex&amp;gt;A_i&amp;lt;/tex&amp;gt; будут представлять из себя все двоичные вектора длины &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;, а значит размер грамматики будет экспоненциальным. Если упорядочить нетерминалы по убыванию в грамматике изменений не будет.&lt;br /&gt;
&lt;br /&gt;
==Пример==&lt;br /&gt;
Дана грамматика&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;A \to S\alpha &amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;S \to S\beta | A\gamma | \beta&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Среди правил &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; непосредственной рекурсии нет, поэтому во время первой итерации внешнего цикла ничего не происходит. &lt;br /&gt;
Во время второй итерации внешнего цикла правило &amp;lt;tex&amp;gt; S \to A\gamma &amp;lt;/tex&amp;gt; переходит в &amp;lt;tex&amp;gt; S \to S\alpha\gamma &amp;lt;/tex&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
Грамматика имеет вид &lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;A \to S\alpha &amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;S \to{S}{\beta} | {S}{\alpha}{\gamma} | \beta&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Устраняем левую рекурсию для &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt; S \to\beta{S_1}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt; {S_1} \to\beta{S_1} | \alpha\gamma{S_1} | {\beta} | {\alpha}{\gamma} &amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Источники информации ==&lt;br /&gt;
* ''Хопкрофт Д., Мотвани Р., Ульман Д.'' — '''Введение в теорию автоматов, языков и вычислений''', 2-е изд. : Пер. с англ. — Москва, Издательский дом «Вильямс», 2002. — 528 с. : ISBN 5-8459-0261-4 (рус.)&lt;br /&gt;
* ''Robert C. Moore'' — [http://aclweb.org/anthology-new/A/A00/A00-2033.pdf Removing  Left  Recursion  from  Context-Free  Grammars ]&lt;br /&gt;
&lt;br /&gt;
[[Категория: Теория формальных языков]]&lt;br /&gt;
[[Категория: Контекстно-свободные грамматики]]&lt;/div&gt;</summary>
		<author><name>KirillTim</name></author>	</entry>

	</feed>