V. Правила.
Применение правил имеет значительные преимущества перед простым перечислением некоторых отношений. Применяя правила, программист может выразить общий закон, управляющий отношением. Например, вопрос: “Имеют ли Абрамов и Федоров одинаковые звания?”
?-военный (фамилия(‘Абрамов’),R),военный(фамилия(‘Федоров’),R).
Этот вопрос представлен конъюнкцией двух функций.
Теперь выразим закон: “Два любых военнослужащих имеют одинаковое звание, если каждый из них имеет звание R.”
одинаковое_ звание (А, В):-
военный (А,R),
военный (В,R).
Правило имеет заголовок и тело, которые разделяются специальным символом “:-”, который называется (произносится) “если”. Тело правила состоит из одной или нескольких подцелей, которые разделяются запятой. Каждая цель может быть структурой. В конце правила ставится знак завершения – точка.
В приведенном примере:
одинаковое_ звание (А, В):- -заголовок правила,
военный (А,R), военный (В, R). -тело правила,
военный (А,R) -первая подцель,
военный (В,R). -вторая подцель.
Приведенное правило говорит о том, что отношение в заголовке правила имеет место, если имеют место все отношения в теле правила. Таким образом, смысл правила в приведенном примере таков:
“Истинно то, что военный А имеет то же самое звание, что и военный В,
если истинно то, что военный А имеет звание R, и то, что военный В
имеет звание R.”
Добавим это правило к нашей программе:
военный (фамилия ('Павлов'), звание ('генерал')).
военный (фамилия ('Климов'), звание ('полковник')).
военный (фамилия ('Максимов'), звание ('полковник')).
военный (фамилия ('Тихонов') звание ('сержант')).
военный (фамилия ('Николаев'), звание ('сержант')).
военный (фамилия ('Абрамов'), ' звание (капитан ')).
военный (фамилия ('Дмитриев') звание ('лейтенант')).
военный (фамилия ('Федоров'), звание ('капитан')).
военный (фамилия ('Дарьин'), звание ( ‘майор')).
одинаковое_ звание (А, В):-
военный (А,R),
военный (В,R).
Теперь форма вопроса, который раньше состоял из двух функций будет следующей:
?-одинаковое_ звание (фамилия (’Абрамов’)), фамилия(‘Федоров’))
ответом будет:
да
Существуют другие возможности использования этого правила. Например, если мы хотим задать вопрос: “Кто из военнослужащих имеет то же звание, что и Максимов?” мы должны задать его следующим образом:
?- одинаковое_ звание (Военный, фамилия (‘Максимов’)).
и получим ответ:
Военный = фамилия (‘Климов’);
Военный = фамилия (‘Максимов’);
нет
Можно задать вопрос, эквивалентный данному:
?- одинаковое_ звание (фамилия(‘Максимов’), Военный).
При этом ответы будут теми же.
Может показаться странным, почему Пролог выдал второй ответ. Но это действие является правильным потому, что в правиле ничего не говориться о том, что военнослужащие должны быть разными людьми. Поэтому является истинным, что каждый военнослужащий имеет то же звание, что и он сам.
Можно задать и такой вопрос: “Какие военные имеют одинаковые звания?”
На Прологе вопрос формулируется так:
?- одинаковые_ звания (X,Y).
Возможны различные варианты подстановок для XиY. Приведем начало этого списка:
X= фамилия (‘Павлов’)
Y= фамилия (‘Павлов’)
X= фамилия (‘Климов’)
Y= фамилия (‘Климов’)
X= фамилия (‘Климов’)
Y= фамилия (‘Максимов’)
X= фамилия (‘Максимов’)
Y= фамилия (‘Климов’)
X= фамилия (‘Максимов’)
Y= фамилия (‘Максимов’)
X= фамилия (‘Тихонов’)
Y= фамилия (‘Тихонов’)
X= фамилия (‘Тихонов’)
Y= фамилия (‘Николаев’)
X= фамилия (‘Николаев’)
Y= фамилия (‘Тихонов’)
и т. д.
По тому, как порождаются эти ответы, становится ясным, что Пролог не только перечисляет идентичные пары, но и выдает дубликаты, связанные с реверсивными подстановками. Это происходит в силу рефлексивности отношения одинаковое_ звание. Такое дублирование ответов Прологом является абсолютно правильным, хотя и ненужным.