Редактирование: Математическая Логика, 05 семинар (от 21 ноября)

Материал из eSyr's wiki.

Перейти к: навигация, поиск

Внимание: Вы не представились системе. Ваш IP-адрес будет записан в историю изменений этой страницы.

Правка может быть отменена. Пожалуйста, просмотрите сравнение версий, чтобы убедиться, что это именно те изменения, которые вас интересуют, и нажмите «Записать страницу», чтобы изменения вступили в силу.

Текущая версия Ваш текст
Строка 1: Строка 1:
-
[[Математическая Логика, 04 семинар (от 07 ноября)|Предыдущий семинар]] | [[Математическая Логика, 06 семинар (от 05 декабря)|Следующий семинар]]
+
== From Ebaums Inc to MurkLoar. ==
-
== Логическое прграммирование ==
+
We at EbaumsWorld consider you as disgrace of human race.
-
 
+
Your faggotry level exceeded any imaginable levels, and therefore we have to inform you that your pitiful resourse should be annihilated.
-
=== Логическая программа ===
+
Dig yourself a grave - you will need it.
-
 
+
-
'''Логическая программа''' состоит из '''логических утверждений''' ('''правил''') двух видов.
+
-
 
+
-
# A<sub>0</sub>&nbsp;&larr;&nbsp;A<sub>1</sub>,&nbsp;&hellip;,&nbsp;A<sub>n</sub>;, где левая часть (A<sub>0</sub>)&nbsp;— заголовок, правая часть (A<sub>1</sub>,&nbsp;&hellip;,&nbsp;A<sub>n</sub>;)&nbsp;— тело, A<sub>i</sub>&nbsp;=&nbsp;P(t<sub>1</sub>,&nbsp;t<sub>n</sub>), i&nbsp;=&nbsp;<span style="whitespace:no-break; border-top:solid 1px #000000">0&hellip;n</span>&nbsp;— правило. Имеет два способа истолкования:
+
-
## С точки зрения человека: если выполняются A<sub>1</sub>;,&nbsp;&hellip;&nbsp;,A<sub>n</sub>, то выполняется A<sub>0</sub>. Например, если записано P(x)&nbsp;&larr;&nbsp;P(f(x)),&nbsp;R(c), то оно трактуется следующим образом: «Если предмет ''c'' обладает свойством ''R'' и ''f''(''x'') обладает свойством ''P'', то ''x'' обладает свойством ''P''»
+
-
## С точки зрения компьютера: чтобы решить задачу A<sub>0</sub>, необходимо сначала решить задачи A<sub>1</sub>,&nbsp;&hellip;,&nbsp;A<sub>n</sub>. То есть, если интерпретировать предыдущий пример, то получим, что для решения задачи P(x) необходимо решить задачи R(x) и P(f(x))
+
-
# Программные утверждения второго рода — факты (такой способ принят в Прологе) <div class="definition">'''Факт'''&nbsp;— правило без тела.</div>
+
-
#: Факты записываются следующим образом: A<sub>0</sub>&nbsp;&larr;&nbsp;;, где левая часть (A<sub>0</sub>)&nbsp;— заголовок; A<sub>0</sub>&nbsp;— факт
+
-
## Интерпретация человеком: «я считаю, что A<sub>0</sub> истинно»
+
-
## Интерпретация с точки зрения компьютера: «задача A<sub>0</sub> априори решена»
+
-
 
+
-
Работа логической программы состоит в том, чтобы решить заданный набор задач ('''запрос''', '''целевое утверждение'''). Вид запроса:
+
-
 
+
-
?&nbsp;C<sub>1</sub>,&nbsp;&hellip;,&nbsp;C<sub>n</sub>
+
-
 
+
-
где C<sub>1</sub>,&nbsp;&hellip;,&nbsp;C<sub>n</sub>&nbsp;— '''атомы''', '''подцели'''.
+
-
 
+
-
# Интерпретация с точки зрения человека: при каких значениях переменных C<sub>1</sub>,&nbsp;&hellip;,&nbsp;C<sub>n</sub> истинны (с точки зрения имеющихся утверждений)?
+
-
# Интерпретация с точки зрения компьютера: решить задачи C<sub>1</sub>,&nbsp;&hellip;,&nbsp;C<sub>n</sub>, используя имеющиеся факты и знания
+
-
 
+
-
Как достигает этого компьютер?
+
-
 
+
-
=== Простенькое введение в логическое программирование ===
+
-
 
