Машина вывода Пролога
2.4. Трассировка в PIE
Процесс вычислений можно проследить в PIE, включив трассировку. Для включения и выключения трассировки в PIE используется пункт меню Engine > Trace Calls. Протокол вычислений выводится в окне Dialog (рис. 2.3).
Используются следующие операторы:
- CALL — вызов цели;
- RETURN — завершение (возврат результата);
- REDO — откат (возврат по успеху для поиска других решений);
- FAIL — возврат по неудаче.
Трассировка вычисления цели мать(X, Y) (см. п. 2.3) отображена на рис. 2.4. Она соответствует полному обходу дерева поиска в глубину (ср. с рис. 2.2).
2.5. Отладчик
Отладчик Visual Prolog запускается с помощью команды меню Debug > Run. Точки останова ставятся с помощью клавиши F9. Переход к первой точке останова, а также переходы между точками останова выполняются с помощью клавиши F5. Окно просмотра значений переменных, которые они принимают в текущем предложении, открывается с помощью команды меню View > Variables for Current Clause (рис. 2.5). Проследить пошаговую процедуру вычислений можно с помощью клавиш F10 и F11.
Упражнение 1.
Проследите
- в PIE;
- в Visual Prolog
процедуру поиска всех птиц (см. листинг 1.1).
2.6. Сложные термы
Термы бывают простые и сложные. Простые термы — это переменные и константы. Сложные термы — это составные термы и списки.
Составные термы определяются в Прологе так же, как и в математической логике, в виде
или
(в последнем случае скобки могут быть опущены), где
— это
-арный функциональный символ,
— нульарный, а
— термы. Функциональные символы в языке Пролог называются функторами, а сложные термы называют еще структурами. Для того чтобы получить возможность использовать в программе на языке Visual Prolog составные термы, следует объявить домен этих термов — указать их тип (см. листинг 2.3).
Список — это конечная последовательность элементов. В виде составного терма список можно представить следующим образом:
, где функтор
обозначает пустой список. Для списков в языке Пролог имеется специальное обозначение. Элементы списка разделяются запятыми и заключаются в квадратные скобки: [1, 2, 3]. Пустой список обозначается [].
Первый элемент списка называется его головой, список остальных элементов — его хвостом. Терм [H | T] обозначает непустой список с головой H и хвостом T. Для списка [1, 2, 3] имеем: H = 1, T = [2, 3].
Для термов вида [1 | [2 | [3 | T]]] используется сокращение [1, 2, 3 | T]. Таким образом, с помощью знака "|" можно отделить как голову списка, так и несколько его первых элементов, после этого знака находится список оставшихся элементов.
Списки унифицируются поэлементно. Например, термы [1, 2, 3 | L] и [A, B | T] унифицирует подстановка A = 1, B = 2, T = [3 | L].
В языке Visual Prolog все элементы списка должны принадлежать одному и тому же домену. Домен списков указывается с помощью приписывания знака "*" к домену элементов списка (см. листинг 2.4).
Анонимная переменная унифицируется с любым термом, но ей не присваивается никакого значения. Так, терм [_, _] унифицируется с любым списком, состоящим ровно из двух элементов, а терм [_ | _] с любым непустым списком.
В следующей программе в виде составных термов описываются печатные издания, которые имеются в домашней библиотеке на книжной полке. Домен publication — это домен термов двух видов, которые представляют два типа печатных изданий — книги и журналы. В объявлении домена для каждого типа термов указывается имя функтора и имена доменов аргументов. Различные типы термов, принадлежащие одному домену, перечисляются через точку с запятой, они называются альтернативами.
publication = book(author, string Название, edition Издание);
magazine(string Название, integer Номер, integer Год).
author = author(string Фамилия, string Имя, string Отчество).
edition = edition(string Место, string Издательство, integer Год).
class facts
library: (publication).
clauses
library(magazine("Компьютерра", 2, 2009)).
library(magazine("Наука и жизнь", 11, 2012)).
library(book(author("Чехов", "Антон", "Павлович"),
"Избранное", edition("Москва", "АСТ, Астрель", 2003))).
library(book(author("Великова", "Людмила", "Викторовна"),
"Русский язык", edition("Москва", "МЦНМО", 2003))).
run():-
% Что есть в библиотеке?
library(X),
write(X), nl,
fail;
% Названия книг, изданных в 2003 году
library(book(_, Title, edition(_, _, 2003))),
write(Title), nl,
fail;
_ = readLine().
Пример
2.3.
"Библиотека"
Упражнение 2.
Добавьте в программу "Библиотека" (см. листинг 2.3) новые факты, содержащие сведения о книгах и журналах. Используя анонимные переменные, найдите ответы на запросы:
- За какие годы имеются журналы в библиотеке?
- Найдите книги, изданные в Москве или в Санкт-Петербурге.
В приведенной ниже программе списки используются для описания сведений об иностранных языках, которые изучает группа студентов.
class facts
knows: (string, string*).
clauses
knows("Даша", ["английский", "испанский", "французский"]).
knows("Маша", ["немецкий", "английский"]).
knows("Глаша", ["английский", "немецкий"]).
knows("Паша", ["английский"]).
run():-
knows(X, Y),
write(X, " - ", Y), nl,
fail;
_ = readLine().
Пример
2.4.
"Иностранные языки"
Упражнение 3.
Добавьте в программу "Иностранные языки" (см. листинг 2.4) новые факты. Найдите с помощью программы ответы на запросы:
- Какие языки знает Маша?
- Кто знает не менее двух иностранных языков?


