Описание данных и знаний в языке пролог
Факты. Прежде чем ввести некоторый факт, выражаемый на естественном языке в БД, нужно его представить в терминах языка Пролог. Например, факт "Виктор является отцом Оли" может быть проанализирован следующим образом: "быть отцом кого-нибудь" - отношение; " Виктор, Оля " - объекты.
На языке Пролог этот факт запишется в виде: отец(виктор,оля).
При написании предложений на языке Пролог нужно соблюдать следующие правила: имена объектов и отношений состоят из букв, цифр, знака подчеркивания и начинаются со строчной буквы; имена переменных начинаются с прописной буквы; первым в .предложении указывается имя отношения, за которым в скобках записываются имена объектов, разделяемых запятыми; факт заканчивается точкой.
Заметим, что необходимо учитывать порядок перечисления объектов в скобках. Он может быть произвольным, но, выбрав определенный порядок, следует сохранять его и далее. Рассмотрим примеры фактов, приведенных вместе с возможной их интерпретацией:
мужчина (виктор). - Виктор - мужчина;
нравится (виктор, анна). - Виктору нравится Анна;
изучает(виктор, пролог). - Виктор изучает Пролог;
руководит(виктор, работа, сту- - Виктор руководит работой
дент). студента
Имена объектов в круглых скобках называются аргументами, а имя отношения перед круглыми скобками – предикатом. Таким образом, "изучает" – это предикат, а "виктор" и "пролог" – аргументы. Предложение с одним предикатом и относящимися к нему аргументами называют термом. Имена объектов и отношений выбираются произвольно и вместо терма "изучает (виктор, пролог)" можно написать: а(Ь,с), где
а - изучает, b - виктор, с - пролог.
Отношения могут иметь произвольное число аргументов, например:
играть (виктор,таня,оля,даша),
что означает "Виктор играет с Таней, Олей, Дашей".
Совокупность фактов составляет часть БЗ. Рассмотрим БЗ семейных отношений:
мужчина(виктор).
женщина(анна).
муж(виктор,анна).
отец(виктор,таня).
отец(виктор,оля).
отец(виктор,даша).
Имея БЗ, т.е. совокупность фактов, можно обращаться к Прологу с вопросами, которые записываются так же, как и факты, например:
отец(виктор.таня).
Смысл этого вопроса заключается в следующем: "Является ли Виктор отцом Тани?" На заданный вопрос получаем ответ:
True (истина).
Рассмотрим более сложный вопрос: "Отцом каких детей является Виктор?" Для получения ответа можно было бы задать три вопроса (см. последние три факта в БЗ), которые соответствуют трем фактам. Более рациональным был бы вопрос: "Является ли Виктор отцом X ?", где X - переменная.
Переменные в Прологе начинаются с прописной буквы. Они могут иметь конкретные значения (конкретизированы) или не иметь их. Названный выше вопрос на Прологе имеет вид:
отец(виктор,Х).
Для поиска ответа Пролог просматривает имена всех объектов, отец которых - Виктор. Обнаружив такой факт, система выдает его на терминал (в нашем случае "таня". "оля","даша").
Вопрос отец (Х,оля) означает "Кто является отцом Оли?", т.е. Х=виктор.
Рассмотрим соединение (конъюнкцию) нескольких подвопросов в одном вопросе, используя следующую БЗ:
нравится(виктор,анна).
нравится(виктор,пролог).
нравится(анна,виктор).
нравится(анна,пролог).
Мы хотим узнать, нравятся ли Виктор и Анна друг другу. Для этого требуется сформулировать вопрос, включающий конъюнкцию двух указанных целей, которые необходимо согласовать с БЗ.
Обе цели отделяются в вопросе знаком ",":
нравится(виктор,анна),нравится(анна,виктор).
Знак "," применяется в качестве логической операции И для соединения произвольного количества целей.
Сочетая возможности конъюнкции и использования переменных, можно строить достаточно сложные вопросы. Например, вопрос " Что нравится обоим - Виктору и Анне?" имеет вид: нравится (виктор,Х), нравится(анна,Х).
Пролог находит факт, соответствующий первой цели, и пытается подобрать факт, удовлетворяющий второй цели таким образом, чтобы переменная X имела одинаковые значения.
Рассмотрим теперь полную программу на языке Пролог, включающую помимо фактов описание аргументов и предикатов (для того, чтобы сделать изложение более понятным, все имена приведены в русской транскрипции):
domains
имя=symbol
predicates
отец(имя,имя)
муж(имя,имя)
clauses
отец(виктор,таня).
отец(виктор,оля).
отец(виктор,даша).
отец(владимир,виктор).
отец(владимир,сергей).
муж(виктор,анна).
муж(владимир,люда).
В первой части программы "domains" дается определение аргументов. Во второй части программы "predicates" указывают формат используемых предикатов. В части программы "clauses" записываются факты и правила. (Подробное описание структуры программы на Турбо-Прологе дается в следующем параграфе). На запрос
Goal: отец(Х, Y).
система Пролог отвечает:
Х=виктор, Y =таня
Х=виктор, Y =оля
Х=виктор, Y =даша
Х=владимир, Y =виктор
Х=владимир, Y=cepreй
Две выходные переменные X и Y называют соответственно каждого отца и каждого ребенка. В следующем примере используется только одна переменная:
Goal: отец(виктор, Y).
Y =таня
Y =оля
Y =даша
В запросе
Goal: отец (виктор, Владимир).
False
применяются только константы. В этом случае запрос требует проверки существования факта в БД. При наличии факта система выдает ответ "True" (истина), при отсутствии - "False" (ложь). На запрос Goal: отец(николай,Х) система отвечает: No solution (нет решения).
Правила. В Прологе правило формируется в том случае, когда некоторый факт зависит от группы других фактов, т.е. когда в естественном языке требуется использовать слово "если", например: "Рейс отменяется, если погода не летная", "рейс отменяется, если испорчен самолет"; "X является сестрой Y, если X является женщиной и X и Y имеют одних и тех же родителей".
Правило состоит из заголовка и тела. Заголовок и тело соединяются с помощью символа ":-" или if (если). Так, предложение "Виктору нравится любой студент, которому нравится учеба" записывается в виде следующего правила:
нравится(виктор, X):-
студент(Х),нравится(Х,учеба).
Рассмотрим правила, содержащие более одной переменной, для чего используем следующую БД:
мужчина(виктор).
женщина(анна).
женщина(таня).
женщина(оля).
женщина(даша).
родители(виктор,анна,таня).
родители(виктор,анна,оля).
родители(виктор,анна,даша).
Предикат "родители(Х,У,Z)", имеющий три аргумента, означает "Родителями Z являются X и Y", где X - отец; Y -мать.
Утверждение "X является сестрой Y" истинно, если X -женщина и X, Y имеют одних и тех же родителей. Это можно записать в виде правила:
сестра(Х, Y):-
женщина(Х),родители(О,М,Х),родители(O,M, Y).
где переменные О и М - отец и мать соответственно. Эти переменные вначале не конкретизированы и им присваивается значение в момент установления соответствия для предиката родители(O,М,Х).
Правила, состоящие из фактов. Правила в БД могут состоять из фактов. Рассмотрим следующую БД:
domains
имя=symbol
predicates
отец(имя,имя)
мать(имя,имя)
clauses
отец(павел,юлия).
мать(юлия,михаил).
Для того, чтобы узнать, кто является дедом Михаила по материнской линии, нужно задать вопрос отец(Х, Y), мaть(Y,михаил). Чтобы получишь решение, Пролог должен решить первую часть вопроса до запятой и только потом – вторую. Следовательно, будет анализироваться факт "отец(Х, Y)". В нашей БД имеется только один факт с предикатом "отец" и поэтому Х=павел, Y =юлия. Затем Пролог ищет предикат "мать(Y,михаил)" более точно. Поскольку значение Y - "юлия" было только что найдено, то нужно искать факт "мать(юлия,михаил)". Последний имеется в БД и поэтому выдается решение: Х=павел, т.е. "Павел - дед Михаила".
Можно улучшить данное описание БД, объединив цели "отец", "мать" в одно правило:
дед(Х, Y):-
отец(Х,Z),
мать(Z,Y).
которое читается так:
X является дедом Y, если X является отцом Z и Z является матерью Y.
Заметим, что приведенное выше правило можно представить в виде факта "дед(Х,У)". Нетрудно видеть, что правило является более компактным описанием, чем множество, фактов.
Правила, состоящие из фактов и правил. Имеется возможность определить правила, которые состоят из правил, а последние, в свою очередь, тоже могут состоять из правил, и т.д.
Рассмотрим такую БД:
domains
имя=symbol
predicates
отец(имя,имя)
супруг(имя,имя)
дед(имя,имя)
мать(имя,имя)
clauses
/* 1 */ отец(андрей,алексей).
/* 2 */ отец(федор.мария).
/* 3 */ отец(алексей,лариса).
/* 4 */ отец(алексей,владимир).
/* 5 */ супруг(алексей,мария).
/* 6 */ дед(Х, Y):-
отец(Х,Z),
отец(Z, Y).
/* 7 */ дед(Х, Y):-
отец(Х,Z),
мать(Z,Y).
/* 8 */ мать(Х, Y):-
супруг(Z,X),
отец(Z,Y).
Правило 8 говорит о том, что мать (X) ребенка (Y) является супругой отца (Z) этого ребенка. И на запрос
мать(Х, Y)
Пролог выдает решение:
Х=мария, Y =лариса
Х=мария, Y =владимир
Правила 6 и 7 называют соответственно деда по отцу и деда по матери.
Рассмотрим в БД факт или правило, которые могут быть унифицированы с запросом дед(Х, Y). Вначале он находит правило 6 и выдает ответ:
Х=андрей, Y =лариса
Х=андрей, Y =владимир
Затем в соответствии с принципом выбора всех решений Пролог переходит к правилу 7 и анализирует первую подцель правила: "отец(андрей,алексей)", и вторая подцель "мать(алексей, Y)" приводит к тупику.
Рассмотрим более детально на уровне переменных, как подцель "мать(Z,Y)" унифицируется с правилом
мать(Х, Y):-
супруг(Z,X),
отец(Z, Y).
Для унификации нужно, чтобы Z стало X и Y=Y, т. е. можно говорить, что все экземпляры X из правила станут экземплярами Z. Однако переменная Z уже имеется в правиле и не должна смешиваться с новой переменной Z. Поэтому интерпретатор переименовывает переменные: XI вместо X, Y1 вместо Y и т.д. Заметим, что в нашем примере Y подцели случайно совпала с Y из правила. Интерпретатор в памяти строит таблицу соответствия новых и старых переменных.
Рассмотрим процесс унификации, когда Z заменяется X1, а Y – Y1:
В результате унификации переменных правило 7 в БД будет иметь следующий вид:
дед(Х,Y1):-
отец(Х,Х1),
супруг(Z1,X1),
отец(Z1,Y1).
Для запроса "мать(Z,Y)" интерпретатор найдет Х=федор, Х1=мария, X1=алексей и два значения Y: Y=лариса и Y=владимир. Естественно, что интерпретатор Пролога не функционирует точно таким образом, как мы описали.