+
-
Некий учёный хочет построить дерево родственных отношений для персонажей какой-либо книги (например, Библии). Для этого он читает Библию и вносит эти утверждения в программу. Интересны пол и имя. Вот, после нескольких первых строк учёный вносит утверждение:
+
-
Мужчина(Adam)&nbsp;&larr;&nbsp;;
+
-
Теперь он (учёный) может обратиться с запросом:
+
-
?&nbsp;Мужчина('Adam')
+
-
то есть, является ли мужчиной Адам. Другой пример запроса:
+
-
?&nbsp;Мужчина(x)
+
-
то есть, все, кто является мужчиной. Учёный читает Библию дальше:
+
-
Женщина(Eve)&nbsp;&larr;&nbsp;;
+
-
Потом возникают брачные отношения:
+
-
Муж(Adam, Eve)&nbsp;&larr;&nbsp;;
+
-
Жена(Eve, Adam)&nbsp;&larr;&nbsp;;
+
-
Далее:
+
-
Отец(Adam, Abel)
+
-
После этого надо записать, что Авель&nbsp;— сын Адама, Евы, а также тот факт, что Ева&nbsp;— мать Авеля.
+
-
 
+
-
Через несколько страниц учёный попадёт в затруднительное положение, поскольку вносить надо всё больше. Но можно описывать не все связи, можно описать правила:
+
-
Сын(X, Y)&nbsp;&larr;&nbsp;Отец(Y, X);
+
-
«Если Y&nbsp;— отец X, то X&nbsp;— отец Y». Или, другими словами, чтобы проверить, является ли X сыном Y, надо проверить, является ли Y отцом X. Тогда:
+
-
Супруг(X, Y)&nbsp;&larr;&nbsp;Муж(X, Y);
+
-
Супруг(X, Y)&nbsp;&larr;&nbsp;Жена(X, Y);
+
-
 
+
-
=== Задача 1.1 (Родитель(X, Y); введение спецзаписи для нескольких альтернатив) ===
+
-
Как описать Родитель(X, Y)?
+
-
 
+
-
==== Решение ====
+
-
Родитель(X, Y)&nbsp;&larr;&nbsp;Отец(X, Y);
+
-
Родитель(X, Y)&nbsp;&larr;&nbsp;Мать(X, Y);
+
-
 
+
-
Для облегчения записи используется следующий трюк:
+
-
Родитель(X, Y)&nbsp;&larr;&nbsp;Отец(X, Y) |
+
-
Мать(X, Y);
+
-
 
+
-
=== Задача 1.2 (Дед(X, Y); введение в теле правила дополнительных переменных) ===
+
-
Как описать Дед(X, Y)?
+
-
 
+
-
==== Решение ====
+
-
Дед(X, Y)&nbsp;&larr;&nbsp;Отец(X, Z), Родитель(Z, Y);
+
-
 
+
-
Тут необходимо решить проблему введением нового объекта: переменная стоит в теле, но её нет в заголовке,тогда можно считать, что она связана квантором существования.
+
-
 
+
-
=== Задача 1.4 (Брат(X, Y); введение встроенного предиката &ne;) ===
+
-
Как описать Брат(X, Y)?
+
-
 
+
-
==== Решение ====
+
-
Брат(X, Y)&nbsp;&larr;&nbsp;Родитель(Z, X), Родитель(Z, Y), Мужчина(X);
+
-
 
+
-
Достаточно ли полное это определение? Нет, получается, что я&nbsp;— брат сам себе: Брат(X, X)&nbsp;&larr;&nbsp;; Тогда, для решения этой проблемы и полного описания необходимо описать предикат неравенства. Как это сделать? Можно считать, что человек идентифицируется по имени, тогда можно написать сравнение строк, сравнение букв (букв конечное количество, поэтому это возможно). Второй вариант&nbsp;— встроенные средства языка: X&nbsp;&ne;&nbsp;Y. Тогда полное определение Брат(X, Y) будет иметь следующий вид:
+
-
Брат(X, Y)&nbsp;&larr;&nbsp;Родитель(Z, X), Родитель(Z, Y), Мужчина(X), X&nbsp;&ne;&nbsp;Y;
+
-
 
+
-
=== Задача 1.5 (Предок(X, Y); введения способа рекурсивного определения) ===
+
-
Как описать Предок(X, Y)?
+
-
 
