Эта лекция будет посвящена теоретическим основам языка Пролог. В принципе, вполне можно писать хорошие программы на языке Пролог, не вдаваясь в глубины математической логики. И в этом смысле можно
считать эту главу необязательной, факультативной. Однако тем, кому интересно узнать, «как она вертится», мы попробуем объяснить, как устроен Пролог, на чем он основывается.
Давайте начнем с самого начала или почти с самого начала, раз уж мы договорились, что никаких предварительных навыков от слушателей не требуется. Нам придется попытаться разобраться с понятиями
логики первого порядка, которая лежит в основе Пролога; они обычно изучаются в курсе математической логики. Конечно, для того чтобы изучить даже самые начала математической логики, одной лекции
недостаточно. Поэтому мы попытаемся пробежаться только по тому кусочку, который имеет отношение к языку Пролог. Часть используемых нами понятий все-таки останется «за кадром».
Говорят, что задана некая формальная система F, если определены:
- алфавит системы — счетное множество символов;
- формулы системы — некоторое подмножество всех слов, которые можно образовать из символов, входящих в алфавит (обычно задается процедура, позволяющая составлять формулы из символов алфавита
системы);
- аксиомы системы — выделенное множество формул системы;
- правила вывода системы — конечное множество отношений между формулами системы.
Зададим логику первого порядка (или логику предикатов), на которой основывается Пролог. Язык логики предикатов — один из формальных языков, наиболее приближенных к человеческому языку.
Алфавит логики первого порядка составляют следующие символы:
- переменные (будем обозначать их последними буквами английского алфавита u, v, x, y, z);
- константы (будем обозначать их первыми буквами английского алфавита a, b, c, d);
- функциональные символы (используем для их обозначения ближние буквы f и g);
- предикатные символы (обозначим их дальними буквами p, q и r);
- пропозициональные константы истина и ложь (true и false);
- логические связки ¬ (отрицание), ∧ (конъюнкция), ∨ (дизъюнкция), → (импликация);
- кванторы:∃ (существования),∀ (всеобщности);
- вспомогательные символы (, ), ,.
Всякий предикатный и функциональный символ имеет определенное число аргументов. Если предикатный (функциональный) символ имеет n аргументов, он называется n-местным предикатным (функциональным) символом.
Термом будем называть выражение, образованное из переменных и констант, возможно, с применением функций, а точнее:
- всякая переменная или константа есть терм;
- если t1,...,tn — термы, а f — n-местный функциональный символ,то f(t1,...,tn) — терм;
- других термов нет.
По сути дела, все объекты в программе на Прологе представляются именно в виде термов.
Если терм не содержит переменных, то он называется основным или константным термом.
Атомная или элементарная формула получается путем применения предиката к термам, точнее, это выражение p(t1,...,tn), где p — n-местный предикатный символ, а t1,...,tn — термы.
Формулы логики первого порядка получаются следующим образом:
- всякая атомная формула есть формула;
- если A и B — формулы, а x — переменная, то выражения ¬A (читается «не A»
или «отрицание A»), A ∧ B (читается «A и B»), A ∨ B (читается «A или B»), A
→ B (читается «A влечет B»), ∃хA (читается «для некоторого x» или «существует x») и ∀xA (читается «для любого x» или «для всякого x»)– формулы;
- других формул нет.
В случае если формула имеет вид ∀xA или ∃хA, ее подформула A называется
областью действия квантора ∀x или ∃х соответственно. Если вхождение переменной
x в формулу находится в области действия квантора ∀
x или ∃х, то оно называется связанным
вхождением. В противном случае вхождение переменной в формулу называется свободным.
Чтобы не увеличивать чрезмерно объем лекции, мы не будем рассматривать полный список аксиом и правил вывода логики первого порядка.Те из них, которые пригодятся нам в дальнейшем, будут приведены в
соответствующих местах.
Литералом будем называть атомную формулу или отрицание атомной формулы. Атом называется положительным литералом, а его отрицание — отрицательным литералом.
Дизъюнкт — это дизъюнкция конечного числа литералов. Если дизъюнкт не содержит литералов, его называют пустым дизъюнктом и обозначают посредством символа ℵ.
Давайте посмотрим, как можно привести любую формулу к множеству дизъюнктов, с которым работает метод резолюций. Для этого нам понадобятся некоторые определения нормальных форм.
Говорят, что формула находится в конъюнктивной нормальной форме,если это конъюнкция конечного числа дизъюнктов. Имеет место теорема о том, что для любой бескванторной формулы существует
формула, логически эквивалентная исходной и находящаяся в конъюнктивной нормальной форме.
Формула находится в предваренной (или пренексной) нормальной форме, если она представлена в виде Q1x1,...,QnxnA, где Qi — это квантор ∀ или ∃
, а формула A не содержит кванторов. Выражение Q1x1,...,Qnxn называют префиксом, а формулу A — матрицей.
Формула находится в сколемовской нормальной форме, если она находится в предваренной нормальной форме и не содержит кванторов существования.
Алгоритм приведения произвольной формулы исчисления предикатов к множеству дизъюнктов
Первый шаг. Приводим исходную формулу к предваренной нормальной форме. Для этого:
- пользуясь эквивалентностью A → B ≡ ¬A ∨ B исключим импликацию;
- перенесем все отрицания внутрь формулы, чтобы они стояли только перед атомными формулами, используя следующие эквивалентности:
¬(A ∨ B) ≡ ¬A ∧ ¬B
¬(A ∧ B) ≡ ¬A ∨ ¬B
¬(∃xA) ≡ ∀x¬A
¬(∀xA) ≡ ∃x¬A
¬¬A ≡ A
- переименовываем связанные переменные так, чтобы ни одна переменная не входила в нашу формулу одновременно связанно и свободно.
- выносим кванторы в начало формулы, используя эквивалентности:
QxA(x) ∨ B ≡ Qx(A(x) ∨ B), если B не содержит переменной x, а Q ∈ {∀, ∃}
QxA(x) ∧ B ≡ Qx(A(x) ∧ B), если
B не содержит переменной x, а Q ∈ {∀, ∃}
∀xA(x) ∧ ∀xB(x) ≡ ∀x(A(x) ∧ B(x))
∃xA(x) ∨ ∃xB(x) ≡ ∃x(A(x) ∨ B(x))
Q1xA(x) ∨ Q2xB ≡ Q1xQ2y(A(x) ∨ B(y)), где Q ∈ {∀, ∃}
Q1xA(x) ∧ Q2xB ≡ Q1xQ2y(A(x) ∧ B(y)), где Q ∈ {∀, ∃}
Второй шаг. Проведем сколемизацию, т.е. элиминируем в формуле кванторы существования. Для этого для каждого квантора существования выполним следующий алгоритм.
Если устраняемый квантор существования — самый левый квантор в префиксе формулы, заменим все вхождения в формулу переменной, связанной этим квантором, на новую константу и вычеркнем квантор из
префикса формулы.
Если левее этого квантора существования имеются кванторы всеобщности, заменим все вхождения в формулу переменной, связанной этим квантором, на новый функциональный символ от переменных, которые
связаны левее стоящими кванторами всеобщности, и вычеркнем квантор из префикса формулы.
Проведя этот процесс для всех кванторов существования, получим формулу, находящуюся в сколемовской нормальной форме. Алгоритм устранения кванторов существования придумал Сколем в 1927 году.
Имеет место теорема о том, что формула и ее сколемизация эквивалентны в смысле выполнимости.
Третий шаг. Элиминируем кванторы всеобщности. Полученная формула будет бескванторной и эквивалентной исходной в смысле выполнимости.
Четвертый шаг. Приведем формулу к конъюнктивной нормальной форме, для чего воспользуемся эквивалентностями, выражающими дистрибутивность:
A ∨ (B ∧ C) ≡ (A ∨ B) ∧ (A ∨ C)
A ∧ (B ∨ C) ≡ (A ∧ B) ∨ (A ∧ C)
Пятый шаг. Элиминируем конъюнкции, представляя формулу в виде множества дизъюнктов.
Получаем множество дизъюнктов, эквивалентное исходной формуле в том смысле, который дает нам следующая теорема.
Теорема. Формула является тождественно ложной тогда и только тогда, когда множество дизъюнктов, полученных из нее, является невыполнимым.
Напомним, что множество формул называется невыполнимым, если не существует такого означивания переменных, чтобы все формулы из этого множества были бы истинными.
Пример. Превратим формулу ∀x(P(x) → ∃y(P(y) ∨ ¬Q(x,y))) в эквивалентное ей множество дизъюнктов.
Первый шаг. Приведем исходную формулу к предваренной нормальной форме. Элиминировав импликацию, получим формулу ∀x(¬P(x) ∨ ∃y(P(y) ∨ ¬Q(x,y))). Вынесем переменную y за скобки: ∀x∃y(¬P(x) ∨ (P(y) ∨
¬Q(x,y))). Это можно сделать, потому что формула ¬P(x) не зависит от переменной y. Если бы она зависела, то можно было бы
переименовать связанную переменную y.
Второй шаг. Проведем сколемизацию полученной формулы. Левее квантора существования стоит квантор всеобщности, значит, нужно заменить все вхождения переменной y новым унарным функциональным
символом, зависящим от x. Получим формулу, находящуюся в сколемовской нормальной форме: ∀x(¬P(x) ∨ (P(f(x) ∨ ¬Q(x,f(x)))).
Третий шаг. Элиминируем квантор всеобщности: ¬P(x) ∨
(P(f(x)) ∨ ¬Q(x,f(x))).
В четвертом и пятом шагах необходимости нет, поскольку формула уже представляет собой дизъюнкт: ¬P(x) ∨ P(f(x)) ∨ ¬Q(x,f(x)).
Следующая техника, лежащая в основе Пролога, с которой мы попробуем разобраться, — это унификация. Унификация позволяет отождествлять
формулы логики первого порядка путем замены свободных переменных на термы.
Подстановка — это множество вида {x1/t1,..., xn/tn}, где для всех i, xi — переменная, а ti — терм, причем xi≠ti (отображение переменных в термы). При этом все переменные, входящие в подстановку, различны (для любого i≠j xi≠xj).
Символом ε
будем обозначать пустую подстановку.
Подстановка, в которой все термы основные, называется основной подстановкой.
Простое выражение — это терм или атомная формула.
Если A — простое выражение, а θ — подстановка, то Aθ получается путем одновременной замены всех вхождений
каждой переменной из θA соответствующим термом. Aθ называется частным случаем (примером) выражения A.
Содержательно подстановка заменяет каждое вхождение переменной xi на терм ti.
Пусть θ и η — подстановки, θ={x1/t1,..., xn/tn}, η={y1/s1,...,yn/sn}. Композиция θη получается из множества
{x1/t1η,...,xn/tn(,y1/s1,..., yn/sn} удалением пар
xi/tiη, где xi≠tiη и пар yi/si, где yi совпадает с одним из
xj.
Пример. Пусть θ={x/f(y),y/z}, η={x/a,y/b,z/y}. Построим θη. Для этого возьмем множество
{x/f(b),y/y,x/a,y/b,z/y} и выбросим из него пары y/y (потому что заменяемая переменная совпадает с термом), ,x/a,y/b (потому что
заменяемая переменная из подстановки η совпадает с заменяемой переменной из подстановки θ). Получим ответ:
θη={x/f(b),z/y}.
Подстановка θ называется более общей, чем подстановка η, если существует такая подстановка γ, что η=θ γ.
Подстановка θ называется унификатором простых выражений A и B, если
Aθ=Bθ. Про A и B в такой ситуации говорят, что они унифицируемы. Унификация используется в
Прологе для композиции и декомпозиции структур данных.
Пример. A=p(f(x),z) и B=p(y,a) унифицируемы. Можно взять в качестве их унификатора подстановку
{y/f(x),z/a} или подстановку {y/f(a),x/a,z/a}.
Вообще говоря, две формулы могут иметь бесконечно много унификаторов. Унификатор θ называют наиболее общим (или простейшим) унификатором простых выражений A и B, если он является более общей подстановкой, чем все другие унификаторы простых выражений A и B.
Пример. В рассмотренном выше примере наиболее общим унификатором является подстановка {y/f(a),z/a}.
Пусть S — конечное множество простых выражений. Определим множество d(S) разногласий (рассогласований). Зафиксируем самую
левую позицию, на которой не во всех выражениях из S стоит один и тот же символ. Занесем в d(S) подвыражения выражений из S, начинающиеся с этой позиции.
Пример. Пусть S={p(f(x),h(y),a),p(f(x),z,a),p(f(x),h(y),b)}. Множество рассогласований для S d(S)={h(y),z}.
Алгоритм унификации
Дадим алгоритм поиска наиболее общего унификатора для конечного множества простых выражений S. В том случае, если это множество не унифицируемо, алгоритм должен
обнаруживать эту ситуацию.
Шаг 1. Полагаем k=0, δ
0=ε.
Шаг 2. Если Sδk — одноэлементное
множество, останавливаем алгоритм, δk — наиболее
общий унификатор для S. В противном случае строим множество рассогласований d(Sδk) и переходим к третьему шагу.
Шаг 3. Если в d(Sδk) существуют
переменная x и терм t такие, что x не входит в t, то полагаем что δk+1=δk{x/t}. Увеличиваем на единицу k, переходим ко второму шагу. Иначе останавливаем алгоритм,
множество S не унифицируемо.
Обратите внимание, что алгоритм унификации заканчивает свою работу за конечное число шагов для любого конечного множества простых выражений, потому что на каждом
проходе мы уменьшаем количество переменных. Так как множество простых выражений было конечным, то и множество различных переменных в нем конечно, и, значит, через число шагов, не превышающее
количества различных переменных, алгоритм завершится.
Утверждение о том, что для любого унифицируемого конечного множества простых выражений S алгоритм унификации закончит свою работу и
выдаст наиболее общий унификатор для S, называется теоремой унификации.
Теперь можно перейти к рассмотрению метода резолюций.
В чем вообще заключается задача? Мы хотим построить алгоритм, который позволял бы нам автоматически давать ответ на вопрос, может ли быть выведено некоторое заключение из множества имеющихся
посылок. Известно, что в общем случае даже для логики первого порядка такой алгоритм невозможен. Как правило, формальные системы, для которых можно построить подобный разрешающий алгоритм, обладают
небольшой выразительной силой. К ним, например, относится логика высказываний и логика одноместных предикатов.
Однако Робинсон решил, что правила вывода, используемые компьютером при автоматическом выводе, не обязательно должны совпадать с правилами вывода, используемыми при «человеческом» выводе. В
частности, он предложил вместо правила вывода «modus ponens», которое утверждает, что из A и A → B выводится B, использовать его обобщение, правило резолюции, которое сложнее
понимается человеком, но эффективно реализуется на компьютере. Давайте попробуем разобраться с этим правилом.
Правило резолюции для логики высказываний можно сформулировать следующим образом.
Если для двух дизъюнктов существует атомная формула, которая в один дизъюнкт входит положительно, а в другой отрицательно, то, вычеркнув соответственно из одного дизъюнкта положительное вхождение
атомной формулы, а из другого — отрицательное, и объединив эти дизъюнкты, мы получим дизъюнкт, называемый резольвентой. Исходные дизъюнкты в таком случае называются родительскими или
резольвируемыми, а вычеркнутые формулы — контрарными литералами. Другими словами, резольвента — это дизъюнкт, полученный из объединения родительских дизъюнктов вычеркиванием контрарных
литералов.
Графически это правило можно изобразить так:
(A ∨B, P ∨ ¬P)/A ∨ B
Здесь A ∨ P и B ∨ ¬P — родительские дизъюнкты, P и
¬P — контрарные литералы, A ∨ B — резольвента.
Если родительские дизъюнкты состояли только из контрарных литералов, то резольвентой будет пустой дизъюнкт.
Пример. Правило вывода «modus ponens» получается из правила резолюции, если взять в качестве родительских дизъюнктов C1=A,
C2=¬A ∨ B(≡ A → B). Контрарными литералами в
применении этого правила будут A и ¬A, резольвентой — формула B.
Сформулируем правило резолюции для логики первого порядка.
Пусть имеется два дизъюнкта C1 и C2, у которых нет общих переменных, L1 —
литерал, входящий в дизъюнкт C1, L2 — литерал, входящий в дизъюнкт C2. Если
литералы имеют наибольший общий унификатор θ, то дизъюнкт (C1θ–L1θ)∪(C2θ–L2θ) называется резольвентой дизъюнктов C1 и C2. Литералы L1 и L2 называются контрарными литералами. То же правило записывается в
графическом виде как
(A ∨ P2, B ∨ ¬P2)/(A ∨ B)θ
Здесь P1 и P2 — контрарные литералы, (A ∨ B)θ — резольвента, полученная из дизъюнкта (A ∨B) применением унификатора θ, A ∨ P1 и B ∨ P2 — родительские дизъюнкты, а θ — наибольший общий унификатор P1 и P2.
Метод резолюций является обобщением метода «доказательства от противного». Вместо того чтобы пытаться вывести некоторую формулу-гипотезу из имеющегося
непротиворечивого множества аксиом, мы добавляем отрицание нашей формулы к множеству аксиом и пытаемся вывести из него противоречие. Если нам удается это сделать, мы приходим к выводу (пользуясь
законом исключенного третьего), что исходная формула была выводима из множества аксиом. Опишем более подробно.
Добавим отрицание исходной формулы к множеству посылок, преобразуем каждую из этих формул во множество дизъюнктов, объединим получившиеся множества дизъюнктов и попытаемся вывести из этого
множества дизъюнктов противоречие (пустой дизъюнкт ℵ). Для этого будем выбирать из нашего множества дизъюнкты, содержащие унифицируемые контрарные литералы, вычислять их
резольвенту по правилу резолюции, добавлять ее к исследуемому множеству дизъюнктов. Этот процесс будем продолжать до тех пор, пока не выведем пустой дизъюнкт.
Возможны, вообще говоря, три случая:
- Этот процесс никогда не завершается.
- Среди текущего множества дизъюнктов не окажется таких, к которым можно применить правило резолюции. Это означает, что множество дизъюнктов выполнимо, и, значит, исходная формула не выводима.
- На очередном шаге получена пустая резольвента. Это означает, что множество дизъюнктов невыполнимо и, следовательно, начальная формула выводима.
Имеет место теорема, утверждающая, что описанный выше процесс обязательно завершится за конечное число шагов, если множество дизъюнктов было невыполнимым.
С другой стороны, мы опираемся на результат, что формула выводима из некоторого множества формул тогда и только тогда, когда описанное множество дизъюнктов невыполнимо. А также на то, что
множество дизъюнктов невыполнимо тогда и только тогда, когда из него применением правила резолюции можно вывести пустой дизъюнкт.
В сущности, метод резолюций несовершенен и приводит к «комбинаторному взрыву». Однако некоторые его разновидности (или стратегии) довольно эффективны. Одной из самых
удачных стратегий является линейная или SLD-резолюция для хорновских дизъюнктов (Linear resolution with Selection function for Definition clauses), то есть
дизъюнктов, содержащих не более одного положительного литерала. Их называют предложениями или клозами.
Если дизъюнкт состоит только из одного положительного литерала, он называется фактом. Дизъюнкт, состоящий только из отрицательных литералов, называется вопросом (или целью или
запросом). Если дизъюнкт содержит и позитивный, и негативные литералы, он называется прави- лом. Правило вывода выглядит примерно следующим образом ¬A1 ∨ ¬A2...¬An ∨ B. Это эквивалентно формуле A1 ∧ A2... ∧An → B, которая на Прологе записывается в виде
B:–A1,A2,...,An.
Логической программой называется конечное непустое множество хорновских дизъюнктов (фактов и правил).
При выполнении программы к множеству фактов и правил добавляется отрицание вопроса, после чего используется линейная резолюция. Ее специфика в том, что правило резолюции применяется не к
произвольным дизъюнктам из программы. Берется самый левый литерал цели (подцель) и первый унифицируемый с ним дизъюнкт. К ним применяется правило резолюции. Полученная резольвента добавляется в
программу в качестве нового вопроса. И так до тех пор, пока не будет получен пустой дизъюнкт, что будет означать успех, или до тех пор, пока очередную подцель будет невозможно унифицировать ни с
одним дизъюнктом программы, что будет означать неудачу.
В последнем случае включается так называемый бэктрекинг — механизм возврата, который осуществляет откат программы к той точке, в которой выбирался унифицирующийся с последней подцелью дизъюнкт.
Для этого точка, где выбирался один из возможных унифицируемых с подцелью дизъюнктов, запоминается в специальном стеке, для последующего возврата к ней и выбора альтернативы в случае неудачи. При
откате все переменные, которые были означены в результате унификации после этой точки, опять становятся свободными.
В итоге выполнение программы может завершиться неудачей, если одну из подцелей не удалось унифицировать ни с одним дизъюнктом программы, и может завершиться успешно, если был выведен пустой
дизъюнкт, а может и просто зациклиться.