Prolog урок 2. Базы фактов, цели и запросы

Данный урок посвящен базовым понятиям языка Prolog. Так, на уроке будут изучаться основы написания программ на Прологе

Нормальная форма Бэкуса-Наура

Для начала вспомним нормальную форму Бэкуса-Наура (БНФ), которая была создана для формального описания синтаксиса языков программирования в 1960 году. Ее авторы — Джон Бэкус и Питер Наур.

Итак, в БНФ приняты следующие обозначения:

1.

Символ ::= читаемый как «по определению» («это», «есть»). Слева от символа располагается объясняемое понятие, справа — разъясняющая конструкция. Например,

<Имя> ::= <Идентификатор>

2.

Части выражения, используемые для обозначения синтаксической конструкции языка, берутся в угловые скобки; в нашем примере это <Имя> и <Идентификатор>.

3.

Символ | означает  логическое  «или» и применяется для разделения различных равнозначных альтернативных объяснений определяемого понятия.

Используя данный символ можно, например, определить десятичную цифру:

<цифра> ::= 0|1|2|3|4|5|6|7|8|9

4.

Если часть конструкции заключена в квадратные скобки [], то это означает, что она является необязательной, т.е. может отсутствовать.

Так запись

<Целое число> ::= [-]<Положительное целое число>

говорит о том, что целое число можно объяснить как положительное целое число, перед которым может стоять знак минус (а может и не стоять).

5.

Символ * указывает на то, что стоящая перед ним синтаксическая конструкция может повторяться произвольное количество раз (начиная с ноля и выше). Вместо символа *  иногда используются фигурные скобки ( {, } ), по сути равнозначные ему.

Снова определим положительное целое число, используя  нотацию БНФ :

<Положительное целое число> ::= <цифра>[<цифра>]*.

Что означает, что положительное целое число состоит из одной или нескольких цифр.

Структура программы на языке Prolog

Стандартная программа на языке Prolog состоит из следующих разделов:

  1. Constants
  2. Необязательный раздел определения констант.

  3. Domains
  4. Раздел описания доменов (аналогичен описанию типов данных).

    В Turbo Prolog можно выделить простые типы данных:
    char — символьный тип
    integer — целое число
    real — вещественное число
    string — последовательность символов типа char, которая заключена в кавычки
    symbol — последовательность букв латинского алфавита, цифр и знаков подчеркивания, которая начинается со строчной буквы (тогда без кавычек) или заключена в кавычки (тогда можно с прописной буквы)
  5. Predicates
  6. Раздел описания предикатов (аналогичен разделу описания процедур и функций); по сути представляет собой шаблон написания фактов в разделе Clauses.

  7. Clauses
  8. Утверждения (аналог: тело основной программы).

  9. Goal
  10. Целевое утверждение – «цель».

Задание prolog 2_1: Запустите компилятор Tprolog. Создайте новый файл и наберите код программы, выводящий ответ на вопрос «Любит ли Мэри яблоки?» (ответ true или false). Код представлен ниже:

domains
 	a=symbol
predicates
 	likes (a,a)
clauses 
 	likes (mary,apples).

Перейдите в окно Dialog (меню Run) и введите запрос:

likes(mary,apples)

В результате в окне должен появиться ответ true

Факты и правила

Часто программу, написанную на Прологе, называют базой знаний.

База знаний на Прологе состоит из предложений, т.е. утверждений, каждое из которых завершается точкой.
Существует два вида предложений: факты и правила.

Предложения-правила имеют вид:

A:- B1,… , Bn.

Где A — это заголовок или голова предложения, а B1,..., Bn – это тело.

Факт обычно утверждает, что между объектами выполнено некоторое отношение и состоит из:

  • отношения
  • объекта или объектов, заключенных в круглые скобки (аргументы)
  • завершается точкой (.)

Пример факта:

likes  (bill, dogs).

где likes — факт
bill, dogs — аргументы факта, между которыми выполнено отношение (likes)

Т.к. отношение в математической логике принято называть предикатами, то и мы иногда будем использовать понятие «предикат» вместо «факта» или «правила».

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