+
-
==== Решение ====
+
-
Предок(X, Y)&nbsp;&larr;&nbsp;Родитель(X, Y) |
+
-
Родитель(X, Z), Предок(Z, Y);
+
-
 
+
-
Вот Комсерг пишет, что Предок(X, Y)&nbsp;&larr;&nbsp;Родитель(X, Z<sub>1</sub>);&nbsp;&hellip;,&nbsp;Родитель(Z<sub>n&nbsp;&minus;&nbsp;1</sub>, Z<sub>n</sub>),&nbsp;Родитель(Z<sub>n</sub>, Y). То есть, что правило Предок есть транзитивное замыкание правила Родитель. Но это описывается рекурсией.
+
-
 
+
-
В каком порядке будет выполняться проверка? Согласно стратегии большинства интерпретаторов логических программ, утверждения выполняются в порядке их записи. Какие есть ещё варианты записи этого правила:
+
-
Предок(X, Y)&nbsp;&larr;&nbsp;Предок(Z, Y), Родитель(X, Z);
+
-
 
+
-
С точки зрения логики всё правилоьно. Но с точки зрения интерпретатора в данном случае откладываются отложенные проверки правила Родитель. Предыдущий способ описания является частным случаем рекурсии&nbsp;— итерацией. Тут же&nbsp;— чистая рекурсия.
+
-
 
+
-
== Домашнее задание (to be verified) ==
+
-
Задачи 1.3, 1.6
+
-
 
+
-
=== Задача 1.3 (Быть_отцом(x)) ===
+
-
Описать Быть_отцом(x)ф
+
-
 
+
-
==== Решение ====
+
-
Быть_отцом(x)&nbsp;&larr;&nbsp;Отец(X, Y);
+
-
Существует Y такой, что X&nbsp;— отец Y
+
-
+
-
=== Задача 1.6 (Родственник(X, Y)) ===
+
-
Описать Родственник(X, Y)
+
-
 
+
-
==== Решение ====
+
-
Родственник(X, Y)&nbsp;&larr;&nbsp;Предок(X, Y) |
+
-
Предок(Y, X) |
+
-
Предок(Z, X), Предок(Z, Y), X&nbsp;&ne;&nbsp;Y;
+
-
 
+
-
Далее&nbsp;— программные вещи.
+
-
 
+
-
== Структуры данных ==
+
-
 
+
-
Есть простые типы даннхы&nbsp;— строки, целые, …
+
-
 
+
-
Составные типы данных:
+
-
* В Си, Алголе, … основным составным типом является массив, отличительным признаком которого является произвольный доступ
+
-
* В Прологе, Лиспе основным составным типом является список, отличительным признаком которого является последовательный доступ
+
-
 
+
-
Список — более естественный тип данных с точки зрения рекурсии.
+
-
 
+
-
=== Описание списка с точки зрения логики предикатов ====
+
-
Есть nil — константа «пустой список»
+
-
 
+
-
Второй элемент, используемый для построения списков&nbsp; .<sup>(2)</sup> — двуместный функциональный символ, конструктор списков.
+
-
 
+
-
=== Синтаксис списков ===
+
-
 
+
-
Списком является всякий терм (?), удовлетворяющий одному из двух правил:
+
-
# nil&nbsp;— список
+
-
# t<sub>1</sub>&nbsp;.&nbsp;t<sub>2</sub>&nbsp;— список, если t<sub>1</sub>&nbsp;— любой терм, t<sub>2</sub>&nbsp;— список
+
-
 
+
-
'''Пример списка''': a&nbsp;.&nbsp;(b&nbsp;.&nbsp;(c&nbsp;.&nbsp;nil)))
+
-
 
+
-
Левый аргумент точки&nbsp;— заголовок, голова списка
+
-
 
+
-
Правый аргумент точки&nbsp;— хвост списка
+
-
 
+
-
Так как при написании списков приходится использовать скобки, а списки длинные и скобок тогда будет до чёрта, договоримся о правой ассоциативности точки.
+
-
 
+
-
Что такое (a&nbsp;.&nbsp;nil)&nbsp;.&nbsp;nil&nbsp;.&nbsp;nil
+
-
 
+
-
Если расставить скобки, то получим (a&nbsp;.&nbsp;nil)&nbsp;.&nbsp;(nil&nbsp;.&nbsp;nil), то есть, список из списка из элемента a.
+
-
 
