Предположим, мы хотим сформулировать утверждение, что Джону нравятся все люди. Один из способов сделать это заключается в записи для каждого человека, упоминаемого в базе данных, отдельного факта:
нравится(джон,альфред).
нравится(джон,бертран).
нравится(джон,чарлз).
нравится(джон,дейвид).
* * *
Это было бы очень утомительным, особенно если в нашей программе на Прологе упоминается несколько сот человек. Другой способ выразить факт, что Джону нравятся все люди, - это сказать Джону нравится любой объект при условии, что этот объект является человеком. Здесь этот факт представлен в форме правила для определения того, что нравится Джону, а не прямого перечисления всех людей, которые ему нравятся. В ситуации, когда Джону мог бы нравиться любой человек, представление утверждения в виде правила является значительно более компактным, чем список фактов.
В Прологе правила используются в том случае, когда необходимо сказать, что некоторый факт зависит от группы других фактов. В естественном языке для выражения правила мы можем использовать слово если. Например:
• Я пользуюсь зонтом, если идет дождь.
• Джон покупает вино, если оно дешевле, чем пиво.
Правила используются также для выражения определений, например:
X является птицей, если:
X является живым существом и X имеет перья.
или
X является сестрой Y , если:
X является женщино и X и Y имеют одних и тех же родителей.
В последних примерах мы использовали переменные X и Y . Важно помнить, что каждое вхождение переменной в правило обозначает один и тот же объект. Иначе мы разрушили бы саму суть определения. Например, используя приведенное выше определение птицы, мы не смогли бы показать, что Фред является птицей на основании того, что Фидо – это живое существо, а Мэри имеет перья. Этот принцип согласованной интерпретации переменных справедлив также и для правил в Прологе.
Правило – это некоторое общее утверждение об объектах и об отношениях между ними. Например, мы можем сказать, что Фред является птицей, если Фред является живым существом и Фред имеет перья, мы можем также сказать, что Бертрам является птицей, если Бертрам является живым существом и Бертрам имеет перья. Таким образом, мы допускаем, что при каждом новом использовании правила переменная обозначает новый, отличный от прежнего объект. Конечно, в рамках конкретного использования правила переменные интерпретируются согласованно, как на это указывалось выше.
Рассмотрим несколько примеров, начав с правила, содержащего одну переменную и конъюнкцию:
Джону нравится любой, кому нравится вино, или,
другими словами,
Джону нравится что-то, если чему-то нравится вино,
или, используя переменные,
Джону нравится X , если X нравится вино.
В Прологе правило состоит из заголовка и тела правила. Заголовок и тело соединяются с помощью символа :-, который состоит из двоеточия : и тире - . Символ ':-' читается если.
Предыдущий пример записывается на Прологе следующим образом:
нравится(джон,X):- нравится(Х,вино).
Отметим, что правила также заканчиваются точкой. Заголовком этого правила является нравится(джон,Х). Заголовок правила описывает факт, для определения которого предназначено это правило. Тело правила, в данном случае нравится(Х,вино), описывает конъюнкцию целей, которые должны быть последовательно согласованы с базой данных, для того чтобы заголовок правила был истинным. Например, мы можем сделать Джона более разборчивым в выборе тех, кто ему нравится, просто добавив к телу правила еще несколько целевых утверждений, разделив их запятыми:
нравится(джон,X):- нравится(Х,вино), нравится(X,пища).
или, другими словами, Джону нравится любой, кому нравятся вино и пища. Или, предположим, что Джону нравится любая женщина, которой нравится вино:
нравится(джон,Х):- женщина(Х), нравится(Х,вино).
Всякий раз, когда мы имеем дело с правилом в Прологе, необходимо отмечать все вхождения переменных. В последнем примере переменная X использована три раза. Всякий раз, как переменная X конкретизируется некоторым объектом (ей присваивается значение), все вхождения X в пределах области действия этой переменной становятся конкретизированными. При каждом употреблении правила область действия переменной X – это все правило, начиная с заголовка и до точки '.' в конце этого правила. Так, если в приведенном выше правиле переменная X оказалась конкретизированной, принимая значение мэри, то Пролог попытается согласовать с базой данных целевые утверждения женщина(мэри) и нравится(мэри,вино).
Теперь, чтобы продемонстрировать правило, использующее более одной переменной, рассмотрим базу данных, содержащую факты о семействе королевы Виктории. Мы будем использовать предикат родители, имеющий три аргумента. родители(Х, Y, Z) означает: Родителями X являются Y и Z . Переменная Y обозначает мать, а переменная Z обозначает отца. Кроме того, мы будем использовать предикаты женщина и мужчина в их очевидном значении. Некоторая часть этой базы данных могла бы выглядеть следующим образом:
мужчина(альберт).
мужчина(эдуард).
женщина(алиса).
женщина(виктория).
родители(эдуард,виктория,альберт).
родители(алиса,виктория,альберт).
Здесь мы воспользуемся описанным ранее правилом является_сестрой. Правило определяет предикат является_сестрой , имеющий два аргумента, таким образом, что является_сестрой(X, Y) истинно, если X является сестрой Y . Обратим внимание на использование в имени предиката символа подчеркивания '_'. Хотя до сих пор не было дано полных правил конструирования имен, отметим, что допускается использование подчеркивания в именах, а более подробно об этом будет сказано в следующей главе. Тогда X является сестрой Y , если:
• X является женщиной,
• X имеет мать М и отца F и
• Y имеет тех же мать и отца, что и X .
Это можно записать в виде следующего правила Пролога:
является_сестрой(X,Y):- женщина(X), родители(X,M,P), родители(Y,M,P).
Мы используем переменные M и F для обозначения матери и отца, хотя при желании мы могли бы использовать имена Мать и Отец . Отметим, что мы употребляем переменные, которые не появляются в заголовке правила. Эти переменные, M и F , обрабатываются таким же образом, как и любая другая переменная. Когда Пролог использует это правило, переменные M и F изначально будут неконкретизированными. Этим переменным будет присвоено некоторое значение в момент установления соответствия для предиката родители(X,M,F) . Однако, как только они конкретизируются, становятся конкретизированными и все вхождения переменных M и F , соответствующие текущему использованию правила. Следующий пример должен помочь объяснить, как используются эти переменные. Давайте зададим вопрос:
?- является_сестрой(алиса,эдуард).
Имея описанные выше базу данных и правила является_сестрой и получив такой вопрос, Пролог выполняет следующие действия:
1. Сначала вопрос сопоставляется с единственным правилом для предиката является_сестрой , приведенным выше. При этом переменная X конкретизируется, принимая значение алиса , и переменная Y конкретизируется значением эдуард . Правило, с которым произошло сопоставление, отмечается маркером. Теперь Пролог пытается последовательно согласовать с базой данных три предиката, входящие в тело правила. |