Если факт состоит только из заголовка, то можно сказать, что факт – это предложение, у которого тело пустое.

Аргументом факта или предиката может быть константапеременная или составной объект; от их числа зависит так называемая местность (n-местность) факта.

Отличие константы от переменной: константа получает свое значение в разделе описания констант, тогда как переменная инициализируется в процессе работы программы.

В TProlog имя предиката или факта может содержать:  латинские буквы, цифры, знаки подчеркивания и начинаться с буквы или знака подчеркивания.

В следующем примере наводите курсор на части конструкций, и появится подсказка:

[simple_tooltip content='предикат или факт']likes[/simple_tooltip] [simple_tooltip content='аргументы'] (bill, dogs).[/simple_tooltip]  - Билл любит собак.
[simple_tooltip content='предикат или факт'] bird [/simple_tooltip] [simple_tooltip content='аргумент'](vorobej). [/simple_tooltip] Птица – воробей.

Таким образом, в примере likes — это имя двухаргументного предиката (факта), у которого строковая константа «bill» является первым аргументом, а «dogs» — вторым аргументом.

Аргументы с известными или постоянными значениями должны начинаться со строчных букв
Задание prolog 2_2: Дано начало программы (раздел domains и predicates) для базы данных «Возраст ребенка». Составить факты для программы, основываясь на данных указанных разделов и следующих сведений: Ивану 2 года, Алексу 3 года, Марии — 5 лет.

domains 
  a=symbol
  b=integer
predicates
  age(a,b)
clauses
 age(...,...).
 ...(...,...).
 ...(...,...).

Наберите код программы в компиляторе.

Цели

Цель — это формулировка задачи, которую программа должна решить. Цель также служит «триггером» для запуска программы.

Турбо-Пролог использует как внутренние цели, которые содержатся в программе, так и внешние цели, которые вводятся с клавиатуры после запуска программы. Здесь существует два варианта:

  1. Если цель является фактом, то Турбо-Пролог отвечает True (истина) или False (ложь):
goal
likes(mary,apples).

Дословно: Мэри любит яблоки.

  1. Если цель содержит переменные, то Турбо-Пролог выдает те их значения, которые приводят к решению:
goal
likes(mary,X).

Дословно: Что любит Мэри?

Важно:  Цели, дающие в результате истинность или ложь, чаще вводятся в окно  Dialog
Важно: Переменные начинаются с прописных букв

* Понятие переменной в Прологе будет рассмотрено в следующем уроке.

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

Так, наш пример может быть как фактом, так и целью:

likes(mary,apples). Мэри любит яблоки и Любит ли Мэри яблоки?

Алгоритм составления программы

Программа для компилятора TProlog состоит из разделов, рассмотренных в примере:

domains
 	a=symbol
Описание доменов
predicates
 	likes (a,a)
Раздел предикатов
Предикат – это логическая формула от одного или нескольких аргументов
clauses 
 	likes (mary,apples).
	likes(mary,oranges).
  	color(apples,red).
Факты
goal
 	likes(mary,X),write("mary lyubit ", X).
Запрос

Результатом примера будет: «mary lyubit apples».

В данном примере цель записана в виде раздела GOAL прямо в программе, но нужно иметь в виду, что чаще всего цели, требующие логический ответ (правда или ложь), записываются в окне Dialog (goal в программе тогда не пишется)

Бесконечный цикл

В примере, описанном выше, в результате выдается значение только первого из трех фактов:

clauses 
 	likes (mary,apples).
	likes(mary,oranges).
  	color(apples,red).
goal
 	likes(mary,X),write("mary lyubit ", X).

Результат выдает только apples. Хотя еще есть oranges.

Чтобы выдать все значения, необходимо организовать бесконечный цикл, который в коде выглядит как оператор fail, установленный в конце раздела GOAL

Раздел gaol того же примера, но с бесконечным циклом будет выглядеть так:

goal
 	likes(mary,X),write("mary lyubit ", X),nl,fail.

nl — означает переход на следующую строку (каждое значение выводится с новой строки).
Результат:
«mary lyubit apples».
«mary lyubit oranges».