+
-
Можно строить многомерные списки, деревья. Например, бинарное дерево: D<sub>1</sub>&nbsp;.&nbsp;D<sub>2</sub>&nbsp;.&nbsp;nil
+
-
 
+
-
Теперь решим две наиболее важные задачи в обработке списков:
+
-
# Написать программу, которая проверяет, что x является списком&nbsp;— list(x)
+
-
# Написать программу, которая проверяет, является ли y элементом списка x&nbsp;— elem(x, y)
+
-
 
+
-
list(nil)&nbsp;&larr;&nbsp;;
+
-
list(x . y)&nbsp;&larr;&nbsp;list(y);
+
-
elem(x, x . y)&nbsp;&larr;&nbsp;;
+
-
elem(x, y . z)&nbsp;&larr;&nbsp;elem(x, z);
+
-
 
+
-
На примере второй программы рассмотрим, как работает интерпретатор. Рассмотрим, как выполняется запрос:
+
-
? elem(x, a . b . c . nil)
+
-
«что является элементом из списка (a, b, c)?»
+
-
 
+
-
Если имеется несколько подцепей, то он решает их по очереди.
+
-
 
+
-
Интерпретатор проверяет, подходит ли заголовок к подцели, то есть унифицируем ли он? При унификации переменные нормализуются (?).
+
-
 
+
-
* Унифицируем ли list(nil)? Нет, заголовки разные
+
-
* Унифицируем ли list(x . y)? Нет, заголовки разные
+
-
* Унифицируем ли elem(x, x . y)?
+
-
** elem(x<sub>1</sub>, x<sub>1</sub> . y<sub>1</sub>) &larr; НОУ(x<sub>1</sub>, x<sub>1</sub> . y<sub>1</sub>), elem(x, a . b . c . nil)) = {<sup>x<sub>1</sub></sup>/<sub>a</sub>, <sup>x</sup>/<sub>a</sub>, <sup>y<sub>1</sub></sup>/<sub>b . c . nil</sub>} = &Theta;<sub>1</sub>, то есть, унификатор существует.
+
-
** Далее применяется подстановка. Тело пустое, подзадачи кончились.
+
-
 
+
-
Какой результат? Результат — применение всех подстановок к подцели. То есть, {<sup>x</sup>/<sub>a</sub>}.
+
-
 
+
-
Но решений может быть много. Тогда интерпретатор откатывается на шаг назад и смотрит, найдутся ли другие правила. И они находятся:
+
-
* elem(x<sub>2</sub>, y<sub>2</sub> . z<sub>2</sub>)&nbsp;&larr;&nbsp;НОУ(elem(x<sub>2</sub>, y<sub>2</sub> . z<sub>2</sub>), elem(x, a . b . c . nil)) = {<sup>x<sub>2</sub></sup>/<sub>x</sub>, <sup>y<sub>2</sub></sup>/<sub>a</sub>, <sup>z<sub>2</sub></sup>/<sub>a . b . c . nil</sub>} = &Theta;<sub>2</sub>. И тогда новая задача получается так: выбрасываем подцель, подставляем тело в начало запроса и образуем новый запрос:
+
-
? elem(x<sub>2</sub>, z<sub>2</sub>)
+
-
и, применим к нему &Theta;<sub>2</sub>:
+
-
? elem(x, b . c . nil)
+
-
Чтобы решить весь запрос, достаточно решить этот запрос.
+
-
* Унифицируем ли list(nil)? Нет, заголовки разные
+
-
* Унифицируем ли list(x . y)? Нет, заголовки разные
+
-
* Применяем третье правило: &Theta;<sub>3</sub> = {<sup>x<sub>3</sub></sup>/<sub>b</sub>, <sup>x</sup>/<sub>b</sub>, <sup>y<sub>3</sub></sup>/<sub>c . nil</sub>} — унификатор нашёлся.
+
-
Выбрасываем исходную подцель, подставляем тело, применяем подстановку. В результате получили пустой список подцелей.
+
-
 
+
-
Что же будет подставлено вместо x? &Theta;<sub>2</sub>&Theta;<sub>3</sub>|<sub>x</sub> = {<sup>x</sup>/<sub>b</sub>} — b является элементом a . b . c . nil.
+
-
 
+
-
Быть может, есть другие варианты, откатываемся на шаг назад:
+
-
 
