Машина вывода Пролога
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) новые факты. Найдите с помощью программы ответы на запросы:
- Какие языки знает Маша?
- Кто знает не менее двух иностранных языков?