Код программы целиком:

domains
 	a=symbol
predicates
 	likes (a,a)
clauses 
 	likes (mary,apples).
	likes(mary,oranges).
  	color(apples,red).	
goal
 	likes(mary,X),write("mary lyubit ", X),nl,fail.

Рассмотрим еще один пример.

* Пример: Составить базу фактов по стихотворению «Дом, который построил Джек».
Составить разные запросы к базе данных (выполнить часть запросов в окне Dialog, а другую часть в разделе Goal программы).

Код программы без запросов:

domains
  a=symbol
predicates
  построил (a,a)
  хранится (a,a)
  ворует (a,a)
  ловит (a,a)
  треплет (a,a)
  доит (a,a)
  бранится (a,a)
  будят (a,a)
clauses 
  построил (джек,дом).
  хранится (пшеница, чулан_дома).
  ворует (птица_синица, пшеница).
  ловит (кот, птица_синица).
  треплет (кот, птица_синица).
  треплет (пес, кот).
  доит (старушка, корова).
  бранится (пастух, старушка).
  будят (два_петуха, пастух).
Выполнение запросов в окне dialog:

? - построил (Х, дом). 
/*Кто построил дом?*/

Ответ: Х=Джек

? – ловит (кот, Y)
/*Кого ловит кот?*/

Ответ: Y= птица_синица

? – бранится (X,Y).	
/*Кто с кем бранится?*/

Ответ: X =пастух, Y= старушка

? – хранится (X, чулан_дома), ворует (X,Y).          
/*Что хранится в чулане дома и кто ворует это */

Ответ: X = пшеница, Y= птица_синица

Выполнение запросов в разделе Goal:

goal
  postroil(X,house),write(X),nl,fail.
* Задание prolog 2_3:

  1. Составить базу данных «Именины и хобби друзей».
  2. Составить запросы к базе данных, исходя из приведенных ниже:
  • чьи именины в сентябре?
  • когда именины у Ивана?
  • кто любит танцы?
  • кто любит книги и спорт?
  • что любит Петр?
domains
	a=symbol
	b=integer
predicates
	birthday(a,b,a)
	likes(a,a)
clauses
	birthday(nataly, 8, september).
	birthday(yana, 25, august).
	birthday(nina, 28, september).
	birthday(peter, 2, august).
	birthday(ivan, 12, august).
	likes(nataly, books).
	likes(nataly, sport).
	likes(yana, books).
	likes(yana, dances).
	likes(peter, music).
	likes(peter, dances).
	likes(ivan, sport).
	likes(ivan, books).
Goal
/* birthday(X,Y,september),write(X," rodilas ", Y, " sentyabrya"),nl,fail.*/,  write(), nl, fail.

* Для удобства после выполнения очередного запроса, комментируйте его (/* ... */) и приступайте к написанию кода следующего запроса.

* Задание prolog 2_4:

  1. Составить базу данных «Предметы и преподаватели», содержащую информацию о названии предмета, должности и фамилии преподавателя, номер семестра, отчетность.
  2. Составить запросы к базе данных, исходя из приведенных ниже:
  • по каким предметам экзамен?
  • какой предмет и когда читает доцент морозов?
  • какая отчетность по тои?
  • кто и когда читает ПРЗ?
domains
	a=symbol
	b=integer
predicates
	 teach(a,a,a,b)
	 vedomost(a,a) 
clauses
	teach(prz, assistent,ivanova,2 ).
	teach(toi, docent, morozov,4).
	teach(mpi,docent, petrova, 5).
	vedomost(toi, exam).
	vedomost(prz, zach).
	vedomost(mpi, exam). 
Goal
/* vedomost(X,exam) ,write("exam po predmetu ", X),nl,fail. */,  write(), nl, fail.

* Для удобства после выполнения очередного запроса, комментируйте его (/* ... */) и приступайте к написанию кода следующего запроса.

* При использовании материалов обязательна ссылка на источник: Кузнецова Т.К., «Программирование Turbo Prolog» — Задачи и решения, Ростов-на-Дону, ПИ ЮФУ — 2011г.