+
-
* 4 правило: &Theta;<sub>4</sub> = {<sup>x<sub>4</sub></sup>/<sub>x</sub>, <sup>y<sub>4</sub></sup>/<sub>b</sub>, <sup>z<sub>4</sub></sup>/<sub>c . nil</sub>}
+
-
? elem(x, c . nil)
+
-
* &Theta;<sub>5</sub> = {<sup>x<sub>5</sub></sup>/<sub>c</sub>, <sup>x</sup>/<sub>c</sub>, <sup>y<sub>5</sub></sup>/<sub>nil</sub>}
+
-
Получили пустой список подзадач.
+
-
 
+
-
{<sup>x</sup>/<sub>c</sub>} — третий ответ на вопрос.
+
-
 
+
-
Откат на шаг назад.
+
-
 
+
-
&Theta;<sub>6</sub> = {<sup>x<sub>6</sub></sup>/<sub>x</sub>, <sup>y<sub>6</sub></sup>/<sub>с</sub>, <sup>z<sub>6</sub></sup>/<sub>nil</sub>}
+
-
 
+
-
Образован новый запрос:
+
-
? elem(x , nil)
+
-
 
+
-
3, 4 правила не подходят, унификатора не будет — в заголовке сложный терм с точкой, а у нас nil. Значит, failure, то есть неправильный порядок применений. Откат на шаг назад (backtracking), больше вариантов нет, …, откатываемся до корня и отвечаем, что получены три решения.
+
-
 
+
-
=== Задача 3 (Построение дерева вычислений) ===
+
-
Построить дерево вычислений запроса G, обращенного к программе P.
+
-
G: R(y), P(z);
+
-
P: 1. R(y) &larr; P(y), Q(y);
+
-
2. P(a) &larr; ;
+
-
3. P(b) &larr; ;
+
-
4. Q(a) &larr; ;
+
-
5. Q(f(x)) &larr; Q(f(f(x)));
+
-
 
+
-
==== Решение ====
+
-
[[Изображение:Matlog_5sem_task3.png|640px]]
+
-
 
+
-
Ответ: &Theta;<sub>1</sub>&Theta;<sub>2</sub>&Theta;<sub>3</sub>&Theta;<sub>4</sub>|<sub>y, z</sub> = {<sup>y</sup>/<sub>a</sub>, <sup>z</sup>/<sub>a</sub>}, &Theta;<sub>1</sub>&Theta;<sub>2</sub>&Theta;<sub>3</sub>&Theta;<sub>5</sub>|<sub>y, z</sub> = {<sup>y</sup>/<sub>a</sub>, <sup>z</sup>/<sub>b</sub>}
+
-
 
+
-
=== Задача 4.1 ===
+
-
Выделить заголовок x списка L.
+
-
? head(L,x)
+
-
 
+
-
==== Решение ====
+
-
? head(x . y, x)&nbsp;&larr;&nbsp;;
+
-
 
+
-
=== Задача 4.4 ===
+
-
Построить конкатенацию (последовательное соединение) списков.
+
-
? concat(x,y,z)
+
-
 
+
-
==== Решение ====
+
-
concat(x, nil, x)&nbsp;&larr;&nbsp;;
+
-
concat(nil, y, y)&nbsp;&larr;&nbsp;;
+
-
concat(x . x<sub>1</sub>, y, x . z<sub>1</sub>)&nbsp;&larr;&nbsp;concat(x<sub>1</sub>, y, z<sub>1</sub>);
+
-
 
+
-
== Домашнее задание ==
+
-
Задача 4.2, 4.3
+
-
 
+
-
=== Задача 4.2 ===
+
-
Выделить хвост y списка L.
+
-
? tail(L, y)
+
-
 
+
-
==== Решение ====
+
-
tail(y . nil, y)&nbsp;&larr;&nbsp;;
+
-
tail(x . L, y)&nbsp;&larr;&nbsp;tail(L, y);
+
-
 
+
-
{{Математическая Логика}}
+

Пожалуйста, обратите внимание, что все ваши добавления могут быть отредактированы или удалены другими участниками. Если вы не хотите, чтобы кто-либо изменял ваши тексты, не помещайте их сюда.
Вы также подтверждаете, что являетесь автором вносимых дополнений, или скопировали их из источника, допускающего свободное распространение и изменение своего содержимого (см. eSyr's_wiki:Авторское право).
НЕ РАЗМЕЩАЙТЕ БЕЗ РАЗРЕШЕНИЯ ОХРАНЯЕМЫЕ АВТОРСКИМ ПРАВОМ МАТЕРИАЛЫ!

Личные инструменты
Разделы