Ярославский Государственный Университет им. П.Г. Демидова
Опубликован: 06.11.2008 | Доступ: свободный | Студентов: 987 / 62 | Оценка: 4.50 / 4.00 | Длительность: 10:47:00
Лекция 7:

Язык ПРОЛОГ: основные конструкции

< Лекция 6 || Лекция 7: 12 || Лекция 8 >

Правила

Хотя универсальные факты могут сократить запись, но все же использование только этого приема не всегда позволяет создать обозримую базу знаний либо в принципе не позволяет ее создать.

Приведем следующий пример. Необходимо создать базу знаний для определенного круга лиц, которая могла бы выразить родственные их связи. Рассмотрим естественный путь, при котором задаются отношения отец, мать, дочь, сын. С одной стороны, эти отношения могут оказаться избыточными или вести к серьезным логическим ошибкам из-за того, что некоторые факты не введены. Скажем, у двух лиц есть отношение отец, но нет симметричного отношения сын. С другой стороны, очень непросто написать предикаты для установления родства между любыми двумя лицами при таком задании фактов. Казалось бы, выход может быть найден, если ввести другие отношения, например, брат, сестра, кузен, кузина, дедушка, бабушка, внук, внучка. Но и в этом случае корректность программы (совокупности фактов) в связи с большой избыточностью будет трудно проверять, а проблемы с простым установлением родства двух любых лиц останутся.

Выходом может быть введение помимо двух отношений отец и мать отношения предок, частным случаем которого являются первые 2 отношения. В результате для выявления родства между любыми двумя лицами достаточно написать предикат, который устанавливает, является ли одно из лиц предком другого либо имеется ли у этих лиц общий предок. Это значительно проще, но надо ввести помимо фактов для отношений отец и мать правило, которое позволяет ввести отношение предок и в то же время не заставляет описывать дополнительные факты для этого отношения.

Правило Пролога есть продукция, посылкой которой является конъюнкция атомарных предикатов, а заключением - 1 атомарный предикат. Правило имеет следующий синтаксис:

A <- B1,..., Bm (m >= 0),

где A, B_{i} (i  \in  \overline {1,m}) - атомарные предикаты и запятая в правой части правила означает конъюнкцию. Читать правило нужно так: "Если B1 и B2 и т.д. и Bm, то A." Нетрудно видеть, что факт Пролога есть правило с пустой правой частью ( m=0 ). Левая часть правила называется его заголовком, а правая часть - телом правила . Совокупность правил с одним и тем же предикатом в заголовке называется процедурой .

Решение вышеописанного примера состоит в определении отношения предок следующим образом: предком лица является либо мать, либо отец, либо мать предка, либо отец предка. Таким образом все решение сводится к следующей процедуре из 4 правил:

предок (X, Y) <- мать (X, Y)
предок (X, Y) <- отец (X, Y)
предок (X, Y) <- предок (Z, Y), мать (X, Z)
предок (X, Y) <- предок (Z, Y), отец (X, Z)

Заметим, что отношение предок определено этими правилами рекурсивно. Теперь для определения родства между двумя лицами достаточно также задать рекурсивно отношение родственники следующей процедурой из 3 правил:

родственники (X, Y) <- предок (X, Y)
родственники (X, Y) <- предок (Y, X)
родственники (X, Y) <- предок (Z, X), предок (Z, Y)

Заметим, что обозначения переменных в правилах несущественны, лишь бы они обозначались одинаково в заголовке и теле процедуры. Но если на все переменные левой части подразумевается наложенным квантор всеобщности \forall, то на все переменные правой части, которые отсутствуют в левой, подразумевается наложенным квантор существования \exists.

Совокупность фактов и правил образует программу Пролога (или базу знаний).

Запросы

Запросы - это цели выполнения программы Пролога. Запрос является атомарным предикатом или конъюнкцией атомарных предикатов и имеет синтаксис:

<- B1,..., Bm (m > 0),

где B_{i} (i \in  \overline {1,m}) - атомарный предикат, а запятая, разделяющая атомы, означает операцию конъюнкции. Обозначение переменных запроса несущественно, и при переобозначении каждой переменной запрос не изменяется.

Если запрос не имеет переменных, то ответом на запрос является значение "Да" в случае, когда истинность конъюнкции предикатов запроса следует из истинности конъюнкции фактов и правил программы, и значение "Нет" в противном случае.

Если запрос имеет переменные, то по умолчанию подразумевается квантор существования перед конъюнкцией предикатов запроса для каждой переменной запроса. Если для какого-либо набора \Upsilon значений переменных запроса и какого-либо соответствующего переобозначения переменных в правилах и фактах и придания им согласованных с запросом значений истинность конъюнкции предикатов запроса следует из истинности конъюнкции фактов и правил, то такой набор \Upsilon является ответом на запрос. Вычисления Пролога состоят в получении всех ответов \Upsilon _{1}, \Upsilon ,... на запрос. Однако если не существует такого набора значений переменных запроса, который ведет к следованию истинности запроса из истинности фактов и правил программы, то ответом на запрос является значение "Нет". Отметим лишь, что данное определение не является достаточно четким и мы его в дальнейшем уточним.

Рассмотрим пример программы, которая образована из следующей совокупности фактов

отец (иван, петр) <-
отец (петр, анна) <-
отец (яков, мария) <-
мать (анна, федор) <-
мать (елена, иван) <-
мать (елена, яков) <-
мать (софья, вера) <-

Пусть имеется запрос

<- родственники (федор, мария).

Этот запрос не имеет переменных. Но правила процедуры предок позволяют установить, что предками федора являются анна, петр, иван и елена, а предками марии являются яков и елена. Поскольку федор и мария имеют общего предка елену, то правила процедуры родственники позволяют установить истинность запроса. Поэтому ответ на него Да.

Для запроса

<- родственники (вера, мария).

не удается установить его верность, так как ни вера не является предком марии, ни мария не является предком веры и нет у них общего предка. Поэтому ответ на запрос Нет.

Пусть теперь имеется запрос

<- предок (X, федор).

Этот запрос требует установить всех лиц, которые являются предками федора. Ответы на запрос образуют список анна, петр, иван, елена значений переменной X, каждое из которых логически выводится из фактов и правил.

Рассмотрим другой запрос

<- предок (елена, X).

Этот запрос требует установить всех лиц, для которых елена является предком (потомки елены ). Ответы на запрос образуют список иван, яков, петр, мария, анна, федор.

Наконец, для запроса

<- предок (вера, X)

нет ни одного значения переменной X, при котором мы могли бы вывести это отношение. Поэтому ответом на запрос является Нет, т. е. вера не имеет потомков.

Рассмотренные примеры показывают, что вопросы (при помощи переменных) можно задавать к любой части запроса. Однако мы не определили, как происходят вычисления в Прологе, дающие эти результаты.

Упражнения

  1. Разработайте базу знаний для программных кодов с отношением включает, если один программный код включает в себя другой код (задать возможно меньшее число фактов для разрабатываемой программной системы), и запрос, который проверяет, включен ли первый код во второй код.
  2. Для базы знаний первого упражнения написать запрос, который для двух произвольных кодов проверяет, включен ди один из них в другой.
  3. Для базы знаний первого упражнения написать запрос, который для заданного кода выдает все коды, которые его включают.
  4. Для базы знаний первого упражнения написать запрос, который для заданного кода выдает все коды, которые он включает.
< Лекция 6 || Лекция 7: 12 || Лекция 8 >